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]);
+}

Reply via email to