Skip to content

Commit 9cf2cc2

Browse files
gandhi56cursoragent
andcommitted
[AMDGPU][GlobalISel] Fold redundant uniform G_AMDGPU_READANYLANE in RegBankCombiner
Add a RegBankCombiner rule that replaces G_AMDGPU_READANYLANE when its source is already uniform (an sgpr value merely copied into a vgpr), eliminating the redundant sgpr -> vgpr -> sgpr round trip. Add a MIR test and update mul.ll check lines. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 1e7c2ac commit 9cf2cc2

4 files changed

Lines changed: 95 additions & 5 deletions

File tree

llvm/lib/Target/AMDGPU/AMDGPUCombine.td

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ class minmax_to_minmax3_opcodes<Instruction minmaxOpcode> : GICombineRule<
173173
[{ return matchMinMaxToMinMax3(*${min_or_max}, ${matchinfo}); }]),
174174
(apply [{ applyMinMaxToMinMax3(*${min_or_max}, ${matchinfo}); }])>;
175175

176+
// Fold a redundant G_AMDGPU_READANYLANE (v_readfirstlane_b32) whose source is
177+
// already uniform, i.e. an sgpr -> vgpr -> sgpr round trip.
178+
def redundant_readanylane : GICombineRule<
179+
(defs root:$readanylane, register_matchinfo:$matchinfo),
180+
(match (G_AMDGPU_READANYLANE $dst, $src):$readanylane,
181+
[{ return matchRedundantReadAnyLane(*${readanylane}, ${matchinfo}); }]),
182+
(apply [{ Helper.replaceSingleDefInstWithReg(*${readanylane}, ${matchinfo}); }])>;
183+
176184
def smax_to_minmax3 : minmax_to_minmax3_opcodes<G_SMAX>;
177185
def smin_to_minmax3 : minmax_to_minmax3_opcodes<G_SMIN>;
178186
def umax_to_minmax3 : minmax_to_minmax3_opcodes<G_UMAX>;
@@ -270,5 +278,6 @@ def AMDGPURegBankCombiner : GICombiner<
270278
cast_of_cast_combines, sext_trunc, zext_of_shift_amount_combines,
271279
d16_load, smax_to_minmax3, smin_to_minmax3, umax_to_minmax3,
272280
umin_to_minmax3, fmax_to_minmax3, fmin_to_minmax3, fmaximum_to_minmax3,
273-
fminimum_to_minmax3, fmax_ieee_to_minmax3, fmin_ieee_to_minmax3]> {
281+
fminimum_to_minmax3, fmax_ieee_to_minmax3, fmin_ieee_to_minmax3,
282+
redundant_readanylane]> {
274283
}

llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
2424
#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
2525
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
26+
#include "llvm/CodeGen/GlobalISel/Utils.h"
2627
#include "llvm/CodeGen/MachineDominators.h"
2728
#include "llvm/CodeGen/TargetPassConfig.h"
2829
#include "llvm/Target/TargetMachine.h"
@@ -103,6 +104,8 @@ class AMDGPURegBankCombinerImpl : public Combiner {
103104
void applyMinMaxToMinMax3(MachineInstr &MI,
104105
MinMaxToMinMax3MatchInfo &MatchInfo) const;
105106

107+
bool matchRedundantReadAnyLane(MachineInstr &MI, Register &Match) const;
108+
106109
private:
107110
SIModeRegisterDefaults getMode() const;
108111
bool getIEEE() const;
@@ -575,6 +578,36 @@ bool AMDGPURegBankCombinerImpl::matchMinMaxToMinMax3(
575578
return true;
576579
}
577580

581+
// Reading any lane of a value that is uniform across all lanes returns that
582+
// same value. G_AMDGPU_READANYLANE (selected as v_readfirstlane_b32) is emitted
583+
// by RegBankLegalize to move a uniform value from a vgpr into an sgpr. When the
584+
// source is itself already uniform (an sgpr value that was merely copied into a
585+
// vgpr), the read is a redundant sgpr -> vgpr -> sgpr round trip and the result
586+
// can be replaced with the original sgpr value.
587+
bool AMDGPURegBankCombinerImpl::matchRedundantReadAnyLane(
588+
MachineInstr &MI, Register &Match) const {
589+
assert(MI.getOpcode() == AMDGPU::G_AMDGPU_READANYLANE);
590+
Register Dst = MI.getOperand(0).getReg();
591+
Register Src = MI.getOperand(1).getReg();
592+
593+
// Look through copies to the value actually being read.
594+
Register SrcNoCopy = getSrcRegIgnoringCopies(Src, MRI);
595+
if (!SrcNoCopy.isValid())
596+
return false;
597+
598+
// Only fold when the read value is uniform (lives in the sgpr bank).
599+
const RegisterBank *RB = MRI.getRegBankOrNull(SrcNoCopy);
600+
if (!RB || RB->getID() != AMDGPU::SGPRRegBankID)
601+
return false;
602+
603+
// Copies preserve the type, but be defensive so we never change it.
604+
if (MRI.getType(SrcNoCopy) != MRI.getType(Dst))
605+
return false;
606+
607+
Match = SrcNoCopy;
608+
return true;
609+
}
610+
578611
bool AMDGPURegBankCombinerImpl::applyD16Load(
579612
unsigned D16Opc, MachineInstr &DstMI, MachineInstr *SmallLoad,
580613
Register SrcReg32ToOverwriteD16) const {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -mtriple=amdgcn -mcpu=gfx1100 -run-pass=amdgpu-regbank-combiner %s -o - | FileCheck %s
3+
4+
# A G_AMDGPU_READANYLANE whose source is a uniform (sgpr) value copied into a
5+
# vgpr is a redundant sgpr -> vgpr -> sgpr round trip and should be folded away.
6+
---
7+
name: readanylane_of_copy_from_sgpr
8+
tracksRegLiveness: true
9+
body: |
10+
bb.0:
11+
liveins: $sgpr0
12+
; CHECK-LABEL: name: readanylane_of_copy_from_sgpr
13+
; CHECK: liveins: $sgpr0
14+
; CHECK-NEXT: {{ $}}
15+
; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0
16+
; CHECK-NEXT: $sgpr0 = COPY [[COPY]](s32)
17+
; CHECK-NEXT: S_ENDPGM 0
18+
%0:sgpr(s32) = COPY $sgpr0
19+
%1:vgpr(s32) = COPY %0
20+
%2:sgpr(s32) = G_AMDGPU_READANYLANE %1
21+
$sgpr0 = COPY %2(s32)
22+
S_ENDPGM 0
23+
...
24+
25+
# Negative test: the source is a genuine vgpr (divergent) value, so the read is
26+
# required and must not be folded.
27+
---
28+
name: readanylane_of_divergent
29+
tracksRegLiveness: true
30+
body: |
31+
bb.0:
32+
liveins: $vgpr0, $vgpr1
33+
; CHECK-LABEL: name: readanylane_of_divergent
34+
; CHECK: liveins: $vgpr0, $vgpr1
35+
; CHECK-NEXT: {{ $}}
36+
; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0
37+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1
38+
; CHECK-NEXT: [[ADD:%[0-9]+]]:vgpr(s32) = G_ADD [[COPY]], [[COPY1]]
39+
; CHECK-NEXT: [[READ:%[0-9]+]]:sgpr(s32) = G_AMDGPU_READANYLANE [[ADD]]
40+
; CHECK-NEXT: $sgpr0 = COPY [[READ]](s32)
41+
; CHECK-NEXT: S_ENDPGM 0
42+
%0:vgpr(s32) = COPY $vgpr0
43+
%1:vgpr(s32) = COPY $vgpr1
44+
%2:vgpr(s32) = G_ADD %0, %1
45+
%3:sgpr(s32) = G_AMDGPU_READANYLANE %2
46+
$sgpr0 = COPY %3(s32)
47+
S_ENDPGM 0
48+
...

llvm/test/CodeGen/AMDGPU/packed-fp64.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2669,7 +2669,7 @@ define void @strict_fma_v2_vv(<2 x double> %x, <2 x double> %y, <2 x double> %z,
26692669
define amdgpu_kernel void @fma_v2_s_imm_imm(ptr addrspace(1) %a) {
26702670
; GFX1251-SDAG-LABEL: fma_v2_s_imm_imm:
26712671
; GFX1251-SDAG: ; %bb.0:
2672-
; GFX1251-SDAG-NEXT: global_wb
2672+
; GFX1251-SDAG-NEXT: global_prefetch_b8 v0, s[0:1] scope:SCOPE_SE
26732673
; GFX1251-SDAG-NEXT: v_nop
26742674
; GFX1251-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
26752675
; GFX1251-SDAG-NEXT: s_load_b64 s[2:3], s[4:5], 0x24 nv
@@ -2688,7 +2688,7 @@ define amdgpu_kernel void @fma_v2_s_imm_imm(ptr addrspace(1) %a) {
26882688
;
26892689
; GFX1251-GISEL-LABEL: fma_v2_s_imm_imm:
26902690
; GFX1251-GISEL: ; %bb.0:
2691-
; GFX1251-GISEL-NEXT: global_wb
2691+
; GFX1251-GISEL-NEXT: global_prefetch_b8 v0, s[0:1] scope:SCOPE_SE
26922692
; GFX1251-GISEL-NEXT: v_nop
26932693
; GFX1251-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
26942694
; GFX1251-GISEL-NEXT: s_load_b64 s[8:9], s[4:5], 0x24 nv
@@ -2731,7 +2731,7 @@ define amdgpu_kernel void @fma_v2_s_imm_imm(ptr addrspace(1) %a) {
27312731
define amdgpu_kernel void @fma_v2_imm_imm_s(ptr addrspace(1) %a) {
27322732
; GFX1251-SDAG-LABEL: fma_v2_imm_imm_s:
27332733
; GFX1251-SDAG: ; %bb.0:
2734-
; GFX1251-SDAG-NEXT: global_wb
2734+
; GFX1251-SDAG-NEXT: global_prefetch_b8 v0, s[0:1] scope:SCOPE_SE
27352735
; GFX1251-SDAG-NEXT: v_nop
27362736
; GFX1251-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
27372737
; GFX1251-SDAG-NEXT: s_load_b64 s[2:3], s[4:5], 0x24 nv
@@ -2749,7 +2749,7 @@ define amdgpu_kernel void @fma_v2_imm_imm_s(ptr addrspace(1) %a) {
27492749
;
27502750
; GFX1251-GISEL-LABEL: fma_v2_imm_imm_s:
27512751
; GFX1251-GISEL: ; %bb.0:
2752-
; GFX1251-GISEL-NEXT: global_wb
2752+
; GFX1251-GISEL-NEXT: global_prefetch_b8 v0, s[0:1] scope:SCOPE_SE
27532753
; GFX1251-GISEL-NEXT: v_nop
27542754
; GFX1251-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
27552755
; GFX1251-GISEL-NEXT: s_load_b64 s[8:9], s[4:5], 0x24 nv

0 commit comments

Comments
 (0)