diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index b37c6c6f94a07..c2510ea75544a 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -1038,6 +1038,21 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node { /// Return value: true => null pointer dereference is not undefined. bool nullPointerIsDefined() const; + /// Returns the alignment of the given function. + /// + /// Note that this is the alignment of the code, not the alignment of a + /// function pointer. + MaybeAlign getAlign() const { return GlobalObject::getAlign(); } + + /// Sets the alignment attribute of the Function. + void setAlignment(Align Align) { GlobalObject::setAlignment(Align); } + + /// Sets the alignment attribute of the Function. + /// + /// This method will be deprecated as the alignment property should always be + /// defined. + void setAlignment(MaybeAlign Align) { GlobalObject::setAlignment(Align); } + private: void allocHungoffUselist(); template void setHungoffOperand(Constant *C); diff --git a/llvm/include/llvm/IR/GlobalObject.h b/llvm/include/llvm/IR/GlobalObject.h index 557add940f452..08a02b42bdc14 100644 --- a/llvm/include/llvm/IR/GlobalObject.h +++ b/llvm/include/llvm/IR/GlobalObject.h @@ -67,12 +67,7 @@ class GlobalObject : public GlobalValue { public: GlobalObject(const GlobalObject &) = delete; - /// FIXME: Remove this function once transition to Align is over. - uint64_t getAlignment() const { - MaybeAlign Align = getAlign(); - return Align ? Align->value() : 0; - } - +protected: /// Returns the alignment of the given variable or function. /// /// Note that for functions this is the alignment of the code, not the @@ -103,6 +98,7 @@ class GlobalObject : public GlobalValue { assert(getGlobalObjectSubClassData() == Val && "representation error"); } +public: /// Check if this global has a custom object file section. /// /// This is more efficient than calling getSection() and checking for an empty diff --git a/llvm/include/llvm/IR/GlobalVariable.h b/llvm/include/llvm/IR/GlobalVariable.h index a411897f5490e..388e1d7cfa808 100644 --- a/llvm/include/llvm/IR/GlobalVariable.h +++ b/llvm/include/llvm/IR/GlobalVariable.h @@ -298,6 +298,23 @@ class GlobalVariable : public GlobalObject, public ilist_node { /// LLVM_ABI void clearCodeModel(); + /// FIXME: Remove this function once transition to Align is over. + uint64_t getAlignment() const { + MaybeAlign Align = getAlign(); + return Align ? Align->value() : 0; + } + + /// Returns the alignment of the given variable. + MaybeAlign getAlign() const { return GlobalObject::getAlign(); } + + /// Sets the alignment attribute of the GlobalVariable. + void setAlignment(Align Align) { GlobalObject::setAlignment(Align); } + + /// Sets the alignment attribute of the GlobalVariable. + /// This method will be deprecated as the alignment property should always be + /// defined. + void setAlignment(MaybeAlign Align) { GlobalObject::setAlignment(Align); } + // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { return V->getValueID() == Value::GlobalVariableVal; diff --git a/llvm/include/llvm/SandboxIR/Constant.h b/llvm/include/llvm/SandboxIR/Constant.h index 2012cf8a8ed3e..e7b18a442d330 100644 --- a/llvm/include/llvm/SandboxIR/Constant.h +++ b/llvm/include/llvm/SandboxIR/Constant.h @@ -976,32 +976,6 @@ class GlobalObject : public GlobalValue { } } - /// FIXME: Remove this function once transition to Align is over. - uint64_t getAlignment() const { - return cast(Val)->getAlignment(); - } - - /// Returns the alignment of the given variable or function. - /// - /// Note that for functions this is the alignment of the code, not the - /// alignment of a function pointer. - MaybeAlign getAlign() const { - return cast(Val)->getAlign(); - } - - // TODO: Add missing: setAlignment(Align) - - /// Sets the alignment attribute of the GlobalObject. - /// This method will be deprecated as the alignment property should always be - /// defined. - void setAlignment(MaybeAlign Align); - - unsigned getGlobalObjectSubClassData() const { - return cast(Val)->getGlobalObjectSubClassData(); - } - - void setGlobalObjectSubClassData(unsigned V); - /// Check if this global has a custom object file section. /// /// This is more efficient than calling getSection() and checking for an empty @@ -1294,6 +1268,18 @@ class GlobalVariable final return cast(Val)->getCodeModel(); } + /// Returns the alignment of the given variable. + MaybeAlign getAlign() const { + return cast(Val)->getAlign(); + } + + // TODO: Add missing: setAligment(Align) + + /// Sets the alignment attribute of the GlobalVariable. + /// This method will be deprecated as the alignment property should always be + /// defined. + void setAlignment(MaybeAlign Align); + // TODO: Missing setCodeModel(). Requires custom tracker. #ifndef NDEBUG diff --git a/llvm/include/llvm/SandboxIR/Function.h b/llvm/include/llvm/SandboxIR/Function.h index a810533f769f7..2c4b53ef6c1e6 100644 --- a/llvm/include/llvm/SandboxIR/Function.h +++ b/llvm/include/llvm/SandboxIR/Function.h @@ -58,6 +58,16 @@ class Function : public GlobalWithNodeAPI(Val)->getAlign(); } + + // TODO: Add missing: setAligment(Align) + + /// Sets the alignment attribute of the Function. + /// This method will be deprecated as the alignment property should always be + /// defined. + void setAlignment(MaybeAlign Align); + #ifndef NDEBUG void verify() const final { assert(isa(Val) && "Expected Function!"); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index bcfc64c6f36bb..e13e92378d4aa 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -369,7 +369,11 @@ Align AsmPrinter::getGVAlignment(const GlobalObject *GV, const DataLayout &DL, Alignment = InAlign; // If the GV has a specified alignment, take it into account. - const MaybeAlign GVAlign(GV->getAlign()); + MaybeAlign GVAlign; + if (auto *GVar = dyn_cast(GV)) + GVAlign = GVar->getAlign(); + else if (auto *F = dyn_cast(GV)) + GVAlign = F->getAlign(); if (!GVAlign) return Alignment; diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 1954b44af22ad..a7c3a56dcc22a 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2108,8 +2108,10 @@ LLVMTypeRef LLVMGlobalGetValueType(LLVMValueRef Global) { unsigned LLVMGetAlignment(LLVMValueRef V) { Value *P = unwrap(V); - if (GlobalObject *GV = dyn_cast(P)) + if (GlobalVariable *GV = dyn_cast(P)) return GV->getAlign() ? GV->getAlign()->value() : 0; + if (Function *F = dyn_cast(P)) + return F->getAlign() ? F->getAlign()->value() : 0; if (AllocaInst *AI = dyn_cast(P)) return AI->getAlign().value(); if (LoadInst *LI = dyn_cast(P)) @@ -2128,8 +2130,10 @@ unsigned LLVMGetAlignment(LLVMValueRef V) { void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes) { Value *P = unwrap(V); - if (GlobalObject *GV = dyn_cast(P)) + if (GlobalVariable *GV = dyn_cast(P)) GV->setAlignment(MaybeAlign(Bytes)); + else if (Function *F = dyn_cast(P)) + F->setAlignment(MaybeAlign(Bytes)); else if (AllocaInst *AI = dyn_cast(P)) AI->setAlignment(Align(Bytes)); else if (LoadInst *LI = dyn_cast(P)) diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 580b0af709337..90ec6626b3a70 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -457,10 +457,10 @@ CallInst *IRBuilderBase::CreateInvariantStart(Value *Ptr, ConstantInt *Size) { } static MaybeAlign getAlign(Value *Ptr) { - if (auto *O = dyn_cast(Ptr)) - return O->getAlign(); + if (auto *V = dyn_cast(Ptr)) + return V->getAlign(); if (auto *A = dyn_cast(Ptr)) - return A->getAliaseeObject()->getAlign(); + return getAlign(A->getAliaseeObject()); return {}; } diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index d6cb65d94a11d..02c16e201abe2 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -957,30 +957,27 @@ uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, Align Value::getPointerAlignment(const DataLayout &DL) const { assert(getType()->isPointerTy() && "must be pointer"); - if (auto *GO = dyn_cast(this)) { - if (isa(GO)) { - Align FunctionPtrAlign = DL.getFunctionPtrAlign().valueOrOne(); - switch (DL.getFunctionPtrAlignType()) { - case DataLayout::FunctionPtrAlignType::Independent: - return FunctionPtrAlign; - case DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign: - return std::max(FunctionPtrAlign, GO->getAlign().valueOrOne()); - } - llvm_unreachable("Unhandled FunctionPtrAlignType"); + if (const Function *F = dyn_cast(this)) { + Align FunctionPtrAlign = DL.getFunctionPtrAlign().valueOrOne(); + switch (DL.getFunctionPtrAlignType()) { + case DataLayout::FunctionPtrAlignType::Independent: + return FunctionPtrAlign; + case DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign: + return std::max(FunctionPtrAlign, F->getAlign().valueOrOne()); } - const MaybeAlign Alignment(GO->getAlign()); + llvm_unreachable("Unhandled FunctionPtrAlignType"); + } else if (auto *GVar = dyn_cast(this)) { + const MaybeAlign Alignment(GVar->getAlign()); if (!Alignment) { - if (auto *GVar = dyn_cast(GO)) { - Type *ObjectType = GVar->getValueType(); - if (ObjectType->isSized()) { - // 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 (GVar->isStrongDefinitionForLinker()) - return DL.getPreferredAlign(GVar); - else - return DL.getABITypeAlign(ObjectType); - } + Type *ObjectType = GVar->getValueType(); + if (ObjectType->isSized()) { + // 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 (GVar->isStrongDefinitionForLinker()) + return DL.getPreferredAlign(GVar); + else + return DL.getABITypeAlign(ObjectType); } } return Alignment.valueOrOne(); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 2d03a7a261b5b..592bb6aa90613 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -735,12 +735,6 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) { "Global is external, but doesn't have external or weak linkage!", &GV); if (const GlobalObject *GO = dyn_cast(&GV)) { - - if (MaybeAlign A = GO->getAlign()) { - Check(A->value() <= Value::MaximumAlignment, - "huge alignment values are unsupported", GO); - } - if (const MDNode *Associated = GO->getMetadata(LLVMContext::MD_associated)) { Check(Associated->getNumOperands() == 1, @@ -830,6 +824,11 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) { void Verifier::visitGlobalVariable(const GlobalVariable &GV) { Type *GVType = GV.getValueType(); + if (MaybeAlign A = GV.getAlign()) { + Check(A->value() <= Value::MaximumAlignment, + "huge alignment values are unsupported", &GV); + } + if (GV.hasInitializer()) { Check(GV.getInitializer()->getType() == GVType, "Global variable initializer type does not match global " @@ -2869,6 +2868,11 @@ void Verifier::visitFunction(const Function &F) { Check(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(), "Invalid struct return type!", &F); + if (MaybeAlign A = F.getAlign()) { + Check(A->value() <= Value::MaximumAlignment, + "huge alignment values are unsupported", &F); + } + AttributeList Attrs = F.getAttributes(); Check(verifyAttributeCount(Attrs, FT->getNumParams()), diff --git a/llvm/lib/LTO/LTOModule.cpp b/llvm/lib/LTO/LTOModule.cpp index 749ae635e610c..e0a975806a31d 100644 --- a/llvm/lib/LTO/LTOModule.cpp +++ b/llvm/lib/LTO/LTOModule.cpp @@ -414,8 +414,11 @@ void LTOModule::addDefinedFunctionSymbol(StringRef Name, const GlobalValue *F) { void LTOModule::addDefinedSymbol(StringRef Name, const GlobalValue *def, bool isFunction) { - const GlobalObject *go = dyn_cast(def); - uint32_t attr = go ? Log2(go->getAlign().valueOrOne()) : 0; + uint32_t attr = 0; + if (auto *gv = dyn_cast(def)) + attr = Log2(gv->getAlign().valueOrOne()); + else if (auto *f = dyn_cast(def)) + attr = Log2(f->getAlign().valueOrOne()); // set permissions part if (isFunction) { diff --git a/llvm/lib/SandboxIR/Constant.cpp b/llvm/lib/SandboxIR/Constant.cpp index fa79a01c7f345..82cf0876d5800 100644 --- a/llvm/lib/SandboxIR/Constant.cpp +++ b/llvm/lib/SandboxIR/Constant.cpp @@ -282,20 +282,11 @@ PoisonValue *PoisonValue::getElementValue(unsigned Idx) const { cast(Val)->getElementValue(Idx))); } -void GlobalObject::setAlignment(MaybeAlign Align) { +void GlobalVariable::setAlignment(MaybeAlign Align) { Ctx.getTracker() - .emplaceIfTracking< - GenericSetter<&GlobalObject::getAlign, &GlobalObject::setAlignment>>( - this); - cast(Val)->setAlignment(Align); -} - -void GlobalObject::setGlobalObjectSubClassData(unsigned V) { - Ctx.getTracker() - .emplaceIfTracking< - GenericSetter<&GlobalObject::getGlobalObjectSubClassData, - &GlobalObject::setGlobalObjectSubClassData>>(this); - cast(Val)->setGlobalObjectSubClassData(V); + .emplaceIfTracking>(this); + cast(Val)->setAlignment(Align); } void GlobalObject::setSection(StringRef S) { diff --git a/llvm/lib/SandboxIR/Function.cpp b/llvm/lib/SandboxIR/Function.cpp index f7a1d35b00465..f400389ed7605 100644 --- a/llvm/lib/SandboxIR/Function.cpp +++ b/llvm/lib/SandboxIR/Function.cpp @@ -17,6 +17,13 @@ FunctionType *Function::getFunctionType() const { Ctx.getType(cast(Val)->getFunctionType())); } +void Function::setAlignment(MaybeAlign Align) { + Ctx.getTracker() + .emplaceIfTracking< + GenericSetter<&Function::getAlign, &Function::setAlignment>>(this); + cast(Val)->setAlignment(Align); +} + #ifndef NDEBUG void Function::dumpNameAndArgs(raw_ostream &OS) const { auto *F = cast(Val); diff --git a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp index 1c53b740b3f81..18350650bfe2d 100644 --- a/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp +++ b/llvm/lib/Target/PowerPC/PPCMIPeephole.cpp @@ -42,6 +42,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachinePostDominators.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/Support/Debug.h" #include "llvm/Support/DebugCounter.h" @@ -997,9 +998,9 @@ bool PPCMIPeephole::simplifyCode() { // the transformation. bool IsWordAligned = false; if (SrcMI->getOperand(1).isGlobal()) { - const GlobalObject *GO = - dyn_cast(SrcMI->getOperand(1).getGlobal()); - if (GO && GO->getAlign() && *GO->getAlign() >= 4 && + const GlobalVariable *GV = + dyn_cast(SrcMI->getOperand(1).getGlobal()); + if (GV && GV->getAlign() && *GV->getAlign() >= 4 && (SrcMI->getOperand(1).getOffset() % 4 == 0)) IsWordAligned = true; } else if (SrcMI->getOperand(1).isImm()) { diff --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp index 6c376e4bf622c..942ef88385620 100644 --- a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -8,7 +8,7 @@ #include "SystemZSubtarget.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/Target/TargetMachine.h" using namespace llvm; @@ -83,9 +83,9 @@ bool SystemZSubtarget::isAddressedViaADA(const GlobalValue *GV) const { // least two byte alignment, then generated code can use relative // instructions to address the variable. Otherwise, use the ADA to address // the variable. - if (GO->getAlignment() & 0x1) { - return true; - } + if (auto *GV = dyn_cast(GO)) + if (GV->getAlign() && (*GV->getAlign()).value() & 0x1) + return true; // getKindForGlobal only works with definitions if (GO->isDeclaration()) { diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index be71cb69ad8cc..cf6a6055afbb6 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -1548,9 +1548,9 @@ Align llvm::tryEnforceAlignment(Value *V, Align PrefAlign, return PrefAlign; } - if (auto *GO = dyn_cast(V)) { + if (auto *GV = dyn_cast(V)) { // TODO: as above, this shouldn't be necessary. - Align CurrentAlign = GO->getPointerAlignment(DL); + Align CurrentAlign = GV->getPointerAlignment(DL); if (PrefAlign <= CurrentAlign) return CurrentAlign; @@ -1558,16 +1558,16 @@ Align llvm::tryEnforceAlignment(Value *V, Align PrefAlign, // of the global. If the memory we set aside for the global may not be the // memory used by the final program then it is impossible for us to reliably // enforce the preferred alignment. - if (!GO->canIncreaseAlignment()) + if (!GV->canIncreaseAlignment()) return CurrentAlign; - if (GO->isThreadLocal()) { - unsigned MaxTLSAlign = GO->getParent()->getMaxTLSAlignment() / CHAR_BIT; + if (GV->isThreadLocal()) { + unsigned MaxTLSAlign = GV->getParent()->getMaxTLSAlignment() / CHAR_BIT; if (MaxTLSAlign && PrefAlign > Align(MaxTLSAlign)) PrefAlign = Align(MaxTLSAlign); } - GO->setAlignment(PrefAlign); + GV->setAlignment(PrefAlign); return PrefAlign; } diff --git a/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.cpp b/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.cpp index 64bf711f23d52..5d958dd2d82ad 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.cpp @@ -13,18 +13,26 @@ using namespace llvm; static bool shouldReduceSection(GlobalObject &GO) { return GO.hasSection(); } -static bool shouldReduceAlign(GlobalObject &GO) { - return GO.getAlign().has_value(); +static bool shouldReduceAlign(GlobalVariable *GV) { + return GV->getAlign().has_value(); } +static bool shouldReduceAlign(Function *F) { return F->getAlign().has_value(); } + static bool shouldReduceComdat(GlobalObject &GO) { return GO.hasComdat(); } void llvm::reduceGlobalObjectsDeltaPass(Oracle &O, ReducerWorkItem &Program) { for (auto &GO : Program.getModule().global_objects()) { if (shouldReduceSection(GO) && !O.shouldKeep()) GO.setSection(""); - if (shouldReduceAlign(GO) && !O.shouldKeep()) - GO.setAlignment(MaybeAlign()); + if (auto *GV = dyn_cast(&GO)) { + if (shouldReduceAlign(GV) && !O.shouldKeep()) + GV->setAlignment(MaybeAlign()); + } + if (auto *F = dyn_cast(&GO)) { + if (shouldReduceAlign(F) && !O.shouldKeep()) + F->setAlignment(MaybeAlign()); + } if (shouldReduceComdat(GO) && !O.shouldKeep()) GO.setComdat(nullptr); } diff --git a/llvm/unittests/SandboxIR/SandboxIRTest.cpp b/llvm/unittests/SandboxIR/SandboxIRTest.cpp index 18882add59941..33928ac118e0c 100644 --- a/llvm/unittests/SandboxIR/SandboxIRTest.cpp +++ b/llvm/unittests/SandboxIR/SandboxIRTest.cpp @@ -1051,29 +1051,6 @@ define void @foo() { auto *Call = cast(&*It++); // Check classof(), creation. auto *GO = cast(Call->getCalledOperand()); - // Check getAlignment(). - EXPECT_EQ(GO->getAlignment(), LLVMGO->getAlignment()); - // Check getAlign(). - EXPECT_EQ(GO->getAlign(), LLVMGO->getAlign()); - // Check setAlignment(). - auto OrigMaybeAlign = GO->getAlign(); - auto NewMaybeAlign = MaybeAlign(128); - EXPECT_NE(NewMaybeAlign, OrigMaybeAlign); - GO->setAlignment(NewMaybeAlign); - EXPECT_EQ(GO->getAlign(), NewMaybeAlign); - GO->setAlignment(OrigMaybeAlign); - EXPECT_EQ(GO->getAlign(), OrigMaybeAlign); - // Check getGlobalObjectSubClassData(). - EXPECT_EQ(GO->getGlobalObjectSubClassData(), - LLVMGO->getGlobalObjectSubClassData()); - // Check setGlobalObjectSubClassData(). - auto OrigGOSCD = GO->getGlobalObjectSubClassData(); - auto NewGOSCD = 1u; - EXPECT_NE(NewGOSCD, OrigGOSCD); - GO->setGlobalObjectSubClassData(NewGOSCD); - EXPECT_EQ(GO->getGlobalObjectSubClassData(), NewGOSCD); - GO->setGlobalObjectSubClassData(OrigGOSCD); - EXPECT_EQ(GO->getGlobalObjectSubClassData(), OrigGOSCD); // Check hasSection(). EXPECT_EQ(GO->hasSection(), LLVMGO->hasSection()); // Check getSection(). @@ -1284,6 +1261,16 @@ define void @foo() { EXPECT_EQ(GV0->getCodeModelRaw(), LLVMGV0->getCodeModelRaw()); // Check getCodeModel(). EXPECT_EQ(GV0->getCodeModel(), LLVMGV0->getCodeModel()); + // Check getAlign(). + EXPECT_EQ(GV0->getAlign(), LLVMGV0->getAlign()); + // Check setAlignment(). + auto OrigMaybeAlign = GV0->getAlign(); + auto NewMaybeAlign = MaybeAlign(128); + EXPECT_NE(NewMaybeAlign, OrigMaybeAlign); + GV0->setAlignment(NewMaybeAlign); + EXPECT_EQ(GV0->getAlign(), NewMaybeAlign); + GV0->setAlignment(OrigMaybeAlign); + EXPECT_EQ(GV0->getAlign(), OrigMaybeAlign); } TEST_F(SandboxIRTest, GlobalAlias) { @@ -1855,6 +1842,17 @@ void @foo0(i32 %arg0, i32 %arg1) { )IR"); } #endif // NDEBUG + + // Check getAlign(). + EXPECT_EQ(F0->getAlign(), F0->getAlign()); + // Check setAlignment(). + auto OrigMaybeAlign = F0->getAlign(); + auto NewMaybeAlign = MaybeAlign(128); + EXPECT_NE(NewMaybeAlign, OrigMaybeAlign); + F0->setAlignment(NewMaybeAlign); + EXPECT_EQ(F0->getAlign(), NewMaybeAlign); + F0->setAlignment(OrigMaybeAlign); + EXPECT_EQ(F0->getAlign(), OrigMaybeAlign); } TEST_F(SandboxIRTest, Module) {