[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Chris Lattner
lattner at cs.uiuc.edu
Fri May 5 14:18:02 PDT 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
SelectionDAGISel.cpp updated: 1.234 -> 1.235
---
Log message:
More aggressively sink GEP offsets into loops. For example, before we
generated:
movl 8(%esp), %eax
movl %eax, %edx
addl $4316, %edx
cmpb $1, %cl
ja LBB1_2 #cond_false
LBB1_1: #cond_true
movl L_QuantizationTables720$non_lazy_ptr, %ecx
movl %ecx, (%edx)
movl L_QNOtoQuantTableShift720$non_lazy_ptr, %edx
movl %edx, 4460(%eax)
ret
...
Now we generate:
movl 8(%esp), %eax
cmpb $1, %cl
ja LBB1_2 #cond_false
LBB1_1: #cond_true
movl L_QuantizationTables720$non_lazy_ptr, %ecx
movl %ecx, 4316(%eax)
movl L_QNOtoQuantTableShift720$non_lazy_ptr, %ecx
movl %ecx, 4460(%eax)
ret
... which uses one fewer register.
---
Diffs of the changes: (+115 -56)
SelectionDAGISel.cpp | 171 ++++++++++++++++++++++++++++++++++-----------------
1 files changed, 115 insertions(+), 56 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.234 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.235
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.234 Thu May 4 20:04:50 2006
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Fri May 5 16:17:49 2006
@@ -2733,45 +2733,18 @@
}
-/// InsertGEPComputeCode - Insert code into BB to compute Ptr+PtrOffset,
-/// casting to the type of GEPI.
-static Value *InsertGEPComputeCode(Value *&V, BasicBlock *BB, Instruction *GEPI,
- Value *Ptr, Value *PtrOffset) {
- if (V) return V; // Already computed.
-
- BasicBlock::iterator InsertPt;
- if (BB == GEPI->getParent()) {
- // If insert into the GEP's block, 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<PHINode>(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<CastInst>(Ptr))
- if (CI->getParent() != BB && isa<PointerType>(CI->getOperand(0)->getType()))
- Ptr = new CastInst(CI->getOperand(0), CI->getType(), "", InsertPt);
-
- // Add the offset, cast it to the right type.
- Ptr = BinaryOperator::createAdd(Ptr, PtrOffset, "", InsertPt);
- Ptr = new CastInst(Ptr, GEPI->getType(), "", InsertPt);
- return V = Ptr;
-}
-
/// OptimizeNoopCopyExpression - We have determined that 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.
-static void OptimizeNoopCopyExpression(CastInst *CI) {
+///
+/// Return true if any changes are made.
+static bool OptimizeNoopCopyExpression(CastInst *CI) {
BasicBlock *DefBB = CI->getParent();
/// InsertedCasts - Only insert a cast in each block once.
std::map<BasicBlock*, CastInst*> InsertedCasts;
+ bool MadeChange = false;
for (Value::use_iterator UI = CI->use_begin(), E = CI->use_end();
UI != E; ) {
Use &TheUse = UI.getUse();
@@ -2800,20 +2773,103 @@
InsertedCast =
new CastInst(CI->getOperand(0), CI->getType(), "", InsertPt);
+ MadeChange = true;
}
// Replace a use of the cast with a use of the new casat.
TheUse = InsertedCast;
}
+
+ // If we removed all uses, nuke the cast.
+ if (CI->use_empty())
+ CI->eraseFromParent();
+
+ return MadeChange;
}
+/// InsertGEPComputeCode - Insert code into BB to compute Ptr+PtrOffset,
+/// casting to the type of GEPI.
+static Value *InsertGEPComputeCode(Value *&V, BasicBlock *BB, Instruction *GEPI,
+ Value *Ptr, Value *PtrOffset) {
+ if (V) return V; // Already computed.
+
+ BasicBlock::iterator InsertPt;
+ if (BB == GEPI->getParent()) {
+ // If insert into the GEP's block, 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<PHINode>(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<CastInst>(Ptr))
+ if (CI->getParent() != BB && isa<PointerType>(CI->getOperand(0)->getType()))
+ Ptr = new CastInst(CI->getOperand(0), CI->getType(), "", InsertPt);
+
+ // Add the offset, cast it to the right type.
+ Ptr = BinaryOperator::createAdd(Ptr, PtrOffset, "", InsertPt);
+ Ptr = new CastInst(Ptr, GEPI->getType(), "", InsertPt);
+ return V = Ptr;
+}
+
+/// 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<BasicBlock*,Value*> &InsertedExprs) {
+ while (!RepPtr->use_empty()) {
+ Instruction *User = cast<Instruction>(RepPtr->use_back());
+
+ // If the user is a Pointer-Pointer cast, recurse.
+ if (isa<CastInst>(User) && isa<PointerType>(User->getType())) {
+ ReplaceUsesOfGEPInst(User, Ptr, PtrOffset, DefBB, GEPI, InsertedExprs);
+
+ // Drop the use of RepPtr. The cast is dead. Don't delete it now, else we
+ // could invalidate an iterator.
+ User->setOperand(0, UndefValue::get(RepPtr->getType()));
+ continue;
+ }
+
+ // If this is a load of the pointer, or a store through the pointer, emit
+ // the increment into the load/store block.
+ Value *NewVal;
+ if (isa<LoadInst>(User) ||
+ (isa<StoreInst>(User) && User->getOperand(0) != RepPtr)) {
+ NewVal = InsertGEPComputeCode(InsertedExprs[User->getParent()],
+ User->getParent(), GEPI,
+ Ptr, PtrOffset);
+ } else {
+ // If this use is not foldable into the addressing mode, use a version
+ // emitted in the GEP block.
+ NewVal = InsertGEPComputeCode(InsertedExprs[DefBB], DefBB, GEPI,
+ Ptr, PtrOffset);
+ }
+
+ if (GEPI->getType() != RepPtr->getType())
+ NewVal = new CastInst(NewVal, RepPtr->getType(), "", User);
+ User->replaceUsesOfWith(RepPtr, NewVal);
+ }
+}
+
+
/// OptimizeGEPExpression - Since we are doing basic-block-at-a-time instruction
/// selection, we want to be a bit careful about some things. In particular, if
/// we have a GEP instruction that is used in a different block than it is
/// defined, the addressing expression of the GEP cannot be folded into loads or
/// stores that use it. In this case, decompose the GEP and move constant
/// indices into blocks that use it.
-static void OptimizeGEPExpression(GetElementPtrInst *GEPI,
+static bool OptimizeGEPExpression(GetElementPtrInst *GEPI,
const TargetData *TD) {
// If this GEP is only used inside the block it is defined in, there is no
// need to rewrite it.
@@ -2826,21 +2882,36 @@
break;
}
}
- if (!isUsedOutsideDefBB) return;
+ if (!isUsedOutsideDefBB) return false;
// If this GEP has no non-zero constant indices, there is nothing we can do,
// ignore it.
bool hasConstantIndex = false;
+ bool hasVariableIndex = false;
for (GetElementPtrInst::op_iterator OI = GEPI->op_begin()+1,
E = GEPI->op_end(); OI != E; ++OI) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(*OI))
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(*OI)) {
if (CI->getRawValue()) {
hasConstantIndex = true;
break;
}
+ } else {
+ hasVariableIndex = true;
+ }
+ }
+
+ // If this is a "GEP X, 0, 0, 0", turn this into a cast.
+ if (!hasConstantIndex && !hasVariableIndex) {
+ Value *NC = new CastInst(GEPI->getOperand(0), GEPI->getType(),
+ GEPI->getName(), GEPI);
+ GEPI->replaceAllUsesWith(NC);
+ GEPI->eraseFromParent();
+ return true;
}
+
// If this is a GEP &Alloca, 0, 0, forward subst the frame index into uses.
- if (!hasConstantIndex && !isa<AllocaInst>(GEPI->getOperand(0))) return;
+ if (!hasConstantIndex && !isa<AllocaInst>(GEPI->getOperand(0)))
+ return false;
// Otherwise, decompose the GEP instruction into multiplies and adds. Sum the
// constant offset (which we now know is non-zero) and deal with it later.
@@ -2900,28 +2971,12 @@
// won't be foldable as addresses, so we might as well share the computation).
std::map<BasicBlock*,Value*> InsertedExprs;
- while (!GEPI->use_empty()) {
- Instruction *User = cast<Instruction>(GEPI->use_back());
-
- // If this use is not foldable into the addressing mode, use a version
- // emitted in the GEP block.
- Value *NewVal;
- if (!isa<LoadInst>(User) &&
- (!isa<StoreInst>(User) || User->getOperand(0) == GEPI)) {
- NewVal = InsertGEPComputeCode(InsertedExprs[DefBB], DefBB, GEPI,
- Ptr, PtrOffset);
- } else {
- // Otherwise, insert the code in the User's block so it can be folded into
- // any users in that block.
- NewVal = InsertGEPComputeCode(InsertedExprs[User->getParent()],
- User->getParent(), GEPI,
- Ptr, PtrOffset);
- }
- User->replaceUsesOfWith(GEPI, NewVal);
- }
+ ReplaceUsesOfGEPInst(GEPI, Ptr, PtrOffset, DefBB, GEPI, InsertedExprs);
// Finally, the GEP is dead, remove it.
GEPI->eraseFromParent();
+
+ return true;
}
bool SelectionDAGISel::runOnFunction(Function &Fn) {
@@ -2938,6 +2993,9 @@
// selection.
//
//
+ bool MadeChange = true;
+ while (MadeChange) {
+ MadeChange = false;
for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
PHINode *PN;
BasicBlock::iterator BBI;
@@ -2949,7 +3007,7 @@
for (BasicBlock::iterator E = BB->end(); BBI != E; ) {
Instruction *I = BBI++;
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
- OptimizeGEPExpression(GEPI, TLI.getTargetData());
+ MadeChange |= OptimizeGEPExpression(GEPI, TLI.getTargetData());
} else if (CastInst *CI = dyn_cast<CastInst>(I)) {
// If this is a noop copy, sink it into user blocks to reduce the number
// of virtual registers that must be created and coallesced.
@@ -2974,10 +3032,11 @@
// If, after promotion, these are the same types, this is a noop copy.
if (SrcVT == DstVT)
- OptimizeNoopCopyExpression(CI);
+ MadeChange |= OptimizeNoopCopyExpression(CI);
}
}
}
+ }
FunctionLoweringInfo FuncInfo(TLI, Fn, MF);
More information about the llvm-commits
mailing list