// Ignore dbg intrinsics.
if (isa<DbgInfoIntrinsic>(I))
continue;
- // I must be safe to execute unconditionally.
- if (!isSafeToSpeculativelyExecute(&*I))
+ if (!I->hasOneUse() || !isSafeToSpeculativelyExecute(&*I))
return Changed;
+ // I has only one use and can be executed unconditionally.
+ Instruction *User = dyn_cast<Instruction>(I->user_back());
+ if (User == nullptr || User->getParent() != BB)
+ return Changed;
+ // I is used in the same BB. Since BI uses Cond and doesn't have more slots
+ // to use any other instruction, User must be an instruction between next(I)
+ // and Cond.
// Account for the cost of duplicating this instruction into each
// predecessor.
PBI->swapSuccessors();
}
- // Before cloning instructions, notify the successor basic block that it
- // is about to have a new predecessor. This will update PHI nodes,
- // which will allow us to update live-out uses of bonus instructions.
- if (BI->isConditional())
- AddPredecessorToBlock(PBI->getSuccessor(0) == BB ? TrueDest : FalseDest,
- PredBlock, BB, MSSAU);
-
// If we have bonus instructions, clone them into the predecessor block.
// Note that there may be multiple predecessor blocks, so we cannot move
// bonus instructions to a predecessor block.
PredBlock->getInstList().insert(PBI->getIterator(), NewBonusInst);
NewBonusInst->takeName(&*BonusInst);
BonusInst->setName(BonusInst->getName() + ".old");
- BonusInst->replaceUsesWithIf(
- NewBonusInst, [CurrBB = BonusInst->getParent(), PredBlock](Use &U) {
- auto *User = cast<Instruction>(U.getUser());
- // Ignore uses in the same block as the bonus instruction itself.
- if (User->getParent() == CurrBB)
- return false;
- // We can safely update external non-PHI uses.
- if (!isa<PHINode>(User))
- return true;
- // For PHI nodes, only update the uses for the current predecessor.
- return cast<PHINode>(User)->getIncomingBlock(U) == PredBlock;
- });
}
// Clone Cond into the predecessor basic block, and or/and the
(SuccFalseWeight + SuccTrueWeight) +
PredTrueWeight * SuccFalseWeight);
}
+ AddPredecessorToBlock(TrueDest, PredBlock, BB, MSSAU);
PBI->setSuccessor(0, TrueDest);
}
if (PBI->getSuccessor(1) == BB) {
// FalseWeight is FalseWeight for PBI * FalseWeight for BI.
NewWeights.push_back(PredFalseWeight * SuccFalseWeight);
}
+ AddPredecessorToBlock(FalseDest, PredBlock, BB, MSSAU);
PBI->setSuccessor(1, FalseDest);
}
if (NewWeights.size() == 2) {
; CHECK-LABEL: @one_pred_with_extra_op_multiuse(
; CHECK-NEXT: pred:
; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
+; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK: dispatch:
; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
; CHECK-NEXT: [[V1_ADJ_ADJ:%.*]] = add i8 [[V1_ADJ]], [[V1_ADJ]]
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ_ADJ]], 0
-; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
-; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: ret void
; CHECK-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]]
; CHECK: pred0:
; 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: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]]
; CHECK: pred1:
-; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2]], 0
+; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0
+; CHECK-NEXT: br i1 [[C2]], label [[DISPATCH]], label [[FINAL_RIGHT:%.*]]
+; CHECK: dispatch:
; CHECK-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
; CHECK-NEXT: [[V3_ADJ_ADJ:%.*]] = add i8 [[V3_ADJ]], [[V3_ADJ]]
; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ_ADJ]], 0
-; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C2]], [[C3]]
-; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
+; CHECK-NEXT: br i1 [[C3]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: ret void
; CHECK-LABEL: @one_pred_with_extra_op_liveout(
; CHECK-NEXT: pred:
; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
+; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK: dispatch:
; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
-; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
-; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
; CHECK-LABEL: @one_pred_with_extra_op_liveout_multiuse(
; CHECK-NEXT: pred:
; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
+; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK: dispatch:
; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1_ADJ]], 0
-; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
-; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: call void @use8(i8 [[V1_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: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
-; 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:%.*]] = 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: br i1 [[C3]], 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:%.*]] = phi i8 [ [[V3_ADJ]], [[DISPATCH]] ], [ 0, [[PRED0]] ]
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: ret void
; 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: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0
-; 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:%.*]] = 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: br i1 [[C3]], 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: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ]], [[DISPATCH]] ], [ 0, [[PRED0]] ]
+; CHECK-NEXT: [[MERGE_LEFT_2:%.*]] = phi i8 [ [[V3_ADJ]], [[DISPATCH]] ], [ 42, [[PRED0]] ]
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT_2]])
; CHECK-NEXT: call void @sideeffect0()
; CHECK-LABEL: @one_pred_with_extra_op_eexternally_used_only(
; CHECK-NEXT: pred:
; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
+; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK: dispatch:
; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1]], 0
-; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
-; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: call void @use8(i8 [[V1_ADJ]])
; CHECK-LABEL: @one_pred_with_extra_op_externally_used_only_multiuse(
; CHECK-NEXT: pred:
; CHECK-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0
+; CHECK-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK: dispatch:
; CHECK-NEXT: [[V1_ADJ:%.*]] = add i8 [[V0]], [[V1:%.*]]
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V1]], 0
-; CHECK-NEXT: [[OR_COND:%.*]] = and i1 [[C0]], [[C1]]
-; CHECK-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]]
+; CHECK-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]]
; CHECK: final_left:
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: call void @use8(i8 [[V1_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: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
-; 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:%.*]] = 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: br i1 [[C3]], 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:%.*]] = phi i8 [ [[V3_ADJ]], [[DISPATCH]] ], [ 0, [[PRED0]] ]
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: ret void
; 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: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]]
; CHECK-NEXT: [[C3:%.*]] = icmp eq i8 [[V3:%.*]], 0
-; 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:%.*]] = 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: br i1 [[C3]], 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: [[MERGE_LEFT:%.*]] = phi i8 [ [[V3_ADJ]], [[DISPATCH]] ], [ 0, [[PRED0]] ]
+; CHECK-NEXT: [[MERGE_LEFT_2:%.*]] = phi i8 [ [[V3_ADJ]], [[DISPATCH]] ], [ 42, [[PRED0]] ]
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT]])
; CHECK-NEXT: call void @use8(i8 [[MERGE_LEFT_2]])
; CHECK-NEXT: call void @sideeffect0()