Index: lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- lib/Transforms/InstCombine/InstCombineInternal.h +++ lib/Transforms/InstCombine/InstCombineInternal.h @@ -544,6 +544,7 @@ Instruction *FoldPHIArgBinOpIntoPHI(PHINode &PN); Instruction *FoldPHIArgGEPIntoPHI(PHINode &PN); Instruction *FoldPHIArgLoadIntoPHI(PHINode &PN); + Instruction *FoldPHIArgZextsIntoPHI(PHINode &PN); Instruction *OptAndOp(Instruction *Op, ConstantInt *OpRHS, ConstantInt *AndRHS, BinaryOperator &TheAnd); Index: lib/Transforms/InstCombine/InstCombinePHI.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombinePHI.cpp +++ lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -381,7 +381,75 @@ return NewLI; } +/// TODO: This function could handle other cast types, but then it might +/// require special-casing a cast from the 'i1' type. See the comment in +/// FoldPHIArgOpIntoPHI() about pessimizing illegal integer types. +Instruction *InstCombiner::FoldPHIArgZextsIntoPHI(PHINode &Phi) { + SmallVector Consts; + ZExtInst *FirstCast = nullptr; + unsigned NumIncomingValues = Phi.getNumIncomingValues(); + + // Walk the phi operands looking for casts and constants. + for (Value *V : Phi.incoming_values()) { + if (auto *Cast = dyn_cast(V)) { + if (FirstCast == nullptr) + // Initialize cast instruction for matching subsequent casts. + FirstCast = Cast; + else if (Cast->getSrcTy() != FirstCast->getSrcTy() || + Cast->getOpcode() != FirstCast->getOpcode() || + !Cast->hasOneUse()) + // All casts must be identical and have one use. + return nullptr; + } else if (auto *C = dyn_cast(V)) { + // Make sure that constants can fit in the new type in the next loop. + Consts.push_back(C); + } else { + // If it's not a cast or a constant, bail out. + return nullptr; + } + } + + // The more common cases of a phi with no constant operands or just one + // variable operand are handled by FoldPHIArgOpIntoPHI() and FoldOpIntoPhi() + // respectively. FoldOpIntoPhi() wants to do the opposite transform that is + // performed here. It tries to replicate a cast in the phi operand's basic + // block to expose other folding opportunities. Thus, InstCombine will + // infinite loop without this check. + if (Consts.empty() || NumIncomingValues - Consts.size() < 2) + return nullptr; + + // Compute the constants that would happen if we truncated to SrcTy then + // re-extended to DstTy. + for (Constant *C : Consts) { + Constant *Trunc = ConstantExpr::getTrunc(C, FirstCast->getSrcTy()); + Constant *Ext = ConstantExpr::getZExt(Trunc, C->getType()); + + // If the re-extended constant changed, then we can't shrink this phi + // operand for free. + if (Ext != C) + return nullptr; + } + // All incoming values are the same cast operation or constants that are safe + // to truncate. Create a new phi node of the correct type, and phi together + // all of the cast operands and constants. + PHINode *NewPhi = PHINode::Create(FirstCast->getSrcTy(), NumIncomingValues, + Phi.getName() + ".shrunk"); + + // Add all operands to the new phi. + for (Use &U : Phi.incoming_values()) { + Value *NewInVal = nullptr; + if (auto *Cast = dyn_cast(U)) + NewInVal = Cast->getOperand(0); + else if (auto *C = dyn_cast(U)) + NewInVal = ConstantExpr::getTrunc(C, FirstCast->getSrcTy()); + + NewPhi->addIncoming(NewInVal, Phi.getIncomingBlock(U)); + } + + InsertNewInstBefore(NewPhi, Phi); + return CastInst::Create(FirstCast->getOpcode(), NewPhi, Phi.getType()); +} /// If all operands to a PHI node are the same "unary" operator and they all are /// only used by the PHI, PHI together their inputs, and do the operation once, @@ -453,7 +521,7 @@ // correct type, and PHI together all of the LHS's of the instructions. PHINode *NewPN = PHINode::Create(FirstInst->getOperand(0)->getType(), PN.getNumIncomingValues(), - PN.getName()+".in"); + PN.getName() + ".in"); Value *InVal = FirstInst->getOperand(0); NewPN->addIncoming(InVal, PN.getIncomingBlock(0)); @@ -787,6 +855,9 @@ if (Value *V = SimplifyInstruction(&PN, DL, TLI, DT, AC)) return ReplaceInstUsesWith(PN, V); + if (Instruction *Result = FoldPHIArgZextsIntoPHI(PN)) + return Result; + // If all PHI operands are the same operation, pull them through the PHI, // reducing code size. if (isa(PN.getIncomingValue(0)) && Index: test/Transforms/InstCombine/phi.ll =================================================================== --- test/Transforms/InstCombine/phi.ll +++ test/Transforms/InstCombine/phi.ll @@ -630,3 +630,35 @@ %y = phi i32 [ undef, %entry ] ret i32 %y } + +; We should be able to fold the zexts to the other side of the phi +; even though there's a constant value input to the phi because we +; can shrink that constant to the smaller phi type. + +define i1 @PR24766(i8 %x1, i8 %x2, i8 %condition) { +entry: + %conv = sext i8 %condition to i32 + switch i32 %conv, label %epilog [ + i32 0, label %sw1 + i32 1, label %sw2 + ] + +sw1: + %cmp1 = icmp eq i8 %x1, %x2 + %frombool1 = zext i1 %cmp1 to i8 + br label %epilog + +sw2: + %cmp2 = icmp sle i8 %x1, %x2 + %frombool2 = zext i1 %cmp2 to i8 + br label %epilog + +epilog: + %conditionMet = phi i8 [ 0, %entry ], [ %frombool2, %sw2 ], [ %frombool1, %sw1 ] + %tobool = icmp ne i8 %conditionMet, 0 + ret i1 %tobool + +; CHECK-LABEL: @PR24766( +; CHECK: phi i1 +} +