Factor out the code for creating SCEVs for GEPs into a

separate function.

llvm-svn: 71252
This commit is contained in:
Dan Gohman 2009-05-08 20:26:55 +00:00
parent 85f4028f2e
commit ee750d142d
2 changed files with 44 additions and 33 deletions

View File

@ -279,6 +279,10 @@ namespace llvm {
/// SCEVs.
SCEVHandle createNodeForPHI(PHINode *PN);
/// createNodeForGEP - Provide the special handling we need to analyze GEP
/// SCEVs.
SCEVHandle createNodeForGEP(GetElementPtrInst *GEP);
/// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value
/// for the specified instruction and replaces any references to the
/// symbolic value SymName with the specified value. This is used during

View File

@ -1863,6 +1863,44 @@ SCEVHandle ScalarEvolution::createNodeForPHI(PHINode *PN) {
return getUnknown(PN);
}
/// createNodeForGEP - Expand GEP instructions into add and multiply
/// operations. This allows them to be analyzed by regular SCEV code.
///
SCEVHandle ScalarEvolution::createNodeForGEP(GetElementPtrInst *GEP) {
const Type *IntPtrTy = TD->getIntPtrType();
Value *Base = U->getOperand(0);
SCEVHandle TotalOffset = getIntegerSCEV(0, IntPtrTy);
gep_type_iterator GTI = gep_type_begin(U);
for (GetElementPtrInst::op_iterator I = next(U->op_begin()),
E = U->op_end();
I != E; ++I) {
Value *Index = *I;
// Compute the (potentially symbolic) offset in bytes for this index.
if (const StructType *STy = dyn_cast<StructType>(*GTI++)) {
// For a struct, add the member offset.
const StructLayout &SL = *TD->getStructLayout(STy);
unsigned FieldNo = cast<ConstantInt>(Index)->getZExtValue();
uint64_t Offset = SL.getElementOffset(FieldNo);
TotalOffset = getAddExpr(TotalOffset,
getIntegerSCEV(Offset, IntPtrTy));
} else {
// For an array, add the element offset, explicitly scaled.
SCEVHandle LocalOffset = getSCEV(Index);
if (!isa<PointerType>(LocalOffset->getType()))
// Getelementptr indicies are signed.
LocalOffset = getTruncateOrSignExtend(LocalOffset,
IntPtrTy);
LocalOffset =
getMulExpr(LocalOffset,
getIntegerSCEV(TD->getTypePaddedSize(*GTI),
IntPtrTy));
TotalOffset = getAddExpr(TotalOffset, LocalOffset);
}
}
return getAddExpr(getSCEV(Base), TotalOffset);
}
/// GetMinTrailingZeros - Determine the minimum number of zero bits that S is
/// guaranteed to end in (at every loop iteration). It is, at the same time,
/// the minimum number of times S is divisible by 2. For example, given {4,+,8}
@ -2073,40 +2111,9 @@ SCEVHandle ScalarEvolution::createSCEV(Value *V) {
return getTruncateOrZeroExtend(getSCEV(U->getOperand(0)),
U->getType());
case Instruction::GetElementPtr: {
case Instruction::GetElementPtr:
if (!TD) break; // Without TD we can't analyze pointers.
const Type *IntPtrTy = TD->getIntPtrType();
Value *Base = U->getOperand(0);
SCEVHandle TotalOffset = getIntegerSCEV(0, IntPtrTy);
gep_type_iterator GTI = gep_type_begin(U);
for (GetElementPtrInst::op_iterator I = next(U->op_begin()),
E = U->op_end();
I != E; ++I) {
Value *Index = *I;
// Compute the (potentially symbolic) offset in bytes for this index.
if (const StructType *STy = dyn_cast<StructType>(*GTI++)) {
// For a struct, add the member offset.
const StructLayout &SL = *TD->getStructLayout(STy);
unsigned FieldNo = cast<ConstantInt>(Index)->getZExtValue();
uint64_t Offset = SL.getElementOffset(FieldNo);
TotalOffset = getAddExpr(TotalOffset,
getIntegerSCEV(Offset, IntPtrTy));
} else {
// For an array, add the element offset, explicitly scaled.
SCEVHandle LocalOffset = getSCEV(Index);
if (!isa<PointerType>(LocalOffset->getType()))
// Getelementptr indicies are signed.
LocalOffset = getTruncateOrSignExtend(LocalOffset,
IntPtrTy);
LocalOffset =
getMulExpr(LocalOffset,
getIntegerSCEV(TD->getTypePaddedSize(*GTI),
IntPtrTy));
TotalOffset = getAddExpr(TotalOffset, LocalOffset);
}
}
return getAddExpr(getSCEV(Base), TotalOffset);
}
return createNodeForGEP(cast<GetElementPtrInst>(U));
case Instruction::PHI:
return createNodeForPHI(cast<PHINode>(U));