diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 2e869e6e45de..1709ee69360a 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -2069,7 +2069,8 @@ static Constant *getVal(DenseMap &ComputedValues, Value *V) { static inline bool isSimpleEnoughValueToCommit(Constant *C, - SmallPtrSet &SimpleConstants); + SmallPtrSet &SimpleConstants, + const TargetData *TD); /// isSimpleEnoughValueToCommit - Return true if the specified constant can be @@ -2081,7 +2082,8 @@ isSimpleEnoughValueToCommit(Constant *C, /// in SimpleConstants to avoid having to rescan the same constants all the /// time. static bool isSimpleEnoughValueToCommitHelper(Constant *C, - SmallPtrSet &SimpleConstants) { + SmallPtrSet &SimpleConstants, + const TargetData *TD) { // Simple integer, undef, constant aggregate zero, global addresses, etc are // all supported. if (C->getNumOperands() == 0 || isa(C) || @@ -2093,7 +2095,7 @@ static bool isSimpleEnoughValueToCommitHelper(Constant *C, isa(C)) { for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { Constant *Op = cast(C->getOperand(i)); - if (!isSimpleEnoughValueToCommit(Op, SimpleConstants)) + if (!isSimpleEnoughValueToCommit(Op, SimpleConstants, TD)) return false; } return true; @@ -2105,34 +2107,42 @@ static bool isSimpleEnoughValueToCommitHelper(Constant *C, ConstantExpr *CE = cast(C); switch (CE->getOpcode()) { case Instruction::BitCast: + // Bitcast is fine if the casted value is fine. + return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, TD); + case Instruction::IntToPtr: case Instruction::PtrToInt: - // These casts are always fine if the casted value is. - return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants); + // int <=> ptr is fine if the int type is the same size as the + // pointer type. + if (!TD || TD->getTypeSizeInBits(CE->getType()) != + TD->getTypeSizeInBits(CE->getOperand(0)->getType())) + return false; + return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, TD); // GEP is fine if it is simple + constant offset. case Instruction::GetElementPtr: for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i) if (!isa(CE->getOperand(i))) return false; - return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants); + return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, TD); case Instruction::Add: // We allow simple+cst. if (!isa(CE->getOperand(1))) return false; - return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants); + return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, TD); } return false; } static inline bool isSimpleEnoughValueToCommit(Constant *C, - SmallPtrSet &SimpleConstants) { + SmallPtrSet &SimpleConstants, + const TargetData *TD) { // If we already checked this constant, we win. if (!SimpleConstants.insert(C)) return true; // Check the constant. - return isSimpleEnoughValueToCommitHelper(C, SimpleConstants); + return isSimpleEnoughValueToCommitHelper(C, SimpleConstants, TD); } @@ -2353,7 +2363,7 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal, // If this might be too difficult for the backend to handle (e.g. the addr // of one global variable divided by another) then we can't commit it. - if (!isSimpleEnoughValueToCommit(Val, SimpleConstants)) + if (!isSimpleEnoughValueToCommit(Val, SimpleConstants, TD)) return false; if (ConstantExpr *CE = dyn_cast(Ptr)) diff --git a/llvm/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll b/llvm/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll index 204f979ed3e1..e3bc473f52ad 100644 --- a/llvm/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll +++ b/llvm/test/Transforms/GlobalOpt/ctor-list-opt-constexpr.ll @@ -4,20 +4,31 @@ target triple = "x86_64-apple-darwin10.0.0" %0 = type { i32, void ()* } %struct.foo = type { i32* } +%struct.bar = type { i128 } @G = global i32 0, align 4 @H = global i32 0, align 4 @X = global %struct.foo zeroinitializer, align 8 -@llvm.global_ctors = appending global [1 x %0] [%0 { i32 65535, void ()* @init }] +@X2 = global %struct.bar zeroinitializer, align 8 +@llvm.global_ctors = appending global [2 x %0] [%0 { i32 65535, void ()* @init1 }, %0 { i32 65535, void ()* @init2 }] ; PR8710 - GlobalOpt shouldn't change the global's initializer to have this ; arbitrary constant expression, the code generator can't handle it. -define internal void @init() { +define internal void @init1() { entry: %tmp = getelementptr inbounds %struct.foo* @X, i32 0, i32 0 store i32* inttoptr (i64 sdiv (i64 ptrtoint (i32* @G to i64), i64 ptrtoint (i32* @H to i64)) to i32*), i32** %tmp, align 8 ret void } - -; CHECK: @init +; CHECK: @init1 ; CHECK: store i32* + +; PR11705 - ptrtoint isn't safe in general in global initializers. +define internal void @init2() { +entry: + %tmp = getelementptr inbounds %struct.bar* @X2, i32 0, i32 0 + store i128 ptrtoint (i32* @G to i128), i128* %tmp, align 16 + ret void +} +; CHECK: @init2 +; CHECK: store i128