diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -662,7 +662,7 @@ void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const; /// Return the alignment for the specified \p GV. - static Align getGVAlignment(const GlobalValue *GV, const DataLayout &DL, + static Align getGVAlignment(const GlobalObject *GV, const DataLayout &DL, Align InAlign = Align(1)); private: diff --git a/llvm/include/llvm/IR/GlobalObject.h b/llvm/include/llvm/IR/GlobalObject.h --- a/llvm/include/llvm/IR/GlobalObject.h +++ b/llvm/include/llvm/IR/GlobalObject.h @@ -76,6 +76,10 @@ return Align ? Align->value() : 0; } + /// 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 { unsigned Data = getGlobalValueSubClassData(); unsigned AlignmentData = Data & AlignmentMask; @@ -183,6 +187,13 @@ void setVCallVisibilityMetadata(VCallVisibility Visibility); VCallVisibility getVCallVisibility() const; + /// Returns true if the alignment of the value can be unilaterally + /// increased. + /// + /// Note that for functions this is the alignment of the code, not the + /// alignment of a function pointer. + bool canIncreaseAlignment() const; + protected: void copyAttributesFrom(const GlobalObject *Src); diff --git a/llvm/include/llvm/IR/GlobalValue.h b/llvm/include/llvm/IR/GlobalValue.h --- a/llvm/include/llvm/IR/GlobalValue.h +++ b/llvm/include/llvm/IR/GlobalValue.h @@ -185,7 +185,6 @@ GlobalValue(const GlobalValue &) = delete; - unsigned getAlignment() const; unsigned getAddressSpace() const; enum class UnnamedAddr { @@ -548,10 +547,6 @@ return !(isDeclarationForLinker() || isWeakForLinker()); } - // Returns true if the alignment of the value can be unilaterally - // increased. - bool canIncreaseAlignment() const; - const GlobalObject *getBaseObject() const; GlobalObject *getBaseObject() { return const_cast( diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1179,7 +1179,7 @@ std::map GCMap; unsigned MaxAlignment = 0; unsigned MaxGlobalType = 0; - for (const GlobalValue &GV : M.globals()) { + for (const GlobalVariable &GV : M.globals()) { MaxAlignment = std::max(MaxAlignment, GV.getAlignment()); MaxGlobalType = std::max(MaxGlobalType, VE.getTypeID(GV.getValueType())); if (GV.hasSection()) { diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -157,7 +157,7 @@ /// getGVAlignment - Return the alignment to use for the specified global /// value. This rounds up to the preferred alignment if possible and legal. -Align AsmPrinter::getGVAlignment(const GlobalValue *GV, const DataLayout &DL, +Align AsmPrinter::getGVAlignment(const GlobalObject *GV, const DataLayout &DL, Align InAlign) { Align Alignment; if (const GlobalVariable *GVar = dyn_cast(GV)) diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -1228,8 +1228,8 @@ // Without a datalayout we have to assume the worst case: that the // function pointer isn't aligned at all. GVAlign = llvm::None; - } else { - GVAlign = MaybeAlign(GV->getAlignment()); + } else if (isa(GV)) { + GVAlign = cast(GV)->getAlign(); } if (GVAlign && *GVAlign > 1) { diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2003,7 +2003,7 @@ unsigned LLVMGetAlignment(LLVMValueRef V) { Value *P = unwrap(V); - if (GlobalValue *GV = dyn_cast(P)) + if (GlobalObject *GV = dyn_cast(P)) return GV->getAlignment(); if (AllocaInst *AI = dyn_cast(P)) return AI->getAlignment(); @@ -2013,7 +2013,7 @@ return SI->getAlignment(); llvm_unreachable( - "only GlobalValue, AllocaInst, LoadInst and StoreInst have alignment"); + "only GlobalObject, AllocaInst, LoadInst and StoreInst have alignment"); } void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes) { diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -101,20 +101,6 @@ !isDSOLocal(); } -unsigned GlobalValue::getAlignment() const { - if (auto *GA = dyn_cast(this)) { - // In general we cannot compute this at the IR level, but we try. - if (const GlobalObject *GO = GA->getBaseObject()) - return GO->getAlignment(); - - // FIXME: we should also be able to handle: - // Alias = Global + Offset - // Alias = Absolute - return 0; - } - return cast(this)->getAlignment(); -} - unsigned GlobalValue::getAddressSpace() const { PointerType *PtrTy = getType(); return PtrTy->getAddressSpace(); @@ -245,7 +231,7 @@ return false; } -bool GlobalValue::canIncreaseAlignment() const { +bool GlobalObject::canIncreaseAlignment() const { // Firstly, can only increase the alignment of a global if it // is a strong definition. if (!isStrongDefinitionForLinker()) diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -570,8 +570,9 @@ Assert(!GV.isDeclaration() || GV.hasValidDeclarationLinkage(), "Global is external, but doesn't have external or weak linkage!", &GV); - Assert(GV.getAlignment() <= Value::MaximumAlignment, - "huge alignment values are unsupported", &GV); + if (const GlobalObject *GO = dyn_cast(&GV)) + Assert(GO->getAlignment() <= Value::MaximumAlignment, + "huge alignment values are unsupported", GO); Assert(!GV.hasAppendingLinkage() || isa(GV), "Only global variables can have appending linkage!", &GV); diff --git a/llvm/lib/LTO/LTOModule.cpp b/llvm/lib/LTO/LTOModule.cpp --- a/llvm/lib/LTO/LTOModule.cpp +++ b/llvm/lib/LTO/LTOModule.cpp @@ -415,7 +415,10 @@ void LTOModule::addDefinedSymbol(StringRef Name, const GlobalValue *def, bool isFunction) { // set alignment part log2() can have rounding errors - uint32_t align = def->getAlignment(); + uint32_t align = 0; + const GlobalObject *go = dyn_cast(def); + if (go) + align = go->getAlignment(); uint32_t attr = align ? countTrailingZeros(align) : 0; // set permissions part diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp --- a/llvm/lib/Object/IRSymtab.cpp +++ b/llvm/lib/Object/IRSymtab.cpp @@ -264,9 +264,13 @@ Sym.Flags |= unsigned(GV->getVisibility()) << storage::Symbol::FB_visibility; if (Flags & object::BasicSymbolRef::SF_Common) { + auto *GVar = dyn_cast(GV); + if (!GVar) + return make_error("Only variables can have common linkage!", + inconvertibleErrorCode()); Uncommon().CommonSize = GV->getParent()->getDataLayout().getTypeAllocSize( GV->getType()->getElementType()); - Uncommon().CommonAlign = GV->getAlignment(); + Uncommon().CommonAlign = GVar->getAlignment(); } const GlobalObject *Base = GV->getBaseObject(); diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -903,16 +903,9 @@ if (!GAN) return true; - if (GAN->getOffset() % Size == 0) { - const GlobalValue *GV = GAN->getGlobal(); - unsigned Alignment = GV->getAlignment(); - Type *Ty = GV->getValueType(); - if (Alignment == 0 && Ty->isSized()) - Alignment = DL.getABITypeAlignment(Ty); - - if (Alignment >= Size) - return true; - } + if (GAN->getOffset() % Size == 0 && + GAN->getGlobal()->getPointerAlignment(DL) >= Size) + return true; } if (CurDAG->isBaseWithConstantOffset(N)) { diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -1321,7 +1321,7 @@ // TODO: We could emit code to handle the initialization somewhere. if (!hasDefinedInitializer(GV)) { - unsigned Offset = MFI->allocateLDSGlobal(DL, *GV); + unsigned Offset = MFI->allocateLDSGlobal(DL, *cast(GV)); return DAG.getConstant(Offset, SDLoc(Op), Op.getValueType()); } } @@ -4585,11 +4585,10 @@ } case AMDGPUISD::LDS: { auto GA = cast(Op.getOperand(0).getNode()); - unsigned Align = GA->getGlobal()->getAlignment(); + Align Alignment = GA->getGlobal()->getPointerAlignment(DAG.getDataLayout()); Known.Zero.setHighBits(16); - if (Align) - Known.Zero.setLowBits(Log2_32(Align)); + Known.Zero.setLowBits(Log2(Alignment)); break; } case ISD::INTRINSIC_WO_CHAIN: { diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -2009,7 +2009,9 @@ return true; // Leave in place; } - B.buildConstant(DstReg, MFI->allocateLDSGlobal(B.getDataLayout(), *GV)); + B.buildConstant( + DstReg, + MFI->allocateLDSGlobal(B.getDataLayout(), *cast(GV))); MI.eraseFromParent(); return true; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.h b/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.h --- a/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.h @@ -77,7 +77,7 @@ return WaveLimiter; } - unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalValue &GV); + unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV); }; } diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp b/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp @@ -38,7 +38,7 @@ } unsigned AMDGPUMachineFunction::allocateLDSGlobal(const DataLayout &DL, - const GlobalValue &GV) { + const GlobalVariable &GV) { auto Entry = LocalMemoryObjects.insert(std::make_pair(&GV, 0)); if (!Entry.second) return Entry.first->second; diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1139,8 +1139,11 @@ // can be enabled for those subtargets. unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1; const MachineOperand &MO = MI->getOperand(OpNum); - if (MO.isGlobal() && MO.getGlobal()->getAlignment() < 4) - llvm_unreachable("Global must be word-aligned for LD, STD, LWA!"); + if (MO.isGlobal()) { + const DataLayout &DL = MO.getGlobal()->getParent()->getDataLayout(); + if (MO.getGlobal()->getPointerAlignment(DL) < 4) + llvm_unreachable("Global must be word-aligned for LD, STD, LWA!"); + } // Now process the instruction normally. break; } diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -6659,7 +6659,8 @@ int MaxDisplacement = 7; if (GlobalAddressSDNode *GA = dyn_cast(ImmOpnd)) { const GlobalValue *GV = GA->getGlobal(); - MaxDisplacement = std::min((int) GV->getAlignment() - 1, MaxDisplacement); + Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout()); + MaxDisplacement = std::min((int)Alignment.value() - 1, MaxDisplacement); } bool UpdateHBase = false; @@ -6725,10 +6726,10 @@ if (GlobalAddressSDNode *GA = dyn_cast(ImmOpnd)) { SDLoc dl(GA); const GlobalValue *GV = GA->getGlobal(); + Align Alignment = GV->getPointerAlignment(CurDAG->getDataLayout()); // We can't perform this optimization for data whose alignment // is insufficient for the instruction encoding. - if (GV->getAlignment() < 4 && - (RequiresMod4Offset || (Offset % 4) != 0)) { + if (Alignment < 4 && (RequiresMod4Offset || (Offset % 4) != 0)) { LLVM_DEBUG(dbgs() << "Rejected this candidate for alignment.\n\n"); continue; } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -3448,9 +3448,11 @@ // not just an immediate but also a multiple of 4, or 16 depending on the // load. A DForm load cannot be represented if it is a multiple of say 2. // XForm loads do not have this restriction. - if (ImmMO.isGlobal() && - ImmMO.getGlobal()->getAlignment() < III.ImmMustBeMultipleOf) - return false; + if (ImmMO.isGlobal()) { + const DataLayout &DL = ImmMO.getGlobal()->getParent()->getDataLayout(); + if (ImmMO.getGlobal()->getPointerAlignment(DL) < III.ImmMustBeMultipleOf) + return false; + } return true; } diff --git a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp --- a/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/llvm/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -73,9 +73,12 @@ bool SystemZSubtarget::isPC32DBLSymbol(const GlobalValue *GV, CodeModel::Model CM) const { - // PC32DBL accesses require the low bit to be clear. Note that a zero - // value selects the default alignment and is therefore OK. - if (GV->getAlignment() == 1) + // PC32DBL accesses require the low bit to be clear. + // + // FIXME: Explicitly check for functions: the datalayout is currently + // missing information about function pointers. + const DataLayout &DL = GV->getParent()->getDataLayout(); + if (GV->getPointerAlignment(DL) == 1 && !GV->getValueType()->isFunctionTy()) return false; // For the small model, all locally-binding symbols are in range. diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/llvm/lib/Target/XCore/XCoreISelLowering.cpp --- a/llvm/lib/Target/XCore/XCoreISelLowering.cpp +++ b/llvm/lib/Target/XCore/XCoreISelLowering.cpp @@ -435,7 +435,7 @@ Offset, DAG); } if (TLI.isGAPlusOffset(BasePtr.getNode(), GV, Offset) && - MinAlign(GV->getAlignment(), 4) == 4) { + GV->getPointerAlignment(DAG.getDataLayout()) >= 4) { SDValue NewBasePtr = DAG.getGlobalAddress(GV, DL, BasePtr->getValueType(0)); return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr, diff --git a/llvm/test/CodeGen/AArch64/funcptr_cast.ll b/llvm/test/CodeGen/AArch64/funcptr_cast.ll --- a/llvm/test/CodeGen/AArch64/funcptr_cast.ll +++ b/llvm/test/CodeGen/AArch64/funcptr_cast.ll @@ -1,10 +1,12 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s define i8 @test() { -; CHECK-LABEL: @test -; CHECK: adrp {{x[0-9]+}}, foo -; CHECK: add {{x[0-9]+}}, {{x[0-9]+}}, :lo12:foo -; CHECK: ldrb w0, [{{x[0-9]+}}] +; CHECK-LABEL: test: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: adrp x8, foo +; CHECK-NEXT: ldrb w0, [x8, :lo12:foo] +; CHECK-NEXT: ret entry: %0 = load i8, i8* bitcast (void (...)* @foo to i8*), align 1 ret i8 %0 diff --git a/llvm/test/CodeGen/AArch64/global-alignment.ll b/llvm/test/CodeGen/AArch64/global-alignment.ll --- a/llvm/test/CodeGen/AArch64/global-alignment.ll +++ b/llvm/test/CodeGen/AArch64/global-alignment.ll @@ -51,11 +51,11 @@ ; CHECK-LABEL: test_var32_alias: %addr = bitcast [3 x i32]* @alias to i64* - ; Test that we can find the alignment for aliases. + ; We don't know anything about the alignment of aliases. %val = load i64, i64* %addr ; CHECK: adrp x[[HIBITS:[0-9]+]], alias -; CHECK-NOT: add x[[HIBITS]] -; CHECK: ldr x0, [x[[HIBITS]], {{#?}}:lo12:alias] +; CHECK: add x[[ADDR:[0-9]+]], x[[HIBITS]], {{#?}}:lo12:alias +; CHECK: ldr x0, [x[[ADDR]]] ret i64 %val } diff --git a/llvm/test/CodeGen/PowerPC/atomics-constant.ll b/llvm/test/CodeGen/PowerPC/atomics-constant.ll --- a/llvm/test/CodeGen/PowerPC/atomics-constant.ll +++ b/llvm/test/CodeGen/PowerPC/atomics-constant.ll @@ -8,11 +8,10 @@ define i64 @foo() { ; CHECK-LABEL: foo: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: addis 3, 2, a@toc@ha ; CHECK-NEXT: li 4, 0 -; CHECK-NEXT: addi 3, 3, a@toc@l +; CHECK-NEXT: addis 3, 2, a@toc@ha +; CHECK-NEXT: ld 3, a@toc@l(3) ; CHECK-NEXT: cmpd 7, 4, 4 -; CHECK-NEXT: ld 3, 0(3) ; CHECK-NEXT: li 3, 0 ; CHECK-NEXT: bne- 7, .+4 ; CHECK-NEXT: isync