diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 939a5cb08a3..5d91c623739 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -662,7 +662,7 @@ public: virtual 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/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index a26c54ce9a3..3a7b718845c 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -76,6 +76,10 @@ public: 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 @@ public: 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/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 1c19011c913..cf704d1f237 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -185,7 +185,6 @@ public: GlobalValue(const GlobalValue &) = delete; - unsigned getAlignment() const; unsigned getAddressSpace() const; enum class UnnamedAddr { @@ -549,10 +548,6 @@ public: 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/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index e9cf5af00da..a23f39be6b2 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1179,7 +1179,7 @@ void ModuleBitcodeWriter::writeModuleInfo() { 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/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 3b5f837ba7c..1540a19687c 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -157,7 +157,7 @@ static gcp_map_type &getGCMap(void *&P) { /// 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/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index ef584afc68b..81eaaafb135 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -1239,8 +1239,8 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1, // 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/lib/IR/Core.cpp b/lib/IR/Core.cpp index 52755f820b6..6f3bbc80d4f 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -2003,7 +2003,7 @@ LLVMTypeRef LLVMGlobalGetValueType(LLVMValueRef Global) { 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 @@ unsigned LLVMGetAlignment(LLVMValueRef V) { 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/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 34c767ff367..dd8e62164de 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -108,20 +108,6 @@ bool GlobalValue::canBenefitFromLocalAlias() const { !isa(this) && !hasComdat(); } -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(); @@ -252,7 +238,7 @@ bool GlobalValue::isDeclaration() const { 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/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index ee4bb72cee1..b5e4ce9f44b 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -570,8 +570,9 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) { 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/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp index 0d37e919ff5..ebe779aea62 100644 --- a/lib/LTO/LTOModule.cpp +++ b/lib/LTO/LTOModule.cpp @@ -414,9 +414,8 @@ void LTOModule::addDefinedFunctionSymbol(StringRef Name, const Function *F) { 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 attr = align ? countTrailingZeros(align) : 0; + const GlobalObject *go = dyn_cast(def); + uint32_t attr = go ? Log2(go->getAlign().valueOrOne()) : 0; // set permissions part if (isFunction) { diff --git a/lib/Object/IRSymtab.cpp b/lib/Object/IRSymtab.cpp index a92cb02ed29..e39cb732add 100644 --- a/lib/Object/IRSymtab.cpp +++ b/lib/Object/IRSymtab.cpp @@ -264,9 +264,13 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, 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/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp index 396ec47e3d7..1c8524be0de 100644 --- a/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -904,16 +904,9 @@ bool AArch64DAGToDAGISel::SelectAddrModeIndexed(SDValue N, unsigned Size, 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/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp index 349def06f04..8df8edd3e0b 100644 --- a/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ b/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -5161,13 +5161,8 @@ AArch64InstructionSelector::tryFoldAddLowIntoImm(MachineInstr &RootDef, if (GV->isThreadLocal()) return None; - unsigned Alignment = GV->getAlignment(); - Type *Ty = GV->getValueType(); auto &MF = *RootDef.getParent()->getParent(); - if (Alignment == 0 && Ty->isSized()) - Alignment = MF.getDataLayout().getABITypeAlignment(Ty); - - if (Alignment < Size) + if (GV->getPointerAlignment(MF.getDataLayout()) < Size) return None; unsigned OpFlags = STI.ClassifyGlobalReference(GV, MF.getTarget()); diff --git a/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/lib/Target/AMDGPU/AMDGPUISelLowering.cpp index 8762b71cbf1..16b81118523 100644 --- a/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -1321,7 +1321,7 @@ SDValue AMDGPUTargetLowering::LowerGlobalAddress(AMDGPUMachineFunction* MFI, // 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()); } } @@ -4589,11 +4589,10 @@ void AMDGPUTargetLowering::computeKnownBitsForTargetNode( } 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/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index 92468e55e15..96a10623d2d 100644 --- a/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -2099,7 +2099,9 @@ bool AMDGPULegalizerInfo::legalizeGlobalValue( 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/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp b/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp index 2c3619b7df2..4c82d056ef6 100644 --- a/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp +++ b/lib/Target/AMDGPU/AMDGPUMachineFunction.cpp @@ -38,7 +38,7 @@ AMDGPUMachineFunction::AMDGPUMachineFunction(const MachineFunction &MF) : } 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/lib/Target/AMDGPU/AMDGPUMachineFunction.h b/lib/Target/AMDGPU/AMDGPUMachineFunction.h index d5298c62e66..c504dd76bc6 100644 --- a/lib/Target/AMDGPU/AMDGPUMachineFunction.h +++ b/lib/Target/AMDGPU/AMDGPUMachineFunction.h @@ -77,7 +77,7 @@ public: return WaveLimiter; } - unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalValue &GV); + unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV); }; } diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 4b51cb94adb..4f92d1092de 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1143,8 +1143,11 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { // 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/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 71fad23b78c..264013c6f0a 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -6659,7 +6659,8 @@ void PPCDAGToDAGISel::PeepholePPC64() { 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 @@ void PPCDAGToDAGISel::PeepholePPC64() { 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/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index 1754bca39dd..7686440087a 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -3591,9 +3591,11 @@ bool PPCInstrInfo::isImmElgibleForForwarding(const MachineOperand &ImmMO, // 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/lib/Target/SystemZ/SystemZSubtarget.cpp b/lib/Target/SystemZ/SystemZSubtarget.cpp index bebfe72a1dc..68e0b7ae66a 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -74,9 +74,12 @@ bool SystemZSubtarget::enableSubRegLiveness() const { 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/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index d8087282ff5..c32653137a1 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -435,7 +435,7 @@ SDValue XCoreTargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const { 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/test/CodeGen/AArch64/funcptr_cast.ll b/test/CodeGen/AArch64/funcptr_cast.ll index 506485ec5b0..19a20c8bcf4 100644 --- a/test/CodeGen/AArch64/funcptr_cast.ll +++ b/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/test/CodeGen/AArch64/global-alignment.ll b/test/CodeGen/AArch64/global-alignment.ll index 5e820b8bb30..84bf20d6736 100644 --- a/test/CodeGen/AArch64/global-alignment.ll +++ b/test/CodeGen/AArch64/global-alignment.ll @@ -51,11 +51,11 @@ define i64 @test_var32_alias() { ; 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/test/CodeGen/PowerPC/atomics-constant.ll b/test/CodeGen/PowerPC/atomics-constant.ll index ac0b16b55f7..cc442898ab8 100644 --- a/test/CodeGen/PowerPC/atomics-constant.ll +++ b/test/CodeGen/PowerPC/atomics-constant.ll @@ -8,11 +8,10 @@ target triple = "powerpc64le-unknown-linux-gnu" 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