diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 1003269e289..80d598dffe9 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -72,16 +72,7 @@ namespace llvm { Instruction *InsertBefore = 0) { const unsigned Idxs[1] = { Idx }; return FindInsertedValue(V, &Idxs[0], &Idxs[1], InsertBefore); - } - - /// GetConstantStringInfo - This function computes the length of a - /// null-terminated C string pointed to by V. If successful, it returns true - /// and returns the string in Str. If unsuccessful, it returns false. If - /// StopAtNul is set to true (the default), the returned string is truncated - /// by a nul character in the global. If StopAtNul is false, the nul - /// character is included in the result string. - bool GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset = 0, - bool StopAtNul = true); + } } // end namespace llvm #endif diff --git a/include/llvm/Constant.h b/include/llvm/Constant.h index c45ec2e77ed..d85771a09a4 100644 --- a/include/llvm/Constant.h +++ b/include/llvm/Constant.h @@ -115,6 +115,13 @@ public: "implemented for all constants that have operands!"); assert(0 && "Constants that do not have operands cannot be using 'From'!"); } + + /// getStringValue - Turn an LLVM constant pointer that eventually points to a + /// global into a string value. Return an empty string if we can't do it. + /// Parameter Chop determines if the result is chopped at the first null + /// terminator. + /// + std::string getStringValue(bool Chop = true, unsigned Offset = 0); }; } // End llvm namespace diff --git a/include/llvm/IntrinsicInst.h b/include/llvm/IntrinsicInst.h index 16a43d41972..c674e47b3a0 100644 --- a/include/llvm/IntrinsicInst.h +++ b/include/llvm/IntrinsicInst.h @@ -96,8 +96,8 @@ namespace llvm { return unsigned(cast(getOperand(2))->getZExtValue()); } - Value* getFileName() const; - Value* getDirectory() const; + std::string getFileName() const; + std::string getDirectory() const; // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const DbgStopPointInst *) { return true; } diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index e7e291fb928..32a77e6f461 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -15,7 +15,6 @@ #include "llvm/Analysis/ValueTracking.h" #include "llvm/Constants.h" #include "llvm/Instructions.h" -#include "llvm/GlobalVariable.h" #include "llvm/IntrinsicInst.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/GetElementPtrTypeIterator.h" @@ -931,102 +930,3 @@ Value *llvm::FindInsertedValue(Value *V, const unsigned *idx_begin, // or load instruction) return 0; } - -/// GetConstantStringInfo - This function computes the length of a -/// null-terminated C string pointed to by V. If successful, it returns true -/// and returns the string in Str. If unsuccessful, it returns false. -bool llvm::GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset, - bool StopAtNul) { - // If V is NULL then return false; - if (V == NULL) return false; - - // Look through bitcast instructions. - if (BitCastInst *BCI = dyn_cast(V)) - return GetConstantStringInfo(BCI->getOperand(0), Str, Offset, StopAtNul); - - // If the value is not a GEP instruction nor a constant expression with a - // GEP instruction, then return false because ConstantArray can't occur - // any other way - User *GEP = 0; - if (GetElementPtrInst *GEPI = dyn_cast(V)) { - GEP = GEPI; - } else if (ConstantExpr *CE = dyn_cast(V)) { - if (CE->getOpcode() == Instruction::BitCast) - return GetConstantStringInfo(CE->getOperand(0), Str, Offset, StopAtNul); - if (CE->getOpcode() != Instruction::GetElementPtr) - return false; - GEP = CE; - } - - if (GEP) { - // Make sure the GEP has exactly three arguments. - if (GEP->getNumOperands() != 3) - return false; - - // Make sure the index-ee is a pointer to array of i8. - const PointerType *PT = cast(GEP->getOperand(0)->getType()); - const ArrayType *AT = dyn_cast(PT->getElementType()); - if (AT == 0 || AT->getElementType() != Type::Int8Ty) - return false; - - // Check to make sure that the first operand of the GEP is an integer and - // has value 0 so that we are sure we're indexing into the initializer. - ConstantInt *FirstIdx = dyn_cast(GEP->getOperand(1)); - if (FirstIdx == 0 || !FirstIdx->isZero()) - return false; - - // If the second index isn't a ConstantInt, then this is a variable index - // into the array. If this occurs, we can't say anything meaningful about - // the string. - uint64_t StartIdx = 0; - if (ConstantInt *CI = dyn_cast(GEP->getOperand(2))) - StartIdx = CI->getZExtValue(); - else - return false; - return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset, - StopAtNul); - } - - // The GEP instruction, constant or instruction, must reference a global - // variable that is a constant and is initialized. The referenced constant - // initializer is the array that we'll use for optimization. - GlobalVariable* GV = dyn_cast(V); - if (!GV || !GV->isConstant() || !GV->hasInitializer()) - return false; - Constant *GlobalInit = GV->getInitializer(); - - // Handle the ConstantAggregateZero case - if (isa(GlobalInit)) { - // This is a degenerate case. The initializer is constant zero so the - // length of the string must be zero. - Str.clear(); - return true; - } - - // Must be a Constant Array - ConstantArray *Array = dyn_cast(GlobalInit); - if (Array == 0 || Array->getType()->getElementType() != Type::Int8Ty) - return false; - - // Get the number of elements in the array - uint64_t NumElts = Array->getType()->getNumElements(); - - if (Offset > NumElts) - return false; - - // Traverse the constant array from 'Offset' which is the place the GEP refers - // to in the array. - Str.reserve(NumElts-Offset); - for (unsigned i = Offset; i != NumElts; ++i) { - Constant *Elt = Array->getOperand(i); - ConstantInt *CI = dyn_cast(Elt); - if (!CI) // This array isn't suitable, non-int initializer. - return false; - if (StopAtNul && CI->isZero()) - return true; // we found end of string, success! - Str += (char)CI->getZExtValue(); - } - - // The array isn't null terminated, but maybe this is a memcpy, not a strcpy. - return true; -} diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index 52737a60454..123ad6d6921 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -10,7 +10,6 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/Constants.h" -#include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineLocation.h" @@ -207,9 +206,7 @@ public: } virtual void Apply(std::string &Field) { Constant *C = CI->getOperand(I++); - // Fills in the string if it succeeds - if (!GetConstantStringInfo(C, Field)) - Field.clear(); + Field = C->getStringValue(); } virtual void Apply(DebugInfoDesc *&Field) { Constant *C = CI->getOperand(I++); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 002821d0a6d..f1c2ecf19d3 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/Constants.h" -#include "llvm/Analysis/ValueTracking.h" #include "llvm/GlobalAlias.h" #include "llvm/GlobalVariable.h" #include "llvm/Intrinsics.h" @@ -2578,7 +2577,8 @@ static SDOperand getMemBasePlusOffset(SDOperand Base, unsigned Offset, /// isMemSrcFromString - Returns true if memcpy source is a string constant. /// -static bool isMemSrcFromString(SDOperand Src, std::string &Str) { +static bool isMemSrcFromString(SDOperand Src, std::string &Str, + uint64_t &SrcOff) { unsigned SrcDelta = 0; GlobalAddressSDNode *G = NULL; if (Src.getOpcode() == ISD::GlobalAddress) @@ -2593,8 +2593,13 @@ static bool isMemSrcFromString(SDOperand Src, std::string &Str) { return false; GlobalVariable *GV = dyn_cast(G->getGlobal()); - if (GV && GetConstantStringInfo(GV, Str, SrcDelta, false)) - return true; + if (GV && GV->isConstant()) { + Str = GV->getStringValue(false); + if (!Str.empty()) { + SrcOff += SrcDelta; + return true; + } + } return false; } @@ -2611,7 +2616,8 @@ bool MeetsMaxMemopRequirement(std::vector &MemOps, bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses(); std::string Str; - bool isSrcStr = isMemSrcFromString(Src, Str); + uint64_t SrcOff = 0; + bool isSrcStr = isMemSrcFromString(Src, Str, SrcOff); bool isSrcConst = isa(Src); MVT VT= TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr); if (VT != MVT::iAny) { @@ -2706,11 +2712,11 @@ static SDOperand getMemcpyLoadsAndStores(SelectionDAG &DAG, return SDOperand(); std::string Str; - bool CopyFromStr = isMemSrcFromString(Src, Str); + uint64_t SrcOff = 0, DstOff = 0; + bool CopyFromStr = isMemSrcFromString(Src, Str, SrcOff); SmallVector OutChains; unsigned NumMemOps = MemOps.size(); - uint64_t SrcOff = 0, DstOff = 0; for (unsigned i = 0; i < NumMemOps; i++) { MVT VT = MemOps[i]; unsigned VTSize = VT.getSizeInBits() / 8; diff --git a/lib/Debugger/ProgramInfo.cpp b/lib/Debugger/ProgramInfo.cpp index 408704dad16..e4380ea4278 100644 --- a/lib/Debugger/ProgramInfo.cpp +++ b/lib/Debugger/ProgramInfo.cpp @@ -14,7 +14,6 @@ #include "llvm/Debugger/ProgramInfo.h" #include "llvm/Constants.h" -#include "llvm/Analysis/ValueTracking.h" #include "llvm/DerivedTypes.h" #include "llvm/Intrinsics.h" #include "llvm/IntrinsicInst.h" @@ -116,10 +115,8 @@ SourceFileInfo::SourceFileInfo(const GlobalVariable *Desc, if (ConstantInt *CUI = dyn_cast(CS->getOperand(1))) Version = CUI->getZExtValue(); - if (!GetConstantStringInfo(CS->getOperand(3), BaseName)) - BaseName = ""; - if (!GetConstantStringInfo(CS->getOperand(4), Directory)) - Directory = ""; + BaseName = CS->getOperand(3)->getStringValue(); + Directory = CS->getOperand(4)->getStringValue(); } } @@ -159,8 +156,7 @@ SourceFunctionInfo::SourceFunctionInfo(ProgramInfo &PI, SourceFile = &PI.getSourceFile(GV); // Entry #2 is the function name. - if (!GetConstantStringInfo(CS->getOperand(2), Name)) - Name = ""; + Name = CS->getOperand(2)->getStringValue(); } } diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 5d75489d14f..d45eb99d939 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -9973,8 +9973,8 @@ static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI, if (ConstantExpr *CE = dyn_cast(CI)) { // Instead of loading constant c string, use corresponding integer value // directly if string length is small enough. - std::string Str; - if (GetConstantStringInfo(CE->getOperand(0), Str) && !Str.empty()) { + const std::string &Str = CE->getOperand(0)->getStringValue(); + if (!Str.empty()) { unsigned len = Str.length(); const Type *Ty = cast(CE->getType())->getElementType(); unsigned numBits = Ty->getPrimitiveSizeInBits(); diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 6bc6ad407f8..79ec3d941fb 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -23,7 +23,6 @@ #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Support/IRBuilder.h" -#include "llvm/Analysis/ValueTracking.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" @@ -230,6 +229,88 @@ void LibCallOptimization::EmitFWrite(Value *Ptr, Value *Size, Value *File, // Helper Functions //===----------------------------------------------------------------------===// +/// GetConstantStringInfo - This function computes the length of a +/// null-terminated C string pointed to by V. If successful, it returns true +/// and returns the string in Str. If unsuccessful, it returns false. +static bool GetConstantStringInfo(Value *V, std::string &Str) { + // Look bitcast instructions. + if (BitCastInst *BCI = dyn_cast(V)) + return GetConstantStringInfo(BCI->getOperand(0), Str); + + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return false because ConstantArray can't occur + // any other way + User *GEP = 0; + if (GetElementPtrInst *GEPI = dyn_cast(V)) { + GEP = GEPI; + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() != Instruction::GetElementPtr) + return false; + GEP = CE; + } else { + return false; + } + + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return false; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + if (ConstantInt *Idx = dyn_cast(GEP->getOperand(1))) { + if (!Idx->isZero()) + return false; + } else + return false; + + // If the second index isn't a ConstantInt, then this is a variable index + // into the array. If this occurs, we can't say anything meaningful about + // the string. + uint64_t StartIdx = 0; + if (ConstantInt *CI = dyn_cast(GEP->getOperand(2))) + StartIdx = CI->getZExtValue(); + else + return false; + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasInitializer()) + return false; + Constant *GlobalInit = GV->getInitializer(); + + // Handle the ConstantAggregateZero case + if (isa(GlobalInit)) { + // This is a degenerate case. The initializer is constant zero so the + // length of the string must be zero. + Str.clear(); + return true; + } + + // Must be a Constant Array + ConstantArray *Array = dyn_cast(GlobalInit); + if (Array == 0 || Array->getType()->getElementType() != Type::Int8Ty) + return false; + + // Get the number of elements in the array + uint64_t NumElts = Array->getType()->getNumElements(); + + // Traverse the constant array from StartIdx (derived above) which is + // the place the GEP refers to in the array. + for (unsigned i = StartIdx; i < NumElts; ++i) { + Constant *Elt = Array->getOperand(i); + ConstantInt *CI = dyn_cast(Elt); + if (!CI) // This array isn't suitable, non-int initializer. + return false; + if (CI->isZero()) + return true; // we found end of string, success! + Str += (char)CI->getZExtValue(); + } + + return false; // The array isn't null terminated. +} + /// GetStringLengthH - If we can compute the length of the string pointed to by /// the specified pointer, return 'len+1'. If we can't, return 0. static uint64_t GetStringLengthH(Value *V, SmallPtrSet &PHIs) { diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 7a08b5fb8f2..b9976a72070 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -2658,4 +2658,44 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, // Delete the old constant! destroyConstant(); -} \ No newline at end of file +} + + +/// getStringValue - Turn an LLVM constant pointer that eventually points to a +/// global into a string value. Return an empty string if we can't do it. +/// Parameter Chop determines if the result is chopped at the first null +/// terminator. +/// +std::string Constant::getStringValue(bool Chop, unsigned Offset) { + if (GlobalVariable *GV = dyn_cast(this)) { + if (GV->hasInitializer() && isa(GV->getInitializer())) { + ConstantArray *Init = cast(GV->getInitializer()); + if (Init->isString()) { + std::string Result = Init->getAsString(); + if (Offset < Result.size()) { + // If we are pointing INTO The string, erase the beginning... + Result.erase(Result.begin(), Result.begin()+Offset); + + // Take off the null terminator, and any string fragments after it. + if (Chop) { + std::string::size_type NullPos = Result.find_first_of((char)0); + if (NullPos != std::string::npos) + Result.erase(Result.begin()+NullPos, Result.end()); + } + return Result; + } + } + } + } else if (ConstantExpr *CE = dyn_cast(this)) { + if (CE->getOpcode() == Instruction::GetElementPtr) { + // Turn a gep into the specified offset. + if (CE->getNumOperands() == 3 && + cast(CE->getOperand(1))->isNullValue() && + isa(CE->getOperand(2))) { + Offset += cast(CE->getOperand(2))->getZExtValue(); + return CE->getOperand(0)->getStringValue(Chop, Offset); + } + } + } + return ""; +} diff --git a/lib/VMCore/IntrinsicInst.cpp b/lib/VMCore/IntrinsicInst.cpp index 6bd9431767e..eca606292dc 100644 --- a/lib/VMCore/IntrinsicInst.cpp +++ b/lib/VMCore/IntrinsicInst.cpp @@ -28,7 +28,6 @@ #include "llvm/IntrinsicInst.h" #include "llvm/Constants.h" #include "llvm/GlobalVariable.h" -#include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/MachineDebugInfoDesc.h" #include "llvm/CodeGen/MachineModuleInfo.h" using namespace llvm; @@ -59,20 +58,20 @@ Value *DbgInfoIntrinsic::StripCast(Value *C) { /// DbgStopPointInst - This represents the llvm.dbg.stoppoint instruction. /// -Value *DbgStopPointInst::getFileName() const { +std::string DbgStopPointInst::getFileName() const { // Once the operand indices are verified, update this assert assert(LLVMDebugVersion == (6 << 16) && "Verify operand indices"); GlobalVariable *GV = cast(getContext()); - if (!GV->hasInitializer()) return NULL; + if (!GV->hasInitializer()) return ""; ConstantStruct *CS = cast(GV->getInitializer()); - return CS->getOperand(4); + return CS->getOperand(3)->getStringValue(); } -Value *DbgStopPointInst::getDirectory() const { +std::string DbgStopPointInst::getDirectory() const { // Once the operand indices are verified, update this assert assert(LLVMDebugVersion == (6 << 16) && "Verify operand indices"); GlobalVariable *GV = cast(getContext()); - if (!GV->hasInitializer()) return NULL; + if (!GV->hasInitializer()) return ""; ConstantStruct *CS = cast(GV->getInitializer()); - return CS->getOperand(4); + return CS->getOperand(4)->getStringValue(); }