[llvm] [Uniformity] Implement per-output machine uniformity analysis (PR #179275)
Pankaj Dwivedi via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 06:58:11 PDT 2026
https://github.com/PankajDwivedi-25 updated https://github.com/llvm/llvm-project/pull/179275
>From 31a492904523d24bf9f23e4c3a50b3791b2bceeb Mon Sep 17 00:00:00 2001
From: padivedi <pankajkumar.divedi at amd.com>
Date: Mon, 8 Jun 2026 23:22:06 +0530
Subject: [PATCH 1/3] [AMDGPU] Make machine uniformity analysis query
uniformity per def
---
llvm/include/llvm/ADT/GenericUniformityImpl.h | 26 +++++--
llvm/include/llvm/CodeGen/TargetInstrInfo.h | 15 +++-
llvm/lib/Analysis/UniformityAnalysis.cpp | 2 +-
.../lib/CodeGen/MachineUniformityAnalysis.cpp | 75 +++++++++++++++----
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 47 +++++++-----
llvm/lib/Target/AMDGPU/SIInstrInfo.h | 5 +-
6 files changed, 128 insertions(+), 42 deletions(-)
diff --git a/llvm/include/llvm/ADT/GenericUniformityImpl.h b/llvm/include/llvm/ADT/GenericUniformityImpl.h
index a9a1211947492..28ef89e01a5ab 100644
--- a/llvm/include/llvm/ADT/GenericUniformityImpl.h
+++ b/llvm/include/llvm/ADT/GenericUniformityImpl.h
@@ -357,8 +357,8 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
const FunctionT &getFunction() const { return F; }
- /// \brief Mark \p UniVal as a value that is always uniform.
- void addUniformOverride(const InstructionT &Instr);
+ /// \brief Mark \p V as a value that is always uniform.
+ void addUniformOverride(ConstValueRefT V);
/// \brief Examine \p I for divergent outputs and add to the worklist.
void markDivergent(const InstructionT &I);
@@ -380,6 +380,9 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
/// operands
bool isAlwaysUniform(const InstructionT &Instr) const;
+ /// \brief Whether \p V is a value that is always uniform.
+ bool isAlwaysUniform(ConstValueRefT V) const;
+
bool hasDivergentDefs(const InstructionT &I) const;
bool isDivergent(const InstructionT &I) const {
@@ -473,8 +476,9 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
// The SDA links divergent branches to divergent control-flow joins.
SyncDependenceAnalysisT SDA;
- // Set of known-uniform values.
- SmallPtrSet<const InstructionT *, 32> UniformOverrides;
+ // Set of known-uniform values. Keyed on values (ConstValueRefT) so that
+ // individual defs of a multi-def instruction can be overridden uniform.
+ DenseSet<ConstValueRefT> UniformOverrides;
/// \brief Mark all nodes in \p JoinBlock as divergent and push them on
/// the worklist.
@@ -842,6 +846,8 @@ void GenericUniformityAnalysisImpl<ContextT>::markDivergent(
template <typename ContextT>
bool GenericUniformityAnalysisImpl<ContextT>::markDivergent(
ConstValueRefT Val) {
+ if (isAlwaysUniform(Val))
+ return false;
if (UniformValues.erase(Val)) {
LLVM_DEBUG(dbgs() << "marked divergent: " << Context.print(Val) << "\n");
return true;
@@ -851,8 +857,8 @@ bool GenericUniformityAnalysisImpl<ContextT>::markDivergent(
template <typename ContextT>
void GenericUniformityAnalysisImpl<ContextT>::addUniformOverride(
- const InstructionT &Instr) {
- UniformOverrides.insert(&Instr);
+ ConstValueRefT V) {
+ UniformOverrides.insert(V);
}
template <typename ContextT>
@@ -1182,7 +1188,13 @@ void GenericUniformityAnalysisImpl<ContextT>::recordTemporalDivergence(
template <typename ContextT>
bool GenericUniformityAnalysisImpl<ContextT>::isAlwaysUniform(
const InstructionT &Instr) const {
- return UniformOverrides.contains(&Instr);
+ return isAlwaysUniform(&Instr);
+}
+
+template <typename ContextT>
+bool GenericUniformityAnalysisImpl<ContextT>::isAlwaysUniform(
+ ConstValueRefT V) const {
+ return UniformOverrides.contains(V);
}
template <typename ContextT>
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 03f3bf26d0608..c24fe3a24500b 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2369,11 +2369,22 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
llvm_unreachable("impossible call instruction");
}
- /// Return the uniformity behavior of the given value.
- virtual ValueUniformity getValueUniformity(const MachineInstr &MI) const {
+ /// Return the uniformity behavior of the value defined by the \p DefIdx-th
+ /// def operand (in MachineInstr::all_defs() order) of \p MI. \p MI must not
+ /// be a terminator and \p DefIdx must refer to a virtual register def; use
+ /// isTerminatorDivergent() to query branch divergence for terminators.
+ virtual ValueUniformity getValueUniformity(const MachineInstr &MI,
+ unsigned DefIdx) const {
return ValueUniformity::Default;
}
+ /// Return true if \p MI is a terminator whose branch divergence is
+ /// independent of its operands (an unconditional source of control
+ /// divergence).
+ virtual bool isTerminatorDivergent(const MachineInstr &MI) const {
+ return false;
+ }
+
/// Returns true if the given \p MI defines a TargetIndex operand that can be
/// tracked by their offset, can have values, and can have debug info
/// associated with it. If so, sets \p Index and \p Offset of the target index
diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index 73b6476fb7b6d..bc85287bfe138 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -81,7 +81,7 @@ template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
switch (IU) {
case ValueUniformity::AlwaysUniform:
UniformValues.insert(&I);
- addUniformOverride(I);
+ addUniformOverride(&I);
continue;
case ValueUniformity::NeverUniform:
// Skip inserting -- divergent by definition. Add to Worklist directly
diff --git a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
index 03a046ea995ed..07188a0b11815 100644
--- a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
+++ b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
@@ -13,6 +13,7 @@
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineSSAContext.h"
+#include "llvm/CodeGen/RegisterBankInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/InitializePasses.h"
@@ -46,6 +47,25 @@ bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::markDefsDivergent(
return InsertedDivergent;
}
+template <>
+bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::isAlwaysUniform(
+ const MachineInstr &Instr) const {
+ // An instruction is always uniform only if it has at least one virtual
+ // register def and every virtual def has been overridden uniform. Because
+ // overrides are tracked per def, a multi-def instruction with a mix of
+ // uniform and divergent outputs is not considered always uniform.
+ bool HasVirtualDef = false;
+ for (const MachineOperand &Op : Instr.all_defs()) {
+ Register Reg = Op.getReg();
+ if (!Reg.isVirtual())
+ continue;
+ HasVirtualDef = true;
+ if (!isAlwaysUniform(Reg))
+ return false;
+ }
+ return HasVirtualDef;
+}
+
template <>
void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
// Pre-populate UniformValues with all register defs. Physical register defs
@@ -62,24 +82,51 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
}
}
- const auto &InstrInfo = *F.getSubtarget().getInstrInfo();
+ const TargetInstrInfo &InstrInfo = *F.getSubtarget().getInstrInfo();
+ const MachineRegisterInfo &MRI = F.getRegInfo();
+ const RegisterBankInfo &RBI = *F.getSubtarget().getRegBankInfo();
+ const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
for (const MachineBasicBlock &MBB : F) {
for (const MachineInstr &MI : MBB) {
- ValueUniformity VU = InstrInfo.getValueUniformity(MI);
-
- switch (VU) {
- case ValueUniformity::AlwaysUniform:
- addUniformOverride(MI);
- break;
- case ValueUniformity::NeverUniform:
- markDivergent(MI);
- break;
- case ValueUniformity::Custom:
- break;
- case ValueUniformity::Default:
- break;
+ // A terminator is a source of control divergence rather than a value;
+ // seed only the unconditionally divergent ones as divergent term blocks.
+ if (MI.isTerminator()) {
+ if (InstrInfo.isTerminatorDivergent(MI))
+ markDivergent(MI);
+ continue;
+ }
+
+ // Seed divergence per def, so an instruction with several outputs (e.g.
+ // inline asm) can mix uniform and divergent results.
+ unsigned DefIdx = 0;
+ bool HasDivergentDef = false;
+ for (const MachineOperand &Op : MI.all_defs()) {
+ Register Reg = Op.getReg();
+ if (!Reg.isVirtual()) {
+ ++DefIdx;
+ continue;
+ }
+ switch (InstrInfo.getValueUniformity(MI, DefIdx++)) {
+ case ValueUniformity::AlwaysUniform:
+ addUniformOverride(Reg);
+ break;
+ case ValueUniformity::NeverUniform:
+ // Inherently uniform registers (e.g. SGPRs) stay uniform even when
+ // the def is reported as a divergence source.
+ if (!TRI.isUniformReg(MRI, RBI, Reg))
+ HasDivergentDef |= markDivergent(Reg);
+ break;
+ case ValueUniformity::Custom:
+ break;
+ case ValueUniformity::Default:
+ break;
+ }
}
+ // Queue the instruction once for propagation if any of its defs became
+ // divergent; the value-level markDivergent() does not touch the worklist.
+ if (HasDivergentDef)
+ Worklist.push_back(&MI);
}
}
}
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index ef9d184555bd6..ff0ac6fb30d07 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -11003,30 +11003,40 @@ const MIRFormatter *SIInstrInfo::getMIRFormatter() const {
return Formatter.get();
}
-ValueUniformity SIInstrInfo::getValueUniformity(const MachineInstr &MI) const {
+bool SIInstrInfo::isTerminatorDivergent(const MachineInstr &MI) const {
+ assert(MI.isTerminator());
+ return isNeverUniform(MI);
+}
+
+ValueUniformity SIInstrInfo::getValueUniformity(const MachineInstr &MI,
+ unsigned DefIdx) const {
+ assert(!MI.isTerminator() &&
+ "use isTerminatorDivergent() to query terminator divergence");
+ assert(DefIdx < (unsigned)std::distance(MI.all_defs().begin(),
+ MI.all_defs().end()) &&
+ "DefIdx is out of range for this instruction's defs");
+ assert(std::next(MI.all_defs().begin(), DefIdx)->getReg().isVirtual() &&
+ "DefIdx must name a virtual register def, not a physical register");
if (isNeverUniform(MI))
return ValueUniformity::NeverUniform;
+ // Inline asm can define several registers with different reg classes, so the
+ // uniformity of each output is answered individually from its def reg class.
+ if (MI.isInlineAsm()) {
+ const MachineOperand &MO = *std::next(MI.all_defs().begin(), DefIdx);
+ const TargetRegisterClass *RC =
+ MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
+ return (!RC || !RI.isSGPRClass(RC)) ? ValueUniformity::NeverUniform
+ : ValueUniformity::Default;
+ }
+
unsigned opcode = MI.getOpcode();
if (opcode == AMDGPU::V_READLANE_B32 ||
opcode == AMDGPU::V_READFIRSTLANE_B32 ||
opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
return ValueUniformity::AlwaysUniform;
- // If any of defs is divergent, report as NeverUniform. isUniformReg will
- // calculate in more detail for each def from its reg class, if available.
- if (MI.isInlineAsm()) {
- for (const MachineOperand &MO : MI.operands()) {
- if (!MO.isReg() || !MO.isDef())
- continue;
- const TargetRegisterClass *RC =
- MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
- if (!RC || !RI.isSGPRClass(RC))
- return ValueUniformity::NeverUniform;
- }
- }
-
if (isCopyInstr(MI)) {
const MachineOperand &srcOp = MI.getOperand(1);
if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
@@ -11071,9 +11081,12 @@ ValueUniformity SIInstrInfo::getValueUniformity(const MachineInstr &MI) const {
const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
- // FIXME: It's conceptually broken to report this for an instruction, and not
- // a specific def operand. For inline asm in particular, there could be mixed
- // uniform and divergent results.
+ // Fallback: the result is divergent if any source operand is divergent. This
+ // gives one whole-instruction verdict (DefIdx is unused), which is exact for
+ // the single-def instructions that reach here.
+ // TODO: For a true per-def answer, scan only the sources feeding MI's DefIdx
+ // def; that input->output mapping is opcode-specific, so it would need
+ // per-opcode handling (similar to the inline-asm case above).
for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
const MachineOperand &SrcOp = MI.getOperand(I);
if (!SrcOp.isReg())
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
index 831aa9ebb8435..75181434374cb 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
@@ -1755,10 +1755,13 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {
const MachineOperand &getCalleeOperand(const MachineInstr &MI) const override;
- ValueUniformity getValueUniformity(const MachineInstr &MI) const final;
+ ValueUniformity getValueUniformity(const MachineInstr &MI,
+ unsigned DefIdx) const final;
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const;
+ bool isTerminatorDivergent(const MachineInstr &MI) const final;
+
const MIRFormatter *getMIRFormatter() const override;
static unsigned getDSShaderTypeValue(const MachineFunction &MF);
>From d58808a3ca77f683fe4d7a830e06a63e79b814c6 Mon Sep 17 00:00:00 2001
From: padivedi <pankajkumar.divedi at amd.com>
Date: Wed, 10 Jun 2026 16:54:30 +0530
Subject: [PATCH 2/3] review
---
llvm/include/llvm/ADT/GenericUniformityImpl.h | 15 ++--------
llvm/lib/Analysis/UniformityAnalysis.cpp | 4 +--
.../lib/CodeGen/MachineUniformityAnalysis.cpp | 29 +------------------
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 11 ++++++-
4 files changed, 16 insertions(+), 43 deletions(-)
diff --git a/llvm/include/llvm/ADT/GenericUniformityImpl.h b/llvm/include/llvm/ADT/GenericUniformityImpl.h
index 28ef89e01a5ab..0901ea4657527 100644
--- a/llvm/include/llvm/ADT/GenericUniformityImpl.h
+++ b/llvm/include/llvm/ADT/GenericUniformityImpl.h
@@ -376,10 +376,6 @@ template <typename ContextT> class GenericUniformityAnalysisImpl {
/// Divergence is seeded by calls to \p markDivergent.
void compute();
- /// \brief Whether \p Val will always return a uniform value regardless of its
- /// operands
- bool isAlwaysUniform(const InstructionT &Instr) const;
-
/// \brief Whether \p V is a value that is always uniform.
bool isAlwaysUniform(ConstValueRefT V) const;
@@ -819,8 +815,9 @@ auto llvm::GenericSyncDependenceAnalysis<ContextT>::getJoinBlocks(
template <typename ContextT>
void GenericUniformityAnalysisImpl<ContextT>::markDivergent(
const InstructionT &I) {
- if (isAlwaysUniform(I))
- return;
+ // Always-uniform values are filtered out below by the per-value/per-register
+ // markDivergent(), so there is no need for a separate instruction-level
+ // uniformity check here.
// For custom uniformity candidates, check if the instruction can be
// proven uniform based on which operands are uniform/divergent.
// The candidate will be re-evaluated as operands become divergent.
@@ -1185,12 +1182,6 @@ void GenericUniformityAnalysisImpl<ContextT>::recordTemporalDivergence(
Cycle);
}
-template <typename ContextT>
-bool GenericUniformityAnalysisImpl<ContextT>::isAlwaysUniform(
- const InstructionT &Instr) const {
- return isAlwaysUniform(&Instr);
-}
-
template <typename ContextT>
bool GenericUniformityAnalysisImpl<ContextT>::isAlwaysUniform(
ConstValueRefT V) const {
diff --git a/llvm/lib/Analysis/UniformityAnalysis.cpp b/llvm/lib/Analysis/UniformityAnalysis.cpp
index bc85287bfe138..5661a18a6424e 100644
--- a/llvm/lib/Analysis/UniformityAnalysis.cpp
+++ b/llvm/lib/Analysis/UniformityAnalysis.cpp
@@ -43,7 +43,7 @@ void llvm::GenericUniformityAnalysisImpl<SSAContext>::pushUsers(
template <>
void llvm::GenericUniformityAnalysisImpl<SSAContext>::pushUsers(
const Instruction &Instr) {
- assert(!isAlwaysUniform(Instr));
+ assert(!isAlwaysUniform(cast<Value>(&Instr)));
if (Instr.isTerminator())
return;
pushUsers(cast<Value>(&Instr));
@@ -110,7 +110,7 @@ template <> void llvm::GenericUniformityAnalysisImpl<SSAContext>::initialize() {
template <>
bool llvm::GenericUniformityAnalysisImpl<SSAContext>::usesValueFromCycle(
const Instruction &I, const Cycle &DefCycle) const {
- assert(!isAlwaysUniform(I));
+ assert(!isAlwaysUniform(cast<Value>(&I)));
for (const Use &U : I.operands()) {
if (auto *I = dyn_cast<Instruction>(&U)) {
if (DefCycle.contains(I->getParent()))
diff --git a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
index 07188a0b11815..e6c6af178bfae 100644
--- a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
+++ b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
@@ -47,25 +47,6 @@ bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::markDefsDivergent(
return InsertedDivergent;
}
-template <>
-bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::isAlwaysUniform(
- const MachineInstr &Instr) const {
- // An instruction is always uniform only if it has at least one virtual
- // register def and every virtual def has been overridden uniform. Because
- // overrides are tracked per def, a multi-def instruction with a mix of
- // uniform and divergent outputs is not considered always uniform.
- bool HasVirtualDef = false;
- for (const MachineOperand &Op : Instr.all_defs()) {
- Register Reg = Op.getReg();
- if (!Reg.isVirtual())
- continue;
- HasVirtualDef = true;
- if (!isAlwaysUniform(Reg))
- return false;
- }
- return HasVirtualDef;
-}
-
template <>
void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
// Pre-populate UniformValues with all register defs. Physical register defs
@@ -83,9 +64,6 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
}
const TargetInstrInfo &InstrInfo = *F.getSubtarget().getInstrInfo();
- const MachineRegisterInfo &MRI = F.getRegInfo();
- const RegisterBankInfo &RBI = *F.getSubtarget().getRegBankInfo();
- const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
for (const MachineBasicBlock &MBB : F) {
for (const MachineInstr &MI : MBB) {
@@ -112,10 +90,7 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
addUniformOverride(Reg);
break;
case ValueUniformity::NeverUniform:
- // Inherently uniform registers (e.g. SGPRs) stay uniform even when
- // the def is reported as a divergence source.
- if (!TRI.isUniformReg(MRI, RBI, Reg))
- HasDivergentDef |= markDivergent(Reg);
+ HasDivergentDef |= markDivergent(Reg);
break;
case ValueUniformity::Custom:
break;
@@ -144,7 +119,6 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
template <>
void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
const MachineInstr &Instr) {
- assert(!isAlwaysUniform(Instr));
if (Instr.isTerminator())
return;
for (const MachineOperand &Op : Instr.all_defs()) {
@@ -157,7 +131,6 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::pushUsers(
template <>
bool llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::usesValueFromCycle(
const MachineInstr &I, const MachineCycle &DefCycle) const {
- assert(!isAlwaysUniform(I));
for (auto &Op : I.operands()) {
if (!Op.isReg() || !Op.readsReg())
continue;
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index ff0ac6fb30d07..7fd6f2ec2ecb8 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -11015,9 +11015,18 @@ ValueUniformity SIInstrInfo::getValueUniformity(const MachineInstr &MI,
assert(DefIdx < (unsigned)std::distance(MI.all_defs().begin(),
MI.all_defs().end()) &&
"DefIdx is out of range for this instruction's defs");
- assert(std::next(MI.all_defs().begin(), DefIdx)->getReg().isVirtual() &&
+ Register DefReg = std::next(MI.all_defs().begin(), DefIdx)->getReg();
+ assert(DefReg.isVirtual() &&
"DefIdx must name a virtual register def, not a physical register");
+ // A def whose register bank/class forces uniformity (e.g. an SGPR, but not a
+ // lane-mask class) cannot hold a divergent value regardless of the
+ // instruction's semantics. Resolve that here so the generic
+ // MachineUniformityAnalysis seeding stays target-agnostic and does not need
+ // to consult the register bank itself.
+ if (RI.isUniformReg(MI.getMF()->getRegInfo(), *ST.getRegBankInfo(), DefReg))
+ return ValueUniformity::Default;
+
if (isNeverUniform(MI))
return ValueUniformity::NeverUniform;
>From 314b4cb4db03eb40827712e33fc3160e25a6c38a Mon Sep 17 00:00:00 2001
From: padivedi <pankajkumar.divedi at amd.com>
Date: Wed, 10 Jun 2026 19:27:48 +0530
Subject: [PATCH 3/3] review
---
llvm/include/llvm/CodeGen/TargetInstrInfo.h | 1 +
llvm/lib/CodeGen/MachineUniformityAnalysis.cpp | 3 ++-
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 4 ++--
llvm/lib/Target/AMDGPU/SIInstrInfo.h | 1 +
4 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index c24fe3a24500b..e571d7eb32c86 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2374,6 +2374,7 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
/// be a terminator and \p DefIdx must refer to a virtual register def; use
/// isTerminatorDivergent() to query branch divergence for terminators.
virtual ValueUniformity getValueUniformity(const MachineInstr &MI,
+ const MachineRegisterInfo &MRI,
unsigned DefIdx) const {
return ValueUniformity::Default;
}
diff --git a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
index e6c6af178bfae..4ad92fe710a77 100644
--- a/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
+++ b/llvm/lib/CodeGen/MachineUniformityAnalysis.cpp
@@ -64,6 +64,7 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
}
const TargetInstrInfo &InstrInfo = *F.getSubtarget().getInstrInfo();
+ const MachineRegisterInfo &MRI = F.getRegInfo();
for (const MachineBasicBlock &MBB : F) {
for (const MachineInstr &MI : MBB) {
@@ -85,7 +86,7 @@ void llvm::GenericUniformityAnalysisImpl<MachineSSAContext>::initialize() {
++DefIdx;
continue;
}
- switch (InstrInfo.getValueUniformity(MI, DefIdx++)) {
+ switch (InstrInfo.getValueUniformity(MI, MRI, DefIdx++)) {
case ValueUniformity::AlwaysUniform:
addUniformOverride(Reg);
break;
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index 7fd6f2ec2ecb8..71614b20824fe 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -11009,6 +11009,7 @@ bool SIInstrInfo::isTerminatorDivergent(const MachineInstr &MI) const {
}
ValueUniformity SIInstrInfo::getValueUniformity(const MachineInstr &MI,
+ const MachineRegisterInfo &MRI,
unsigned DefIdx) const {
assert(!MI.isTerminator() &&
"use isTerminatorDivergent() to query terminator divergence");
@@ -11024,7 +11025,7 @@ ValueUniformity SIInstrInfo::getValueUniformity(const MachineInstr &MI,
// instruction's semantics. Resolve that here so the generic
// MachineUniformityAnalysis seeding stays target-agnostic and does not need
// to consult the register bank itself.
- if (RI.isUniformReg(MI.getMF()->getRegInfo(), *ST.getRegBankInfo(), DefReg))
+ if (RI.isUniformReg(MRI, *ST.getRegBankInfo(), DefReg))
return ValueUniformity::Default;
if (isNeverUniform(MI))
@@ -11087,7 +11088,6 @@ ValueUniformity SIInstrInfo::getValueUniformity(const MachineInstr &MI,
return ValueUniformity::Default;
}
- const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();
// Fallback: the result is divergent if any source operand is divergent. This
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
index 75181434374cb..2af8c603de6c5 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
@@ -1756,6 +1756,7 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {
const MachineOperand &getCalleeOperand(const MachineInstr &MI) const override;
ValueUniformity getValueUniformity(const MachineInstr &MI,
+ const MachineRegisterInfo &MRI,
unsigned DefIdx) const final;
ValueUniformity getGenericValueUniformity(const MachineInstr &MI) const;
More information about the llvm-commits
mailing list