Skip to content

Commit

Permalink
Reapply [InstCombine] Switch foldOpIntoPhi() to use InstSimplify
Browse files Browse the repository at this point in the history
Relative to the previous attempt, this is rebased over the
InstSimplify fix in ac74e7a,
which addresses the miscompile reported in PR58401.

-----

foldOpIntoPhi() currently only folds operations into the phi if all
but one operands constant-fold. The two exceptions to this are freeze
and select, where we allow more general simplification.

This patch makes foldOpIntoPhi() generally simplification based and
removes all the instruction-specific logic. We just try to simplify
the instruction for each operand, and for the (potentially) one
non-simplified operand, we move it into the new block with adjusted
operands.

This fixes #57448, which
was my original motivation for the change.

Differential Revision: https://reviews.llvm.org/D134954
  • Loading branch information
nikic committed Oct 17, 2022
1 parent efd0d66 commit 779fd39
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 148 deletions.
170 changes: 55 additions & 115 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1155,22 +1155,6 @@ Instruction *InstCombinerImpl::FoldOpIntoSelect(Instruction &Op, SelectInst *SI,
return SelectInst::Create(SI->getCondition(), NewTV, NewFV, "", nullptr, SI);
}

static Value *foldOperationIntoPhiValue(BinaryOperator *I, Value *InV,
InstCombiner::BuilderTy &Builder) {
bool ConstIsRHS = isa<Constant>(I->getOperand(1));
Constant *C = cast<Constant>(I->getOperand(ConstIsRHS));

Value *Op0 = InV, *Op1 = C;
if (!ConstIsRHS)
std::swap(Op0, Op1);

Value *RI = Builder.CreateBinOp(I->getOpcode(), Op0, Op1, "phi.bo");
auto *FPInst = dyn_cast<Instruction>(RI);
if (FPInst && isa<FPMathOperator>(FPInst))
FPInst->copyFastMathFlags(I);
return RI;
}

Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
unsigned NumPHIValues = PN->getNumIncomingValues();
if (NumPHIValues == 0)
Expand All @@ -1189,48 +1173,69 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {
// Otherwise, we can replace *all* users with the new PHI we form.
}

// Check to see if all of the operands of the PHI are simple constants
// (constantint/constantfp/undef). If there is one non-constant value,
// remember the BB it is in. If there is more than one or if *it* is a PHI,
// bail out. We don't do arbitrary constant expressions here because moving
// their computation can be expensive without a cost model.
BasicBlock *NonConstBB = nullptr;
// Check to see whether the instruction can be folded into each phi operand.
// If there is one operand that does not fold, remember the BB it is in.
// If there is more than one or if *it* is a PHI, bail out.
SmallVector<Value *> NewPhiValues;
BasicBlock *NonSimplifiedBB = nullptr;
Value *NonSimplifiedInVal = nullptr;
for (unsigned i = 0; i != NumPHIValues; ++i) {
Value *InVal = PN->getIncomingValue(i);
// For non-freeze, require constant operand
// For freeze, require non-undef, non-poison operand
if (!isa<FreezeInst>(I) && match(InVal, m_ImmConstant()))
continue;
if (isa<FreezeInst>(I) && isGuaranteedNotToBeUndefOrPoison(InVal))
BasicBlock *InBB = PN->getIncomingBlock(i);

// NB: It is a precondition of this transform that the operands be
// phi translatable! This is usually trivially satisfied by limiting it
// to constant ops, and for selects we do a more sophisticated check.
SmallVector<Value *> Ops;
for (Value *Op : I.operands()) {
if (Op == PN)
Ops.push_back(InVal);
else
Ops.push_back(Op->DoPHITranslation(PN->getParent(), InBB));
}

// Don't consider the simplification successful if we get back a constant
// expression. That's just an instruction in hiding.
// Also reject the case where we simplify back to the phi node. We wouldn't
// be able to remove it in that case.
Value *NewVal = simplifyInstructionWithOperands(
&I, Ops, SQ.getWithInstruction(InBB->getTerminator()));
if (NewVal && NewVal != PN && !match(NewVal, m_ConstantExpr())) {
NewPhiValues.push_back(NewVal);
continue;
}

if (isa<PHINode>(InVal)) return nullptr; // Itself a phi.
if (NonConstBB) return nullptr; // More than one non-const value.
if (NonSimplifiedBB) return nullptr; // More than one non-simplified value.

NonConstBB = PN->getIncomingBlock(i);
NonSimplifiedBB = InBB;
NonSimplifiedInVal = InVal;
NewPhiValues.push_back(nullptr);

// If the InVal is an invoke at the end of the pred block, then we can't
// insert a computation after it without breaking the edge.
if (isa<InvokeInst>(InVal))
if (cast<Instruction>(InVal)->getParent() == NonConstBB)
if (cast<Instruction>(InVal)->getParent() == NonSimplifiedBB)
return nullptr;

// If the incoming non-constant value is reachable from the phis block,
// we'll push the operation across a loop backedge. This could result in
// an infinite combine loop, and is generally non-profitable (especially
// if the operation was originally outside the loop).
if (isPotentiallyReachable(PN->getParent(), NonConstBB, nullptr, &DT, LI))
if (isPotentiallyReachable(PN->getParent(), NonSimplifiedBB, nullptr, &DT,
LI))
return nullptr;
}

// If there is exactly one non-constant value, we can insert a copy of the
// If there is exactly one non-simplified value, we can insert a copy of the
// operation in that block. However, if this is a critical edge, we would be
// inserting the computation on some other paths (e.g. inside a loop). Only
// do this if the pred block is unconditionally branching into the phi block.
// Also, make sure that the pred block is not dead code.
if (NonConstBB != nullptr) {
BranchInst *BI = dyn_cast<BranchInst>(NonConstBB->getTerminator());
if (!BI || !BI->isUnconditional() || !DT.isReachableFromEntry(NonConstBB))
if (NonSimplifiedBB != nullptr) {
BranchInst *BI = dyn_cast<BranchInst>(NonSimplifiedBB->getTerminator());
if (!BI || !BI->isUnconditional() ||
!DT.isReachableFromEntry(NonSimplifiedBB))
return nullptr;
}

Expand All @@ -1241,88 +1246,23 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) {

// If we are going to have to insert a new computation, do so right before the
// predecessor's terminator.
if (NonConstBB)
Builder.SetInsertPoint(NonConstBB->getTerminator());

// Next, add all of the operands to the PHI.
if (SelectInst *SI = dyn_cast<SelectInst>(&I)) {
// We only currently try to fold the condition of a select when it is a phi,
// not the true/false values.
Value *TrueV = SI->getTrueValue();
Value *FalseV = SI->getFalseValue();
BasicBlock *PhiTransBB = PN->getParent();
for (unsigned i = 0; i != NumPHIValues; ++i) {
BasicBlock *ThisBB = PN->getIncomingBlock(i);
Value *TrueVInPred = TrueV->DoPHITranslation(PhiTransBB, ThisBB);
Value *FalseVInPred = FalseV->DoPHITranslation(PhiTransBB, ThisBB);
Value *InV = nullptr;
// Beware of ConstantExpr: it may eventually evaluate to getNullValue,
// even if currently isNullValue gives false.
Constant *InC = dyn_cast<Constant>(PN->getIncomingValue(i));
// For vector constants, we cannot use isNullValue to fold into
// FalseVInPred versus TrueVInPred. When we have individual nonzero
// elements in the vector, we will incorrectly fold InC to
// `TrueVInPred`.
if (InC && isa<ConstantInt>(InC))
InV = InC->isNullValue() ? FalseVInPred : TrueVInPred;
else {
// Generate the select in the same block as PN's current incoming block.
// Note: ThisBB need not be the NonConstBB because vector constants
// which are constants by definition are handled here.
// FIXME: This can lead to an increase in IR generation because we might
// generate selects for vector constant phi operand, that could not be
// folded to TrueVInPred or FalseVInPred as done for ConstantInt. For
// non-vector phis, this transformation was always profitable because
// the select would be generated exactly once in the NonConstBB.
Builder.SetInsertPoint(ThisBB->getTerminator());
InV = Builder.CreateSelect(PN->getIncomingValue(i), TrueVInPred,
FalseVInPred, "phi.sel");
}
NewPN->addIncoming(InV, ThisBB);
}
} else if (CmpInst *CI = dyn_cast<CmpInst>(&I)) {
Constant *C = cast<Constant>(I.getOperand(1));
for (unsigned i = 0; i != NumPHIValues; ++i) {
Value *InV = nullptr;
if (auto *InC = dyn_cast<Constant>(PN->getIncomingValue(i)))
InV = ConstantExpr::getCompare(CI->getPredicate(), InC, C);
else
InV = Builder.CreateCmp(CI->getPredicate(), PN->getIncomingValue(i),
C, "phi.cmp");
NewPN->addIncoming(InV, PN->getIncomingBlock(i));
}
} else if (auto *BO = dyn_cast<BinaryOperator>(&I)) {
for (unsigned i = 0; i != NumPHIValues; ++i) {
Value *InV = foldOperationIntoPhiValue(BO, PN->getIncomingValue(i),
Builder);
NewPN->addIncoming(InV, PN->getIncomingBlock(i));
}
} else if (isa<FreezeInst>(&I)) {
for (unsigned i = 0; i != NumPHIValues; ++i) {
Value *InV;
if (NonConstBB == PN->getIncomingBlock(i))
InV = Builder.CreateFreeze(PN->getIncomingValue(i), "phi.fr");
Instruction *Clone = nullptr;
if (NonSimplifiedBB) {
Clone = I.clone();
for (Use &U : Clone->operands()) {
if (U == PN)
U = NonSimplifiedInVal;
else
InV = PN->getIncomingValue(i);
NewPN->addIncoming(InV, PN->getIncomingBlock(i));
}
} else if (auto *EV = dyn_cast<ExtractValueInst>(&I)) {
for (unsigned i = 0; i != NumPHIValues; ++i)
NewPN->addIncoming(Builder.CreateExtractValue(PN->getIncomingValue(i),
EV->getIndices(), "phi.ev"),
PN->getIncomingBlock(i));
} else {
CastInst *CI = cast<CastInst>(&I);
Type *RetTy = CI->getType();
for (unsigned i = 0; i != NumPHIValues; ++i) {
Value *InV;
if (Constant *InC = dyn_cast<Constant>(PN->getIncomingValue(i)))
InV = ConstantExpr::getCast(CI->getOpcode(), InC, RetTy);
else
InV = Builder.CreateCast(CI->getOpcode(), PN->getIncomingValue(i),
I.getType(), "phi.cast");
NewPN->addIncoming(InV, PN->getIncomingBlock(i));
U = U->DoPHITranslation(PN->getParent(), NonSimplifiedBB);
}
InsertNewInstBefore(Clone, *NonSimplifiedBB->getTerminator());
}

for (unsigned i = 0; i != NumPHIValues; ++i) {
if (NewPhiValues[i])
NewPN->addIncoming(NewPhiValues[i], PN->getIncomingBlock(i));
else
NewPN->addIncoming(Clone, PN->getIncomingBlock(i));
}

for (User *U : make_early_inc_range(PN->users())) {
Expand Down
9 changes: 4 additions & 5 deletions llvm/test/Transforms/InstCombine/intptr1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,18 @@ define void @test1_neg(ptr %a, ptr readnone %a_end, ptr %b.i64) {
; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
; CHECK: for.body.preheader:
; CHECK-NEXT: [[B:%.*]] = load i64, ptr [[B_I64:%.*]], align 8
; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[B]] to ptr
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[A_ADDR_03:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[BB:%.*]] ], [ [[A]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[B_ADDR_02:%.*]] = phi i64 [ [[ADD_INT:%.*]], [[BB]] ], [ [[B]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[TMP:%.*]] = inttoptr i64 [[B_ADDR_02]] to ptr
; CHECK-NEXT: [[PTRCMP:%.*]] = icmp ult ptr [[TMP]], [[A_END]]
; CHECK-NEXT: [[B_ADDR_02:%.*]] = phi ptr [ [[ADD:%.*]], [[BB]] ], [ [[TMP0]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[PTRCMP:%.*]] = icmp ult ptr [[B_ADDR_02]], [[A_END]]
; CHECK-NEXT: br i1 [[PTRCMP]], label [[FOR_END]], label [[BB]]
; CHECK: bb:
; CHECK-NEXT: [[I1:%.*]] = load float, ptr [[A]], align 4
; CHECK-NEXT: [[MUL_I:%.*]] = fmul float [[I1]], 4.200000e+01
; CHECK-NEXT: store float [[MUL_I]], ptr [[A_ADDR_03]], align 4
; CHECK-NEXT: [[ADD:%.*]] = getelementptr inbounds float, ptr [[A]], i64 1
; CHECK-NEXT: [[ADD_INT]] = ptrtoint ptr [[ADD]] to i64
; CHECK-NEXT: [[ADD]] = getelementptr inbounds float, ptr [[A]], i64 1
; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds float, ptr [[A_ADDR_03]], i64 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[INCDEC_PTR]], [[A_END]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]]
Expand Down
7 changes: 3 additions & 4 deletions llvm/test/Transforms/InstCombine/intptr4.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,17 @@ define void @test(ptr %a, ptr readnone %a_end, i64 %b, ptr %bf) unnamed_addr {
; CHECK-NEXT: [[B_FLOAT:%.*]] = inttoptr i64 [[B:%.*]] to ptr
; CHECK-NEXT: br i1 [[CMP1]], label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[B]] to ptr
; CHECK-NEXT: br label [[FOR_BODY_PREHEADER:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[BFI:%.*]] = ptrtoint ptr [[BF:%.*]] to i64
; CHECK-NEXT: br label [[FOR_BODY_PREHEADER]]
; CHECK: for.body.preheader:
; CHECK-NEXT: [[B_PHI:%.*]] = phi i64 [ [[B]], [[BB1]] ], [ [[BFI]], [[BB2]] ]
; CHECK-NEXT: [[B_PHI_PTR:%.*]] = inttoptr i64 [[B_PHI]] to ptr
; CHECK-NEXT: [[B_PHI:%.*]] = phi ptr [ [[TMP0]], [[BB1]] ], [ [[BF:%.*]], [[BB2]] ]
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[A_ADDR_03:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[A]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[B_ADDR_FLOAT:%.*]] = phi ptr [ [[B_ADDR_FLOAT_INC:%.*]], [[FOR_BODY]] ], [ [[B_FLOAT]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[B_ADDR_I64_PTR:%.*]] = phi ptr [ [[B_ADDR_FLOAT_INC]], [[FOR_BODY]] ], [ [[B_PHI_PTR]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[B_ADDR_I64_PTR:%.*]] = phi ptr [ [[B_ADDR_FLOAT_INC]], [[FOR_BODY]] ], [ [[B_PHI]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[L:%.*]] = load float, ptr [[B_ADDR_FLOAT]], align 4
; CHECK-NEXT: [[MUL_I:%.*]] = fmul float [[L]], 4.200000e+01
; CHECK-NEXT: store float [[MUL_I]], ptr [[A_ADDR_03]], align 4
Expand Down
7 changes: 3 additions & 4 deletions llvm/test/Transforms/InstCombine/intptr5.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,19 @@ define void @test(ptr %a, ptr readnone %a_end, i64 %b, ptr %bf) unnamed_addr {
; CHECK-NEXT: [[B_FLOAT:%.*]] = inttoptr i64 [[B:%.*]] to ptr
; CHECK-NEXT: br i1 [[CMP1]], label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[B]] to ptr
; CHECK-NEXT: br label [[FOR_BODY_PREHEADER:%.*]]
; CHECK: bb2:
; CHECK-NEXT: [[BFI:%.*]] = ptrtoint ptr [[BF:%.*]] to i64
; CHECK-NEXT: br label [[FOR_BODY_PREHEADER]]
; CHECK: for.body.preheader:
; CHECK-NEXT: [[B_PHI:%.*]] = phi i64 [ [[B]], [[BB1]] ], [ [[BFI]], [[BB2]] ]
; CHECK-NEXT: [[B_PHI_PTR:%.*]] = inttoptr i64 [[B_PHI]] to ptr
; CHECK-NEXT: [[B_PHI:%.*]] = phi ptr [ [[TMP0]], [[BB1]] ], [ [[BF:%.*]], [[BB2]] ]
; CHECK-NEXT: switch i64 [[B]], label [[FOR_BODY:%.*]] [
; CHECK-NEXT: i64 1, label [[FOR_BODY]]
; CHECK-NEXT: ]
; CHECK: for.body:
; CHECK-NEXT: [[A_ADDR_03:%.*]] = phi ptr [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[A]], [[FOR_BODY_PREHEADER]] ], [ [[A]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[B_ADDR_FLOAT:%.*]] = phi ptr [ [[B_ADDR_FLOAT_INC:%.*]], [[FOR_BODY]] ], [ [[B_FLOAT]], [[FOR_BODY_PREHEADER]] ], [ [[B_FLOAT]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[B_ADDR_I64_PTR:%.*]] = phi ptr [ [[B_ADDR_FLOAT_INC]], [[FOR_BODY]] ], [ [[B_PHI_PTR]], [[FOR_BODY_PREHEADER]] ], [ [[B_PHI_PTR]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[B_ADDR_I64_PTR:%.*]] = phi ptr [ [[B_ADDR_FLOAT_INC]], [[FOR_BODY]] ], [ [[B_PHI]], [[FOR_BODY_PREHEADER]] ], [ [[B_PHI]], [[FOR_BODY_PREHEADER]] ]
; CHECK-NEXT: [[L:%.*]] = load float, ptr [[B_ADDR_FLOAT]], align 4
; CHECK-NEXT: [[MUL_I:%.*]] = fmul float [[L]], 4.200000e+01
; CHECK-NEXT: store float [[MUL_I]], ptr [[A_ADDR_03]], align 4
Expand Down
7 changes: 3 additions & 4 deletions llvm/test/Transforms/InstCombine/intptr7.ll
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,16 @@ define void @no_matching_phi(i64 %a, ptr %b, i1 %cond) {
; CHECK-NEXT: [[ADDB:%.*]] = getelementptr inbounds float, ptr [[B:%.*]], i64 2
; CHECK-NEXT: br i1 [[COND:%.*]], label [[B:%.*]], label [[A:%.*]]
; CHECK: A:
; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[ADD_INT]] to ptr
; CHECK-NEXT: br label [[C:%.*]]
; CHECK: B:
; CHECK-NEXT: [[ADDB_INT:%.*]] = ptrtoint ptr [[ADDB]] to i64
; CHECK-NEXT: [[ADD:%.*]] = inttoptr i64 [[ADD_INT]] to ptr
; CHECK-NEXT: store float 1.000000e+01, ptr [[ADD]], align 4
; CHECK-NEXT: br label [[C]]
; CHECK: C:
; CHECK-NEXT: [[A_ADDR_03:%.*]] = phi ptr [ [[ADDB]], [[A]] ], [ [[ADD]], [[B]] ]
; CHECK-NEXT: [[B_ADDR_02:%.*]] = phi i64 [ [[ADD_INT]], [[A]] ], [ [[ADDB_INT]], [[B]] ]
; CHECK-NEXT: [[I0:%.*]] = inttoptr i64 [[B_ADDR_02]] to ptr
; CHECK-NEXT: [[I1:%.*]] = load float, ptr [[I0]], align 4
; CHECK-NEXT: [[B_ADDR_02:%.*]] = phi ptr [ [[TMP0]], [[A]] ], [ [[ADDB]], [[B]] ]
; CHECK-NEXT: [[I1:%.*]] = load float, ptr [[B_ADDR_02]], align 4
; CHECK-NEXT: [[MUL_I:%.*]] = fmul float [[I1]], 4.200000e+01
; CHECK-NEXT: store float [[MUL_I]], ptr [[A_ADDR_03]], align 4
; CHECK-NEXT: ret void
Expand Down
8 changes: 3 additions & 5 deletions llvm/test/Transforms/InstCombine/phi-select-constant.ll
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,15 @@ final:
define <2 x i8> @vec3(i1 %cond1, i1 %cond2, <2 x i1> %x, <2 x i8> %y, <2 x i8> %z) {
; CHECK-LABEL: @vec3(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[PHI_SEL1:%.*]] = shufflevector <2 x i8> [[Z:%.*]], <2 x i8> [[Y:%.*]], <2 x i32> <i32 0, i32 3>
; CHECK-NEXT: br i1 [[COND1:%.*]], label [[IF1:%.*]], label [[ELSE:%.*]]
; CHECK: if1:
; CHECK-NEXT: [[PHI_SEL2:%.*]] = shufflevector <2 x i8> [[Y]], <2 x i8> [[Z]], <2 x i32> <i32 0, i32 3>
; CHECK-NEXT: br i1 [[COND2:%.*]], label [[IF2:%.*]], label [[ELSE]]
; CHECK: if2:
; CHECK-NEXT: [[PHI_SEL:%.*]] = select <2 x i1> [[X:%.*]], <2 x i8> [[Y]], <2 x i8> [[Z]]
; CHECK-NEXT: br label [[ELSE]]
; CHECK: else:
; CHECK-NEXT: [[PHI:%.*]] = phi <2 x i8> [ [[PHI_SEL]], [[IF2]] ], [ [[PHI_SEL1]], [[ENTRY:%.*]] ], [ [[PHI_SEL2]], [[IF1]] ]
; CHECK-NEXT: ret <2 x i8> [[PHI]]
; CHECK-NEXT: [[PHI:%.*]] = phi <2 x i1> [ [[X:%.*]], [[IF2]] ], [ <i1 false, i1 true>, [[ENTRY:%.*]] ], [ <i1 true, i1 false>, [[IF1]] ]
; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[PHI]], <2 x i8> [[Y:%.*]], <2 x i8> [[Z:%.*]]
; CHECK-NEXT: ret <2 x i8> [[SEL]]
;
entry:
br i1 %cond1, label %if1, label %else
Expand Down
16 changes: 7 additions & 9 deletions llvm/test/Transforms/InstCombine/phi.ll
Original file line number Diff line number Diff line change
Expand Up @@ -697,10 +697,10 @@ ret:
define i32 @test23(i32 %A, i1 %pb, ptr %P) {
; CHECK-LABEL: @test23(
; CHECK-NEXT: BB0:
; CHECK-NEXT: [[PHI_BO:%.*]] = add i32 [[A:%.*]], 19
; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[A:%.*]], 19
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: Loop:
; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[PHI_BO]], [[BB0:%.*]] ], [ 61, [[LOOP]] ]
; CHECK-NEXT: [[B:%.*]] = phi i32 [ [[TMP0]], [[BB0:%.*]] ], [ 61, [[LOOP]] ]
; CHECK-NEXT: store i32 [[B]], ptr [[P:%.*]], align 4
; CHECK-NEXT: br i1 [[PB:%.*]], label [[LOOP]], label [[EXIT:%.*]]
; CHECK: Exit:
Expand Down Expand Up @@ -1280,14 +1280,12 @@ define i1 @pr57488_icmp_of_phi(ptr %ptr.base, i64 %len) {
; CHECK-NEXT: [[LEN_ZERO:%.*]] = icmp eq i64 [[LEN]], 0
; CHECK-NEXT: br i1 [[LEN_ZERO]], label [[EXIT:%.*]], label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[ACCUM:%.*]] = phi i8 [ [[ACCUM_NEXT:%.*]], [[LOOP]] ], [ 1, [[START:%.*]] ]
; CHECK-NEXT: [[ACCUM:%.*]] = phi i1 [ [[AND:%.*]], [[LOOP]] ], [ true, [[START:%.*]] ]
; CHECK-NEXT: [[PTR:%.*]] = phi ptr [ [[PTR_NEXT:%.*]], [[LOOP]] ], [ [[PTR_BASE]], [[START]] ]
; CHECK-NEXT: [[PTR_NEXT]] = getelementptr inbounds i64, ptr [[PTR]], i64 1
; CHECK-NEXT: [[ACCUM_BOOL:%.*]] = icmp ne i8 [[ACCUM]], 0
; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[PTR]], align 8
; CHECK-NEXT: [[VAL_ZERO:%.*]] = icmp eq i64 [[VAL]], 0
; CHECK-NEXT: [[AND:%.*]] = and i1 [[ACCUM_BOOL]], [[VAL_ZERO]]
; CHECK-NEXT: [[ACCUM_NEXT]] = zext i1 [[AND]] to i8
; CHECK-NEXT: [[AND]] = and i1 [[ACCUM]], [[VAL_ZERO]]
; CHECK-NEXT: [[EXIT_COND:%.*]] = icmp eq ptr [[PTR_NEXT]], [[END]]
; CHECK-NEXT: br i1 [[EXIT_COND]], label [[EXIT]], label [[LOOP]]
; CHECK: exit:
Expand Down Expand Up @@ -1344,17 +1342,17 @@ loop:
define i32 @phi_op_self_simplify_2(i32 %x) {
; CHECK-LABEL: @phi_op_self_simplify_2(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[X:%.*]], 1
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[X:%.*]], [[ENTRY:%.*]] ], [ [[OR:%.*]], [[LOOP]] ], [ 10, [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[OR]] = or i32 [[PHI]], 1
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[TMP0]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ], [ 11, [[LOOP_LATCH:%.*]] ]
; CHECK-NEXT: [[C1:%.*]] = call i1 @get.i1()
; CHECK-NEXT: br i1 [[C1]], label [[LOOP_LATCH]], label [[LOOP]]
; CHECK: loop.latch:
; CHECK-NEXT: [[C2:%.*]] = call i1 @get.i1()
; CHECK-NEXT: br i1 [[C2]], label [[EXIT:%.*]], label [[LOOP]]
; CHECK: exit:
; CHECK-NEXT: ret i32 [[OR]]
; CHECK-NEXT: ret i32 [[PHI]]
;
entry:
br label %loop
Expand Down
Loading

0 comments on commit 779fd39

Please sign in to comment.