unsigned PointerReg,
ArrayRef<MachineInstr *> PrevInsts);
+ /// Returns true if \p DependenceMI can clobber the liveIns in NullSucc block
+ /// if it was hoisted to the NullCheck block. This is used by caller
+ /// canHoistInst to decide if DependenceMI can be hoisted safely.
+ bool canDependenceHoistingClobberLiveIns(MachineInstr *DependenceMI,
+ MachineBasicBlock *NullSucc,
+ unsigned PointerReg);
+
/// Return true if \p FaultingMI can be hoisted from after the
/// instructions in \p InstsSeenSoFar to before them. Set \p Dependence to a
/// non-null value if we also need to (and legally can) hoist a depedency.
return SR_Suitable;
}
-bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI,
- unsigned PointerReg,
- ArrayRef<MachineInstr *> InstsSeenSoFar,
- MachineBasicBlock *NullSucc,
- MachineInstr *&Dependence) {
- auto DepResult = computeDependence(FaultingMI, InstsSeenSoFar);
- if (!DepResult.CanReorder)
- return false;
-
- if (!DepResult.PotentialDependence) {
- Dependence = nullptr;
- return true;
- }
-
- auto DependenceItr = *DepResult.PotentialDependence;
- auto *DependenceMI = *DependenceItr;
-
- // We don't want to reason about speculating loads. Note -- at this point
- // we should have already filtered out all of the other non-speculatable
- // things, like calls and stores.
- // We also do not want to hoist stores because it might change the memory
- // while the FaultingMI may result in faulting.
- assert(canHandle(DependenceMI) && "Should never have reached here!");
- if (DependenceMI->mayLoadOrStore())
- return false;
-
+bool ImplicitNullChecks::canDependenceHoistingClobberLiveIns(
+ MachineInstr *DependenceMI, MachineBasicBlock *NullSucc,
+ unsigned PointerReg) {
for (auto &DependenceMO : DependenceMI->operands()) {
if (!(DependenceMO.isReg() && DependenceMO.getReg()))
continue;
// same as it would have been had the load not have executed and we'd have
// branched to NullSucc directly.
if (AnyAliasLiveIn(TRI, NullSucc, DependenceMO.getReg()))
- return false;
+ return true;
// The Dependency can't be re-defining the base register -- then we won't
// get the memory operation on the address we want. This is already
"Should have been checked before!");
}
+ // The dependence does not clobber live-ins in NullSucc block.
+ return false;
+}
+
+bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI,
+ unsigned PointerReg,
+ ArrayRef<MachineInstr *> InstsSeenSoFar,
+ MachineBasicBlock *NullSucc,
+ MachineInstr *&Dependence) {
+ auto DepResult = computeDependence(FaultingMI, InstsSeenSoFar);
+ if (!DepResult.CanReorder)
+ return false;
+
+ if (!DepResult.PotentialDependence) {
+ Dependence = nullptr;
+ return true;
+ }
+
+ auto DependenceItr = *DepResult.PotentialDependence;
+ auto *DependenceMI = *DependenceItr;
+
+ // We don't want to reason about speculating loads. Note -- at this point
+ // we should have already filtered out all of the other non-speculatable
+ // things, like calls and stores.
+ // We also do not want to hoist stores because it might change the memory
+ // while the FaultingMI may result in faulting.
+ assert(canHandle(DependenceMI) && "Should never have reached here!");
+ if (DependenceMI->mayLoadOrStore())
+ return false;
+
+ if (canDependenceHoistingClobberLiveIns(DependenceMI, NullSucc, PointerReg))
+ return false;
+
auto DepDepResult =
computeDependence(DependenceMI, {InstsSeenSoFar.begin(), DependenceItr});