diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -734,16 +734,23 @@ return MaybeAlign(CI->getLimitedValue()); } } else if (auto *CstPtr = dyn_cast(this)) { - if (auto *CstInt = dyn_cast_or_null(ConstantExpr::getPtrToInt( - const_cast(CstPtr), DL.getIntPtrType(getType()), - /*OnlyIfReduced=*/true))) { + MaybeAlign Alignment(llvm::None); + // NOTE: getPtrToInt call may create extra constant operator + Constant *CstPTI = ConstantExpr::getPtrToInt(const_cast(CstPtr), + DL.getIntPtrType(getType()), + /*OnlyIfReduced=*/true); + if (auto *CstInt = dyn_cast_or_null(CstPTI)) { size_t TrailingZeros = CstInt->getValue().countTrailingZeros(); // While the actual alignment may be large, elsewhere we have - // an arbitrary upper alignmet limit, so let's clamp to it. - return Align(TrailingZeros < Value::MaxAlignmentExponent - ? uint64_t(1) << TrailingZeros - : Value::MaximumAlignment); + // an arbitrary upper alignment limit, so let's clamp to it. + Alignment = Align(TrailingZeros < Value::MaxAlignmentExponent + ? uint64_t(1) << TrailingZeros + : Value::MaximumAlignment); } + // Remove unused ptrtoint operator if it has been created + if (CstPTI && !CstPTI->isConstantUsed()) + CstPTI->destroyConstant(); + return Alignment; } return llvm::None; } diff --git a/llvm/unittests/IR/ConstantsTest.cpp b/llvm/unittests/IR/ConstantsTest.cpp --- a/llvm/unittests/IR/ConstantsTest.cpp +++ b/llvm/unittests/IR/ConstantsTest.cpp @@ -638,5 +638,33 @@ EXPECT_FALSE(CP00U->isElementWiseEqual(CP00U0)); } +TEST(ConstantsTest, GlobalValueImmutabilityOnGetPtrAlignmentTest) { + LLVMContext Context; + SMDiagnostic Error; + std::unique_ptr M = parseAssemblyString( + "@gs = common global [8 x i32] zeroinitializer, align 8 " + "define void @f() { " + "entry: " + " %0 = load i32, i32* getelementptr inbounds " + " ([8 x i32], [8 x i32]* @gs, i64 0, i64 0), align 8 " + " ret void " + "}", + Error, Context); + + const Function *F = M->getFunction("f"); + const BasicBlock &BB = F->getEntryBlock(); + const Instruction &I = BB.front(); + const Value *GEP = I.getOperand(0); + EXPECT_TRUE(isa(GEP)); + + GlobalVariable *GV = M->getGlobalVariable("gs"); + unsigned GVUsesNumBefore = GV->getNumUses(); + + MaybeAlign Align = GEP->getPointerAlignment(DataLayout("")); + (void)Align; + + ASSERT_EQ(GVUsesNumBefore, GV->getNumUses()); +} + } // end anonymous namespace } // end namespace llvm