[llvm] [GISel][X86] port X86PreLegalizerCombiner to npm (PR #182638)
Gergo Stomfai via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 21 12:35:37 PST 2026
https://github.com/stomfaig updated https://github.com/llvm/llvm-project/pull/182638
>From 5489c59880d37b6f923a2ee6d2238da0473c8d1c Mon Sep 17 00:00:00 2001
From: stomfaig <stomfaig at gmail.com>
Date: Sat, 21 Feb 2026 00:45:17 +0000
Subject: [PATCH 1/3] port X86PreLegalizerCombiner to npm
---
.../X86/GISel/X86PreLegalizerCombiner.cpp | 38 +++++++++++++++++++
llvm/lib/Target/X86/X86.h | 8 ++++
llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp | 6 +++
llvm/lib/Target/X86/X86PassRegistry.def | 1 +
4 files changed, 53 insertions(+)
diff --git a/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp b/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
index 01c3473d16292..14195766bd887 100644
--- a/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
@@ -171,6 +171,44 @@ INITIALIZE_PASS_END(X86PreLegalizerCombiner, DEBUG_TYPE,
false)
namespace llvm {
+
+PreservedAnalyses
+X86PreLegalizerCombinerPass::run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM) {
+ if (MF.getProperties().hasFailedISel())
+ return PreservedAnalyses::all();
+
+ X86PreLegalizerCombinerImplRuleConfig RuleConfig;
+ if (!RuleConfig.parseCommandLineOption())
+ report_fatal_error("Invalid rule identifier");
+
+ auto &CSEInfo = MFAM.getResult<GISelCSEAnalysis>(MF);
+
+ const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
+ const LegalizerInfo *LI = ST.getLegalizerInfo();
+
+ const Function &F = MF.getFunction();
+ bool EnableOpt = MF.getTarget().getOptLevel() != CodeGenOptLevel::None;
+ GISelValueTracking &VT = MFAM.getResult<GISelValueTrackingAnalysis>(MF);
+ MachineDominatorTree &MDT = MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
+ CombinerInfo CInfo(/*AllowIllegalOps=*/true, /*ShouldLegalizeIllegal=*/false,
+ /*LegalizerInfo=*/LI, EnableOpt, F.hasOptSize(),
+ F.hasMinSize());
+
+ // This is the first Combiner, so the input IR might contain dead
+ // instructions.
+ CInfo.EnableFullDCE = true;
+ X86PreLegalizerCombinerImpl Impl(MF, CInfo, nullptr, VT, CSEInfo.get(),
+ RuleConfig, ST, &MDT, LI);
+ Impl.combineMachineInstrs();
+
+ PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
+ PA.preserve<GISelCSEAnalysis>();
+ PA.preserve<GISelValueTrackingAnalysis>();
+ PA.preserve<MachineDominatorTreeAnalysis>();
+ return PA;
+}
+
FunctionPass *createX86PreLegalizerCombiner() {
return new X86PreLegalizerCombiner();
}
diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h
index 9e67c71427853..df259347cce9a 100644
--- a/llvm/lib/Target/X86/X86.h
+++ b/llvm/lib/Target/X86/X86.h
@@ -392,6 +392,14 @@ InstructionSelector *createX86InstructionSelector(const X86TargetMachine &TM,
const X86RegisterBankInfo &);
FunctionPass *createX86PostLegalizerCombiner();
+
+class X86PreLegalizerCombinerPass
+ : public PassInfoMixin<X86PreLegalizerCombinerPass> {
+public:
+ PreservedAnalyses run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM);
+};
+
FunctionPass *createX86PreLegalizerCombiner();
class X86LoadValueInjectionLoadHardeningPass
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index 11d843c8d371e..4f237437a8ca8 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -56,6 +56,7 @@ class X86CodeGenPassBuilder
// TODO(boomanaiden154): We need to add addRegAssignAndRewriteOptimized here
// once it is available to support AMX.
void addAsmPrinter(PassManagerWrapper &PMW, CreateMCStreamer) const;
+ void addPreLegalizeMachineIR(PassManagerWrapper &PMW) const;
};
void X86CodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const {
@@ -250,6 +251,11 @@ void X86CodeGenPassBuilder::addPreEmitPass2(PassManagerWrapper &PMW) const {
}
}
+void X86CodeGenPassBuilder::addPreLegalizeMachineIR(
+ PassManagerWrapper &PMW) const {
+ addMachineFunctionPass(X86PreLegalizerCombinerPass(), PMW);
+}
+
void X86CodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW,
CreateMCStreamer) const {
// TODO: Add AsmPrinter.
diff --git a/llvm/lib/Target/X86/X86PassRegistry.def b/llvm/lib/Target/X86/X86PassRegistry.def
index 14235f27a55f9..cc2a88d38a0de 100644
--- a/llvm/lib/Target/X86/X86PassRegistry.def
+++ b/llvm/lib/Target/X86/X86PassRegistry.def
@@ -57,6 +57,7 @@ MACHINE_FUNCTION_PASS("x86-lvi-load", X86LoadValueInjectionLoadHardeningPass())
MACHINE_FUNCTION_PASS("x86-lvi-ret", X86LoadValueInjectionRetHardeningPass())
MACHINE_FUNCTION_PASS("x86-optimize-leas", X86OptimizeLEAsPass())
MACHINE_FUNCTION_PASS("x86-pre-tile-config", X86PreTileConfigPass())
+MACHINE_FUNCTION_PASS("x86-pre-legalizer-combiner-pass", X86PreLegalizerCombinerPass())
MACHINE_FUNCTION_PASS("x86-return-thunks", X86ReturnThunksPass())
MACHINE_FUNCTION_PASS("x86-seses", X86SpeculativeExecutionSideEffectSuppressionPass())
MACHINE_FUNCTION_PASS("x86-slh", X86SpeculativeLoadHardeningPass())
>From 88a7a5783a3c8a5eb6afa8042e46a03b5159d4ed Mon Sep 17 00:00:00 2001
From: stomfaig <stomfaig at gmail.com>
Date: Sat, 21 Feb 2026 20:07:57 +0000
Subject: [PATCH 2/3] resolve comments
---
.../X86/GISel/X86PreLegalizerCombiner.cpp | 13 +-
llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp | 12 +-
.../prelegalizercombiner-trivial-arith.mir | 520 ++++++++++++++++++
3 files changed, 532 insertions(+), 13 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/GlobalISel/prelegalizercombiner-trivial-arith.mir
diff --git a/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp b/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
index 14195766bd887..706aab0ec3786 100644
--- a/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
@@ -55,8 +55,7 @@ class X86PreLegalizerCombinerImpl : public Combiner {
MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
const X86PreLegalizerCombinerImplRuleConfig &RuleConfig,
- const X86Subtarget &STI, MachineDominatorTree *MDT,
- const LegalizerInfo *LI);
+ MachineDominatorTree *MDT, const LegalizerInfo *LI);
static const char *getName() { return "X86PreLegalizerCombiner"; }
@@ -78,10 +77,10 @@ X86PreLegalizerCombinerImpl::X86PreLegalizerCombinerImpl(
MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
const X86PreLegalizerCombinerImplRuleConfig &RuleConfig,
- const X86Subtarget &STI, MachineDominatorTree *MDT, const LegalizerInfo *LI)
+ MachineDominatorTree *MDT, const LegalizerInfo *LI)
: Combiner(MF, CInfo, TPC, &VT, CSEInfo),
Helper(Observer, B, /*IsPreLegalize=*/true, &VT, MDT, LI),
- RuleConfig(RuleConfig), STI(STI),
+ RuleConfig(RuleConfig), STI(MF.getSubtarget<X86Subtarget>()),
#define GET_GICOMBINER_CONSTRUCTOR_INITS
#include "X86GenPreLegalizeGICombiner.inc"
#undef GET_GICOMBINER_CONSTRUCTOR_INITS
@@ -155,7 +154,7 @@ bool X86PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
// instructions.
CInfo.EnableFullDCE = true;
X86PreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *VT, CSEInfo, RuleConfig,
- ST, MDT, LI);
+ MDT, LI);
return Impl.combineMachineInstrs();
}
@@ -199,13 +198,13 @@ X86PreLegalizerCombinerPass::run(MachineFunction &MF,
// instructions.
CInfo.EnableFullDCE = true;
X86PreLegalizerCombinerImpl Impl(MF, CInfo, nullptr, VT, CSEInfo.get(),
- RuleConfig, ST, &MDT, LI);
+ RuleConfig, &MDT, LI);
Impl.combineMachineInstrs();
PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
+ PA.preserveSet<CFGAnalyses>();
PA.preserve<GISelCSEAnalysis>();
PA.preserve<GISelValueTrackingAnalysis>();
- PA.preserve<MachineDominatorTreeAnalysis>();
return PA;
}
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index 4f237437a8ca8..48d768c7c12ac 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -44,6 +44,7 @@ class X86CodeGenPassBuilder
void addIRPasses(PassManagerWrapper &PMW) const;
void addPreISel(PassManagerWrapper &PMW) const;
Error addInstSelector(PassManagerWrapper &PMW) const;
+ void addPreLegalizeMachineIR(PassManagerWrapper &PMW) const;
void addILPOpts(PassManagerWrapper &PMW) const;
void addMachineSSAOptimization(PassManagerWrapper &PMW) const;
void addPreRegAlloc(PassManagerWrapper &PMW) const;
@@ -56,7 +57,6 @@ class X86CodeGenPassBuilder
// TODO(boomanaiden154): We need to add addRegAssignAndRewriteOptimized here
// once it is available to support AMX.
void addAsmPrinter(PassManagerWrapper &PMW, CreateMCStreamer) const;
- void addPreLegalizeMachineIR(PassManagerWrapper &PMW) const;
};
void X86CodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) const {
@@ -115,6 +115,11 @@ Error X86CodeGenPassBuilder::addInstSelector(PassManagerWrapper &PMW) const {
return Error::success();
}
+void X86CodeGenPassBuilder::addPreLegalizeMachineIR(
+ PassManagerWrapper &PMW) const {
+ addMachineFunctionPass(X86PreLegalizerCombinerPass(), PMW);
+}
+
void X86CodeGenPassBuilder::addILPOpts(PassManagerWrapper &PMW) const {
addMachineFunctionPass(EarlyIfConverterPass(), PMW);
if (X86EnableMachineCombinerPass) {
@@ -251,11 +256,6 @@ void X86CodeGenPassBuilder::addPreEmitPass2(PassManagerWrapper &PMW) const {
}
}
-void X86CodeGenPassBuilder::addPreLegalizeMachineIR(
- PassManagerWrapper &PMW) const {
- addMachineFunctionPass(X86PreLegalizerCombinerPass(), PMW);
-}
-
void X86CodeGenPassBuilder::addAsmPrinter(PassManagerWrapper &PMW,
CreateMCStreamer) const {
// TODO: Add AsmPrinter.
diff --git a/llvm/test/CodeGen/X86/GlobalISel/prelegalizercombiner-trivial-arith.mir b/llvm/test/CodeGen/X86/GlobalISel/prelegalizercombiner-trivial-arith.mir
new file mode 100644
index 0000000000000..c85421a434208
--- /dev/null
+++ b/llvm/test/CodeGen/X86/GlobalISel/prelegalizercombiner-trivial-arith.mir
@@ -0,0 +1,520 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple x86_64 -run-pass=x86-prelegalizer-combiner %s -o - | FileCheck %s
+
+---
+name: right_ident_sub
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $eax
+ ; Fold (x - 0) -> x
+ ; CHECK-LABEL: name: right_ident_sub
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %x(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_SUB %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+
+...
+---
+name: right_ident_add
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (x + 0) -> x
+ ; CHECK-LABEL: name: right_ident_add
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %x(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_ADD %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: mul_0
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (x * 0) -> 0
+ ; CHECK-LABEL: name: mul_0
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %cst:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: $eax = COPY %cst(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_MUL %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: mul_0_cant_replace
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (x * 0) -> 0
+ ; CHECK-LABEL: name: mul_0_cant_replace
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: %cst:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: %op:gpr(s32) = G_MUL %x, %cst
+ ; CHECK-NEXT: $eax = COPY %op(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:gpr(s32) = G_MUL %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: sdiv_0
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (0 / x) -> 0
+ ; CHECK-LABEL: name: sdiv_0
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %cst:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: $eax = COPY %cst(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_SDIV %cst, %x
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: udiv_0
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (0 / x) -> 0
+ ; CHECK-LABEL: name: udiv_0
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %cst:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: $eax = COPY %cst(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_UDIV %cst, %x
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: srem_0
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (0 % x) -> 0
+ ; CHECK-LABEL: name: srem_0
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %cst:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: $eax = COPY %cst(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_SREM %cst, %x
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+
+---
+name: urem_0
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (0 % x) -> 0
+ ; CHECK-LABEL: name: urem_0
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %cst:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: $eax = COPY %cst(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_UREM %cst, %x
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: right_ident_or
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (x || 0) -> x
+ ; CHECK-LABEL: name: right_ident_or
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %x(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_OR %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+
+---
+name: right_ident_xor
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (x | 0) -> x
+ ; CHECK-LABEL: name: right_ident_xor
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %x(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_XOR %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: right_ident_shl
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (x << 0) -> x
+ ; CHECK-LABEL: name: right_ident_shl
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %x(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_SHL %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: right_ident_ashr
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (x ashr 0) -> x
+ ; CHECK-LABEL: name: right_ident_ashr
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %x(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_ASHR %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: right_ident_lshr
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Fold (x lshr 0) -> x
+ ; CHECK-LABEL: name: right_ident_lshr
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %x(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 0
+ %op:_(s32) = G_LSHR %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: dont_fold_sub
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; Not an identity, no folding.
+ ; CHECK-LABEL: name: dont_fold_sub
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; CHECK-NEXT: %op:_(s32) = G_ADD %x, [[C]]
+ ; CHECK-NEXT: $eax = COPY %op(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 1
+ %op:_(s32) = G_SUB %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: look_through_zext
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $rax
+ ; CHECK-LABEL: name: look_through_zext
+ ; CHECK: liveins: $rax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %zero:_(s8) = G_CONSTANT i8 0
+ ; CHECK-NEXT: %zext_zero:_(s64) = G_ZEXT %zero(s8)
+ ; CHECK-NEXT: $rax = COPY %zext_zero(s64)
+ ; CHECK-NEXT: RET implicit $rax
+ %zero:_(s8) = G_CONSTANT i8 0
+ %zext_zero:_(s64) = G_ZEXT %zero(s8)
+ %c:_(s64) = G_CONSTANT i64 72340172838076673
+ %mul:_(s64) = G_MUL %c, %zext_zero
+ $rax = COPY %mul(s64)
+ RET implicit $rax
+...
+---
+name: right_ident_ptr_add
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $rax
+ ; Fold (x + 0) -> x
+ ; CHECK-LABEL: name: right_ident_ptr_add
+ ; CHECK: liveins: $rax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(p0) = COPY $rax
+ ; CHECK-NEXT: $rax = COPY %x(p0)
+ ; CHECK-NEXT: RET implicit $rax
+ %x:_(p0) = COPY $rax
+ %cst:_(s64) = G_CONSTANT i64 0
+ %op:_(p0) = G_PTR_ADD %x(p0), %cst
+ $rax = COPY %op(p0)
+ RET implicit $rax
+...
+---
+name: right_identity_rotl
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $eax, $ebx
+ ; CHECK-LABEL: name: right_identity_rotl
+ ; CHECK: liveins: $eax, $ebx
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %copy:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %copy(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %copy:_(s32) = COPY $eax
+ %zero:_(s32) = G_CONSTANT i32 0
+ %rot:_(s32) = G_ROTL %copy(s32), %zero(s32)
+ $eax = COPY %rot(s32)
+ RET implicit $eax
+...
+---
+name: right_identity_rotr
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $eax, $ebx
+ ; CHECK-LABEL: name: right_identity_rotr
+ ; CHECK: liveins: $eax, $ebx
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %copy:_(s32) = COPY $eax
+ ; CHECK-NEXT: $eax = COPY %copy(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %copy:_(s32) = COPY $eax
+ %zero:_(s32) = G_CONSTANT i32 0
+ %rot:_(s32) = G_ROTR %copy(s32), %zero(s32)
+ $eax = COPY %rot(s32)
+ RET implicit $eax
+...
+---
+name: lshr_of_vec_zero
+body: |
+ bb.1:
+ liveins: $xmm0
+ ; CHECK-LABEL: name: lshr_of_vec_zero
+ ; CHECK: liveins: $xmm0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<8 x s16>) = COPY $xmm0
+ ; CHECK-NEXT: $xmm0 = COPY [[COPY]](<8 x s16>)
+ ; CHECK-NEXT: RET implicit $xmm0
+ %0:_(<8 x s16>) = COPY $xmm0
+ %5:_(s16) = G_CONSTANT i16 0
+ %zero_vec:_(<8 x s16>) = G_BUILD_VECTOR %5(s16), %5(s16), %5(s16), %5(s16), %5(s16), %5(s16), %5(s16), %5(s16)
+ %shift:_(<8 x s16>) = G_LSHR %0, %zero_vec(<8 x s16>)
+ $xmm0 = COPY %shift(<8 x s16>)
+ RET implicit $xmm0
+...
+---
+name: ptradd_of_vec_zero
+body: |
+ bb.1:
+ liveins: $xmm0
+ ; CHECK-LABEL: name: ptradd_of_vec_zero
+ ; CHECK: liveins: $xmm0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x p0>) = COPY $xmm0
+ ; CHECK-NEXT: $xmm0 = COPY [[COPY]](<2 x p0>)
+ ; CHECK-NEXT: RET implicit $xmm0
+ %0:_(<2 x p0>) = COPY $xmm0
+ %5:_(s64) = G_CONSTANT i64 0
+ %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %5(s64), %5(s64)
+ %ptr:_(<2 x p0>) = G_PTR_ADD %0, %zero_vec(<2 x s64>)
+ $xmm0 = COPY %ptr(<2 x p0>)
+ RET implicit $xmm0
+...
+---
+name: i128_or_cst
+liveins:
+ - { reg: '$rax' }
+body: |
+ bb.1:
+ liveins: $rax
+
+ ; CHECK-LABEL: name: i128_or_cst
+ ; CHECK: liveins: $rax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $rax
+ ; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s128) = G_LOAD [[COPY]](p0) :: (load (s128))
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 9223372036854775808
+ ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s128) = G_OR [[LOAD]], [[C]]
+ ; CHECK-NEXT: G_STORE [[OR]](s128), [[COPY]](p0) :: (store (s128), align 4)
+ ; CHECK-NEXT: RET 0
+ %0:_(p0) = COPY $rax
+ %2:_(s128) = G_LOAD %0(p0) :: (load (s128))
+ %4:_(s128) = G_CONSTANT i128 9223372036854775808
+ %5:_(s128) = G_OR %2, %4
+ G_STORE %5(s128), %0(p0) :: (store (s128), align 4)
+ RET 0
+...
+---
+name: mul_1_shift_of_shift
+liveins:
+ - { reg: '$rax' }
+body: |
+ bb.1:
+ liveins: $rax
+
+ ; CHECK-LABEL: name: mul_1_shift_of_shift
+ ; CHECK: liveins: $rax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $rax
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+ ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[COPY]], [[C]](s64)
+ ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR [[SHL]], [[C]]
+ ; CHECK-NEXT: $rax = COPY [[OR]](s64)
+ ; CHECK-NEXT: RET implicit $rax
+ %0:_(s64) = COPY $rax
+ %1:_(s64) = G_CONSTANT i64 1
+ %2:_(s64) = G_SHL %0, %1(s64)
+ %3:_(s64) = G_OR %2, %1
+ %4:_(s64) = G_MUL %3, %1
+ $rax = COPY %4(s64)
+ RET implicit $rax
+...
+---
+name: sub_to_add
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; CHECK-LABEL: name: sub_to_add
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; CHECK-NEXT: %op:_(s32) = G_ADD %x, [[C]]
+ ; CHECK-NEXT: $eax = COPY %op(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 1
+ %op:_(s32) = G_SUB %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: sub_to_add_nuw
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $eax
+ ; CHECK-LABEL: name: sub_to_add_nuw
+ ; CHECK: liveins: $eax
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:_(s32) = COPY $eax
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; CHECK-NEXT: %op:_(s32) = G_ADD %x, [[C]]
+ ; CHECK-NEXT: $eax = COPY %op(s32)
+ ; CHECK-NEXT: RET implicit $eax
+ %x:_(s32) = COPY $eax
+ %cst:_(s32) = G_CONSTANT i32 1
+ %op:_(s32) = nuw G_SUB %x(s32), %cst
+ $eax = COPY %op(s32)
+ RET implicit $eax
+...
+---
+name: sub_to_add_nsw_128
+body: |
+ bb.0:
+ liveins: $eax, $ebx
+
+ ; CHECK-LABEL: name: sub_to_add_nsw_128
+ ; CHECK: liveins: $eax, $ebx
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s32) = COPY $eax
+ ; CHECK-NEXT: %b:_(s8) = G_TRUNC %a(s32)
+ ; CHECK-NEXT: %c:_(s8) = G_CONSTANT i8 -128
+ ; CHECK-NEXT: %add:_(s8) = G_ADD %b, %c
+ ; CHECK-NEXT: %d:_(s32) = G_ZEXT %add(s8)
+ ; CHECK-NEXT: $eax = COPY %d(s32)
+ ; CHECK-NEXT: RET implicit $rax
+ %a:_(s32) = COPY $eax
+ %b:_(s8) = G_TRUNC %a
+ %c:_(s8) = G_CONSTANT i8 -128
+ %add:_(s8) = nsw nuw G_SUB %b, %c
+ %d:_(s32) = G_ZEXT %add
+ $eax = COPY %d
+ RET implicit $rax
+...
+---
+name: sub_to_add_nsw_intmin
+body: |
+ bb.0:
+ liveins: $eax, $ebx
+
+ ; CHECK-LABEL: name: sub_to_add_nsw_intmin
+ ; CHECK: liveins: $eax, $ebx
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s32) = COPY $eax
+ ; CHECK-NEXT: %c:_(s32) = G_CONSTANT i32 -2147483648
+ ; CHECK-NEXT: %add:_(s32) = G_ADD %a, %c
+ ; CHECK-NEXT: $eax = COPY %add(s32)
+ ; CHECK-NEXT: RET implicit $rax
+ %a:_(s32) = COPY $eax
+ %c:_(s32) = G_CONSTANT i32 -2147483648
+ %add:_(s32) = nsw nuw G_SUB %a, %c
+ $eax = COPY %add
+ RET implicit $rax
+...
>From 4997a0a213b0c0b25a458b9870c4cd3c8db0bf7c Mon Sep 17 00:00:00 2001
From: stomfaig <stomfaig at gmail.com>
Date: Sat, 21 Feb 2026 20:35:04 +0000
Subject: [PATCH 3/3] remove LI duplicated dependence
---
llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp b/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
index 706aab0ec3786..5ab3b4b06771e 100644
--- a/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/X86/GISel/X86PreLegalizerCombiner.cpp
@@ -55,7 +55,7 @@ class X86PreLegalizerCombinerImpl : public Combiner {
MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
const X86PreLegalizerCombinerImplRuleConfig &RuleConfig,
- MachineDominatorTree *MDT, const LegalizerInfo *LI);
+ MachineDominatorTree *MDT);
static const char *getName() { return "X86PreLegalizerCombiner"; }
@@ -77,9 +77,10 @@ X86PreLegalizerCombinerImpl::X86PreLegalizerCombinerImpl(
MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
GISelValueTracking &VT, GISelCSEInfo *CSEInfo,
const X86PreLegalizerCombinerImplRuleConfig &RuleConfig,
- MachineDominatorTree *MDT, const LegalizerInfo *LI)
+ MachineDominatorTree *MDT)
: Combiner(MF, CInfo, TPC, &VT, CSEInfo),
- Helper(Observer, B, /*IsPreLegalize=*/true, &VT, MDT, LI),
+ Helper(Observer, B, /*IsPreLegalize=*/true, &VT, MDT,
+ MF.getSubtarget<X86Subtarget>().getLegalizerInfo()),
RuleConfig(RuleConfig), STI(MF.getSubtarget<X86Subtarget>()),
#define GET_GICOMBINER_CONSTRUCTOR_INITS
#include "X86GenPreLegalizeGICombiner.inc"
@@ -154,7 +155,7 @@ bool X86PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
// instructions.
CInfo.EnableFullDCE = true;
X86PreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *VT, CSEInfo, RuleConfig,
- MDT, LI);
+ MDT);
return Impl.combineMachineInstrs();
}
@@ -198,7 +199,7 @@ X86PreLegalizerCombinerPass::run(MachineFunction &MF,
// instructions.
CInfo.EnableFullDCE = true;
X86PreLegalizerCombinerImpl Impl(MF, CInfo, nullptr, VT, CSEInfo.get(),
- RuleConfig, &MDT, LI);
+ RuleConfig, &MDT);
Impl.combineMachineInstrs();
PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
More information about the llvm-commits
mailing list