unsigned OpcodeForCandidate,
MachineInstr *MIForCandidate) {
if (!CurrentUse.Ty.isValid()) {
- if (CurrentUse.ExtendOpcode == OpcodeForCandidate)
- return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
- if (CurrentUse.ExtendOpcode == TargetOpcode::G_ANYEXT &&
- (OpcodeForCandidate == TargetOpcode::G_SEXT ||
- OpcodeForCandidate == TargetOpcode::G_ZEXT ||
- OpcodeForCandidate == TargetOpcode::G_ANYEXT))
+ if (CurrentUse.ExtendOpcode == OpcodeForCandidate ||
+ CurrentUse.ExtendOpcode == TargetOpcode::G_ANYEXT)
return {TyForCandidate, OpcodeForCandidate, MIForCandidate};
return CurrentUse;
}
PreferredTuple Preferred = {LLT(), PreferredOpcode, nullptr};
for (auto &UseMI : MRI.use_instructions(LoadValue.getReg())) {
if (UseMI.getOpcode() == TargetOpcode::G_SEXT ||
- UseMI.getOpcode() == TargetOpcode::G_ZEXT || !Preferred.Ty.isValid())
+ UseMI.getOpcode() == TargetOpcode::G_ZEXT ||
+ UseMI.getOpcode() == TargetOpcode::G_ANYEXT) {
Preferred = ChoosePreferredUse(Preferred,
MRI.getType(UseMI.getOperand(0).getReg()),
UseMI.getOpcode(), &UseMI);
+ }
}
// There were no extends
ret void
}
+ define void @use_doesnt_def_anything(i8* %addr) {
+ entry:
+ ret void
+ }
+
+ define void @op0_isnt_a_reg(i8* %addr) {
+ entry:
+ ret void
+ }
+
...
---
---
name: sink_to_phi_nondominating
# CHECK-LABEL: name: sink_to_phi_nondominating
-# This test currently tests that we don't sink if we would sink to a phi. This
-# is needed to avoid inserting into the middle of the leading G_PHI instructions
-# of a BB
tracksRegLiveness: true
body: |
bb.0.entry:
$w1 = COPY %9
...
+---
+name: use_doesnt_def_anything
+# CHECK-LABEL: name: use_doesnt_def_anything
+# Check that we don't crash when inspecting a use that doesn't define anything.
+# The real issue which was that the combine rule was looking through
+# non-truncates as if they were truncates and attempting to obtain the result
+# register. It would usually go on to make the right overall decision anyway but
+# would sometimes crash on things like (SOME_INTRINSIC imm). This test covers
+# the case that it would recover from.
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $x0, $w1
+ %0:_(p0) = COPY $x0
+ %1:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr)
+ ; CHECK: %1:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr)
+ G_STORE %1(s8), %0(p0) :: (store 1 into %ir.addr)
+ ; CHECK: G_STORE %1(s8), %0(p0) :: (store 1 into %ir.addr)
+...
+---
+name: op0_isnt_a_reg
+# CHECK-LABEL: name: op0_isnt_a_reg
+# This test covers the variant of use_doesnt_def_anything that would crash.
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $x0, $w1
+ %0:_(p0) = COPY $x0
+ %1:_(s8) = G_LOAD %0 :: (load 1 from %ir.addr)
+ ; CHECK: %1:_(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr)
+ G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.hint), %1(s8)
+ ; CHECK: G_INTRINSIC_W_SIDE_EFFECTS intrinsic(@llvm.aarch64.hint), %1(s8)
+...