[llvm] [NewPM][AArch64][GlobalISel] Port AArch64PostLegalizerCombiner to NewPM (PR #194156)
Anshul Nigham via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 3 22:25:56 PDT 2026
https://github.com/nigham updated https://github.com/llvm/llvm-project/pull/194156
>From 4520860758c347d4e268afd5b10929b96afc6445 Mon Sep 17 00:00:00 2001
From: Anshul Nigham <nigham at google.com>
Date: Sat, 25 Apr 2026 08:52:20 -0700
Subject: [PATCH 1/7] [NewPM][AArch64][GlobalISel] Port
AArch64PostLegalizerCombiner to NewPM
---
llvm/lib/Target/AArch64/AArch64.h | 16 +-
.../Target/AArch64/AArch64PassRegistry.def | 2 +
.../Target/AArch64/AArch64TargetMachine.cpp | 2 +-
.../GISel/AArch64PostLegalizerCombiner.cpp | 253 +++++++++++-------
.../AArch64/GlobalISel/combine-cast.mir | 1 +
.../AArch64/GlobalISel/combine-trunc.mir | 1 +
.../form-bitfield-extract-from-and.mir | 1 +
.../opt-overlapping-and-postlegalize.mir | 1 +
.../postlegalizer-combine-ptr-add-chain.mir | 1 +
.../prelegalizercombiner-hoist-same-hands.mir | 1 +
10 files changed, 175 insertions(+), 104 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64.h b/llvm/lib/Target/AArch64/AArch64.h
index 8cc60d3116a17..7169244c8e7eb 100644
--- a/llvm/lib/Target/AArch64/AArch64.h
+++ b/llvm/lib/Target/AArch64/AArch64.h
@@ -26,6 +26,7 @@
struct AArch64O0PreLegalizerCombinerImplRuleConfig;
struct AArch64PreLegalizerCombinerImplRuleConfig;
+struct AArch64PostLegalizerCombinerImplRuleConfig;
struct AArch64PostLegalizerLoweringImplRuleConfig;
namespace llvm {
@@ -102,6 +103,19 @@ class AArch64PreLegalizerCombinerPass
MachineFunctionAnalysisManager &MFAM);
};
+class AArch64PostLegalizerCombinerPass
+ : public PassInfoMixin<AArch64PostLegalizerCombinerPass> {
+ std::unique_ptr<AArch64PostLegalizerCombinerImplRuleConfig> RuleConfig;
+
+public:
+ AArch64PostLegalizerCombinerPass();
+ AArch64PostLegalizerCombinerPass(AArch64PostLegalizerCombinerPass &&);
+ ~AArch64PostLegalizerCombinerPass();
+
+ PreservedAnalyses run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM);
+};
+
class AArch64PostSelectOptimizePass
: public PassInfoMixin<AArch64PostSelectOptimizePass> {
public:
@@ -156,7 +170,7 @@ void initializeAArch64LowerHomogeneousPrologEpilogPass(PassRegistry &);
void initializeAArch64MIPeepholeOptLegacyPass(PassRegistry &);
void initializeAArch64O0PreLegalizerCombinerLegacyPass(PassRegistry &);
void initializeAArch64PostCoalescerLegacyPass(PassRegistry &);
-void initializeAArch64PostLegalizerCombinerPass(PassRegistry &);
+void initializeAArch64PostLegalizerCombinerLegacyPass(PassRegistry &);
void initializeAArch64PostSelectOptimizeLegacyPass(PassRegistry &);
void initializeAArch64PostLegalizerLoweringLegacyPass(PassRegistry &);
void initializeAArch64PreLegalizerCombinerLegacyPass(PassRegistry &);
diff --git a/llvm/lib/Target/AArch64/AArch64PassRegistry.def b/llvm/lib/Target/AArch64/AArch64PassRegistry.def
index 5f6eed29ae734..ae2b1f73381a9 100644
--- a/llvm/lib/Target/AArch64/AArch64PassRegistry.def
+++ b/llvm/lib/Target/AArch64/AArch64PassRegistry.def
@@ -42,6 +42,8 @@ MACHINE_FUNCTION_PASS("aarch64-post-select-optimize",
AArch64PostSelectOptimizePass())
MACHINE_FUNCTION_PASS("aarch64-postlegalizer-lowering",
AArch64PostLegalizerLoweringPass())
+MACHINE_FUNCTION_PASS("aarch64-postlegalizer-combiner",
+ AArch64PostLegalizerCombinerPass())
MACHINE_FUNCTION_PASS("aarch64-prelegalizer-combiner",
AArch64PreLegalizerCombinerPass())
MACHINE_FUNCTION_PASS("aarch64-ptrauth", AArch64PointerAuthPass())
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index 04506be1eb28d..56c8108e30292 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -256,7 +256,7 @@ LLVMInitializeAArch64Target() {
initializeAArch64PreLegalizerCombinerLegacyPass(PR);
initializeAArch64PointerAuthLegacyPass(PR);
initializeAArch64PostCoalescerLegacyPass(PR);
- initializeAArch64PostLegalizerCombinerPass(PR);
+ initializeAArch64PostLegalizerCombinerLegacyPass(PR);
initializeAArch64PostSelectOptimizeLegacyPass(PR);
initializeAArch64PostLegalizerLoweringLegacyPass(PR);
initializeAArch64PromoteConstantPass(PR);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
index 59349db88289b..8fc07ca4c9edb 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
@@ -19,6 +19,7 @@
///
//===----------------------------------------------------------------------===//
+#include "AArch64.h"
#include "AArch64TargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
@@ -34,7 +35,9 @@
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachineFunctionAnalysisManager.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/Support/Debug.h"
@@ -48,12 +51,12 @@
using namespace llvm;
using namespace MIPatternMatch;
-namespace {
-
#define GET_GICOMBINER_TYPES
#include "AArch64GenPostLegalizeGICombiner.inc"
#undef GET_GICOMBINER_TYPES
+namespace {
+
/// This combine tries do what performExtractVectorEltCombine does in SDAG.
/// Rewrite for pairwise fadd pattern
/// (s32 (g_extract_vector_elt
@@ -630,102 +633,18 @@ AArch64PostLegalizerCombinerImpl::AArch64PostLegalizerCombinerImpl(
{
}
-class AArch64PostLegalizerCombiner : public MachineFunctionPass {
-public:
- static char ID;
-
- AArch64PostLegalizerCombiner(bool IsOptNone = false);
-
- StringRef getPassName() const override {
- return "AArch64PostLegalizerCombiner";
- }
-
- bool runOnMachineFunction(MachineFunction &MF) override;
- void getAnalysisUsage(AnalysisUsage &AU) const override;
-
-private:
- bool IsOptNone;
- AArch64PostLegalizerCombinerImplRuleConfig RuleConfig;
-
-
- struct StoreInfo {
- GStore *St = nullptr;
- // The G_PTR_ADD that's used by the store. We keep this to cache the
- // MachineInstr def.
- GPtrAdd *Ptr = nullptr;
- // The signed offset to the Ptr instruction.
- int64_t Offset = 0;
- LLT StoredType;
- };
- bool tryOptimizeConsecStores(SmallVectorImpl<StoreInfo> &Stores,
- CSEMIRBuilder &MIB);
-
- bool optimizeConsecutiveMemOpAddressing(MachineFunction &MF,
- CSEMIRBuilder &MIB);
+struct StoreInfo {
+ GStore *St = nullptr;
+ // The G_PTR_ADD that's used by the store. We keep this to cache the
+ // MachineInstr def.
+ GPtrAdd *Ptr = nullptr;
+ // The signed offset to the Ptr instruction.
+ int64_t Offset = 0;
+ LLT StoredType;
};
-} // end anonymous namespace
-
-void AArch64PostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
- getSelectionDAGFallbackAnalysisUsage(AU);
- AU.addRequired<GISelValueTrackingAnalysisLegacy>();
- AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
- if (!IsOptNone) {
- AU.addRequired<MachineDominatorTreeWrapperPass>();
- AU.addPreserved<MachineDominatorTreeWrapperPass>();
- AU.addRequired<GISelCSEAnalysisWrapperPass>();
- AU.addPreserved<GISelCSEAnalysisWrapperPass>();
- }
- MachineFunctionPass::getAnalysisUsage(AU);
-}
-
-AArch64PostLegalizerCombiner::AArch64PostLegalizerCombiner(bool IsOptNone)
- : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
- if (!RuleConfig.parseCommandLineOption())
- report_fatal_error("Invalid rule identifier");
-}
-
-bool AArch64PostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
- if (MF.getProperties().hasFailedISel())
- return false;
- assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");
- const Function &F = MF.getFunction();
- bool EnableOpt =
- MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);
-
- const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();
- const auto *LI = ST.getLegalizerInfo();
-
- GISelValueTracking *VT =
- &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
- MachineDominatorTree *MDT =
- IsOptNone ? nullptr
- : &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
- GISelCSEAnalysisWrapper &Wrapper =
- getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
- auto *CSEInfo =
- &Wrapper.get(getStandardCSEConfigForOpt(MF.getTarget().getOptLevel()));
-
- CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
- /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(),
- F.hasMinSize());
- // Disable fixed-point iteration to reduce compile-time
- CInfo.MaxIterations = 1;
- CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
- // Legalizer performs DCE, so a full DCE pass is unnecessary.
- CInfo.EnableFullDCE = false;
- AArch64PostLegalizerCombinerImpl Impl(MF, CInfo, *VT, CSEInfo, RuleConfig, ST,
- MDT, LI);
- bool Changed = Impl.combineMachineInstrs();
-
- auto MIB = CSEMIRBuilder(MF);
- MIB.setCSEInfo(CSEInfo);
- Changed |= optimizeConsecutiveMemOpAddressing(MF, MIB);
- return Changed;
-}
-bool AArch64PostLegalizerCombiner::tryOptimizeConsecStores(
- SmallVectorImpl<StoreInfo> &Stores, CSEMIRBuilder &MIB) {
+static bool tryOptimizeConsecStores(SmallVectorImpl<StoreInfo> &Stores,
+ CSEMIRBuilder &MIB) {
if (Stores.size() <= 2)
return false;
@@ -770,8 +689,8 @@ static cl::opt<bool>
cl::desc("Enable consecutive memop optimization "
"in AArch64PostLegalizerCombiner"));
-bool AArch64PostLegalizerCombiner::optimizeConsecutiveMemOpAddressing(
- MachineFunction &MF, CSEMIRBuilder &MIB) {
+static bool optimizeConsecutiveMemOpAddressing(MachineFunction &MF,
+ CSEMIRBuilder &MIB) {
// This combine needs to run after all reassociations/folds on pointer
// addressing have been done, specifically those that combine two G_PTR_ADDs
// with constant offsets into a single G_PTR_ADD with a combined offset.
@@ -908,17 +827,147 @@ bool AArch64PostLegalizerCombiner::optimizeConsecutiveMemOpAddressing(
return Changed;
}
-char AArch64PostLegalizerCombiner::ID = 0;
-INITIALIZE_PASS_BEGIN(AArch64PostLegalizerCombiner, DEBUG_TYPE,
+bool runCombiner(MachineFunction &MF, GISelCSEInfo *CSEInfo,
+ GISelValueTracking *VT, MachineDominatorTree *MDT,
+ const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig,
+ bool EnableOpt, bool IsOptNone) {
+ if (MF.getProperties().hasFailedISel())
+ return false;
+ assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");
+ const Function &F = MF.getFunction();
+
+ const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();
+ const auto *LI = ST.getLegalizerInfo();
+
+ CombinerInfo CInfo(/*AllowIllegalOps=*/true, /*ShouldLegalizeIllegal=*/false,
+ /*LegalizerInfo=*/nullptr, EnableOpt, F.hasOptSize(),
+ F.hasMinSize());
+ // Disable fixed-point iteration to reduce compile-time
+ CInfo.MaxIterations = 1;
+ CInfo.ObserverLvl = CombinerInfo::ObserverLevel::SinglePass;
+ // Legalizer performs DCE, so a full DCE pass is unnecessary.
+ CInfo.EnableFullDCE = false;
+ AArch64PostLegalizerCombinerImpl Impl(MF, CInfo, *VT, CSEInfo, RuleConfig, ST,
+ MDT, LI);
+ bool Changed = Impl.combineMachineInstrs();
+
+ auto MIB = CSEMIRBuilder(MF);
+ MIB.setCSEInfo(CSEInfo);
+ Changed |= optimizeConsecutiveMemOpAddressing(MF, MIB);
+ return Changed;
+}
+
+class AArch64PostLegalizerCombinerLegacy : public MachineFunctionPass {
+public:
+ static char ID;
+
+ AArch64PostLegalizerCombinerLegacy(bool IsOptNone = false);
+
+ StringRef getPassName() const override {
+ return "AArch64PostLegalizerCombiner";
+ }
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override;
+
+private:
+ bool IsOptNone;
+ AArch64PostLegalizerCombinerImplRuleConfig RuleConfig;
+};
+} // end anonymous namespace
+
+void AArch64PostLegalizerCombinerLegacy::getAnalysisUsage(
+ AnalysisUsage &AU) const {
+ AU.setPreservesCFG();
+ getSelectionDAGFallbackAnalysisUsage(AU);
+ AU.addRequired<GISelValueTrackingAnalysisLegacy>();
+ AU.addPreserved<GISelValueTrackingAnalysisLegacy>();
+ if (!IsOptNone) {
+ AU.addRequired<MachineDominatorTreeWrapperPass>();
+ AU.addPreserved<MachineDominatorTreeWrapperPass>();
+ AU.addRequired<GISelCSEAnalysisWrapperPass>();
+ AU.addPreserved<GISelCSEAnalysisWrapperPass>();
+ }
+ MachineFunctionPass::getAnalysisUsage(AU);
+}
+
+AArch64PostLegalizerCombinerLegacy::AArch64PostLegalizerCombinerLegacy(
+ bool IsOptNone)
+ : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
+ if (!RuleConfig.parseCommandLineOption())
+ report_fatal_error("Invalid rule identifier");
+}
+
+bool AArch64PostLegalizerCombinerLegacy::runOnMachineFunction(
+ MachineFunction &MF) {
+ if (MF.getProperties().hasFailedISel())
+ return false;
+
+ GISelValueTracking *VT =
+ &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
+ MachineDominatorTree *MDT =
+ IsOptNone ? nullptr
+ : &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
+ GISelCSEAnalysisWrapper &Wrapper =
+ getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
+ auto *CSEInfo =
+ &Wrapper.get(getStandardCSEConfigForOpt(MF.getTarget().getOptLevel()));
+
+ bool EnableOpt = MF.getTarget().getOptLevel() != CodeGenOptLevel::None &&
+ !skipFunction(MF.getFunction());
+
+ return runCombiner(MF, CSEInfo, VT, MDT, RuleConfig, EnableOpt, IsOptNone);
+}
+
+char AArch64PostLegalizerCombinerLegacy::ID = 0;
+INITIALIZE_PASS_BEGIN(AArch64PostLegalizerCombinerLegacy, DEBUG_TYPE,
"Combine AArch64 MachineInstrs after legalization", false,
false)
INITIALIZE_PASS_DEPENDENCY(GISelValueTrackingAnalysisLegacy)
-INITIALIZE_PASS_END(AArch64PostLegalizerCombiner, DEBUG_TYPE,
+INITIALIZE_PASS_END(AArch64PostLegalizerCombinerLegacy, DEBUG_TYPE,
"Combine AArch64 MachineInstrs after legalization", false,
false)
+AArch64PostLegalizerCombinerPass::AArch64PostLegalizerCombinerPass()
+ : RuleConfig(
+ std::make_unique<AArch64PostLegalizerCombinerImplRuleConfig>()) {
+ if (!RuleConfig->parseCommandLineOption())
+ reportFatalUsageError("invalid rule identifier");
+}
+
+AArch64PostLegalizerCombinerPass::AArch64PostLegalizerCombinerPass(
+ AArch64PostLegalizerCombinerPass &&) = default;
+
+AArch64PostLegalizerCombinerPass::~AArch64PostLegalizerCombinerPass() = default;
+
+PreservedAnalyses
+AArch64PostLegalizerCombinerPass::run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM) {
+ if (MF.getProperties().hasFailedISel())
+ return PreservedAnalyses::all();
+
+ bool IsOptNone = MF.getTarget().getOptLevel() == CodeGenOptLevel::None;
+ bool EnableOpt = !IsOptNone;
+
+ GISelValueTracking *VT = &MFAM.getResult<GISelValueTrackingAnalysis>(MF);
+ MachineDominatorTree *MDT =
+ IsOptNone ? nullptr : &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
+ auto *CSEInfo = MFAM.getResult<GISelCSEAnalysis>(MF).get();
+
+ if (!runCombiner(MF, CSEInfo, VT, MDT, *RuleConfig, EnableOpt, IsOptNone))
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
+ PA.preserveSet<CFGAnalyses>();
+ PA.preserve<GISelValueTrackingAnalysis>();
+ if (MDT)
+ PA.preserve<MachineDominatorTreeAnalysis>();
+ PA.preserve<GISelCSEAnalysis>();
+ return PA;
+}
+
namespace llvm {
FunctionPass *createAArch64PostLegalizerCombiner(bool IsOptNone) {
- return new AArch64PostLegalizerCombiner(IsOptNone);
+ return new AArch64PostLegalizerCombinerLegacy(IsOptNone);
}
} // end namespace llvm
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-cast.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-cast.mir
index 8eab47171e0d1..5724f36d60183 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-cast.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-cast.mir
@@ -1,6 +1,7 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -o - -mtriple=aarch64-unknown-unknown -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRE
# RUN: llc -o - -mtriple=aarch64-unknown-unknown -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s | FileCheck %s --check-prefixes=CHECK,CHECK-POST
+# RUN: llc -o - -mtriple=aarch64-unknown-unknown -passes=aarch64-postlegalizer-combiner %s | FileCheck %s --check-prefixes=CHECK,CHECK-POST
---
name: test_combine_trunc_select
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-trunc.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-trunc.mir
index 9a2b9dd4b2b60..655e1ddaaa704 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-trunc.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-trunc.mir
@@ -1,6 +1,7 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -o - -mtriple=aarch64-unknown-unknown -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRE
# RUN: llc -o - -mtriple=aarch64-unknown-unknown -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s | FileCheck %s --check-prefixes=CHECK,CHECK-POST
+# RUN: llc -o - -mtriple=aarch64-unknown-unknown -passes=aarch64-postlegalizer-combiner %s | FileCheck %s --check-prefixes=CHECK,CHECK-POST
---
name: test_combine_trunc_undef
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-and.mir b/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-and.mir
index 16e84a6c1af80..49ffdf4f3ddaf 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-and.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-and.mir
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner --aarch64postlegalizercombiner-only-enable-rule="bitfield_extract_from_and" -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple aarch64 -passes=aarch64-postlegalizer-combiner --aarch64postlegalizercombiner-only-enable-rule="bitfield_extract_from_and" %s -o - | FileCheck %s
# REQUIRES: asserts
# Check that we can combine
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/opt-overlapping-and-postlegalize.mir b/llvm/test/CodeGen/AArch64/GlobalISel/opt-overlapping-and-postlegalize.mir
index 831212d6cb014..eb2dfd10b89f1 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/opt-overlapping-and-postlegalize.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/opt-overlapping-and-postlegalize.mir
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -debugify-and-strip-all-safe -mtriple arm64-apple-ios -O0 -run-pass=aarch64-postlegalizer-combiner --aarch64postlegalizercombiner-only-enable-rule="overlapping_and" -global-isel -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -debugify-and-strip-all-safe -mtriple arm64-apple-ios -O0 -passes=aarch64-postlegalizer-combiner --aarch64postlegalizercombiner-only-enable-rule="overlapping_and" -global-isel %s -o - | FileCheck %s
# REQUIRES: asserts
# Test running the overlapping_and combine post-legalization.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combine-ptr-add-chain.mir b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combine-ptr-add-chain.mir
index cfce267f40096..ec64c9e02791d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combine-ptr-add-chain.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/postlegalizer-combine-ptr-add-chain.mir
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple aarch64-apple-ios -run-pass=aarch64-postlegalizer-combiner --aarch64postlegalizercombiner-only-enable-rule="ptr_add_immed_chain" %s -o - -verify-machineinstrs | FileCheck %s
+# RUN: llc -mtriple aarch64-apple-ios -passes=aarch64-postlegalizer-combiner --aarch64postlegalizercombiner-only-enable-rule="ptr_add_immed_chain" %s -o - | FileCheck %s
# REQUIRES: asserts
# Check that we fold two adds of constant offsets with G_PTR_ADD into a single G_PTR_ADD.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-hoist-same-hands.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-hoist-same-hands.mir
index 1b85cec49226c..7f51b69c1e20e 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-hoist-same-hands.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-hoist-same-hands.mir
@@ -1,6 +1,7 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-PRE
# RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POST
+# RUN: llc -mtriple aarch64 -passes=aarch64-postlegalizer-combiner %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-POST
---
name: or_combine_sext
>From ec69700651b8a8148bf2c8c2471db518bf67006b Mon Sep 17 00:00:00 2001
From: Anshul Nigham <nigham at google.com>
Date: Sat, 25 Apr 2026 13:56:36 -0700
Subject: [PATCH 2/7] Removed redundant MDT preserve
---
llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
index 29df311bba4dd..12c2754bc167e 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
@@ -962,8 +962,6 @@ AArch64PostLegalizerCombinerPass::run(MachineFunction &MF,
PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
PA.preserveSet<CFGAnalyses>();
PA.preserve<GISelValueTrackingAnalysis>();
- if (MDT)
- PA.preserve<MachineDominatorTreeAnalysis>();
PA.preserve<GISelCSEAnalysis>();
return PA;
}
>From de68d8dcae105e4a09fa722a13d86035b18c706a Mon Sep 17 00:00:00 2001
From: Anshul Nigham <nigham at google.com>
Date: Wed, 6 May 2026 23:24:29 -0700
Subject: [PATCH 3/7] Review comments
---
llvm/lib/Target/AArch64/AArch64.h | 2 +-
.../Target/AArch64/AArch64TargetMachine.cpp | 22 +++++++++++--------
.../lib/Target/AArch64/AArch64TargetMachine.h | 9 +++++++-
.../GISel/AArch64PostLegalizerCombiner.cpp | 6 ++---
4 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64.h b/llvm/lib/Target/AArch64/AArch64.h
index 730a83cb17114..da4c59b5958e6 100644
--- a/llvm/lib/Target/AArch64/AArch64.h
+++ b/llvm/lib/Target/AArch64/AArch64.h
@@ -143,7 +143,7 @@ class AArch64PostLegalizerLoweringPass
FunctionPass *createAArch64O0PreLegalizerCombiner();
FunctionPass *createAArch64PreLegalizerCombiner();
-FunctionPass *createAArch64PostLegalizerCombiner(bool IsOptNone);
+FunctionPass *createAArch64PostLegalizerCombinerLegacy(bool IsOptNone);
FunctionPass *createAArch64PostLegalizerLowering();
FunctionPass *createAArch64PostSelectOptimize();
FunctionPass *createAArch64StackTaggingPass(bool IsOptNone);
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index 635ba7fc6fcad..48f7d85b7bcb6 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -281,6 +281,16 @@ LLVMInitializeAArch64Target() {
initializeAArch64Arm64ECCallLoweringPass(PR);
}
+bool llvm::isGlobalISelOptNone(const TargetMachine *TM) {
+ const bool GlobalISelFlag =
+ getCGPassBuilderOption().EnableGlobalISelOption.value_or(false);
+
+ return TM->getOptLevel() == CodeGenOptLevel::None ||
+ (static_cast<unsigned>(TM->getOptLevel()) >
+ AArch64TargetMachine::getEnableGlobalISelAtO() &&
+ !GlobalISelFlag);
+}
+
void AArch64TargetMachine::reset() { SubtargetMap.clear(); }
//===----------------------------------------------------------------------===//
@@ -413,7 +423,7 @@ AArch64TargetMachine::AArch64TargetMachine(const Target &T, const Triple &TT,
setCFIFixup(true);
}
-unsigned AArch64TargetMachine::getEnableGlobalISelAtO() const {
+unsigned AArch64TargetMachine::getEnableGlobalISelAtO() {
return EnableGlobalISelAtO;
}
@@ -615,13 +625,7 @@ std::unique_ptr<CSEConfigBase> AArch64PassConfig::getCSEConfig() const {
// globalisel at, and it wasn't enabled via CLI, we know that it must be because
// of an optnone function.
bool AArch64PassConfig::isGlobalISelOptNone() const {
- const bool GlobalISelFlag =
- getCGPassBuilderOption().EnableGlobalISelOption.value_or(false);
-
- return getOptLevel() == CodeGenOptLevel::None ||
- (static_cast<unsigned>(getOptLevel()) >
- getAArch64TargetMachine().getEnableGlobalISelAtO() &&
- !GlobalISelFlag);
+ return llvm::isGlobalISelOptNone(&getAArch64TargetMachine());
}
void AArch64PassConfig::addIRPasses() {
@@ -770,7 +774,7 @@ bool AArch64PassConfig::addLegalizeMachineIR() {
void AArch64PassConfig::addPreRegBankSelect() {
if (!isGlobalISelOptNone()) {
- addPass(createAArch64PostLegalizerCombiner(isGlobalISelOptNone()));
+ addPass(createAArch64PostLegalizerCombinerLegacy(isGlobalISelOptNone()));
if (EnableGISelLoadStoreOptPostLegal)
addPass(new LoadStoreOpt());
}
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.h b/llvm/lib/Target/AArch64/AArch64TargetMachine.h
index 209374553d297..09fd5f485da60 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.h
@@ -21,6 +21,13 @@
namespace llvm {
+// This function checks whether the opt level is explicitly set to none,
+// or whether GlobalISel was enabled due to SDAG encountering an optnone
+// function. If the opt level is greater than the level we automatically enable
+// globalisel at, and it wasn't enabled via CLI, we know that it must be because
+// of an optnone function.
+bool isGlobalISelOptNone(const TargetMachine *TM);
+
class AArch64TargetMachine : public CodeGenTargetMachineImpl {
protected:
std::unique_ptr<TargetLoweringObjectFile> TLOF;
@@ -80,7 +87,7 @@ class AArch64TargetMachine : public CodeGenTargetMachineImpl {
const SmallPtrSetImpl<MachineInstr *> &MIs) const override;
/// Returns the optimisation level that enables GlobalISel.
- unsigned getEnableGlobalISelAtO() const;
+ static unsigned getEnableGlobalISelAtO();
private:
bool isLittle;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
index 12c2754bc167e..313c0bc72f921 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
@@ -948,13 +948,13 @@ AArch64PostLegalizerCombinerPass::run(MachineFunction &MF,
if (MF.getProperties().hasFailedISel())
return PreservedAnalyses::all();
- bool IsOptNone = MF.getTarget().getOptLevel() == CodeGenOptLevel::None;
+ bool IsOptNone = llvm::isGlobalISelOptNone(&MF.getTarget());
bool EnableOpt = !IsOptNone;
GISelValueTracking *VT = &MFAM.getResult<GISelValueTrackingAnalysis>(MF);
MachineDominatorTree *MDT =
IsOptNone ? nullptr : &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
- auto *CSEInfo = MFAM.getResult<GISelCSEAnalysis>(MF).get();
+ GISelCSEInfo *CSEInfo = MFAM.getResult<GISelCSEAnalysis>(MF).get();
if (!runCombiner(MF, CSEInfo, VT, MDT, *RuleConfig, EnableOpt, IsOptNone))
return PreservedAnalyses::all();
@@ -967,7 +967,7 @@ AArch64PostLegalizerCombinerPass::run(MachineFunction &MF,
}
namespace llvm {
-FunctionPass *createAArch64PostLegalizerCombiner(bool IsOptNone) {
+FunctionPass *createAArch64PostLegalizerCombinerLegacy(bool IsOptNone) {
return new AArch64PostLegalizerCombinerLegacy(IsOptNone);
}
} // end namespace llvm
>From e13c5cacfbc67cf2d3eed19c5037d7d430a8d2e8 Mon Sep 17 00:00:00 2001
From: Anshul Nigham <nigham at google.com>
Date: Tue, 12 May 2026 19:50:41 -0700
Subject: [PATCH 4/7] Remove spurious decl
---
llvm/lib/Target/AArch64/AArch64TargetMachine.h | 7 -------
1 file changed, 7 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.h b/llvm/lib/Target/AArch64/AArch64TargetMachine.h
index 71ae3276d854c..98eaecbb6d2af 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.h
@@ -21,13 +21,6 @@
namespace llvm {
-// This function checks whether the opt level is explicitly set to none,
-// or whether GlobalISel was enabled due to SDAG encountering an optnone
-// function. If the opt level is greater than the level we automatically enable
-// globalisel at, and it wasn't enabled via CLI, we know that it must be because
-// of an optnone function.
-bool isGlobalISelOptNone(const TargetMachine *TM);
-
class AArch64TargetMachine : public CodeGenTargetMachineImpl {
protected:
std::unique_ptr<TargetLoweringObjectFile> TLOF;
>From 5456de4de7b089a7d6ec041a4f079ece6b1c2539 Mon Sep 17 00:00:00 2001
From: Anshul Nigham <nigham at google.com>
Date: Sat, 16 May 2026 12:22:07 -0700
Subject: [PATCH 5/7] Review comments
---
llvm/lib/Target/AArch64/AArch64.h | 4 ++++
.../Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp | 8 ++++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64.h b/llvm/lib/Target/AArch64/AArch64.h
index 5a285c2bd5a16..c85324bf2d998 100644
--- a/llvm/lib/Target/AArch64/AArch64.h
+++ b/llvm/lib/Target/AArch64/AArch64.h
@@ -118,6 +118,10 @@ class AArch64PostLegalizerCombinerPass
PreservedAnalyses run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM);
+ MachineFunctionProperties getRequiredProperties() const {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::Legalized);
+ }
};
class AArch64PostSelectOptimizePass
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
index 386ede391b972..7073154052d9b 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
@@ -835,11 +835,10 @@ bool runCombiner(MachineFunction &MF, GISelCSEInfo *CSEInfo,
bool EnableOpt, bool IsOptNone) {
if (MF.getProperties().hasFailedISel())
return false;
- assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");
const Function &F = MF.getFunction();
const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();
- const auto *LI = ST.getLegalizerInfo();
+ const LegalizerInfo *LI = ST.getLegalizerInfo();
CombinerInfo CInfo(/*AllowIllegalOps=*/true, /*ShouldLegalizeIllegal=*/false,
/*LegalizerInfo=*/nullptr, EnableOpt, F.hasOptSize(),
@@ -872,6 +871,11 @@ class AArch64PostLegalizerCombinerLegacy : public MachineFunctionPass {
bool runOnMachineFunction(MachineFunction &MF) override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::Legalized);
+ }
+
private:
bool IsOptNone;
AArch64PostLegalizerCombinerImplRuleConfig RuleConfig;
>From 518204246d348bd5f1724e89836e03f703610315 Mon Sep 17 00:00:00 2001
From: Anshul Nigham <nigham at google.com>
Date: Thu, 21 May 2026 15:36:03 -0700
Subject: [PATCH 6/7] Use Legalizer for CombinerInfo and disallow illegal ops
---
.../lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
index 7073154052d9b..c57a99a9bccf7 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
@@ -840,8 +840,8 @@ bool runCombiner(MachineFunction &MF, GISelCSEInfo *CSEInfo,
const AArch64Subtarget &ST = MF.getSubtarget<AArch64Subtarget>();
const LegalizerInfo *LI = ST.getLegalizerInfo();
- CombinerInfo CInfo(/*AllowIllegalOps=*/true, /*ShouldLegalizeIllegal=*/false,
- /*LegalizerInfo=*/nullptr, EnableOpt, F.hasOptSize(),
+ CombinerInfo CInfo(/*AllowIllegalOps=*/false, /*ShouldLegalizeIllegal=*/false,
+ /*LegalizerInfo=*/LI, EnableOpt, F.hasOptSize(),
F.hasMinSize());
// Disable fixed-point iteration to reduce compile-time
CInfo.MaxIterations = 1;
>From 4a37b03c964d1358e9208c80822347c860f5e663 Mon Sep 17 00:00:00 2001
From: Anshul Nigham <nigham at google.com>
Date: Wed, 3 Jun 2026 22:25:38 -0700
Subject: [PATCH 7/7] Address review comments
---
.../Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
index c57a99a9bccf7..9b30aecb03102 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
@@ -852,7 +852,7 @@ bool runCombiner(MachineFunction &MF, GISelCSEInfo *CSEInfo,
MDT, LI);
bool Changed = Impl.combineMachineInstrs();
- auto MIB = CSEMIRBuilder(MF);
+ CSEMIRBuilder MIB(MF);
MIB.setCSEInfo(CSEInfo);
Changed |= optimizeConsecutiveMemOpAddressing(MF, MIB);
return Changed;
@@ -901,7 +901,7 @@ AArch64PostLegalizerCombinerLegacy::AArch64PostLegalizerCombinerLegacy(
bool IsOptNone)
: MachineFunctionPass(ID), IsOptNone(IsOptNone) {
if (!RuleConfig.parseCommandLineOption())
- report_fatal_error("Invalid rule identifier");
+ reportFatalUsageError("Invalid rule identifier");
}
bool AArch64PostLegalizerCombinerLegacy::runOnMachineFunction(
@@ -954,7 +954,7 @@ AArch64PostLegalizerCombinerPass::run(MachineFunction &MF,
if (MF.getProperties().hasFailedISel())
return PreservedAnalyses::all();
- bool IsOptNone = TM->isGlobalISelOptNone();
+ const bool IsOptNone = TM->isGlobalISelOptNone();
bool EnableOpt = !IsOptNone;
GISelValueTracking *VT = &MFAM.getResult<GISelValueTrackingAnalysis>(MF);
More information about the llvm-commits
mailing list