https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/221669
>From 5ade7660875f00377916302f86e7b5a99a8c58d2 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sun, 6 Sep 2026 13:48:59 +0200 Subject: [PATCH] PPC: Read the ELF ABI from the "target-abi" module flag Resolve the ELFv2 ABI from the effective ABI name module flag, rather than strictly relying on the -target-abi flag. Also start emitting "target-abi" for PPC from clang. Co-authored-by: Claude (Claude-Opus-4.8) <[email protected]> --- clang/lib/CodeGen/CodeGenModule.cpp | 3 +- clang/test/CodeGen/stack-protector-guard.c | 2 +- llvm/lib/Target/PowerPC/PPC.h | 4 ++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 3 +- llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 2 +- llvm/lib/Target/PowerPC/PPCSubtarget.cpp | 8 ++-- llvm/lib/Target/PowerPC/PPCSubtarget.h | 5 ++- llvm/lib/Target/PowerPC/PPCTargetMachine.cpp | 35 +++++++++--------- llvm/lib/Target/PowerPC/PPCTargetMachine.h | 7 ++-- .../Target/PowerPC/PPCTargetTransformInfo.cpp | 3 +- .../CodeGen/PowerPC/target-abi-module-flag.ll | 37 +++++++++++++++++++ 11 files changed, 79 insertions(+), 30 deletions(-) create mode 100644 llvm/test/CodeGen/PowerPC/target-abi-module-flag.ll diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index b7bd5744bcb09..1df75fcef38cb 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1490,7 +1490,8 @@ void CodeGenModule::Release() { // Other targets have no apparent need for the ABI name, but set a non-empty // value. if (StringRef ABIStr = Target.getABI(); - !ABIStr.empty() && (T.isARM() || T.isThumb() || T.isRISCV())) { + !ABIStr.empty() && + (T.isARM() || T.isThumb() || T.isRISCV() || T.isPPC())) { getModule().addModuleFlag(llvm::Module::Error, "target-abi", llvm::MDString::get(VMContext, ABIStr)); } diff --git a/clang/test/CodeGen/stack-protector-guard.c b/clang/test/CodeGen/stack-protector-guard.c index 5438671483aff..e90b2070f630f 100644 --- a/clang/test/CodeGen/stack-protector-guard.c +++ b/clang/test/CodeGen/stack-protector-guard.c @@ -67,7 +67,7 @@ void bar(int x) { // RISCV: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"tp"} // RISCV: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 44} -// POWERPC64: !llvm.module.flags = !{[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]]} +// POWERPC64: !llvm.module.flags = !{{{.*}}[[ATTR1:![0-9]+]], [[ATTR2:![0-9]+]], [[ATTR3:![0-9]+]]} // POWERPC64: [[ATTR1]] = !{i32 1, !"stack-protector-guard", !"tls"} // POWERPC64: [[ATTR2]] = !{i32 1, !"stack-protector-guard-reg", !"r13"} // POWERPC64: [[ATTR3]] = !{i32 1, !"stack-protector-guard-offset", i32 52} diff --git a/llvm/lib/Target/PowerPC/PPC.h b/llvm/lib/Target/PowerPC/PPC.h index cf60a23aa5b4a..7fe80d5ba52f3 100644 --- a/llvm/lib/Target/PowerPC/PPC.h +++ b/llvm/lib/Target/PowerPC/PPC.h @@ -97,6 +97,10 @@ class ModulePass; InstructionSelector * createPPCInstructionSelector(const PPCTargetMachine &, const PPCSubtarget &, const PPCRegisterBankInfo &); + + /// The PowerPC ABI variant. + enum PPCABI { PPC_ABI_UNKNOWN, PPC_ABI_ELFv1, PPC_ABI_ELFv2 }; + namespace PPCII { /// Target Operand Flag enum. diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index f4b7a7d701e65..e78eb5239871f 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1941,7 +1941,8 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) { } void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) { - if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) { + if (PPCTargetMachine::computeABI(M.getTargetTriple(), + TM.getTargetABIName(M)) == PPC_ABI_ELFv2) { PPCTargetStreamer *TS = static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer()); TS->emitAbiVersion(2); diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp index 1f6c9e4c4a7a8..ea96394f97ff3 100644 --- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -687,7 +687,7 @@ PPCRegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC, // For Power9 we allow the user to enable GPR to vector spills. // FIXME: Currently limited to spilling GP8RC. A follow on patch will add // support to spill GPRC. - if (TM.isELFv2ABI() || Subtarget.isAIXABI()) { + if (Subtarget.isELFv2ABI() || Subtarget.isAIXABI()) { if (Subtarget.hasP9Vector() && EnableGPRToVecSpills && RC == &PPC::G8RCRegClass) { InflateGP8RC++; diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp index 1641e335159a7..2dfb67ff4c33d 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.cpp @@ -52,8 +52,10 @@ PPCSubtarget &PPCSubtarget::initializeSubtargetDependencies(StringRef CPU, } PPCSubtarget::PPCSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, - StringRef FS, const PPCTargetMachine &TM) - : PPCGenSubtargetInfo(TT, CPU, TuneCPU, FS), TM(TM), + StringRef FS, StringRef ABIName, + const PPCTargetMachine &TM) + : PPCGenSubtargetInfo(TT, CPU, TuneCPU, FS), + TargetABI(PPCTargetMachine::computeABI(TT, ABIName)), TM(TM), FrameLowering(initializeSubtargetDependencies(CPU, TuneCPU, FS)), InstrInfo(*this), TLInfo(TM, *this) { TSInfo = std::make_unique<PPCSelectionDAGInfo>(); @@ -247,7 +249,7 @@ CodeModel::Model PPCSubtarget::getCodeModel(const TargetMachine &TM, return ModuleModel; } -bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); } +bool PPCSubtarget::isELFv2ABI() const { return TargetABI == PPC_ABI_ELFv2; } bool PPCSubtarget::isUsingPCRelativeCalls() const { return isPPC64() && hasPCRelativeMemops() && isELFv2ABI() && diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.h b/llvm/lib/Target/PowerPC/PPCSubtarget.h index eec0e141debd4..f303a3e7ee217 100644 --- a/llvm/lib/Target/PowerPC/PPCSubtarget.h +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.h @@ -94,6 +94,9 @@ class PPCSubtarget : public PPCGenSubtargetInfo { bool IsLittleEndian; + /// The selected ABI variant. + PPCABI TargetABI = PPC_ABI_UNKNOWN; + POPCNTDKind HasPOPCNTD; const PPCTargetMachine &TM; @@ -115,7 +118,7 @@ class PPCSubtarget : public PPCGenSubtargetInfo { /// of the specified triple. /// PPCSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, - const PPCTargetMachine &TM); + StringRef ABIName, const PPCTargetMachine &TM); ~PPCSubtarget() override; diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp index 07638bcf507e3..ef86320bd5c87 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -192,26 +192,23 @@ static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { return std::make_unique<PPC64LinuxTargetObjectFile>(); } -static PPCTargetMachine::PPCABI computeTargetABI(const Triple &TT, - const TargetOptions &Options) { - if (Options.MCOptions.getABIName().starts_with("elfv1")) - return PPCTargetMachine::PPC_ABI_ELFv1; - else if (Options.MCOptions.getABIName().starts_with("elfv2")) - return PPCTargetMachine::PPC_ABI_ELFv2; +// An explicit ABI name takes precedence; otherwise use the triple default. +PPCABI PPCTargetMachine::computeABI(const Triple &TT, StringRef ABIName) { + if (ABIName.starts_with("elfv1")) + return PPC_ABI_ELFv1; + if (ABIName.starts_with("elfv2")) + return PPC_ABI_ELFv2; - assert(Options.MCOptions.getABIName().empty() && - "Unknown target-abi option!"); + if (TT.isOSAIX()) + return PPC_ABI_UNKNOWN; switch (TT.getArch()) { case Triple::ppc64le: - return PPCTargetMachine::PPC_ABI_ELFv2; + return PPC_ABI_ELFv2; case Triple::ppc64: - if (TT.isPPC64ELFv2ABI()) - return PPCTargetMachine::PPC_ABI_ELFv2; - else - return PPCTargetMachine::PPC_ABI_ELFv1; + return TT.isPPC64ELFv2ABI() ? PPC_ABI_ELFv2 : PPC_ABI_ELFv1; default: - return PPCTargetMachine::PPC_ABI_UNKNOWN; + return PPC_ABI_UNKNOWN; } } @@ -306,7 +303,6 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT, getEffectiveRelocModel(TT, RM), getEffectivePPCCodeModel(TT, CM, JIT), OL), TLOF(createTLOF(getTargetTriple())), - TargetABI(computeTargetABI(TT, Options)), Endianness(TT.isLittleEndian() ? Endian::LITTLE : Endian::BIG) { initAsmInfo(); } @@ -337,7 +333,11 @@ PPCTargetMachine::getSubtargetImpl(const Function &F) const { if (SoftFloat) FS += FS.empty() ? "-hard-float" : ",-hard-float"; - auto &I = SubtargetMap[CPU + TuneCPU + FS]; + // Prefer the "target-abi" module flag, falling back to the -target-abi + // option. + StringRef ABIName = getTargetABIName(*F.getParent()); + + auto &I = SubtargetMap[CPU + TuneCPU + FS + ABIName.str()]; if (!I) { I = std::make_unique<PPCSubtarget>( TargetTriple, CPU, TuneCPU, @@ -347,7 +347,8 @@ PPCTargetMachine::getSubtargetImpl(const Function &F) const { // shouldn't require adding them. Fixing this means pulling Feature64Bit // out of most of the target cpus in the .td file and making it set only // as part of initialization via the TargetTriple. - computeFSAdditions(FS, getOptLevel(), getTargetTriple()), *this); + computeFSAdditions(FS, getOptLevel(), getTargetTriple()), ABIName, + *this); } return I.get(); } diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.h b/llvm/lib/Target/PowerPC/PPCTargetMachine.h index cb02b446fadb3..660f47b355648 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.h +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.h @@ -25,12 +25,10 @@ namespace llvm { /// class PPCTargetMachine final : public CodeGenTargetMachineImpl { public: - enum PPCABI { PPC_ABI_UNKNOWN, PPC_ABI_ELFv1, PPC_ABI_ELFv2 }; enum Endian { NOT_DETECTED, LITTLE, BIG }; private: std::unique_ptr<TargetLoweringObjectFile> TLOF; - PPCABI TargetABI; Endian Endianness = Endian::NOT_DETECTED; mutable bool HasGlibcHWCAPAccess = false; @@ -68,7 +66,10 @@ class PPCTargetMachine final : public CodeGenTargetMachineImpl { ScheduleDAGInstrs * createPostMachineScheduler(MachineSchedContext *C) const override; - bool isELFv2ABI() const { return TargetABI == PPC_ABI_ELFv2; } + /// Compute the ABI variant for \p TT and \p ABIName (the "target-abi" module + /// flag), falling back to the triple default. + static PPCABI computeABI(const Triple &TT, StringRef ABIName); + bool hasGlibcHWCAPAccess() const { return HasGlibcHWCAPAccess; } void setGlibcHWCAPAccess(bool Val = true) const { HasGlibcHWCAPAccess = Val; } bool isPPC64() const { diff --git a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp index 32a7f3701f9f2..3b2c5b06e0cfa 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetTransformInfo.cpp @@ -983,9 +983,8 @@ bool PPCTTIImpl::isLSRCostLess(const TargetTransformInfo::LSRCost &C1, bool PPCTTIImpl::isNumRegsMajorCostOfLSR() const { return false; } bool PPCTTIImpl::shouldBuildRelLookupTables() const { - const PPCTargetMachine &TM = ST->getTargetMachine(); // XCOFF hasn't implemented lowerRelativeReference, disable non-ELF for now. - if (!TM.isELFv2ABI()) + if (!ST->isELFv2ABI()) return false; return BaseT::shouldBuildRelLookupTables(); } diff --git a/llvm/test/CodeGen/PowerPC/target-abi-module-flag.ll b/llvm/test/CodeGen/PowerPC/target-abi-module-flag.ll new file mode 100644 index 0000000000000..b2b778f0e25e4 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/target-abi-module-flag.ll @@ -0,0 +1,37 @@ +; Check that the "target-abi" module flag selects the PPC ELF ABI, so the ABI +; is taken from the IR when no -target-abi option is given. The flag overrides +; the triple default in both directions (.abiversion 2 is emitted for ELFv2). + +; RUN: split-file %s %t + +; powerpc64 big-endian defaults to ELFv1; an elfv2 module flag overrides that. +; RUN: llc -mtriple=powerpc64-unknown-linux < %t/elfv2.ll | FileCheck %s --check-prefix=ELFv2 + +; powerpc64le defaults to ELFv2; an elfv1 module flag overrides that. +; RUN: llc -mtriple=powerpc64le-unknown-linux < %t/elfv1.ll | FileCheck %s --check-prefix=ELFv1 + +; A matching -target-abi option is accepted. +; RUN: llc -mtriple=powerpc64-unknown-linux -target-abi elfv2 < %t/elfv2.ll | FileCheck %s --check-prefix=ELFv2 + +; A conflicting -target-abi option is rejected. +; RUN: not llc -mtriple=powerpc64-unknown-linux -target-abi elfv1 < %t/elfv2.ll 2>&1 | FileCheck %s --check-prefix=CONFLICT + +; ELFv2: .abiversion 2 +; ELFv1-NOT: .abiversion 2 +; CONFLICT: -target-abi option != target-abi module flag + +;--- elfv1.ll +define void @f() { + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"elfv1"} + +;--- elfv2.ll +define void @g() { + ret void +} + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"target-abi", !"elfv2"} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
