From cf9138307dba746470ece630e3eeb340af5f3432 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 28 Jan 2010 02:15:55 +0000 Subject: Remove SCEVAllocSizeExpr and SCEVFieldOffsetExpr, and in their place use plain SCEVUnknowns with ConstantExpr::getSizeOf and ConstantExpr::getOffsetOf constants. This eliminates a bunch of special-case code. Also add code for pattern-matching these expressions, for clients that want to recognize them. Move ScalarEvolution's logic for expanding array and vector sizeof expressions into an element count times the element size, to expose the multiplication to subsequent folding, into the regular constant folder. llvm-svn: 94737 --- llvm/lib/Analysis/ScalarEvolution.cpp | 179 +++++++++++++++++----------------- 1 file changed, 91 insertions(+), 88 deletions(-) (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp') diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index b2395af9243..f19e153e0d4 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/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(V)) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr) + if (CE->getOperand(0)->isNullValue()) { + const Type *Ty = + cast(CE->getOperand(0)->getType())->getElementType(); + if (const StructType *StructTy = dyn_cast(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(V)) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr) + if (CE->getOperand(0)->isNullValue()) { + const Type *Ty = + cast(CE->getOperand(0)->getType())->getElementType(); + if (CE->getNumOperands() == 2) + if (ConstantInt *CI = dyn_cast(CE->getOperand(1))) + if (CI->isOne()) { + AllocTy = Ty; + return true; + } + } + + return false; +} + +bool SCEVUnknown::isAlignOf(const Type *&AllocTy) const { + if (ConstantExpr *VCE = dyn_cast(V)) + if (VCE->getOpcode() == Instruction::PtrToInt) + if (ConstantExpr *CE = dyn_cast(VCE->getOperand(0))) + if (CE->getOpcode() == Instruction::GetElementPtr) + if (CE->getOperand(0)->isNullValue()) { + const Type *Ty = + cast(CE->getOperand(0)->getType())->getElementType(); + if (const StructType *STy = dyn_cast(Ty)) + if (CE->getNumOperands() == 3 && + CE->getOperand(1)->isNullValue()) { + if (ConstantInt *CI = dyn_cast(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(LHS)) { - const SCEVFieldOffsetExpr *RA = cast(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(LHS)) { - const SCEVAllocSizeExpr *RA = cast(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(); + Constant *C = ConstantExpr::getOffsetOf(STy, FieldNo); + if (ConstantExpr *CE = dyn_cast(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(AllocTy)) { - const SCEV *E = getAllocSizeExpr(ATy->getElementType()); - return getMulExpr( - E, getConstant(ConstantInt::get(cast(E->getType()), - ATy->getNumElements()))); - } - - // Expand a vector size into the element size times the number - // of elements. - if (const VectorType *VTy = dyn_cast(AllocTy)) { - const SCEV *E = getAllocSizeExpr(VTy->getElementType()); - return getMulExpr( - E, getConstant(ConstantInt::get(cast(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(); + Constant *C = ConstantExpr::getSizeOf(AllocTy); + if (ConstantExpr *CE = dyn_cast(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(V)) - return V; - llvm_unreachable("Unknown SCEV type!"); return 0; } -- cgit v1.2.3