Changes in directory llvm/lib/Transforms/Scalar:
InstructionCombining.cpp updated: 1.529 -> 1.530 --- Log message: Fold things like "phi [add (a,b), add(c,d)]" into two phi's and one add. This triggers thousands of times on multisource. --- Diffs of the changes: (+57 -3) InstructionCombining.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 57 insertions(+), 3 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.529 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.530 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.529 Thu Oct 26 14:19:06 2006 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue Oct 31 22:51:18 2006 @@ -276,7 +276,9 @@ // operator and they all are only used by the PHI, PHI together their // inputs, and do the operation once, to the result of the PHI. Instruction *FoldPHIArgOpIntoPHI(PHINode &PN); - + Instruction *FoldPHIArgBinOpIntoPHI(PHINode &PN); + + Instruction *OptAndOp(Instruction *Op, ConstantIntegral *OpRHS, ConstantIntegral *AndRHS, BinaryOperator &TheAnd); @@ -6778,6 +6780,56 @@ return true; } +/// FoldPHIArgBinOpIntoPHI - If we have something like phi [add (a,b), add(c,d)] +/// and if a/b/c/d and the add's all have a single use, turn this into two phi's +/// and a single binop. +Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) { + Instruction *FirstInst = cast<Instruction>(PN.getIncomingValue(0)); + assert(isa<BinaryOperator>(FirstInst) || isa<ShiftInst>(FirstInst)); + unsigned Opc = FirstInst->getOpcode(); + + // Scan to see if all operands are the same opcode, all have one use, and all + // kill their operands (i.e. the operands have one use). + unsigned NumValues = PN.getNumIncomingValues(); + for (unsigned i = 0; i != NumValues; ++i) { + Instruction *I = dyn_cast<Instruction>(PN.getIncomingValue(i)); + if (!I || I->getOpcode() != Opc || !I->hasOneUse()) + return 0; + } + + // Otherwise, this is safe and profitable to transform. Create two phi nodes. + PHINode *NewLHS = new PHINode(FirstInst->getOperand(0)->getType(), + FirstInst->getOperand(0)->getName()+".pn"); + NewLHS->reserveOperandSpace(PN.getNumOperands()/2); + PHINode *NewRHS = new PHINode(FirstInst->getOperand(1)->getType(), + FirstInst->getOperand(1)->getName()+".pn"); + NewRHS->reserveOperandSpace(PN.getNumOperands()/2); + + Value *InLHS = FirstInst->getOperand(0); + NewLHS->addIncoming(InLHS, PN.getIncomingBlock(0)); + Value *InRHS = FirstInst->getOperand(1); + NewRHS->addIncoming(InRHS, PN.getIncomingBlock(0)); + + // Add all operands to the new PHsI. + for (unsigned i = 1, e = PN.getNumIncomingValues(); i != e; ++i) { + Value *NewInLHS = cast<Instruction>(PN.getIncomingValue(i))->getOperand(0); + Value *NewInRHS = cast<Instruction>(PN.getIncomingValue(i))->getOperand(1); + if (NewInLHS != InLHS) InLHS = 0; + if (NewInRHS != InRHS) InRHS = 0; + NewLHS->addIncoming(NewInLHS, PN.getIncomingBlock(i)); + NewRHS->addIncoming(NewInRHS, PN.getIncomingBlock(i)); + } + + InsertNewInstBefore(NewLHS, PN); + InsertNewInstBefore(NewRHS, PN); + + if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst)) + return BinaryOperator::create(BinOp->getOpcode(), NewLHS, NewRHS); + else + return new ShiftInst(cast<ShiftInst>(FirstInst)->getOpcode(), + NewLHS, NewRHS); +} + // FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary" // operator and they all are only used by the PHI, PHI together their @@ -6794,9 +6846,11 @@ if (isa<CastInst>(FirstInst)) { CastSrcTy = FirstInst->getOperand(0)->getType(); } else if (isa<BinaryOperator>(FirstInst) || isa<ShiftInst>(FirstInst)) { - // Can fold binop or shift if the RHS is a constant. + // Can fold binop or shift here if the RHS is a constant, otherwise call + // FoldPHIArgBinOpIntoPHI. ConstantOp = dyn_cast<Constant>(FirstInst->getOperand(1)); - if (ConstantOp == 0) return 0; + if (ConstantOp == 0) + return FoldPHIArgBinOpIntoPHI(PN); } else { return 0; // Cannot fold this operation. } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits