// If we have seen an instruction with side effects, it's unsafe to reorder an
// instruction which reads memory or itself has side effects.
if ((Flags & SkipSideEffect) &&
- (I->mayReadFromMemory() || I->mayHaveSideEffects()))
+ (I->mayReadFromMemory() || I->mayHaveSideEffects() || isa<AllocaInst>(I)))
return false;
// Reordering across an instruction which does not necessarily transfer
static bool passingValueIsAlwaysUndefined(Value *V, Instruction *I, bool PtrValueMayBeModified = false);
+/// Helper function for HoistThenElseCodeToIf. Return true if identical
+/// instructions \p I1 and \p I2 can and should be hoisted.
+static bool shouldHoistCommonInstructions(Instruction *I1, Instruction *I2,
+ const TargetTransformInfo &TTI) {
+ // If we're going to hoist a call, make sure that the two instructions
+ // we're commoning/hoisting are both marked with musttail, or neither of
+ // them is marked as such. Otherwise, we might end up in a situation where
+ // we hoist from a block where the terminator is a `ret` to a block where
+ // the terminator is a `br`, and `musttail` calls expect to be followed by
+ // a return.
+ auto *C1 = dyn_cast<CallInst>(I1);
+ auto *C2 = dyn_cast<CallInst>(I2);
+ if (C1 && C2)
+ if (C1->isMustTailCall() != C2->isMustTailCall())
+ return false;
+
+ if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2))
+ return false;
+
+ // If any of the two call sites has nomerge or convergent attribute, stop
+ // hoisting.
+ if (const auto *CB1 = dyn_cast<CallBase>(I1))
+ if (CB1->cannotMerge() || CB1->isConvergent())
+ return false;
+ if (const auto *CB2 = dyn_cast<CallBase>(I2))
+ if (CB2->cannotMerge() || CB2->isConvergent())
+ return false;
+
+ return true;
+}
+
/// Given a conditional branch that goes to BB1 and BB2, hoist any common code
/// in the two blocks up into the branch block. The caller of this function
/// guarantees that BI's block dominates BB1 and BB2. If EqTermsOnly is given,
goto HoistTerminator;
}
- if (I1->isIdenticalToWhenDefined(I2)) {
- // Even if the instructions are identical, it may not be safe to hoist
- // them if we have skipped over instructions with side effects or their
- // operands weren't hoisted.
- if (!isSafeToHoistInstr(I1, SkipFlagsBB1) ||
- !isSafeToHoistInstr(I2, SkipFlagsBB2))
- return Changed;
-
- // If we're going to hoist a call, make sure that the two instructions
- // we're commoning/hoisting are both marked with musttail, or neither of
- // them is marked as such. Otherwise, we might end up in a situation where
- // we hoist from a block where the terminator is a `ret` to a block where
- // the terminator is a `br`, and `musttail` calls expect to be followed by
- // a return.
- auto *C1 = dyn_cast<CallInst>(I1);
- auto *C2 = dyn_cast<CallInst>(I2);
- if (C1 && C2)
- if (C1->isMustTailCall() != C2->isMustTailCall())
- return Changed;
-
- if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2))
- return Changed;
-
- // If any of the two call sites has nomerge or convergent attribute, stop
- // hoisting.
- if (const auto *CB1 = dyn_cast<CallBase>(I1))
- if (CB1->cannotMerge() || CB1->isConvergent())
- return Changed;
- if (const auto *CB2 = dyn_cast<CallBase>(I2))
- if (CB2->cannotMerge() || CB2->isConvergent())
- return Changed;
-
+ if (I1->isIdenticalToWhenDefined(I2) &&
+ // Even if the instructions are identical, it may not be safe to hoist
+ // them if we have skipped over instructions with side effects or their
+ // operands weren't hoisted.
+ isSafeToHoistInstr(I1, SkipFlagsBB1) &&
+ isSafeToHoistInstr(I2, SkipFlagsBB2) &&
+ shouldHoistCommonInstructions(I1, I2, TTI)) {
if (isa<DbgInfoIntrinsic>(I1) || isa<DbgInfoIntrinsic>(I2)) {
assert(isa<DbgInfoIntrinsic>(I1) && isa<DbgInfoIntrinsic>(I2));
// The debug location is an integral part of a debug info intrinsic
; SINK-NEXT: [[TMP0:%.*]] = tail call i32 @tid()
; SINK-NEXT: [[REM:%.*]] = and i32 [[TMP0]], 1
; SINK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[REM]], 0
+; SINK-NEXT: [[IDXPROM4:%.*]] = zext i32 [[TMP0]] to i64
+; SINK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr [[Y_COERCE:%.*]], i64 [[IDXPROM4]]
; SINK-NEXT: br i1 [[CMP_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
; SINK: if.then:
; SINK-NEXT: [[TMP1:%.*]] = tail call i32 @mbcnt(i32 -1, i32 0)
; SINK-NEXT: br label [[IF_END]]
; SINK: if.end:
; SINK-NEXT: [[DOTSINK:%.*]] = phi i32 [ [[TMP6]], [[IF_ELSE]] ], [ [[TMP3]], [[IF_THEN]] ]
-; SINK-NEXT: [[IDXPROM4:%.*]] = zext i32 [[TMP0]] to i64
-; SINK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds i32, ptr [[Y_COERCE:%.*]], i64 [[IDXPROM4]]
; SINK-NEXT: store i32 [[DOTSINK]], ptr [[ARRAYIDX5]], align 4
; SINK-NEXT: ret void
;