static enum gimplify_status
gimplify_scalar_mode_aggregate_compare (tree *expr_p)
{
- location_t loc = EXPR_LOCATION (*expr_p);
+ const location_t loc = EXPR_LOCATION (*expr_p);
+ const enum tree_code code = TREE_CODE (*expr_p);
tree op0 = TREE_OPERAND (*expr_p, 0);
tree op1 = TREE_OPERAND (*expr_p, 1);
-
tree type = TREE_TYPE (op0);
tree scalar_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1);
op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op0);
op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op1);
- *expr_p
- = fold_build2_loc (loc, TREE_CODE (*expr_p), TREE_TYPE (*expr_p), op0, op1);
+ /* We need to perform ordering comparisons in memory order like memcmp and,
+ therefore, may need to byte-swap operands for little-endian targets. */
+ if (code != EQ_EXPR && code != NE_EXPR)
+ {
+ gcc_assert (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN);
+ gcc_assert (TREE_CODE (scalar_type) == INTEGER_TYPE);
+ tree fndecl;
+
+ if (BYTES_BIG_ENDIAN)
+ fndecl = NULL_TREE;
+ else
+ switch (int_size_in_bytes (scalar_type))
+ {
+ case 1:
+ fndecl = NULL_TREE;
+ break;
+ case 2:
+ fndecl = builtin_decl_implicit (BUILT_IN_BSWAP16);
+ break;
+ case 4:
+ fndecl = builtin_decl_implicit (BUILT_IN_BSWAP32);
+ break;
+ case 8:
+ fndecl = builtin_decl_implicit (BUILT_IN_BSWAP64);
+ break;
+ case 16:
+ fndecl = builtin_decl_implicit (BUILT_IN_BSWAP128);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (fndecl)
+ {
+ op0 = build_call_expr_loc (loc, fndecl, 1, op0);
+ op1 = build_call_expr_loc (loc, fndecl, 1, op1);
+ }
+ }
+
+ *expr_p = fold_build2_loc (loc, code, TREE_TYPE (*expr_p), op0, op1);
return GS_OK;
}
else
goto expr_2;
}
- else if (TYPE_MODE (type) != BLKmode)
+ else if (SCALAR_INT_MODE_P (TYPE_MODE (type)))
ret = gimplify_scalar_mode_aggregate_compare (expr_p);
else
ret = gimplify_variable_sized_compare (expr_p);
--- /dev/null
+-- { dg-do run }
+
+with Array42_Pkg; use Array42_Pkg;
+
+procedure Array42 is
+
+ procedure Raise_Error_If_False (Test : Boolean; N : Positive) is
+ begin
+ if not Test then
+ raise Program_Error with "Test" & N'Img & " fails";
+ end if;
+ end;
+
+begin
+ Raise_Error_If_False (LT2 ("12", "21"), 1);
+ Raise_Error_If_False (LT4 ("1234", "4321"), 2);
+ Raise_Error_If_False (LT8 ("12345678", "87654321"), 3);
+ Raise_Error_If_False (LT8 ("12345678", "87654321"), 4);
+ Raise_Error_If_False (LT16 ("12345678ABCDEFGH", "HGFEDCBA87654321"), 5);
+
+ Raise_Error_If_False (LT5 ("12345", "54321"), 6);
+ Raise_Error_If_False (LE5 ("12345", "54321"), 7);
+ Raise_Error_If_False (not GT5 ("12345", "54321"), 8);
+ Raise_Error_If_False (not GE5 ("12345", "54321"), 9);
+
+ Raise_Error_If_False (LT45 ("1234", "12345"), 10);
+ Raise_Error_If_False (not LT54 ("12345", "1234"), 11);
+ Raise_Error_If_False (LT54 ("12345", "1235"), 12);
+
+ Raise_Error_If_False (LT ("1234", "12345"), 13);
+ Raise_Error_If_False (not LT ("12345", "1234"), 14);
+ Raise_Error_If_False (LT ("12345", "1235"), 15);
+end;
--- /dev/null
+package Array42_Pkg is
+
+ subtype S2 is String (1 .. 2);
+ subtype S4 is String (1 .. 4);
+ subtype S5 is String (1 .. 5);
+ subtype S8 is String (1 .. 8);
+ subtype S12 is String (1 .. 12);
+ subtype S16 is String (1 .. 16);
+
+ function LT2 (A, B : S2) return Boolean is (A < B);
+ function LT4 (A, B : S4) return Boolean is (A < B);
+ function LT8 (A, B : S8) return Boolean is (A < B);
+ function LT16 (A, B : S16) return Boolean is (A < B);
+
+ function LT5 (A, B : S5) return Boolean is (A < B);
+ function LE5 (A, B : S5) return Boolean is (A <= B);
+ function GT5 (A, B : S5) return Boolean is (A > B);
+ function GE5 (A, B : S5) return Boolean is (A >= B);
+
+ function LT45 (A : S4; B : S5) return Boolean is (A < B);
+ function LT54 (A : S5; B : S4) return Boolean is (A < B);
+
+ function LT (A, B : String) return Boolean is (A < B);
+
+end Array42_Pkg;