[llvm] GlobalISel: Use MIPatternMatch to look up defs in the artifact combiner (PR #216358)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 14 09:59:55 PDT 2026
https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/216358
Replace direct getVRegDef uses in the legalization artifact combiner with
the mi_match/m_MInstr idiom. To avoid awkwardly split handling of G_IMPLICIT_DEF,
add a similar matcher for G_CONSTANT.
Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
>From 989823351491be88d3b35000292b85006db6a10f Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 14 Aug 2026 17:51:58 +0200
Subject: [PATCH] GlobalISel: Use MIPatternMatch to look up defs in the
artifact combiner
Replace direct getVRegDef uses in the legalization artifact combiner with
the mi_match/m_MInstr idiom. To avoid awkwardly split handling of G_IMPLICIT_DEF,
add a similar matcher for G_CONSTANT.
Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
---
.../CodeGen/GlobalISel/GenericMachineInstrs.h | 11 ++++
.../GlobalISel/LegalizationArtifactCombiner.h | 57 +++++++++----------
.../llvm/CodeGen/GlobalISel/MIPatternMatch.h | 24 ++++++++
3 files changed, 62 insertions(+), 30 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 3be9d31bc57c9..6daa7f3808f43 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -978,6 +978,17 @@ class GStepVector : public GenericMachineInstr {
};
};
+/// Represents a G_CONSTANT.
+class GConstant : public GenericMachineInstr {
+public:
+ const ConstantInt *getConstantInt() const { return getOperand(1).getCImm(); }
+ const APInt &getValue() const { return getConstantInt()->getValue(); }
+
+ static bool classof(const MachineInstr *MI) {
+ return MI->getOpcode() == TargetOpcode::G_CONSTANT;
+ };
+};
+
/// Represents an integer subtraction.
class GSub : public GIntBinOp {
public:
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
index 08e567f2e640a..dca2babbe112b 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h
@@ -95,20 +95,19 @@ class LegalizationArtifactCombiner {
}
// Try to fold aext(g_constant) when the larger constant type is legal.
- auto *SrcMI = MRI.getVRegDef(SrcReg);
- if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
+ GConstant *SrcCst;
+ if (mi_match(SrcReg, MRI, m_GConstant(SrcCst))) {
const LLT DstTy = MRI.getType(DstReg);
if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
- auto &CstVal = SrcMI->getOperand(1);
- auto MergedLocation =
- DebugLoc::getMergedLocation(MI.getDebugLoc(), SrcMI->getDebugLoc());
- // Set the debug location to the merged location of the SrcMI and the MI
- // if the aext fold is successful.
+ auto MergedLocation = DebugLoc::getMergedLocation(
+ MI.getDebugLoc(), SrcCst->getDebugLoc());
+ // Set the debug location to the merged location of the SrcCst and the
+ // MI if the aext fold is successful.
Builder.setDebugLoc(MergedLocation);
- Builder.buildConstant(
- DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
+ Builder.buildConstant(DstReg,
+ SrcCst->getValue().sext(DstTy.getSizeInBits()));
UpdatedDefs.push_back(DstReg);
- markInstAndDefDead(MI, *SrcMI, DeadInsts);
+ markInstAndDefDead(MI, *SrcCst, DeadInsts);
return true;
}
}
@@ -175,15 +174,14 @@ class LegalizationArtifactCombiner {
}
// Try to fold zext(g_constant) when the larger constant type is legal.
- auto *SrcMI = MRI.getVRegDef(SrcReg);
- if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
+ GConstant *SrcCst;
+ if (mi_match(SrcReg, MRI, m_GConstant(SrcCst))) {
const LLT DstTy = MRI.getType(DstReg);
if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
- auto &CstVal = SrcMI->getOperand(1);
- Builder.buildConstant(
- DstReg, CstVal.getCImm()->getValue().zext(DstTy.getSizeInBits()));
+ Builder.buildConstant(DstReg,
+ SrcCst->getValue().zext(DstTy.getSizeInBits()));
UpdatedDefs.push_back(DstReg);
- markInstAndDefDead(MI, *SrcMI, DeadInsts);
+ markInstAndDefDead(MI, *SrcCst, DeadInsts);
return true;
}
}
@@ -242,15 +240,14 @@ class LegalizationArtifactCombiner {
}
// Try to fold sext(g_constant) when the larger constant type is legal.
- auto *SrcMI = MRI.getVRegDef(SrcReg);
- if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
+ GConstant *SrcCst;
+ if (mi_match(SrcReg, MRI, m_GConstant(SrcCst))) {
const LLT DstTy = MRI.getType(DstReg);
if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
- auto &CstVal = SrcMI->getOperand(1);
- Builder.buildConstant(
- DstReg, CstVal.getCImm()->getValue().sext(DstTy.getSizeInBits()));
+ Builder.buildConstant(DstReg,
+ SrcCst->getValue().sext(DstTy.getSizeInBits()));
UpdatedDefs.push_back(DstReg);
- markInstAndDefDead(MI, *SrcMI, DeadInsts);
+ markInstAndDefDead(MI, *SrcCst, DeadInsts);
return true;
}
}
@@ -271,20 +268,20 @@ class LegalizationArtifactCombiner {
Register SrcReg = lookThroughCopyInstrs(MI.getOperand(1).getReg());
// Try to fold trunc(g_constant) when the smaller constant type is legal.
- auto *SrcMI = MRI.getVRegDef(SrcReg);
- if (SrcMI->getOpcode() == TargetOpcode::G_CONSTANT) {
+ GConstant *SrcCst;
+ if (mi_match(SrcReg, MRI, m_GConstant(SrcCst))) {
if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) {
- auto &CstVal = SrcMI->getOperand(1);
- Builder.buildConstant(
- DstReg, CstVal.getCImm()->getValue().trunc(DstTy.getSizeInBits()));
+ Builder.buildConstant(DstReg,
+ SrcCst->getValue().trunc(DstTy.getSizeInBits()));
UpdatedDefs.push_back(DstReg);
- markInstAndDefDead(MI, *SrcMI, DeadInsts);
+ markInstAndDefDead(MI, *SrcCst, DeadInsts);
return true;
}
}
// Try to fold trunc(merge) to directly use the source of the merge.
// This gets rid of large, difficult to legalize, merges
+ MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
if (auto *SrcMerge = dyn_cast<GMerge>(SrcMI)) {
const Register MergeSrcReg = SrcMerge->getSourceReg(0);
const LLT MergeSrcTy = MRI.getType(MergeSrcReg);
@@ -964,6 +961,7 @@ class LegalizationArtifactCombiner {
GUnmerge *Unmerge, unsigned UnmergeIdxStart,
unsigned NumElts, unsigned EltSize,
bool AllowUndef) {
+ using namespace llvm::MIPatternMatch;
assert(MergeStartIdx + NumElts <= MI.getNumSources());
for (unsigned i = MergeStartIdx; i < MergeStartIdx + NumElts; ++i) {
unsigned EltUnmergeIdx;
@@ -975,8 +973,7 @@ class LegalizationArtifactCombiner {
if (i - MergeStartIdx != EltUnmergeIdx - UnmergeIdxStart)
return false;
} else if (!AllowUndef ||
- MRI.getVRegDef(MI.getSourceReg(i))->getOpcode() !=
- TargetOpcode::G_IMPLICIT_DEF)
+ !mi_match(MI.getSourceReg(i), MRI, m_GImplicitDef()))
return false;
}
return true;
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
index db1f4a89d3469..5353d8dbb7bcd 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
@@ -471,6 +471,30 @@ struct ImplicitDefMatch {
inline ImplicitDefMatch m_GImplicitDef() { return ImplicitDefMatch(); }
+/// Matches a G_CONSTANT and binds the defining instruction. Unlike m_ICst, this
+/// returns the instruction (not the value) and does not look through vector
+/// splats.
+template <typename Class> struct GConstantMatch {
+ Class *&Inst;
+
+ GConstantMatch(Class *&Inst) : Inst(Inst) {}
+ bool match(const MachineRegisterInfo &MRI, Register Reg) {
+ MachineInstr *TmpMI;
+ if (mi_match(Reg, MRI, m_MInstr(TmpMI))) {
+ if (auto *Cst = dyn_cast<Class>(TmpMI)) {
+ Inst = Cst;
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+inline GConstantMatch<GConstant> m_GConstant(GConstant *&Inst) { return Inst; }
+inline GConstantMatch<const GConstant> m_GConstant(const GConstant *&Inst) {
+ return Inst;
+}
+
// Helper for matching G_FCONSTANT
inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
More information about the llvm-commits
mailing list