[pushed] aarch64: Handle debug references to removed registers [PR113636]
Checks
Commit Message
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
@@ -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);
}
new file mode 100644
@@ -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))
+}