In this PR, we entered early-ra with quite a bit of dead code.
The code was duly removed (to avoid wasting registers), but there
was a dangling reference in debug instructions, which caused an
ICE later.

Fixed by resetting a debug instruction if it references a register
that is no longer needed by non-debug instructions.

Tested on aarch64-linux-gnu & pushed.

Richard


gcc/
        PR target/113636
        * config/aarch64/aarch64-early-ra.cc (early_ra::replace_regs): Take
        the containing insn as an extra parameter.  Reset debug instructions
        if they reference a register that is no longer used by real insns.
        (early_ra::apply_allocation): Update calls accordingly.

gcc/testsuite/
        PR target/113636
        * go.dg/pr113636.go: New test.
---
 gcc/config/aarch64/aarch64-early-ra.cc | 19 ++++++++----
 gcc/testsuite/go.dg/pr113636.go        | 40 ++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/go.dg/pr113636.go

diff --git a/gcc/config/aarch64/aarch64-early-ra.cc 
b/gcc/config/aarch64/aarch64-early-ra.cc
index 033eac7aaf1..028296639b8 100644
--- a/gcc/config/aarch64/aarch64-early-ra.cc
+++ b/gcc/config/aarch64/aarch64-early-ra.cc
@@ -478,7 +478,7 @@ private:
   void broaden_colors ();
   void finalize_allocation ();
 
-  bool replace_regs (df_ref);
+  bool replace_regs (rtx_insn *, df_ref);
   int try_enforce_constraints (rtx_insn *, vec<std::pair<int, int>> &);
   void enforce_constraints (rtx_insn *);
   bool maybe_convert_to_strided_access (rtx_insn *);
@@ -2981,8 +2981,9 @@ early_ra::finalize_allocation ()
 }
 
 // Replace any allocno references in REFS with the allocated register.
+// INSN is the instruction that contains REFS.
 bool
-early_ra::replace_regs (df_ref refs)
+early_ra::replace_regs (rtx_insn *insn, df_ref refs)
 {
   bool changed = false;
   for (df_ref ref = refs; ref; ref = DF_REF_NEXT_LOC (ref))
@@ -2992,6 +2993,14 @@ early_ra::replace_regs (df_ref refs)
        continue;
 
       auto new_regno = range.allocno (0)->hard_regno;
+      if (new_regno == FIRST_PSEUDO_REGISTER)
+       {
+         // Reset a debug instruction if, after DCE, the only remaining
+         // references to a register are in such instructions.
+         gcc_assert (DEBUG_INSN_P (insn));
+         INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+         return true;
+       }
       *DF_REF_LOC (ref) = gen_rtx_REG (GET_MODE (DF_REF_REG (ref)), new_regno);
       changed = true;
     }
@@ -3224,8 +3233,8 @@ early_ra::apply_allocation ()
          continue;
 
        bool changed = maybe_convert_to_strided_access (insn);
-       changed |= replace_regs (DF_INSN_DEFS (insn));
-       changed |= replace_regs (DF_INSN_USES (insn));
+       changed |= replace_regs (insn, DF_INSN_DEFS (insn));
+       changed |= replace_regs (insn, DF_INSN_USES (insn));
        if (changed && NONDEBUG_INSN_P (insn))
          {
            if (GET_CODE (PATTERN (insn)) != USE
@@ -3245,7 +3254,7 @@ early_ra::apply_allocation ()
              else
                ptr = &XEXP (*ptr, 1);
          }
-       changed |= replace_regs (DF_INSN_EQ_USES (insn));
+       changed |= replace_regs (insn, DF_INSN_EQ_USES (insn));
        if (changed)
          df_insn_rescan (insn);
       }
diff --git a/gcc/testsuite/go.dg/pr113636.go b/gcc/testsuite/go.dg/pr113636.go
new file mode 100644
index 00000000000..3f43b696765
--- /dev/null
+++ b/gcc/testsuite/go.dg/pr113636.go
@@ -0,0 +1,40 @@
+// { dg-do compile }
+// { dg-options "-O3 -g" }
+// { dg-additional-options "-mtune=thunderxt88" { target aarch64*-*-* } }
+
+package main
+
+import "math"
+
+func sinhcosh(x float64) (sh, ch float64) {
+       if math.Abs(x) <= 0.5 {
+               return math.Sinh(x), math.Cosh(x)
+       }
+       e := math.Exp(x)
+       ei := 0.5 / e
+       e *= 0.5
+       return e - ei, e + ei
+}
+
+func Cos(x complex128) complex128 {
+       switch re, im := real(x), imag(x); {
+       case im == 0 && (math.IsInf(re, 0) || math.IsNaN(re)):
+               return complex(math.NaN(), -im*math.Copysign(0, re))
+       case math.IsInf(im, 0):
+               switch {
+               // case re == 0:
+               //      return complex(math.Inf(1), -re*math.Copysign(0, im))
+               case math.IsInf(re, 0) || math.IsNaN(re):
+                       return complex(math.Inf(1), math.NaN())
+               }
+       // case re == 0 && math.IsNaN(im):
+       //      return complex(math.NaN(), 0)
+       }
+       s, c := math.Sincos(real(x))
+       sh, ch := sinhcosh(imag(x))
+       return complex(c*ch, -s*sh)
+}
+
+func main() {
+       Cos(complex(2.5, 3.5))
+}
-- 
2.25.1

Reply via email to