Index: llvm/trunk/include/llvm/Analysis/ConstantFolding.h =================================================================== --- llvm/trunk/include/llvm/Analysis/ConstantFolding.h +++ llvm/trunk/include/llvm/Analysis/ConstantFolding.h @@ -147,6 +147,12 @@ ArrayRef Operands, const TargetLibraryInfo *TLI = nullptr); +/// ConstantFoldLoadThroughBitcast - try to cast constant to destination type +/// returning null if unsuccessful. Can cast pointer to pointer or pointer to +/// integer and vice versa if their sizes are equal. +Constant *ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, + const DataLayout &DL); + /// \brief Check whether the given call has no side-effects. /// Specifically checks for math routimes which sometimes set errno. bool isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI); Index: llvm/trunk/lib/Analysis/ConstantFolding.cpp =================================================================== --- llvm/trunk/lib/Analysis/ConstantFolding.cpp +++ llvm/trunk/lib/Analysis/ConstantFolding.cpp @@ -320,6 +320,41 @@ return true; } +Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, + const DataLayout &DL) { + do { + Type *SrcTy = C->getType(); + + // If the type sizes are the same and a cast is legal, just directly + // cast the constant. + if (DL.getTypeSizeInBits(DestTy) == DL.getTypeSizeInBits(SrcTy)) { + Instruction::CastOps Cast = Instruction::BitCast; + // If we are going from a pointer to int or vice versa, we spell the cast + // differently. + if (SrcTy->isIntegerTy() && DestTy->isPointerTy()) + Cast = Instruction::IntToPtr; + else if (SrcTy->isPointerTy() && DestTy->isIntegerTy()) + Cast = Instruction::PtrToInt; + + if (CastInst::castIsValid(Cast, C, DestTy)) + return ConstantExpr::getCast(Cast, C, DestTy); + } + + // If this isn't an aggregate type, there is nothing we can do to drill down + // and find a bitcastable constant. + if (!SrcTy->isAggregateType()) + return nullptr; + + // We're simulating a load through a pointer that was bitcast to point to + // a different type, so we can try to walk down through the initial + // elements of an aggregate to see if some part of th e aggregate is + // castable to implement the "load" semantic model. + C = C->getAggregateElement(0u); + } while (C); + + return nullptr; +} + namespace { /// Recursive helper to read bits out of global. C is the constant being copied @@ -537,8 +572,8 @@ return ConstantInt::get(IntType->getContext(), ResultVal); } -Constant *ConstantFoldLoadThroughBitcast(ConstantExpr *CE, Type *DestTy, - const DataLayout &DL) { +Constant *ConstantFoldLoadThroughBitcastExpr(ConstantExpr *CE, Type *DestTy, + const DataLayout &DL) { auto *SrcPtr = CE->getOperand(0); auto *SrcPtrTy = dyn_cast(SrcPtr->getType()); if (!SrcPtrTy) @@ -549,37 +584,7 @@ if (!C) return nullptr; - do { - Type *SrcTy = C->getType(); - - // If the type sizes are the same and a cast is legal, just directly - // cast the constant. - if (DL.getTypeSizeInBits(DestTy) == DL.getTypeSizeInBits(SrcTy)) { - Instruction::CastOps Cast = Instruction::BitCast; - // If we are going from a pointer to int or vice versa, we spell the cast - // differently. - if (SrcTy->isIntegerTy() && DestTy->isPointerTy()) - Cast = Instruction::IntToPtr; - else if (SrcTy->isPointerTy() && DestTy->isIntegerTy()) - Cast = Instruction::PtrToInt; - - if (CastInst::castIsValid(Cast, C, DestTy)) - return ConstantExpr::getCast(Cast, C, DestTy); - } - - // If this isn't an aggregate type, there is nothing we can do to drill down - // and find a bitcastable constant. - if (!SrcTy->isAggregateType()) - return nullptr; - - // We're simulating a load through a pointer that was bitcast to point to - // a different type, so we can try to walk down through the initial - // elements of an aggregate to see if some part of th e aggregate is - // castable to implement the "load" semantic model. - C = C->getAggregateElement(0u); - } while (C); - - return nullptr; + return llvm::ConstantFoldLoadThroughBitcast(C, DestTy, DL); } } // end anonymous namespace @@ -611,7 +616,7 @@ } if (CE->getOpcode() == Instruction::BitCast) - if (Constant *LoadedC = ConstantFoldLoadThroughBitcast(CE, Ty, DL)) + if (Constant *LoadedC = ConstantFoldLoadThroughBitcastExpr(CE, Ty, DL)) return LoadedC; // Instead of loading constant c string, use corresponding integer value Index: llvm/trunk/lib/Transforms/Utils/Evaluator.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/Evaluator.cpp +++ llvm/trunk/lib/Transforms/Utils/Evaluator.cpp @@ -174,6 +174,11 @@ return false; } +static Constant *getInitializer(Constant *C) { + auto *GV = dyn_cast(C); + return GV && GV->hasDefinitiveInitializer() ? GV->getInitializer() : nullptr; +} + /// Return the value that would be computed by a load from P after the stores /// reflected by 'memory' have been performed. If we can't decide, return null. Constant *Evaluator::ComputeLoadResult(Constant *P) { @@ -189,14 +194,21 @@ return nullptr; } - // Handle a constantexpr getelementptr. - if (ConstantExpr *CE = dyn_cast(P)) - if (CE->getOpcode() == Instruction::GetElementPtr && - isa(CE->getOperand(0))) { - GlobalVariable *GV = cast(CE->getOperand(0)); - if (GV->hasDefinitiveInitializer()) - return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE); + if (ConstantExpr *CE = dyn_cast(P)) { + switch (CE->getOpcode()) { + // Handle a constantexpr getelementptr. + case Instruction::GetElementPtr: + if (auto *I = getInitializer(CE->getOperand(0))) + return ConstantFoldLoadThroughGEPConstantExpr(I, CE); + break; + // Handle a constantexpr bitcast. + case Instruction::BitCast: + if (auto *I = getInitializer(CE->getOperand(0))) + return ConstantFoldLoadThroughBitcast( + I, P->getType()->getPointerElementType(), DL); + break; } + } return nullptr; // don't know how to evaluate. } @@ -252,7 +264,8 @@ // In order to push the bitcast onto the stored value, a bitcast // from NewTy to Val's type must be legal. If it's not, we can try // introspecting NewTy to find a legal conversion. - while (!Val->getType()->canLosslesslyBitCastTo(NewTy)) { + Constant *NewVal; + while (!(NewVal = ConstantFoldLoadThroughBitcast(Val, NewTy, DL))) { // If NewTy is a struct, we can convert the pointer to the struct // into a pointer to its first member. // FIXME: This could be extended to support arrays as well. @@ -276,10 +289,7 @@ } } - // If we found compatible types, go ahead and push the bitcast - // onto the stored value. - Val = ConstantExpr::getBitCast(Val, NewTy); - + Val = NewVal; DEBUG(dbgs() << "Evaluated bitcast: " << *Val << "\n"); } } Index: llvm/trunk/test/Transforms/GlobalOpt/evaluate-bitcast.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/evaluate-bitcast.ll +++ llvm/trunk/test/Transforms/GlobalOpt/evaluate-bitcast.ll @@ -0,0 +1,28 @@ +; RUN: opt -globalopt -instcombine %s -S -o - | FileCheck %s + +; Static constructor should have been optimized out +; CHECK: i32 @main +; CHECK-NEXT: ret i32 69905 +; CHECK-NOT: _GLOBAL__sub_I_main.cpp + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +%struct.S = type { %struct.A* } +%struct.A = type { i64, i64 } + +@s = internal local_unnamed_addr global %struct.S zeroinitializer, align 8 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_main.cpp, i8* null }] +@gA = available_externally dso_local local_unnamed_addr global %struct.A* inttoptr (i64 69905 to %struct.A*), align 8 + +define dso_local i32 @main() local_unnamed_addr { + %1 = load i64, i64* bitcast (%struct.S* @s to i64*), align 8 + %2 = trunc i64 %1 to i32 + ret i32 %2 +} + +define internal void @_GLOBAL__sub_I_main.cpp() section ".text.startup" { + %1 = load i64, i64* bitcast (%struct.A** @gA to i64*), align 8 + store i64 %1, i64* bitcast (%struct.S* @s to i64*), align 8 + ret void +}