Hi, This is a fix tring to solve PR94121.
The ICE appears when generating an add insn with the offset. If the offset is negative, function aarch64_add_offset_1 in aarch64.c will take its absolute value. With this fix, offset does not take absolute value if it equals to the minimum value of machine. Added one test case for this. Bootstrap and tested on aarch64 Linux platform. Zekun Li Log: PR 94121 * aarch64.c (aarch64_add_offset_1): Add a branch when generating addition assembly expression with offset HOST_WIDE_INT_MIN. * gcc.target/aarch64/PR94121.c: New test.
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 4b9747b4c5e..a6b60cf8a92 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3713,9 +3713,31 @@ aarch64_add_offset_1 (scalar_int_mode mode, rtx dest, gcc_assert (emit_move_imm || temp1 != NULL_RTX); gcc_assert (temp1 == NULL_RTX || !reg_overlap_mentioned_p (temp1, src)); - HOST_WIDE_INT moffset = abs_hwi (offset); rtx_insn *insn; + if (offset == HOST_WIDE_INT_MIN) + { + if (emit_move_imm) + { + gcc_assert (temp1 != NULL_RTX || can_create_pseudo_p ()); + temp1 = aarch64_force_temporary (mode, temp1, GEN_INT (offset)); + insn = emit_insn (gen_add3_insn (dest, src, temp1)); + } + else + { + insn = emit_insn (gen_sub3_insn (dest, src, temp1)); + } + if (frame_related_p) + { + RTX_FRAME_RELATED_P (insn) = frame_related_p; + rtx adj = plus_constant (mode, src, offset); + add_reg_note (insn, REG_CFA_ADJUST_CFA, gen_rtx_SET (dest, adj)); + } + return; + } + + HOST_WIDE_INT moffset = abs_hwi (offset); + if (!moffset) { if (!rtx_equal_p (dest, src)) diff --git a/gcc/testsuite/gcc.target/aarch64/PR94121.c b/gcc/testsuite/gcc.target/aarch64/PR94121.c new file mode 100644 index 00000000000..8960f8cbf62 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/PR94121.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fpie" } */ + +#define DIFF_MAX __PTRDIFF_MAX__ +#define DIFF_MIN (-DIFF_MAX - 1) + +extern +void foo (); + +void test_global_char_array (void) +{ + extern char gcar3[1]; + char *p = gcar3; + foo (&p[DIFF_MIN]); +}