refactor the interface to ConvertUsesOfLoadToScalar,

renaming it to ConvertScalar_ExtractValue

llvm-svn: 63658
This commit is contained in:
Chris Lattner 2009-02-03 21:01:03 +00:00
parent fcc6fd5c39
commit f5df53cb46
1 changed files with 35 additions and 34 deletions

View File

@ -129,7 +129,7 @@ namespace {
bool CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy,
bool &SawVec, uint64_t Offset, unsigned AllocaSize);
void ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset);
Value *ConvertUsesOfLoadToScalar(LoadInst *LI, AllocaInst *NewAI,
Value *ConvertScalar_ExtractValue(Value *NV, const Type *ToType,
uint64_t Offset, IRBuilder<> &Builder);
Value *ConvertScalar_InsertValue(Value *StoredVal, Value *ExistingVal,
uint64_t Offset, IRBuilder<> &Builder);
@ -1338,8 +1338,11 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) {
IRBuilder<> Builder(User->getParent(), User);
if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
Value *LoadVal = ConvertUsesOfLoadToScalar(LI, NewAI, Offset, Builder);
LI->replaceAllUsesWith(LoadVal);
// The load is a bit extract from NewAI shifted right by Offset bits.
Value *LoadedVal = Builder.CreateLoad(NewAI, "tmp");
Value *NewLoadVal
= ConvertScalar_ExtractValue(LoadedVal, LI->getType(), Offset, Builder);
LI->replaceAllUsesWith(NewLoadVal);
LI->eraseFromParent();
continue;
}
@ -1383,28 +1386,27 @@ void SROA::ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, uint64_t Offset) {
}
}
/// ConvertUsesOfLoadToScalar - Convert all of the users of the specified load
/// to use the new alloca directly, returning the value that should replace the
/// load. This happens when we are converting an "integer union" to a single
/// ConvertScalar_ExtractValue - Extract a value of type ToType from an integer
/// or vector value FromVal, extracting the bits from the offset specified by
/// Offset. This returns the value, which is of type ToType.
///
/// This happens when we are converting an "integer union" to a single
/// integer scalar, or when we are converting a "vector union" to a vector with
/// insert/extractelement instructions.
///
/// Offset is an offset from the original alloca, in bits that need to be
/// shifted to the right. By the end of this, there should be no uses of Ptr.
Value *SROA::ConvertUsesOfLoadToScalar(LoadInst *LI, AllocaInst *NewAI,
uint64_t Offset, IRBuilder<> &Builder) {
// The load is a bit extract from NewAI shifted right by Offset bits.
Value *NV = Builder.CreateLoad(NewAI, "tmp");
/// shifted to the right.
Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType,
uint64_t Offset, IRBuilder<> &Builder) {
// If the load is of the whole new alloca, no conversion is needed.
if (NV->getType() == LI->getType() && Offset == 0)
return NV;
if (FromVal->getType() == ToType && Offset == 0)
return FromVal;
// If the result alloca is a vector type, this is either an element
// access or a bitcast to another vector type of the same size.
if (const VectorType *VTy = dyn_cast<VectorType>(NV->getType())) {
if (isa<VectorType>(LI->getType()))
return Builder.CreateBitCast(NV, LI->getType(), "tmp");
if (const VectorType *VTy = dyn_cast<VectorType>(FromVal->getType())) {
if (isa<VectorType>(ToType))
return Builder.CreateBitCast(FromVal, ToType, "tmp");
// Otherwise it must be an element access.
unsigned Elt = 0;
@ -1414,16 +1416,16 @@ Value *SROA::ConvertUsesOfLoadToScalar(LoadInst *LI, AllocaInst *NewAI,
assert(EltSize*Elt == Offset && "Invalid modulus in validity checking");
}
// Return the element extracted out of it.
Value *V = Builder.CreateExtractElement(NV,
Value *V = Builder.CreateExtractElement(FromVal,
ConstantInt::get(Type::Int32Ty,Elt),
"tmp");
if (V->getType() != LI->getType())
V = Builder.CreateBitCast(V, LI->getType(), "tmp");
if (V->getType() != ToType)
V = Builder.CreateBitCast(V, ToType, "tmp");
return V;
}
// Otherwise, this must be a union that was converted to an integer value.
const IntegerType *NTy = cast<IntegerType>(NV->getType());
const IntegerType *NTy = cast<IntegerType>(FromVal->getType());
// If this is a big-endian system and the load is narrower than the
// full alloca type, we need to do a shift to get the right bits.
@ -1433,7 +1435,7 @@ Value *SROA::ConvertUsesOfLoadToScalar(LoadInst *LI, AllocaInst *NewAI,
// from the pointer given by getTypeStoreSizeInBits. This matters for
// integers with a bitwidth that is not a multiple of 8.
ShAmt = TD->getTypeStoreSizeInBits(NTy) -
TD->getTypeStoreSizeInBits(LI->getType()) - Offset;
TD->getTypeStoreSizeInBits(ToType) - Offset;
} else {
ShAmt = Offset;
}
@ -1442,30 +1444,29 @@ Value *SROA::ConvertUsesOfLoadToScalar(LoadInst *LI, AllocaInst *NewAI,
// We do this to support (f.e.) loads off the end of a structure where
// only some bits are used.
if (ShAmt > 0 && (unsigned)ShAmt < NTy->getBitWidth())
NV = Builder.CreateLShr(NV, ConstantInt::get(NV->getType(), ShAmt), "tmp");
FromVal = Builder.CreateLShr(FromVal, ConstantInt::get(FromVal->getType(), ShAmt), "tmp");
else if (ShAmt < 0 && (unsigned)-ShAmt < NTy->getBitWidth())
NV = Builder.CreateShl(NV, ConstantInt::get(NV->getType(), -ShAmt), "tmp");
FromVal = Builder.CreateShl(FromVal, ConstantInt::get(FromVal->getType(), -ShAmt), "tmp");
// Finally, unconditionally truncate the integer to the right width.
unsigned LIBitWidth = TD->getTypeSizeInBits(LI->getType());
unsigned LIBitWidth = TD->getTypeSizeInBits(ToType);
if (LIBitWidth < NTy->getBitWidth())
NV = Builder.CreateTrunc(NV, IntegerType::get(LIBitWidth), "tmp");
FromVal = Builder.CreateTrunc(FromVal, IntegerType::get(LIBitWidth), "tmp");
else if (LIBitWidth > NTy->getBitWidth())
NV = Builder.CreateZExt(NV, IntegerType::get(LIBitWidth), "tmp");
FromVal = Builder.CreateZExt(FromVal, IntegerType::get(LIBitWidth), "tmp");
// If the result is an integer, this is a trunc or bitcast.
if (isa<IntegerType>(LI->getType())) {
if (isa<IntegerType>(ToType)) {
// Should be done.
} else if (LI->getType()->isFloatingPoint() ||
isa<VectorType>(LI->getType())) {
} else if (ToType->isFloatingPoint() || isa<VectorType>(ToType)) {
// Just do a bitcast, we know the sizes match up.
NV = Builder.CreateBitCast(NV, LI->getType(), "tmp");
FromVal = Builder.CreateBitCast(FromVal, ToType, "tmp");
} else {
// Otherwise must be a pointer.
NV = Builder.CreateIntToPtr(NV, LI->getType(), "tmp");
FromVal = Builder.CreateIntToPtr(FromVal, ToType, "tmp");
}
assert(NV->getType() == LI->getType() && "Didn't convert right?");
return NV;
assert(FromVal->getType() == ToType && "Didn't convert right?");
return FromVal;
}