Index: lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- lib/Transforms/InstCombine/InstCombineInternal.h +++ lib/Transforms/InstCombine/InstCombineInternal.h @@ -703,6 +703,7 @@ Instruction *FoldPHIArgGEPIntoPHI(PHINode &PN); Instruction *FoldPHIArgLoadIntoPHI(PHINode &PN); Instruction *FoldPHIArgZextsIntoPHI(PHINode &PN); + Instruction *FoldPHIArgOrIntoPHI(PHINode &PN); /// If an integer typed PHI has only one use which is an IntToPtr operation, /// replace the PHI with an existing pointer typed PHI if it exists. Otherwise Index: lib/Transforms/InstCombine/InstCombinePHI.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombinePHI.cpp +++ lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -635,6 +635,50 @@ return NewLI; } +// FoldPHIArgOrIntoPHI finds a phi node, which has OR instruction as an incoming value +// and AND instruction as its use. If the OR and AND instructions take the same operand +// as (%A OR %B) AND %B then replace the incoming value as %B. +// For example, +// BB1: +// %or = or i64 %val, 1 +// br %BB2 +// BB2: +// %phi = phi i64 [ %or, %BB1 ], ... # -> phi i64 [ 1, %BB1 ], ... +// %and = and i64 %phi, 1 +// This optimization allows jump threading pass to find the opportunity in method call +// whose return value is std::pair. +Instruction *InstCombiner::FoldPHIArgOrIntoPHI(PHINode &Phi) { + for (User *User : Phi.users()) { + // Try to find OR - Phi - AND code sequence. + Value *UserVal = nullptr; + if (!match(User, m_And(m_Specific(&Phi), m_Value(UserVal)))) + continue; + + auto IsEligible = [&](Value *V) { + return match(V, m_Or(m_Value(), m_Specific(UserVal))); + }; + if (llvm::none_of(Phi.incoming_values(), IsEligible)) + continue; + + PHINode* NewPhi = Φ + // If there is another use of the phi node, we create a new one + // for this AND instruction by cloning the original phi node. + if (!Phi.hasOneUse()) { + NewPhi = cast(Phi.clone()); + InsertNewInstBefore(NewPhi, Phi); + cast(User)->setOperand(0, NewPhi); + } + + // We replace the incoming OR with UserVal. + for (unsigned Idx = 0; Idx < NewPhi->getNumIncomingValues(); Idx++) { + Value *V = NewPhi->getIncomingValue(Idx); + if (match(V, m_Or(m_Value(), m_Specific(UserVal)))) + NewPhi->setIncomingValue(Idx, UserVal); + } + } + return nullptr; +} + /// 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. @@ -1130,6 +1174,9 @@ if (Instruction *Result = FoldPHIArgOpIntoPHI(PN)) return Result; + if (Instruction *Result = FoldPHIArgOrIntoPHI(PN)) + return Result; + // If this is a trivial cycle in the PHI node graph, remove it. Basically, if // this PHI only has a single use (a PHI), and if that PHI only has one use (a // PHI)... break the cycle.