Cond->getParent() != BB || !Cond->hasOneUse())
return Changed;
- // Make sure the instruction after the condition is the cond branch.
- BasicBlock::iterator CondIt = ++Cond->getIterator();
-
- // Ignore dbg intrinsics.
- while (isa<DbgInfoIntrinsic>(CondIt))
- ++CondIt;
-
- if (&*CondIt != BI)
- return Changed;
-
// Only allow this transformation if computing the condition doesn't involve
// too many instructions and these involved instructions can be executed
// unconditionally. We denote all involved instructions except the condition
// number of the bonus instructions we'll need to create when cloning into
// each predecessor does not exceed a certain threshold.
unsigned NumBonusInsts = 0;
- for (auto I = BB->begin(); Cond != &*I; ++I) {
- // Ignore dbg intrinsics.
- if (isa<DbgInfoIntrinsic>(I))
+ for (Instruction &I : *BB) {
+ // Don't check the branch condition comparison itself.
+ if (&I == Cond)
+ continue;
+ // Ignore dbg intrinsics, and the terminator.
+ if (isa<DbgInfoIntrinsic>(I) || isa<BranchInst>(I))
continue;
// I must be safe to execute unconditionally.
- if (!isSafeToSpeculativelyExecute(&*I))
+ if (!isSafeToSpeculativelyExecute(&I))
return Changed;
// Account for the cost of duplicating this instruction into each
// Note that there may be multiple predecessor blocks, so we cannot move
// bonus instructions to a predecessor block.
ValueToValueMapTy VMap; // maps original values to cloned values
- // We already make sure Cond is the last instruction before BI. Therefore,
- // all instructions before Cond other than DbgInfoIntrinsic are bonus
- // instructions.
- for (auto BonusInst = BB->begin(); Cond != &*BonusInst; ++BonusInst) {
- if (isa<DbgInfoIntrinsic>(BonusInst))
+ Instruction *CondInPred;
+ for (Instruction &BonusInst : *BB) {
+ if (isa<DbgInfoIntrinsic>(BonusInst) || isa<BranchInst>(BonusInst))
continue;
- Instruction *NewBonusInst = BonusInst->clone();
+
+ Instruction *NewBonusInst = BonusInst.clone();
+
+ if (&BonusInst == Cond)
+ CondInPred = NewBonusInst;
// When we fold the bonus instructions we want to make sure we
// reset their debug locations in order to avoid stepping on dead
RemapInstruction(NewBonusInst, VMap,
RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
- VMap[&*BonusInst] = NewBonusInst;
+ VMap[&BonusInst] = NewBonusInst;
// If we moved a load, we cannot any longer claim any knowledge about
// its potential value. The previous information might have been valid
NewBonusInst->dropUnknownNonDebugMetadata();
PredBlock->getInstList().insert(PBI->getIterator(), NewBonusInst);
- NewBonusInst->takeName(&*BonusInst);
- BonusInst->setName(BonusInst->getName() + ".old");
- BonusInst->replaceUsesWithIf(NewBonusInst, [BB](Use &U) {
+ NewBonusInst->takeName(&BonusInst);
+ BonusInst.setName(BonusInst.getName() + ".old");
+ BonusInst.replaceUsesWithIf(NewBonusInst, [BB](Use &U) {
auto *User = cast<Instruction>(U.getUser());
// Ignore uses in the same block as the bonus instruction itself.
if (User->getParent() == BB)
});
}
- // Clone Cond into the predecessor basic block, and or/and the
- // two conditions together.
- Instruction *CondInPred = Cond->clone();
-
- // Reset the condition debug location to avoid jumping on dead code
- // as the result of folding dead branches.
- CondInPred->setDebugLoc(DebugLoc());
-
- RemapInstruction(CondInPred, VMap,
- RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
- PredBlock->getInstList().insert(PBI->getIterator(), CondInPred);
- CondInPred->takeName(Cond);
- Cond->setName(CondInPred->getName() + ".old");
-
+ // Now that the Cond was cloned into the predecessor basic block,
+ // or/and the two conditions together.
if (BI->isConditional()) {
Instruction *NewCond = cast<Instruction>(
Builder.CreateBinOp(Opc, PBI->getCondition(), CondInPred, "or.cond"));
; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
; CHECK: pred0:
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
-; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3:%.*]], 0
-; CHECK-NEXT: [[OR_COND1:%.*]] = or i1 [[C1]], [[C3_OLD]]
-; CHECK-NEXT: br i1 [[OR_COND1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK-NEXT: [[DOTOLD:%.*]] = icmp eq i8 [[V3:%.*]], 0
+; CHECK-NEXT: [[OR_COND2:%.*]] = or i1 [[C1]], [[DOTOLD]]
+; CHECK-NEXT: br i1 [[OR_COND2]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
; CHECK: pred1:
; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3]], 0
; CHECK: pred0:
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
; CHECK-NEXT: [[DOTOLD:%.*]] = add i8 [[V1]], [[V2:%.*]]
-; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[DOTOLD]], 0
-; CHECK-NEXT: [[OR_COND2:%.*]] = or i1 [[C1]], [[C3_OLD]]
-; CHECK-NEXT: br i1 [[OR_COND2]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK-NEXT: [[DOTOLD1:%.*]] = icmp eq i8 [[DOTOLD]], 0
+; CHECK-NEXT: [[OR_COND4:%.*]] = or i1 [[C1]], [[DOTOLD1]]
+; CHECK-NEXT: br i1 [[OR_COND4]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
; CHECK: pred1:
; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2]], 0
; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
; CHECK-NEXT: [[DOTOLD:%.*]] = add i8 [[V1]], [[V2:%.*]]
; CHECK-NEXT: [[DOTOLD1:%.*]] = add i8 [[DOTOLD]], [[DOTOLD]]
-; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[DOTOLD1]], 0
-; CHECK-NEXT: [[OR_COND4:%.*]] = or i1 [[C1]], [[C3_OLD]]
-; CHECK-NEXT: br i1 [[OR_COND4]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK-NEXT: [[DOTOLD2:%.*]] = icmp eq i8 [[DOTOLD1]], 0
+; CHECK-NEXT: [[OR_COND6:%.*]] = or i1 [[C1]], [[DOTOLD2]]
+; CHECK-NEXT: br i1 [[OR_COND6]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
; CHECK: pred1:
; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2]], 0
; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
; CHECK: dispatch:
; CHECK-NEXT: [[DOTOLD:%.*]] = add i8 [[V1]], [[V2]]
-; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[DOTOLD]], 0
-; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
+; CHECK-NEXT: [[DOTOLD1:%.*]] = icmp eq i8 [[DOTOLD]], 0
+; CHECK-NEXT: br i1 [[DOTOLD1]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[DOTOLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
; CHECK: dispatch:
; CHECK-NEXT: [[DOTOLD:%.*]] = add i8 [[V1]], [[V2]]
-; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[DOTOLD]], 0
-; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
+; CHECK-NEXT: [[DOTOLD1:%.*]] = icmp eq i8 [[DOTOLD]], 0
+; CHECK-NEXT: br i1 [[DOTOLD1]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[DOTOLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
; CHECK-NEXT: [[MERGE_LEFT_2:%.*]] = phi i8 [ [[DOTOLD]], [[DISPATCH]] ], [ 42, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
; CHECK: dispatch:
; CHECK-NEXT: [[DOTOLD:%.*]] = add i8 [[V1]], [[V2]]
-; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
-; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
+; CHECK-NEXT: [[DOTOLD1:%.*]] = icmp eq i8 [[V3]], 0
+; CHECK-NEXT: br i1 [[DOTOLD1]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[DOTOLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
; CHECK: dispatch:
; CHECK-NEXT: [[DOTOLD:%.*]] = add i8 [[V1]], [[V2]]
-; CHECK-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3]], 0
-; CHECK-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
+; CHECK-NEXT: [[DOTOLD1:%.*]] = icmp eq i8 [[V3]], 0
+; CHECK-NEXT: br i1 [[DOTOLD1]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[DOTOLD]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
; CHECK-NEXT: [[MERGE_LEFT_2:%.*]] = phi i8 [ [[DOTOLD]], [[DISPATCH]] ], [ 42, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
; CHECK-NEXT: br i1 [[C0]], label [[PRED:%.*]], label [[LEFT_END:%.*]]
; CHECK: pred:
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0
-; CHECK-NEXT: br i1 [[C1]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
-; CHECK: dispatch:
; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
; CHECK-NEXT: [[V2_ADJ:%.*]] = add i8 [[V4:%.*]], [[V5:%.*]]
-; CHECK-NEXT: br i1 [[C3]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
+; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C1]], [[C3]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
; CHECK: final_left:
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: call void @use8(i8 [[V2_ADJ]])
; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
; CHECK: pred1:
; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
-; CHECK-NEXT: br i1 [[C2]], label [[DISPATCH]], label [[FINAL_RIGHT:%.*]]
-; CHECK: dispatch:
; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V4:%.*]], [[V5:%.*]]
-; CHECK-NEXT: br i1 [[C3]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
+; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]]
+; CHECK: dispatch:
+; CHECK-NEXT: [[DOTOLD:%.*]] = icmp eq i8 [[V3]], 0
+; CHECK-NEXT: [[DOTOLD1:%.*]] = add i8 [[V4]], [[V5]]
+; CHECK-NEXT: br i1 [[DOTOLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
; CHECK: final_left:
-; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ]], [[DISPATCH]] ], [ 0, [[PRED0]] ]
+; CHECK-NEXT: [[MERGE_LEFT:%.*]] = phi i8 [ [[DOTOLD1]], [[DISPATCH]] ], [ 0, [[PRED0]] ], [ [[V3_ADJ]], [[PRED1]] ]
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: ret void