From 779fd3968412dd2c8b75a0f5884d39bd5ba29bfd Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 30 Sep 2022 12:13:40 +0200 Subject: [PATCH] Reapply [InstCombine] Switch foldOpIntoPhi() to use InstSimplify Relative to the previous attempt, this is rebased over the InstSimplify fix in ac74e7a7806480a000c9a3502405c3dedd8810de, 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 https://github.com/llvm/llvm-project/issues/57448, which was my original motivation for the change. Differential Revision: https://reviews.llvm.org/D134954 --- .../InstCombine/InstructionCombining.cpp | 170 +++++++-------------- llvm/test/Transforms/InstCombine/intptr1.ll | 9 +- llvm/test/Transforms/InstCombine/intptr4.ll | 7 +- llvm/test/Transforms/InstCombine/intptr5.ll | 7 +- llvm/test/Transforms/InstCombine/intptr7.ll | 7 +- .../Transforms/InstCombine/phi-select-constant.ll | 8 +- llvm/test/Transforms/InstCombine/phi.ll | 16 +- llvm/test/Transforms/InstCombine/recurrence.ll | 4 +- 8 files changed, 80 insertions(+), 148 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 29fb40b..6771cd9 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -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(I->getOperand(1)); - Constant *C = cast(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(RI); - if (FPInst && isa(FPInst)) - FPInst->copyFastMathFlags(I); - return RI; -} - Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN) { unsigned NumPHIValues = PN->getNumIncomingValues(); if (NumPHIValues == 0) @@ -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 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(I) && match(InVal, m_ImmConstant())) - continue; - if (isa(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 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(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(InVal)) - if (cast(InVal)->getParent() == NonConstBB) + if (cast(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(NonConstBB->getTerminator()); - if (!BI || !BI->isUnconditional() || !DT.isReachableFromEntry(NonConstBB)) + if (NonSimplifiedBB != nullptr) { + BranchInst *BI = dyn_cast(NonSimplifiedBB->getTerminator()); + if (!BI || !BI->isUnconditional() || + !DT.isReachableFromEntry(NonSimplifiedBB)) return nullptr; } @@ -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(&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(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(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(&I)) { - Constant *C = cast(I.getOperand(1)); - for (unsigned i = 0; i != NumPHIValues; ++i) { - Value *InV = nullptr; - if (auto *InC = dyn_cast(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(&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(&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(&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(&I); - Type *RetTy = CI->getType(); - for (unsigned i = 0; i != NumPHIValues; ++i) { - Value *InV; - if (Constant *InC = dyn_cast(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())) { diff --git a/llvm/test/Transforms/InstCombine/intptr1.ll b/llvm/test/Transforms/InstCombine/intptr1.ll index 37febe3..0f46efa 100644 --- a/llvm/test/Transforms/InstCombine/intptr1.ll +++ b/llvm/test/Transforms/InstCombine/intptr1.ll @@ -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]] diff --git a/llvm/test/Transforms/InstCombine/intptr4.ll b/llvm/test/Transforms/InstCombine/intptr4.ll index 333d278..193b45a 100644 --- a/llvm/test/Transforms/InstCombine/intptr4.ll +++ b/llvm/test/Transforms/InstCombine/intptr4.ll @@ -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 diff --git a/llvm/test/Transforms/InstCombine/intptr5.ll b/llvm/test/Transforms/InstCombine/intptr5.ll index b88eb45..e2793d4 100644 --- a/llvm/test/Transforms/InstCombine/intptr5.ll +++ b/llvm/test/Transforms/InstCombine/intptr5.ll @@ -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 diff --git a/llvm/test/Transforms/InstCombine/intptr7.ll b/llvm/test/Transforms/InstCombine/intptr7.ll index f640c87..8bd5aaf 100644 --- a/llvm/test/Transforms/InstCombine/intptr7.ll +++ b/llvm/test/Transforms/InstCombine/intptr7.ll @@ -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 diff --git a/llvm/test/Transforms/InstCombine/phi-select-constant.ll b/llvm/test/Transforms/InstCombine/phi-select-constant.ll index e51cb3d..15760e2 100644 --- a/llvm/test/Transforms/InstCombine/phi-select-constant.ll +++ b/llvm/test/Transforms/InstCombine/phi-select-constant.ll @@ -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> ; 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> ; 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]] ], [ , [[ENTRY:%.*]] ], [ , [[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 diff --git a/llvm/test/Transforms/InstCombine/phi.ll b/llvm/test/Transforms/InstCombine/phi.ll index f8c834e..521bb4a 100644 --- a/llvm/test/Transforms/InstCombine/phi.ll +++ b/llvm/test/Transforms/InstCombine/phi.ll @@ -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: @@ -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: @@ -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 diff --git a/llvm/test/Transforms/InstCombine/recurrence.ll b/llvm/test/Transforms/InstCombine/recurrence.ll index 74fdbf3..c00ecd5 100644 --- a/llvm/test/Transforms/InstCombine/recurrence.ll +++ b/llvm/test/Transforms/InstCombine/recurrence.ll @@ -4,9 +4,9 @@ define i64 @test_or(i64 %a) { ; CHECK-LABEL: @test_or( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = or i64 [[A:%.*]], 15 ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[TMP0:%.*]] = or i64 [[A:%.*]], 15 ; CHECK-NEXT: tail call void @use(i64 [[TMP0]]) ; CHECK-NEXT: br label [[LOOP]] ; @@ -84,9 +84,9 @@ loop: ; preds = %loop, %entry define i64 @test_and(i64 %a) { ; CHECK-LABEL: @test_and( ; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[A:%.*]], 15 ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[A:%.*]], 15 ; CHECK-NEXT: tail call void @use(i64 [[TMP0]]) ; CHECK-NEXT: br label [[LOOP]] ; -- 2.7.4