diff options
-rw-r--r-- | include/llvm/Analysis/ScalarEvolutionExpander.h | 4 | ||||
-rw-r--r-- | include/llvm/Analysis/ScalarEvolutionExpressions.h | 105 | ||||
-rw-r--r-- | lib/Analysis/ScalarEvolution.cpp | 179 | ||||
-rw-r--r-- | lib/Analysis/ScalarEvolutionExpander.cpp | 26 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 33 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 4 |
6 files changed, 144 insertions, 207 deletions
diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index 01df503a5e..796b1685a7 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -167,10 +167,6 @@ namespace llvm { Value *visitUMaxExpr(const SCEVUMaxExpr *S); - Value *visitFieldOffsetExpr(const SCEVFieldOffsetExpr *S); - - Value *visitAllocSizeExpr(const SCEVAllocSizeExpr *S); - Value *visitUnknown(const SCEVUnknown *S) { return S->getValue(); } diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 64b8b0bf78..5b93458f11 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -27,7 +27,7 @@ namespace llvm { // folders simpler. scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr, scUDivExpr, scAddRecExpr, scUMaxExpr, scSMaxExpr, - scFieldOffset, scAllocSize, scUnknown, scCouldNotCompute + scUnknown, scCouldNotCompute }; //===--------------------------------------------------------------------===// @@ -512,95 +512,6 @@ namespace llvm { }; //===--------------------------------------------------------------------===// - /// SCEVTargetDataConstant - This node is the base class for representing - /// target-dependent values in a target-independent way. - /// - class SCEVTargetDataConstant : public SCEV { - protected: - const Type *Ty; - SCEVTargetDataConstant(const FoldingSetNodeID &ID, enum SCEVTypes T, - const Type *ty) : - SCEV(ID, T), Ty(ty) {} - - public: - virtual bool isLoopInvariant(const Loop *) const { return true; } - virtual bool hasComputableLoopEvolution(const Loop *) const { - return false; // not computable - } - - virtual bool hasOperand(const SCEV *) const { - return false; - } - - bool dominates(BasicBlock *, DominatorTree *) const { - return true; - } - - bool properlyDominates(BasicBlock *, DominatorTree *) const { - return true; - } - - virtual const Type *getType() const { return Ty; } - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVTargetDataConstant *S) { return true; } - static inline bool classof(const SCEV *S) { - return S->getSCEVType() == scFieldOffset || - S->getSCEVType() == scAllocSize; - } - }; - - //===--------------------------------------------------------------------===// - /// SCEVFieldOffsetExpr - This node represents an offsetof expression. - /// - class SCEVFieldOffsetExpr : public SCEVTargetDataConstant { - friend class ScalarEvolution; - - const StructType *STy; - unsigned FieldNo; - SCEVFieldOffsetExpr(const FoldingSetNodeID &ID, const Type *ty, - const StructType *sty, unsigned fieldno) : - SCEVTargetDataConstant(ID, scFieldOffset, ty), - STy(sty), FieldNo(fieldno) {} - - public: - const StructType *getStructType() const { return STy; } - unsigned getFieldNo() const { return FieldNo; } - - virtual void print(raw_ostream &OS) const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVFieldOffsetExpr *S) { return true; } - static inline bool classof(const SCEV *S) { - return S->getSCEVType() == scFieldOffset; - } - }; - - //===--------------------------------------------------------------------===// - /// SCEVAllocSize - This node represents a sizeof expression. - /// - class SCEVAllocSizeExpr : public SCEVTargetDataConstant { - friend class ScalarEvolution; - - const Type *AllocTy; - SCEVAllocSizeExpr(const FoldingSetNodeID &ID, - const Type *ty, const Type *allocty) : - SCEVTargetDataConstant(ID, scAllocSize, ty), - AllocTy(allocty) {} - - public: - const Type *getAllocType() const { return AllocTy; } - - virtual void print(raw_ostream &OS) const; - - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SCEVAllocSizeExpr *S) { return true; } - static inline bool classof(const SCEV *S) { - return S->getSCEVType() == scAllocSize; - } - }; - - //===--------------------------------------------------------------------===// /// SCEVUnknown - This means that we are dealing with an entirely unknown SCEV /// value, and only represent it as its LLVM Value. This is the "bottom" /// value for the analysis. @@ -615,6 +526,16 @@ namespace llvm { public: Value *getValue() const { return V; } + /// isSizeOf, isAlignOf, isOffsetOf - Test whether this is a special + /// constant representing a type size, alignment, or field offset in + /// a target-independent manner, and hasn't happened to have been + /// folded with other operations into something unrecognizable. This + /// is mainly only useful for pretty-printing and other situations + /// where it isn't absolutely required for these to succeed. + bool isSizeOf(const Type *&AllocTy) const; + bool isAlignOf(const Type *&AllocTy) const; + bool isOffsetOf(const StructType *&STy, Constant *&FieldNo) const; + virtual bool isLoopInvariant(const Loop *L) const; virtual bool hasComputableLoopEvolution(const Loop *QL) const { return false; // not computable @@ -665,10 +586,6 @@ namespace llvm { return ((SC*)this)->visitSMaxExpr((const SCEVSMaxExpr*)S); case scUMaxExpr: return ((SC*)this)->visitUMaxExpr((const SCEVUMaxExpr*)S); - case scFieldOffset: - return ((SC*)this)->visitFieldOffsetExpr((const SCEVFieldOffsetExpr*)S); - case scAllocSize: - return ((SC*)this)->visitAllocSizeExpr((const SCEVAllocSizeExpr*)S); case scUnknown: return ((SC*)this)->visitUnknown((const SCEVUnknown*)S); case scCouldNotCompute: diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index b2395af924..f19e153e0d 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -321,15 +321,6 @@ void SCEVAddRecExpr::print(raw_ostream &OS) const { OS << ">"; } -void SCEVFieldOffsetExpr::print(raw_ostream &OS) const { - // LLVM struct fields don't have names, so just print the field number. - OS << "offsetof(" << *STy << ", " << FieldNo << ")"; -} - -void SCEVAllocSizeExpr::print(raw_ostream &OS) const { - OS << "sizeof(" << *AllocTy << ")"; -} - bool SCEVUnknown::isLoopInvariant(const Loop *L) const { // All non-instruction values are loop invariant. All instructions are loop // invariant if they are not contained in the specified loop. @@ -356,7 +347,90 @@ const Type *SCEVUnknown::getType() const { return V->getType(); } +bool SCEVUnknown::isOffsetOf(const StructType *&STy, Constant *&FieldNo) const { + if (ConstantExpr *VCE = dyn_cast<ConstantExpr>(V)) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr) + if (CE->getOperand(0)->isNullValue()) { + const Type *Ty = + cast<PointerType>(CE->getOperand(0)->getType())->getElementType(); + if (const StructType *StructTy = dyn_cast<StructType>(Ty)) + if (CE->getNumOperands() == 3 && + CE->getOperand(1)->isNullValue()) { + STy = StructTy; + FieldNo = CE->getOperand(2); + return true; + } + } + + return false; +} + +bool SCEVUnknown::isSizeOf(const Type *&AllocTy) const { + if (ConstantExpr *VCE = dyn_cast<ConstantExpr>(V)) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr) + if (CE->getOperand(0)->isNullValue()) { + const Type *Ty = + cast<PointerType>(CE->getOperand(0)->getType())->getElementType(); + if (CE->getNumOperands() == 2) + if (ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(1))) + if (CI->isOne()) { + AllocTy = Ty; + return true; + } + } + + return false; +} + +bool SCEVUnknown::isAlignOf(const Type *&AllocTy) const { + if (ConstantExpr *VCE = dyn_cast<ConstantExpr>(V)) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr) + if (CE->getOperand(0)->isNullValue()) { + const Type *Ty = + cast<PointerType>(CE->getOperand(0)->getType())->getElementType(); + if (const StructType *STy = dyn_cast<StructType>(Ty)) + if (CE->getNumOperands() == 3 && + CE->getOperand(1)->isNullValue()) { + if (ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(2))) + if (CI->isOne() && + STy->getNumElements() == 2 && + STy->getElementType(0)->isInteger(1)) { + AllocTy = STy->getElementType(1); + return true; + } + } + } + + return false; +} + void SCEVUnknown::print(raw_ostream &OS) const { + const Type *AllocTy; + if (isSizeOf(AllocTy)) { + OS << "sizeof(" << *AllocTy << ")"; + return; + } + if (isAlignOf(AllocTy)) { + OS << "alignof(" << *AllocTy << ")"; + return; + } + + const StructType *STy; + Constant *FieldNo; + if (isOffsetOf(STy, FieldNo)) { + OS << "offsetof(" << *STy << ", "; + WriteAsOperand(OS, FieldNo, false); + OS << ")"; + return; + } + + // Otherwise just print it normally. WriteAsOperand(OS, V, false); } @@ -515,21 +589,6 @@ namespace { return operator()(LC->getOperand(), RC->getOperand()); } - // Compare offsetof expressions. - if (const SCEVFieldOffsetExpr *LA = dyn_cast<SCEVFieldOffsetExpr>(LHS)) { - const SCEVFieldOffsetExpr *RA = cast<SCEVFieldOffsetExpr>(RHS); - if (CompareTypes(LA->getStructType(), RA->getStructType()) || - CompareTypes(RA->getStructType(), LA->getStructType())) - return CompareTypes(LA->getStructType(), RA->getStructType()); - return LA->getFieldNo() < RA->getFieldNo(); - } - - // Compare sizeof expressions by the allocation type. - if (const SCEVAllocSizeExpr *LA = dyn_cast<SCEVAllocSizeExpr>(LHS)) { - const SCEVAllocSizeExpr *RA = cast<SCEVAllocSizeExpr>(RHS); - return CompareTypes(LA->getAllocType(), RA->getAllocType()); - } - llvm_unreachable("Unknown SCEV kind!"); return false; } @@ -2174,72 +2233,19 @@ const SCEV *ScalarEvolution::getUMinExpr(const SCEV *LHS, const SCEV *ScalarEvolution::getFieldOffsetExpr(const StructType *STy, unsigned FieldNo) { - // If we have TargetData we can determine the constant offset. - if (TD) { - const Type *IntPtrTy = TD->getIntPtrType(getContext()); - const StructLayout &SL = *TD->getStructLayout(STy); - uint64_t Offset = SL.getElementOffset(FieldNo); - return getIntegerSCEV(Offset, IntPtrTy); - } - - // Field 0 is always at offset 0. - if (FieldNo == 0) { - const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(STy)); - return getIntegerSCEV(0, Ty); - } - - // Okay, it looks like we really DO need an offsetof expr. Check to see if we - // already have one, otherwise create a new one. - FoldingSetNodeID ID; - ID.AddInteger(scFieldOffset); - ID.AddPointer(STy); - ID.AddInteger(FieldNo); - void *IP = 0; - if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; - SCEV *S = SCEVAllocator.Allocate<SCEVFieldOffsetExpr>(); + Constant *C = ConstantExpr::getOffsetOf(STy, FieldNo); + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) + C = ConstantFoldConstantExpression(CE, TD); const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(STy)); - new (S) SCEVFieldOffsetExpr(ID, Ty, STy, FieldNo); - UniqueSCEVs.InsertNode(S, IP); - return S; + return getTruncateOrZeroExtend(getSCEV(C), Ty); } const SCEV *ScalarEvolution::getAllocSizeExpr(const Type *AllocTy) { - // If we have TargetData we can determine the constant size. - if (TD && AllocTy->isSized()) { - const Type *IntPtrTy = TD->getIntPtrType(getContext()); - return getIntegerSCEV(TD->getTypeAllocSize(AllocTy), IntPtrTy); - } - - // Expand an array size into the element size times the number - // of elements. - if (const ArrayType *ATy = dyn_cast<ArrayType>(AllocTy)) { - const SCEV *E = getAllocSizeExpr(ATy->getElementType()); - return getMulExpr( - E, getConstant(ConstantInt::get(cast<IntegerType>(E->getType()), - ATy->getNumElements()))); - } - - // Expand a vector size into the element size times the number - // of elements. - if (const VectorType *VTy = dyn_cast<VectorType>(AllocTy)) { - const SCEV *E = getAllocSizeExpr(VTy->getElementType()); - return getMulExpr( - E, getConstant(ConstantInt::get(cast<IntegerType>(E->getType()), - VTy->getNumElements()))); - } - - // Okay, it looks like we really DO need a sizeof expr. Check to see if we - // already have one, otherwise create a new one. - FoldingSetNodeID ID; - ID.AddInteger(scAllocSize); - ID.AddPointer(AllocTy); - void *IP = 0; - if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; - SCEV *S = SCEVAllocator.Allocate<SCEVAllocSizeExpr>(); + Constant *C = ConstantExpr::getSizeOf(AllocTy); + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) + C = ConstantFoldConstantExpression(CE, TD); const Type *Ty = getEffectiveSCEVType(PointerType::getUnqual(AllocTy)); - new (S) SCEVAllocSizeExpr(ID, Ty, AllocTy); - UniqueSCEVs.InsertNode(S, IP); - return S; + return getTruncateOrZeroExtend(getSCEV(C), Ty); } const SCEV *ScalarEvolution::getUnknown(Value *V) { @@ -4242,9 +4248,6 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { return getTruncateExpr(Op, Cast->getType()); } - if (isa<SCEVTargetDataConstant>(V)) - return V; - llvm_unreachable("Unknown SCEV type!"); return 0; } diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index a72f58f64f..9e2e712cdd 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -427,22 +427,22 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, } } } else { - // Without TargetData, just check for a SCEVFieldOffsetExpr of the + // Without TargetData, just check for an offsetof expression of the // appropriate struct type. for (unsigned i = 0, e = Ops.size(); i != e; ++i) - if (const SCEVFieldOffsetExpr *FO = - dyn_cast<SCEVFieldOffsetExpr>(Ops[i])) - if (FO->getStructType() == STy) { - unsigned FieldNo = FO->getFieldNo(); - GepIndices.push_back( - ConstantInt::get(Type::getInt32Ty(Ty->getContext()), - FieldNo)); - ElTy = STy->getTypeAtIndex(FieldNo); + if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(Ops[i])) { + const StructType *StructTy; + Constant *FieldNo; + if (U->isOffsetOf(StructTy, FieldNo) && StructTy == STy) { + GepIndices.push_back(FieldNo); + ElTy = + STy->getTypeAtIndex(cast<ConstantInt>(FieldNo)->getZExtValue()); Ops[i] = SE.getConstant(Ty, 0); AnyNonZeroIndices = true; FoundFieldNo = true; break; } + } } // If no struct field offsets were found, tentatively assume that // field zero was selected (since the zero offset would obviously @@ -1001,14 +1001,6 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) { return LHS; } -Value *SCEVExpander::visitFieldOffsetExpr(const SCEVFieldOffsetExpr *S) { - return ConstantExpr::getOffsetOf(S->getStructType(), S->getFieldNo()); -} - -Value *SCEVExpander::visitAllocSizeExpr(const SCEVAllocSizeExpr *S) { - return ConstantExpr::getSizeOf(S->getAllocType()); -} - Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty) { // Expand the code for this SCEV. Value *V = expand(SH); diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index ddd55878cb..24b78ae969 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -415,9 +415,38 @@ Constant *llvm::ConstantFoldCastInstruction(LLVMContext &Context, return ConstantPointerNull::get(cast<PointerType>(DestTy)); return 0; // Other pointer types cannot be casted case Instruction::PtrToInt: // always treated as unsigned - if (V->isNullValue()) // is it a null pointer value? + // Is it a null pointer value? + if (V->isNullValue()) return ConstantInt::get(DestTy, 0); - return 0; // Other pointer types cannot be casted + // If this is a sizeof of an array or vector, pull out a multiplication + // by the element size to expose it to subsequent folding. + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + if (CE->getOpcode() == Instruction::GetElementPtr && + CE->getNumOperands() == 2 && + CE->getOperand(0)->isNullValue()) + if (ConstantInt *CI = dyn_cast<ConstantInt>(CE->getOperand(1))) + if (CI->isOne()) { + const Type *Ty = + cast<PointerType>(CE->getOperand(0)->getType())->getElementType(); + if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) { + Constant *N = ConstantInt::get(DestTy, ATy->getNumElements()); + Constant *E = ConstantExpr::getSizeOf(ATy->getElementType()); + E = ConstantExpr::getCast(CastInst::getCastOpcode(E, false, + DestTy, false), + E, DestTy); + return ConstantExpr::getMul(N, E); + } + if (const VectorType *VTy = dyn_cast<VectorType>(Ty)) { + Constant *N = ConstantInt::get(DestTy, VTy->getNumElements()); + Constant *E = ConstantExpr::getSizeOf(VTy->getElementType()); + E = ConstantExpr::getCast(CastInst::getCastOpcode(E, false, + DestTy, false), + E, DestTy); + return ConstantExpr::getMul(N, E); + } + } + // Other pointer types cannot be casted + return 0; case Instruction::UIToFP: case Instruction::SIToFP: if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) { diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 436083f62b..9e1154e95e 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1479,10 +1479,10 @@ Constant* ConstantExpr::getSizeOf(const Type* Ty) { } Constant* ConstantExpr::getAlignOf(const Type* Ty) { - // alignof is implemented as: (i64) gep ({i8,Ty}*)null, 0, 1 + // alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1 // Note that a non-inbounds gep is used, as null isn't within any object. const Type *AligningTy = StructType::get(Ty->getContext(), - Type::getInt8Ty(Ty->getContext()), Ty, NULL); + Type::getInt1Ty(Ty->getContext()), Ty, NULL); Constant *NullPtr = Constant::getNullValue(AligningTy->getPointerTo()); Constant *Zero = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 0); Constant *One = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1); |