From edfec0b5153c3d0234fa40233a47868c0b531173 Mon Sep 17 00:00:00 2001 From: Dale Johannesen Date: Tue, 12 Jun 2007 16:50:17 +0000 Subject: [PATCH] Sink CmpInst's to their uses to reduce register pressure. llvm-svn: 37554 --- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp index 9fa044e4c764..2969df38a696 100644 --- a/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -317,7 +317,7 @@ static void SplitEdgeNicely(TerminatorInst *TI, unsigned SuccNum, Pass *P) { /// OptimizeNoopCopyExpression - If the specified cast instruction is a noop /// copy (e.g. it's casting from one pointer type to another, int->uint, or /// int->sbyte on PPC), sink it into user blocks to reduce the number of virtual -/// registers that must be created and coallesced. +/// registers that must be created and coalesced. /// /// Return true if any changes are made. static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI){ @@ -348,7 +348,7 @@ static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI){ BasicBlock *DefBB = CI->getParent(); /// InsertedCasts - Only insert a cast in each block once. - std::map InsertedCasts; + DenseMap InsertedCasts; bool MadeChange = false; for (Value::use_iterator UI = CI->use_begin(), E = CI->use_end(); @@ -383,7 +383,7 @@ static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI){ MadeChange = true; } - // Replace a use of the cast with a use of the new casat. + // Replace a use of the cast with a use of the new cast. TheUse = InsertedCast; } @@ -394,6 +394,62 @@ static bool OptimizeNoopCopyExpression(CastInst *CI, const TargetLowering &TLI){ return MadeChange; } +/// OptimizeCmpExpression - sink the given CmpInst into user blocks to reduce +/// the number of virtual registers that must be created and coalesced. This is +/// a clear win except on targets with multiple condition code registers (powerPC), +/// where it might lose; some adjustment may be wanted there. +/// +/// Return true if any changes are made. +static bool OptimizeCmpExpression(CmpInst *CI){ + + BasicBlock *DefBB = CI->getParent(); + + /// InsertedCmp - Only insert a cmp in each block once. + DenseMap InsertedCmps; + + bool MadeChange = false; + for (Value::use_iterator UI = CI->use_begin(), E = CI->use_end(); + UI != E; ) { + Use &TheUse = UI.getUse(); + Instruction *User = cast(*UI); + + // Preincrement use iterator so we don't invalidate it. + ++UI; + + // Don't bother for PHI nodes. + if (isa(User)) + continue; + + // Figure out which BB this cmp is used in. + BasicBlock *UserBB = User->getParent(); + + // If this user is in the same block as the cmp, don't change the cmp. + if (UserBB == DefBB) continue; + + // If we have already inserted a cmp into this block, use it. + CmpInst *&InsertedCmp = InsertedCmps[UserBB]; + + if (!InsertedCmp) { + BasicBlock::iterator InsertPt = UserBB->begin(); + while (isa(InsertPt)) ++InsertPt; + + InsertedCmp = + CmpInst::create(CI->getOpcode(), CI->getPredicate(), CI->getOperand(0), + CI->getOperand(1), "", InsertPt); + MadeChange = true; + } + + // Replace a use of the cmp with a use of the new cmp. + TheUse = InsertedCmp; + } + + // If we removed all uses, nuke the cmp. + if (CI->use_empty()) + CI->eraseFromParent(); + + return MadeChange; +} + /// EraseDeadInstructions - Erase any dead instructions static void EraseDeadInstructions(Value *V) { Instruction *I = dyn_cast(V); @@ -894,6 +950,8 @@ bool CodeGenPrepare::OptimizeBlock(BasicBlock &BB) { if (TLI) MadeChange |= OptimizeNoopCopyExpression(CI, *TLI); + } else if (CmpInst *CI = dyn_cast(I)) { + MadeChange |= OptimizeCmpExpression(CI); } else if (LoadInst *LI = dyn_cast(I)) { if (TLI) MadeChange |= OptimizeLoadStoreInst(I, I->getOperand(0), LI->getType(),