bool isProfitable(const FlowPattern &FP) const;
bool isPredicableStore(const MachineInstr *MI) const;
bool isSafeToSpeculate(const MachineInstr *MI) const;
+ bool isPredicate(unsigned R) const;
unsigned getCondStoreOpcode(unsigned Opc, bool IfTrue) const;
void predicateInstr(MachineBasicBlock *ToB, MachineBasicBlock::iterator At,
unsigned R = MO.getReg();
if (!TargetRegisterInfo::isVirtualRegister(R))
continue;
- switch (MRI->getRegClass(R)->getID()) {
- case Hexagon::PredRegsRegClassID:
- case Hexagon::HvxQRRegClassID:
- break;
- default:
- continue;
- }
+ if (!isPredicate(R))
+ continue;
for (auto U = MRI->use_begin(R); U != MRI->use_end(); ++U)
if (U->getParent()->isPHI())
return false;
if (usesUndefVReg(&MI))
return false;
unsigned DefR = MI.getOperand(0).getReg();
- const TargetRegisterClass *RC = MRI->getRegClass(DefR);
- if (RC == &Hexagon::PredRegsRegClass)
+ if (isPredicate(DefR))
return false;
}
}
return false;
if (MI->hasUnmodeledSideEffects())
return false;
+ if (MI->getOpcode() == TargetOpcode::LIFETIME_END)
+ return false;
return true;
}
+bool HexagonEarlyIfConversion::isPredicate(unsigned R) const {
+ const TargetRegisterClass *RC = MRI->getRegClass(R);
+ return RC == &Hexagon::PredRegsRegClass ||
+ RC == &Hexagon::HvxQRRegClass;
+}
+
unsigned HexagonEarlyIfConversion::getCondStoreOpcode(unsigned Opc,
bool IfTrue) const {
return HII->getCondOpcode(Opc, !IfTrue);
--- /dev/null
+# RUN: llc -march=hexagon -run-pass hexagon-early-if %s -o - | FileCheck %s
+
+# Test that the LIFETIME_END instruction is not speculated and moved to a
+# different basic block.
+
+# CHECK: bb.1.b1:
+# CHECK: LIFETIME_END
+# CHECK: bb.2.b2:
+
+--- |
+
+ %s.0 = type { %s.1 }
+ %s.1 = type { %s.2 }
+ %s.2 = type { %s.3 }
+ %s.3 = type { %s.4 }
+ %s.4 = type { %s.5 }
+ %s.5 = type { i32, i32, i8* }
+
+ declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #0
+
+ define hidden fastcc void @f0() {
+ b0:
+ %v0 = alloca %s.0, align 4
+ %v1 = load i8, i8* undef, align 1
+ %v2 = add i8 %v1, -102
+ %v3 = icmp ult i8 %v2, 1
+ br i1 %v3, label %b1, label %b2
+
+ b1: ; preds = %b0
+ %v4 = bitcast %s.0* %v0 to i8*
+ call void @llvm.lifetime.end.p0i8(i64 12, i8* nonnull %v4)
+ br label %b2
+
+ b2: ; preds = %b1, %b0
+ ret void
+ }
+
+ attributes #0 = { argmemonly nounwind }
+
+...
+---
+name: f0
+alignment: 4
+registers:
+ - { id: 0, class: intregs, preferred-register: '' }
+ - { id: 1, class: intregs, preferred-register: '' }
+ - { id: 2, class: predregs, preferred-register: '' }
+ - { id: 3, class: predregs, preferred-register: '' }
+liveins:
+frameInfo:
+ maxAlignment: 4
+fixedStack:
+stack:
+ - { id: 0, name: v0, type: default, offset: 0, size: 12, alignment: 4 }
+constants:
+body: |
+ bb.0.b0:
+ successors: %bb.1.b1(0x40000000), %bb.2.b2(0x40000000)
+
+ %1 = IMPLICIT_DEF
+ %0 = L2_loadrb_io killed %1, 0 :: (load 1 from `i8* undef`)
+ %2 = C2_cmpeqi killed %0, 102
+ %3 = COPY killed %2
+ J2_jumpf killed %3, %bb.2.b2, implicit-def dead $pc
+ J2_jump %bb.1.b1, implicit-def dead $pc
+
+ bb.1.b1:
+ successors: %bb.2.b2(0x80000000)
+
+ LIFETIME_END %stack.0.v0
+
+ bb.2.b2:
+ PS_jmpret $r31, implicit-def dead $pc
+
+...