improve comments.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101429 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-04-16 00:38:19 +00:00
parent 0b09e12bc7
commit a001b66498

View File

@ -148,14 +148,27 @@ FunctionPass *llvm::createScalarReplAggregatesPass(signed int Threshold) {
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
namespace { namespace {
/// ConvertToScalarInfo - This struct is used by CanConvertToScalar /// ConvertToScalarInfo - This class implements the "Convert To Scalar"
/// optimization, which scans the uses of an alloca and determines if it can
/// rewrite it in terms of a single new alloca that can be mem2reg'd.
class ConvertToScalarInfo { class ConvertToScalarInfo {
/// AllocaSize - The size of the alloca being considered. /// AllocaSize - The size of the alloca being considered.
unsigned AllocaSize; unsigned AllocaSize;
const TargetData &TD; const TargetData &TD;
/// IsNotTrivial - This is set to true if there is somee access to the object
/// which means that mem2reg can't promote it.
bool IsNotTrivial; bool IsNotTrivial;
/// VectorTy - This tracks the type that we should promote the vector to if
/// it is possible to turn it into a vector. This starts out null, and if it
/// isn't possible to turn into a vector type, it gets set to VoidTy.
const Type *VectorTy; const Type *VectorTy;
/// HadAVector - True if there is at least one vector access to the alloca.
/// We don't want to turn random arrays into vectors and use vector element
/// insert/extract, but if there are element accesses to something that is
/// also declared as a vector, we do want to promote to a vector.
bool HadAVector; bool HadAVector;
public: public:
@ -166,33 +179,7 @@ public:
HadAVector = false; HadAVector = false;
} }
AllocaInst *TryConvert(AllocaInst *AI) { AllocaInst *TryConvert(AllocaInst *AI);
// If we can't convert this scalar, or if mem2reg can trivially do it, bail
// out.
if (!CanConvertToScalar(AI, 0) || !IsNotTrivial)
// FIXME: In the trivial case, just use mem2reg.
return 0;
// If we were able to find a vector type that can handle this with
// insert/extract elements, and if there was at least one use that had
// a vector type, promote this to a vector. We don't want to promote
// random stuff that doesn't use vectors (e.g. <9 x double>) because then
// we just get a lot of insert/extracts. If at least one vector is
// involved, then we probably really do have a union of vector/array.
const Type *NewTy;
if (VectorTy && VectorTy->isVectorTy() && HadAVector) {
DEBUG(dbgs() << "CONVERT TO VECTOR: " << *AI << "\n TYPE = "
<< *VectorTy << '\n');
NewTy = VectorTy; // Use the vector type.
} else {
DEBUG(dbgs() << "CONVERT TO SCALAR INTEGER: " << *AI << "\n");
// Create and insert the integer alloca.
NewTy = IntegerType::get(AI->getContext(), AllocaSize*8);
}
AllocaInst *NewAI = new AllocaInst(NewTy, 0, "", AI->getParent()->begin());
ConvertUsesToScalar(AI, NewAI, 0);
return NewAI;
}
private: private:
bool CanConvertToScalar(Value *V, uint64_t Offset); bool CanConvertToScalar(Value *V, uint64_t Offset);
@ -206,8 +193,38 @@ private:
}; };
} // end anonymous namespace. } // end anonymous namespace.
/// MergeInType - Add the 'In' type to the accumulated type (Accum) so far at /// TryConvert - Analyze the specified alloca, and if it is safe to do so,
/// the offset specified by Offset (which is specified in bytes). /// rewrite it to be a new alloca which is mem2reg'able. This returns the new
/// alloca if possible or null if not.
AllocaInst *ConvertToScalarInfo::TryConvert(AllocaInst *AI) {
// If we can't convert this scalar, or if mem2reg can trivially do it, bail
// out.
if (!CanConvertToScalar(AI, 0) || !IsNotTrivial)
return 0;
// If we were able to find a vector type that can handle this with
// insert/extract elements, and if there was at least one use that had
// a vector type, promote this to a vector. We don't want to promote
// random stuff that doesn't use vectors (e.g. <9 x double>) because then
// we just get a lot of insert/extracts. If at least one vector is
// involved, then we probably really do have a union of vector/array.
const Type *NewTy;
if (VectorTy && VectorTy->isVectorTy() && HadAVector) {
DEBUG(dbgs() << "CONVERT TO VECTOR: " << *AI << "\n TYPE = "
<< *VectorTy << '\n');
NewTy = VectorTy; // Use the vector type.
} else {
DEBUG(dbgs() << "CONVERT TO SCALAR INTEGER: " << *AI << "\n");
// Create and insert the integer alloca.
NewTy = IntegerType::get(AI->getContext(), AllocaSize*8);
}
AllocaInst *NewAI = new AllocaInst(NewTy, 0, "", AI->getParent()->begin());
ConvertUsesToScalar(AI, NewAI, 0);
return NewAI;
}
/// MergeInType - Add the 'In' type to the accumulated vector type (VectorTy)
/// so far at the offset specified by Offset (which is specified in bytes).
/// ///
/// There are two cases we handle here: /// There are two cases we handle here:
/// 1) A union of vector types of the same size and potentially its elements. /// 1) A union of vector types of the same size and potentially its elements.
@ -216,11 +233,11 @@ private:
/// into a <4 x float> that uses insert element. /// into a <4 x float> that uses insert element.
/// 2) A fully general blob of memory, which we turn into some (potentially /// 2) A fully general blob of memory, which we turn into some (potentially
/// large) integer type with extract and insert operations where the loads /// large) integer type with extract and insert operations where the loads
/// and stores would mutate the memory. /// and stores would mutate the memory. We mark this by setting VectorTy
/// to VoidTy.
void ConvertToScalarInfo::MergeInType(const Type *In, uint64_t Offset) { void ConvertToScalarInfo::MergeInType(const Type *In, uint64_t Offset) {
// Remember if we saw a vector type. // If we already decided to turn this into a blob of integer memory, there is
HadAVector |= In->isVectorTy(); // nothing to be done.
if (VectorTy && VectorTy->isVoidTy()) if (VectorTy && VectorTy->isVoidTy())
return; return;
@ -229,10 +246,15 @@ void ConvertToScalarInfo::MergeInType(const Type *In, uint64_t Offset) {
// If the In type is a vector that is the same size as the alloca, see if it // If the In type is a vector that is the same size as the alloca, see if it
// matches the existing VecTy. // matches the existing VecTy.
if (const VectorType *VInTy = dyn_cast<VectorType>(In)) { if (const VectorType *VInTy = dyn_cast<VectorType>(In)) {
// Remember if we saw a vector type.
HadAVector = true;
if (VInTy->getBitWidth()/8 == AllocaSize && Offset == 0) { if (VInTy->getBitWidth()/8 == AllocaSize && Offset == 0) {
// If we're storing/loading a vector of the right size, allow it as a // If we're storing/loading a vector of the right size, allow it as a
// vector. If this the first vector we see, remember the type so that // vector. If this the first vector we see, remember the type so that
// we know the element size. // we know the element size. If this is a subsequent access, ignore it
// even if it is a differing type but the same size. Worst case we can
// bitcast the resultant vectors.
if (VectorTy == 0) if (VectorTy == 0)
VectorTy = VInTy; VectorTy = VInTy;
return; return;
@ -288,9 +310,9 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
} }
if (BitCastInst *BCI = dyn_cast<BitCastInst>(User)) { if (BitCastInst *BCI = dyn_cast<BitCastInst>(User)) {
IsNotTrivial = true; // Can't be mem2reg'd.
if (!CanConvertToScalar(BCI, Offset)) if (!CanConvertToScalar(BCI, Offset))
return false; return false;
IsNotTrivial = true;
continue; continue;
} }
@ -306,7 +328,7 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
// See if all uses can be converted. // See if all uses can be converted.
if (!CanConvertToScalar(GEP, Offset+GEPOffset)) if (!CanConvertToScalar(GEP, Offset+GEPOffset))
return false; return false;
IsNotTrivial = true; IsNotTrivial = true; // Can't be mem2reg'd.
continue; continue;
} }
@ -314,21 +336,22 @@ bool ConvertToScalarInfo::CanConvertToScalar(Value *V, uint64_t Offset) {
// handle it. // handle it.
if (MemSetInst *MSI = dyn_cast<MemSetInst>(User)) { if (MemSetInst *MSI = dyn_cast<MemSetInst>(User)) {
// Store of constant value and constant size. // Store of constant value and constant size.
if (isa<ConstantInt>(MSI->getValue()) && if (!isa<ConstantInt>(MSI->getValue()) ||
isa<ConstantInt>(MSI->getLength())) { !isa<ConstantInt>(MSI->getLength()))
IsNotTrivial = true; return false;
continue; IsNotTrivial = true; // Can't be mem2reg'd.
} continue;
} }
// If this is a memcpy or memmove into or out of the whole allocation, we // If this is a memcpy or memmove into or out of the whole allocation, we
// can handle it like a load or store of the scalar type. // can handle it like a load or store of the scalar type.
if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(User)) { if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(User)) {
if (ConstantInt *Len = dyn_cast<ConstantInt>(MTI->getLength())) ConstantInt *Len = dyn_cast<ConstantInt>(MTI->getLength());
if (Len->getZExtValue() == AllocaSize && Offset == 0) { if (Len == 0 || Len->getZExtValue() != AllocaSize || Offset != 0)
IsNotTrivial = true; return false;
continue;
} IsNotTrivial = true; // Can't be mem2reg'd.
continue;
} }
// Otherwise, we cannot handle this! // Otherwise, we cannot handle this!