diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index dbaadd824a1..af8649499b2 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -81,8 +81,16 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, // The address of an aligned GlobalValue has trailing zeros. if (GlobalValue *GV = dyn_cast(V)) { unsigned Align = GV->getAlignment(); - if (Align == 0 && TD && GV->getType()->getElementType()->isSized()) - Align = TD->getPrefTypeAlignment(GV->getType()->getElementType()); + if (Align == 0 && TD && GV->getType()->getElementType()->isSized()) { + const Type *ObjectType = GV->getType()->getElementType(); + // If the object is defined in the current Module, we'll be giving + // it the preferred alignment. Otherwise, we have to assume that it + // may only have the minimum ABI alignment. + if (!GV->isDeclaration() && !GV->mayBeOverridden()) + Align = TD->getPrefTypeAlignment(ObjectType); + else + Align = TD->getABITypeAlignment(ObjectType); + } if (Align > 0) KnownZero = Mask & APInt::getLowBitsSet(BitWidth, CountTrailingZeros_32(Align)); diff --git a/test/Transforms/InstCombine/align-external.ll b/test/Transforms/InstCombine/align-external.ll new file mode 100644 index 00000000000..38be3143eda --- /dev/null +++ b/test/Transforms/InstCombine/align-external.ll @@ -0,0 +1,22 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | FileCheck %s + +; Don't assume that external global variables have their preferred +; alignment. They may only have the ABI minimum alignment. + +; CHECK: %s = shl i64 %a, 3 +; CHECK: %r = or i64 %s, ptrtoint (i32* @A to i64) +; CHECK: %q = add i64 %r, 1 +; CHECK: ret i64 %q + +target datalayout = "-i32:8:32" + +@A = external global i32 +@B = external global i32 + +define i64 @foo(i64 %a) { + %t = ptrtoint i32* @A to i64 + %s = shl i64 %a, 3 + %r = or i64 %t, %s + %q = add i64 %r, 1 + ret i64 %q +}