[llvm-commits] CVS: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp

2007-03-30 Thread Chris Lattner


Changes in directory llvm/lib/Transforms/Scalar:

CodeGenPrepare.cpp added (r1.1)
---
Log message:

Split the sdisel code munging stuff out into its own opt-pass, CodeGenPrepare.


---
Diffs of the changes:  (+548 -0)

 CodeGenPrepare.cpp |  548 +
 1 files changed, 548 insertions(+)


Index: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
diff -c /dev/null llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.1
*** /dev/null   Fri Mar 30 23:06:46 2007
--- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp   Fri Mar 30 23:06:36 2007
***
*** 0 
--- 1,548 
+ //===- CodeGenPrepare.cpp - Prepare a function for code generation 
===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by Chris Lattner and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for 
details.
+ //
+ 
//===--===//
+ //
+ // This pass munges the code in the input function to better prepare it for
+ // SelectionDAG-based code generation.  This works around limitations in it's
+ // basic-block-at-a-time approach.  It should eventually be removed.
+ //
+ 
//===--===//
+ 
+ #define DEBUG_TYPE "codegenprepare"
+ #include "llvm/Transforms/Scalar.h"
+ #include "llvm/Constants.h"
+ #include "llvm/DerivedTypes.h"
+ #include "llvm/Function.h"
+ #include "llvm/Instructions.h"
+ #include "llvm/Pass.h"
+ #include "llvm/Support/Compiler.h"
+ #include "llvm/Target/TargetAsmInfo.h"
+ #include "llvm/Target/TargetData.h"
+ #include "llvm/Target/TargetLowering.h"
+ #include "llvm/Target/TargetMachine.h"
+ #include "llvm/Transforms/Utils/BasicBlockUtils.h"
+ #include "llvm/ADT/SmallSet.h"
+ using namespace llvm;
+ 
+ namespace {  
+   class VISIBILITY_HIDDEN CodeGenPrepare : public FunctionPass {
+ /// TLI - Keep a pointer of a TargetLowering to consult for determining
+ /// transformation profitability.
+ const TargetLowering *TLI;
+   public:
+ CodeGenPrepare(const TargetLowering *tli = 0) : TLI(tli) {}
+ bool runOnFunction(Function &F);
+ 
+   private:
+ bool OptimizeBlock(BasicBlock &BB);
+ bool OptimizeGEPExpression(GetElementPtrInst *GEPI);
+   };
+ }
+ static RegisterPass X("codegenprepare",
+   "Optimize for code generation");
+ 
+ FunctionPass *llvm::createCodeGenPreparePass(const TargetLowering *TLI) {
+   return new CodeGenPrepare(TLI);
+ }
+ 
+ 
+ bool CodeGenPrepare::runOnFunction(Function &F) {
+   bool MadeChange = true;
+   bool EverMadeChange = false;
+   while (MadeChange) {
+ MadeChange = false;
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+   MadeChange |= OptimizeBlock(*BB);
+ EverMadeChange |= MadeChange;
+   }
+   return EverMadeChange;
+ }
+ 
+ /// SplitEdgeNicely - Split the critical edge from TI to it's specified
+ /// successor if it will improve codegen.  We only do this if the successor 
has
+ /// phi nodes (otherwise critical edges are ok).  If there is already another
+ /// predecessor of the succ that is empty (and thus has no phi nodes), use it
+ /// instead of introducing a new block.
+ static void SplitEdgeNicely(TerminatorInst *TI, unsigned SuccNum, Pass *P) {
+   BasicBlock *TIBB = TI->getParent();
+   BasicBlock *Dest = TI->getSuccessor(SuccNum);
+   assert(isa(Dest->begin()) &&
+  "This should only be called if Dest has a PHI!");
+   
+   /// TIPHIValues - This array is lazily computed to determine the values of
+   /// PHIs in Dest that TI would provide.
+   std::vector TIPHIValues;
+   
+   // Check to see if Dest has any blocks that can be used as a split edge for
+   // this terminator.
+   for (pred_iterator PI = pred_begin(Dest), E = pred_end(Dest); PI != E; 
++PI) {
+ BasicBlock *Pred = *PI;
+ // To be usable, the pred has to end with an uncond branch to the dest.
+ BranchInst *PredBr = dyn_cast(Pred->getTerminator());
+ if (!PredBr || !PredBr->isUnconditional() ||
+ // Must be empty other than the branch.
+ &Pred->front() != PredBr)
+   continue;
+ 
+ // Finally, since we know that Dest has phi nodes in it, we have to make
+ // sure that jumping to Pred will have the same affect as going to Dest in
+ // terms of PHI values.
+ PHINode *PN;
+ unsigned PHINo = 0;
+ bool FoundMatch = true;
+ for (BasicBlock::iterator I = Dest->begin();
+  (PN = dyn_cast(I)); ++I, ++PHINo) {
+   if (PHINo == TIPHIValues.size())
+ TIPHIValues.push_back(PN->getIncomingValueForBlock(TIBB));
+   
+   // If the PHI entry doesn't work, we can't use this pred.
+   if (TIPHIValues[PHINo] != PN->getIncomingValueForBlock(Pred)) {
+ FoundMatch = false;
+ break;
+   }
+ }
+ 
+ // If we found a workable predecesso

[llvm-commits] CVS: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp

2007-04-01 Thread Chris Lattner


Changes in directory llvm/lib/Transforms/Scalar:

CodeGenPrepare.cpp updated: 1.1 -> 1.2
---
Log message:

Various passes before isel split edges and do other CFG-restructuring changes.

isel has its own particular features that it wants in the CFG, in order to
reduce the number of times a constant is computed, etc.  Make sure that we
clean up the CFG before doing any other things for isel.  Doing so can 
dramatically reduce the number of split edges and reduce the number of
places that constants get computed.  For example, this shrinks
CodeGen/Generic/phi-immediate-factoring.ll from 44 to 37 instructions on X86,
and from 21 to 17 MBB's in the output.  This is primarily a code size win,
not a performance win.

This implements CodeGen/Generic/phi-immediate-factoring.ll and PR1296: 
http://llvm.org/PR1296 .



---
Diffs of the changes:  (+175 -2)

 CodeGenPrepare.cpp |  177 -
 1 files changed, 175 insertions(+), 2 deletions(-)


Index: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
diff -u llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.1 
llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.2
--- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.1   Fri Mar 30 23:06:36 2007
+++ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp   Sun Apr  1 20:35:34 2007
@@ -20,13 +20,14 @@
 #include "llvm/Function.h"
 #include "llvm/Instructions.h"
 #include "llvm/Pass.h"
-#include "llvm/Support/Compiler.h"
 #include "llvm/Target/TargetAsmInfo.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Compiler.h"
 using namespace llvm;
 
 namespace {  
@@ -39,6 +40,9 @@
 bool runOnFunction(Function &F);
 
   private:
+bool EliminateMostlyEmptyBlocks(Function &F);
+bool CanMergeBlocks(const BasicBlock *BB, const BasicBlock *DestBB) const;
+void EliminateMostlyEmptyBlock(BasicBlock *BB);
 bool OptimizeBlock(BasicBlock &BB);
 bool OptimizeGEPExpression(GetElementPtrInst *GEPI);
   };
@@ -52,8 +56,13 @@
 
 
 bool CodeGenPrepare::runOnFunction(Function &F) {
-  bool MadeChange = true;
   bool EverMadeChange = false;
+  
+  // First pass, eliminate blocks that contain only PHI nodes and an
+  // unconditional branch.
+  EverMadeChange |= EliminateMostlyEmptyBlocks(F);
+  
+  bool MadeChange = true;
   while (MadeChange) {
 MadeChange = false;
 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
@@ -63,6 +72,170 @@
   return EverMadeChange;
 }
 
+/// EliminateMostlyEmptyBlocks - eliminate blocks that contain only PHI nodes
+/// and an unconditional branch.  Passes before isel (e.g. LSR/loopsimplify) 
+/// often split edges in ways that are non-optimal for isel.  Start by
+/// eliminating these blocks so we can split them the way we want them.
+bool CodeGenPrepare::EliminateMostlyEmptyBlocks(Function &F) {
+  bool MadeChange = false;
+  // Note that this intentionally skips the entry block.
+  for (Function::iterator I = ++F.begin(), E = F.end(); I != E; ) {
+BasicBlock *BB = I++;
+
+// If this block doesn't end with an uncond branch, ignore it.
+BranchInst *BI = dyn_cast(BB->getTerminator());
+if (!BI || !BI->isUnconditional())
+  continue;
+
+// If the instruction before the branch isn't a phi node, then other stuff
+// is happening here.
+BasicBlock::iterator BBI = BI;
+if (BBI != BB->begin()) {
+  --BBI;
+  if (!isa(BBI)) continue;
+}
+
+// Do not break infinite loops.
+BasicBlock *DestBB = BI->getSuccessor(0);
+if (DestBB == BB)
+  continue;
+
+if (!CanMergeBlocks(BB, DestBB))
+  continue;
+
+EliminateMostlyEmptyBlock(BB);
+MadeChange = true;
+  }
+  return MadeChange;
+}
+
+/// CanMergeBlocks - Return true if we can merge BB into DestBB if there is a
+/// single uncond branch between them, and BB contains no other non-phi
+/// instructions.
+bool CodeGenPrepare::CanMergeBlocks(const BasicBlock *BB,
+const BasicBlock *DestBB) const {
+  // We only want to eliminate blocks whose phi nodes are used by phi nodes in
+  // the successor.  If there are more complex condition (e.g. preheaders),
+  // don't mess around with them.
+  BasicBlock::const_iterator BBI = BB->begin();
+  while (const PHINode *PN = dyn_cast(BBI++)) {
+for (Value::use_const_iterator UI = PN->use_begin(), E = PN->use_end();
+ UI != E; ++UI) {
+  const Instruction *User = cast(*UI);
+  if (User->getParent() != DestBB || !isa(User))
+return false;
+}
+  }
+  
+  // If BB and DestBB contain any common predecessors, then the phi nodes in BB
+  // and DestBB may have conflicting incoming values for the block.  If so, we
+  // can't merge the block.
+  const PHINode *DestBBPN = dyn_cast(DestBB->begin());
+  if 

[llvm-commits] CVS: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp

2007-04-09 Thread Chris Lattner


Changes in directory llvm/lib/Transforms/Scalar:

CodeGenPrepare.cpp updated: 1.2 -> 1.3
---
Log message:

eliminate the last uses of some TLI methods.


---
Diffs of the changes:  (+7 -3)

 CodeGenPrepare.cpp |   10 +++---
 1 files changed, 7 insertions(+), 3 deletions(-)


Index: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
diff -u llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.2 
llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.3
--- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.2   Sun Apr  1 20:35:34 2007
+++ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp   Mon Apr  9 18:29:07 2007
@@ -536,11 +536,15 @@
 
 // Check if it is possible to fold the expression to address mode.
 if (UseTy && isa(BinOp->getOperand(1))) {
-  uint64_t Scale = TLI.getTargetData()->getTypeSize(UseTy);
   int64_t Cst = 
cast(BinOp->getOperand(1))->getSExtValue();
   // e.g. load (gep i32 * %P, (X+42)) => load (%P + X*4 + 168).
-  if (TLI.isLegalAddressImmediate(Cst*Scale, UseTy) &&
-  (Scale == 1 || TLI.isLegalAddressScale(Scale, UseTy))) {
+  TargetLowering::AddrMode AM;
+  // FIXME: This computation isn't right, scale is incorrect.
+  AM.Scale = TLI.getTargetData()->getTypeSize(UseTy);
+  // FIXME: Should should also include other fixed offsets.
+  AM.BaseOffs = Cst*AM.Scale;
+  
+  if (TLI.isLegalAddressingMode(AM, UseTy)) {
 DestBBs.insert(GEPIBB);
 MadeChange = true;
 break;



___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


[llvm-commits] CVS: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp

2007-04-13 Thread Chris Lattner


Changes in directory llvm/lib/Transforms/Scalar:

CodeGenPrepare.cpp updated: 1.3 -> 1.4
---
Log message:

Completely rewrite addressing-mode related sinking of code.  In particular,
this fixes problems where codegenprepare would sink expressions into load/stores
that are not valid, and fixes cases where it would miss important valid ones.

This fixes several serious codesize and perf issues, particularly on targets
with complex addressing modes like arm and x86.  For example, now we compile 
CodeGen/X86/isel-sink.ll to:

_test:
movl 8(%esp), %eax
movl 4(%esp), %ecx
cmpl $1233, %eax
ja LBB1_2   #F
LBB1_1: #T
movl $4, (%ecx,%eax,4)
movl $141, %eax
ret
LBB1_2: #F
movl (%ecx,%eax,4), %eax
ret

instead of:

_test:
movl 8(%esp), %eax
leal (,%eax,4), %ecx
addl 4(%esp), %ecx
cmpl $1233, %eax
ja LBB1_2   #F
LBB1_1: #T
movl $4, (%ecx)
movl $141, %eax
ret
LBB1_2: #F
movl (%ecx), %eax
ret



---
Diffs of the changes:  (+543 -342)

 CodeGenPrepare.cpp |  885 -
 1 files changed, 543 insertions(+), 342 deletions(-)


Index: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
diff -u llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.3 
llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.4
--- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.3   Mon Apr  9 18:29:07 2007
+++ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp   Fri Apr 13 15:30:56 2007
@@ -25,9 +25,12 @@
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
 using namespace llvm;
 
 namespace {  
@@ -44,7 +47,9 @@
 bool CanMergeBlocks(const BasicBlock *BB, const BasicBlock *DestBB) const;
 void EliminateMostlyEmptyBlock(BasicBlock *BB);
 bool OptimizeBlock(BasicBlock &BB);
-bool OptimizeGEPExpression(GetElementPtrInst *GEPI);
+bool OptimizeLoadStoreInst(Instruction *I, Value *Addr,
+   const Type *AccessTy,
+   DenseMap &SunkAddrs);
   };
 }
 static RegisterPass X("codegenprepare",
@@ -291,312 +296,37 @@
   SplitCriticalEdge(TI, SuccNum, P, true);  
 }
 
-
-/// InsertGEPComputeCode - Insert code into BB to compute Ptr+PtrOffset,
-/// casting to the type of GEPI.
-static Instruction *InsertGEPComputeCode(Instruction *&V, BasicBlock *BB,
- Instruction *GEPI, Value *Ptr,
- Value *PtrOffset) {
-  if (V) return V;   // Already computed.
-  
-  // Figure out the insertion point
-  BasicBlock::iterator InsertPt;
-  if (BB == GEPI->getParent()) {
-// If GEP is already inserted into BB, insert right after the GEP.
-InsertPt = GEPI;
-++InsertPt;
-  } else {
-// Otherwise, insert at the top of BB, after any PHI nodes
-InsertPt = BB->begin();
-while (isa(InsertPt)) ++InsertPt;
-  }
-  
-  // If Ptr is itself a cast, but in some other BB, emit a copy of the cast 
into
-  // BB so that there is only one value live across basic blocks (the cast 
-  // operand).
-  if (CastInst *CI = dyn_cast(Ptr))
-if (CI->getParent() != BB && 
isa(CI->getOperand(0)->getType()))
-  Ptr = CastInst::create(CI->getOpcode(), CI->getOperand(0), CI->getType(),
- "", InsertPt);
-  
-  // Add the offset, cast it to the right type.
-  Ptr = BinaryOperator::createAdd(Ptr, PtrOffset, "", InsertPt);
-  // Ptr is an integer type, GEPI is pointer type ==> IntToPtr
-  return V = CastInst::create(Instruction::IntToPtr, Ptr, GEPI->getType(), 
-  "", InsertPt);
-}
-
-/// ReplaceUsesOfGEPInst - Replace all uses of RepPtr with inserted code to
-/// compute its value.  The RepPtr value can be computed with Ptr+PtrOffset. 
One
-/// trivial way of doing this would be to evaluate Ptr+PtrOffset in RepPtr's
-/// block, then ReplaceAllUsesWith'ing everything.  However, we would prefer to
-/// sink PtrOffset into user blocks where doing so will likely allow us to fold
-/// the constant add into a load or store instruction.  Additionally, if a user
-/// is a pointer-pointer cast, we look through it to find its users.
-static void ReplaceUsesOfGEPInst(Instruction *RepPtr, Value *Ptr, 
- Constant *PtrOffset, BasicBlock *DefBB,
- GetElementPtrInst *GEPI,
-   std::map &InsertedExprs) {
-  while (!RepPtr->use_empty()) {
-Instruction *User = cast(RepPtr->use_back());
-
-// If the user is a Pointer-Pointer cast, recurse. Only BitCast can be
-// used for a Pointer-Pointer cast.
-if 

[llvm-commits] CVS: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp

2007-04-13 Thread Chris Lattner


Changes in directory llvm/lib/Transforms/Scalar:

CodeGenPrepare.cpp updated: 1.4 -> 1.5
---
Log message:

use an accessor to simplify code.


---
Diffs of the changes:  (+1 -15)

 CodeGenPrepare.cpp |   16 +---
 1 files changed, 1 insertion(+), 15 deletions(-)


Index: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
diff -u llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.4 
llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.5
--- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.4   Fri Apr 13 15:30:56 2007
+++ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp   Fri Apr 13 19:17:39 2007
@@ -886,21 +886,7 @@
 SI->getOperand(0)->getType(),
 SunkAddrs);
 } else if (GetElementPtrInst *GEPI = dyn_cast(I)) {
-  bool HasNonZeroIdx = false;
-  for (GetElementPtrInst::op_iterator OI = GEPI->op_begin()+1,
-   E = GEPI->op_end(); OI != E; ++OI) {
-if (ConstantInt *CI = dyn_cast(*OI)) {
-  if (!CI->isZero()) {
-HasNonZeroIdx = true;
-break;
-  }
-} else {
-  HasNonZeroIdx = true;
-  break;
-}
-  }
-  
-  if (!HasNonZeroIdx) {
+  if (GEPI->hasAllZeroIndices()) {
 /// The GEP operand must be a pointer, so must its result -> BitCast
 Instruction *NC = new BitCastInst(GEPI->getOperand(0), 
GEPI->getType(), 
   GEPI->getName(), GEPI);



___
llvm-commits mailing list
[EMAIL PROTECTED]
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


[llvm-commits] CVS: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp

2007-04-24 Thread Devang Patel


Changes in directory llvm/lib/Transforms/Scalar:

CodeGenPrepare.cpp updated: 1.5 -> 1.6
---
Log message:

Fix 
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20070423/048376.html


---
Diffs of the changes:  (+12 -0)

 CodeGenPrepare.cpp |   12 
 1 files changed, 12 insertions(+)


Index: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
diff -u llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.5 
llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.6
--- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.5   Fri Apr 13 19:17:39 2007
+++ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp   Tue Apr 24 19:37:04 2007
@@ -129,6 +129,18 @@
   const Instruction *User = cast(*UI);
   if (User->getParent() != DestBB || !isa(User))
 return false;
+  // If User is inside DestBB block and it is a PHINode then check 
+  // incoming value. If incoming value is not from BB then this is 
+  // a complex condition (e.g. preheaders) we want to avoid here.
+  if (User->getParent() == DestBB) {
+if (const PHINode *UPN = dyn_cast(User))
+  for (unsigned I = 0, E = UPN->getNumIncomingValues(); I != E; ++I) {
+Instruction *Insn = 
dyn_cast(UPN->getIncomingValue(I));
+if (Insn && Insn->getParent() == BB &&
+Insn->getParent() != UPN->getIncomingBlock(I))
+  return false;
+  }
+  }
 }
   }
   



___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


[llvm-commits] CVS: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp

2007-05-07 Thread Dale Johannesen


Changes in directory llvm/lib/Transforms/Scalar:

CodeGenPrepare.cpp updated: 1.10 -> 1.11
---
Log message:

Don't generate branch to entry block.


---
Diffs of the changes:  (+3 -1)

 CodeGenPrepare.cpp |4 +++-
 1 files changed, 3 insertions(+), 1 deletion(-)


Index: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
diff -u llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.10 
llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.11
--- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.10  Sun May  6 08:37:16 2007
+++ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp   Mon May  7 20:01:04 2007
@@ -280,7 +280,9 @@
 BranchInst *PredBr = dyn_cast(Pred->getTerminator());
 if (!PredBr || !PredBr->isUnconditional() ||
 // Must be empty other than the branch.
-&Pred->front() != PredBr)
+&Pred->front() != PredBr ||
+// Cannot be the entry block; its label does not get emitted.
+Pred == &(Dest->getParent()->getEntryBlock()))
   continue;
 
 // Finally, since we know that Dest has phi nodes in it, we have to make



___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits


[llvm-commits] CVS: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp

2007-06-12 Thread Dale Johannesen


Changes in directory llvm/lib/Transforms/Scalar:

CodeGenPrepare.cpp updated: 1.11 -> 1.12
---
Log message:

Sink CmpInst's to their uses to reduce register pressure.


---
Diffs of the changes:  (+61 -3)

 CodeGenPrepare.cpp |   64 ++---
 1 files changed, 61 insertions(+), 3 deletions(-)


Index: llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp
diff -u llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.11 
llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.12
--- llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp:1.11  Mon May  7 20:01:04 2007
+++ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp   Tue Jun 12 11:50:17 2007
@@ -317,7 +317,7 @@
 /// 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 @@
   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 @@
   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 @@
   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 @@
   
   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(),



___
llvm-commits mailing list
llvm-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits