[llvm] [MachineOutliner] Don't outline ADRP pair to avoid incorrect ICF (PR #160232)
Sam Elliott via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 24 22:59:17 PDT 2025
================
@@ -10179,11 +10179,33 @@ AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
return outliner::InstrType::Illegal;
}
- // Special cases for instructions that can always be outlined, but will fail
- // the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
- // be outlined because they don't require a *specific* value to be in LR.
- if (MI.getOpcode() == AArch64::ADRP)
+ // An ADRP instruction referencing a GOT should not be outlined.
+ // This is to avoid splitting ADRP/(LDR/ADD/etc.) pair into different
+ // functions which can lead to linker ICF merging sections incorrectly.
+ if (MI.getOpcode() == AArch64::ADRP) {
+ bool IsPage = (MI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0;
+ bool IsGot = (MI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0;
+ if (IsPage && IsGot)
+ return outliner::InstrType::Illegal;
+
+ // Special cases for instructions that can always be outlined, but will fail
+ // the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
+ // be outlined because they don't require a *specific* value to be in LR.
return outliner::InstrType::Legal;
+ }
+
+ // Similarly, any user of ADRP instruction referencing a GOT should not be
+ // outlined. It's hard/costly to check exact users of ADRP. So we use check
+ // all operands and reject any that's a page offset and references a GOT.
+ const auto &F = MI.getMF()->getFunction();
+ for (const auto &MO : MI.operands()) {
+ bool IsPageOff = (MO.getTargetFlags() & AArch64II::MO_PAGEOFF) != 0;
+ bool IsGot = (MO.getTargetFlags() & AArch64II::MO_GOT) != 0;
+ if (IsPageOff && IsGot &&
+ (MI.getMF()->getTarget().getFunctionSections() || F.hasComdat() ||
----------------
lenary wrote:
The additional conditions are to detect the cases where the outlined function will be in a separate section to the original function. If you're outlining from a function to create a function in the same section, then you shouldn't need to worry about ICF (which only works with -ffunction-sections, iirc). This is the approach we made on RISC-V, but I note that ADRP does work slightly differently to AUIPC.
https://github.com/llvm/llvm-project/pull/160232
More information about the llvm-commits
mailing list