https://github.com/harrisonGPU created https://github.com/llvm/llvm-project/pull/225083
Move constant dot product source operands to the right hand side and add tests for signed and unsigned dot intrinsics. --- <sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub> >From 1cb8c43d60333bf13b72046a0cbe5478fb283b82 Mon Sep 17 00:00:00 2001 From: Harrison Hao <[email protected]> Date: Mon, 21 Sep 2026 21:01:31 +0800 Subject: [PATCH] [AMDGPU][InstCombine] Canonicalize dot constant operands Move constant dot product source operands to the right hand side and add tests for signed and unsigned dot intrinsics. --- .../AMDGPU/AMDGPUInstCombineIntrinsic.cpp | 9 +++++++ .../InstCombine/AMDGPU/llvm.amdgcn.dot.ll | 24 +++++++++---------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp index dcbdde6ccbdfa3..f6c08bdc58d3d9 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp @@ -1974,6 +1974,15 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const { case Intrinsic::amdgcn_udot4: case Intrinsic::amdgcn_sdot8: case Intrinsic::amdgcn_udot8: { + Value *Src0 = II.getArgOperand(0); + Value *Src1 = II.getArgOperand(1); + + if (isa<Constant>(Src0) && !isa<Constant>(Src1)) { + II.setArgOperand(0, Src1); + II.setArgOperand(1, Src0); + return &II; + } + if (!match(II.getArgOperand(3), m_Zero()) || !II.hasOneUse()) break; diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dot.ll b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dot.ll index 09bebfb29fdf03..d73048239288d5 100644 --- a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dot.ll +++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dot.ll @@ -26,7 +26,7 @@ define i32 @sdot2_sub(<2 x i16> %a, <2 x i16> %b) { define i32 @sdot2_a_zero(<2 x i16> %b) { ; CHECK-LABEL: define i32 @sdot2_a_zero( ; CHECK-SAME: <2 x i16> [[B:%.*]]) { -; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.sdot2(<2 x i16> zeroinitializer, <2 x i16> [[B]], i32 16, i1 false) +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.sdot2(<2 x i16> [[B]], <2 x i16> zeroinitializer, i32 16, i1 false) ; CHECK-NEXT: ret i32 [[R]] ; %dot = call i32 @llvm.amdgcn.sdot2(<2 x i16> zeroinitializer, <2 x i16> %b, i32 7, i1 false) @@ -37,7 +37,7 @@ define i32 @sdot2_a_zero(<2 x i16> %b) { define i32 @sdot2_const_lhs(<2 x i16> %b, i32 %acc) { ; CHECK-LABEL: define i32 @sdot2_const_lhs( ; CHECK-SAME: <2 x i16> [[B:%.*]], i32 [[ACC:%.*]]) { -; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.sdot2(<2 x i16> zeroinitializer, <2 x i16> [[B]], i32 [[ACC]], i1 false) +; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.sdot2(<2 x i16> [[B]], <2 x i16> zeroinitializer, i32 [[ACC]], i1 false) ; CHECK-NEXT: ret i32 [[DOT]] ; %dot = call i32 @llvm.amdgcn.sdot2(<2 x i16> zeroinitializer, <2 x i16> %b, i32 %acc, i1 false) @@ -129,7 +129,7 @@ define i32 @udot2_sub(<2 x i16> %a, <2 x i16> %b) { define i32 @udot2_a_zero(<2 x i16> %b) { ; CHECK-LABEL: define i32 @udot2_a_zero( ; CHECK-SAME: <2 x i16> [[B:%.*]]) { -; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.udot2(<2 x i16> zeroinitializer, <2 x i16> [[B]], i32 16, i1 false) +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.udot2(<2 x i16> [[B]], <2 x i16> zeroinitializer, i32 16, i1 false) ; CHECK-NEXT: ret i32 [[R]] ; %dot = call i32 @llvm.amdgcn.udot2(<2 x i16> zeroinitializer, <2 x i16> %b, i32 7, i1 false) @@ -140,7 +140,7 @@ define i32 @udot2_a_zero(<2 x i16> %b) { define i32 @udot2_const_lhs(<2 x i16> %b, i32 %acc) { ; CHECK-LABEL: define i32 @udot2_const_lhs( ; CHECK-SAME: <2 x i16> [[B:%.*]], i32 [[ACC:%.*]]) { -; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.udot2(<2 x i16> zeroinitializer, <2 x i16> [[B]], i32 [[ACC]], i1 false) +; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.udot2(<2 x i16> [[B]], <2 x i16> zeroinitializer, i32 [[ACC]], i1 false) ; CHECK-NEXT: ret i32 [[DOT]] ; %dot = call i32 @llvm.amdgcn.udot2(<2 x i16> zeroinitializer, <2 x i16> %b, i32 %acc, i1 false) @@ -217,7 +217,7 @@ define i32 @sdot4_sub(i32 %a, i32 %b) { define i32 @sdot4_a_zero(i32 %b) { ; CHECK-LABEL: define i32 @sdot4_a_zero( ; CHECK-SAME: i32 [[B:%.*]]) { -; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.sdot4(i32 0, i32 [[B]], i32 16, i1 false) +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.sdot4(i32 [[B]], i32 0, i32 16, i1 false) ; CHECK-NEXT: ret i32 [[R]] ; %dot = call i32 @llvm.amdgcn.sdot4(i32 0, i32 %b, i32 7, i1 false) @@ -228,7 +228,7 @@ define i32 @sdot4_a_zero(i32 %b) { define i32 @sdot4_const_lhs(i32 %b, i32 %acc) { ; CHECK-LABEL: define i32 @sdot4_const_lhs( ; CHECK-SAME: i32 [[B:%.*]], i32 [[ACC:%.*]]) { -; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.sdot4(i32 16843009, i32 [[B]], i32 [[ACC]], i1 false) +; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.sdot4(i32 [[B]], i32 16843009, i32 [[ACC]], i1 false) ; CHECK-NEXT: ret i32 [[DOT]] ; %dot = call i32 @llvm.amdgcn.sdot4(i32 16843009, i32 %b, i32 %acc, i1 false) @@ -367,7 +367,7 @@ define i32 @udot4_sub(i32 %a, i32 %b) { define i32 @udot4_a_zero(i32 %b) { ; CHECK-LABEL: define i32 @udot4_a_zero( ; CHECK-SAME: i32 [[B:%.*]]) { -; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.udot4(i32 0, i32 [[B]], i32 16, i1 false) +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.udot4(i32 [[B]], i32 0, i32 16, i1 false) ; CHECK-NEXT: ret i32 [[R]] ; %dot = call i32 @llvm.amdgcn.udot4(i32 0, i32 %b, i32 7, i1 false) @@ -378,7 +378,7 @@ define i32 @udot4_a_zero(i32 %b) { define i32 @udot4_const_lhs(i32 %b, i32 %acc) { ; CHECK-LABEL: define i32 @udot4_const_lhs( ; CHECK-SAME: i32 [[B:%.*]], i32 [[ACC:%.*]]) { -; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.udot4(i32 6, i32 [[B]], i32 [[ACC]], i1 false) +; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.udot4(i32 [[B]], i32 6, i32 [[ACC]], i1 false) ; CHECK-NEXT: ret i32 [[DOT]] ; %dot = call i32 @llvm.amdgcn.udot4(i32 6, i32 %b, i32 %acc, i1 false) @@ -444,7 +444,7 @@ define i32 @sdot8_sub(i32 %a, i32 %b) { define i32 @sdot8_a_zero(i32 %b) { ; CHECK-LABEL: define i32 @sdot8_a_zero( ; CHECK-SAME: i32 [[B:%.*]]) { -; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.sdot8(i32 0, i32 [[B]], i32 16, i1 false) +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.sdot8(i32 [[B]], i32 0, i32 16, i1 false) ; CHECK-NEXT: ret i32 [[R]] ; %dot = call i32 @llvm.amdgcn.sdot8(i32 0, i32 %b, i32 7, i1 false) @@ -455,7 +455,7 @@ define i32 @sdot8_a_zero(i32 %b) { define i32 @sdot8_const_lhs(i32 %b, i32 %acc) { ; CHECK-LABEL: define i32 @sdot8_const_lhs( ; CHECK-SAME: i32 [[B:%.*]], i32 [[ACC:%.*]]) { -; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.sdot8(i32 16843009, i32 [[B]], i32 [[ACC]], i1 false) +; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.sdot8(i32 [[B]], i32 16843009, i32 [[ACC]], i1 false) ; CHECK-NEXT: ret i32 [[DOT]] ; %dot = call i32 @llvm.amdgcn.sdot8(i32 16843009, i32 %b, i32 %acc, i1 false) @@ -521,7 +521,7 @@ define i32 @udot8_sub(i32 %a, i32 %b) { define i32 @udot8_a_zero(i32 %b) { ; CHECK-LABEL: define i32 @udot8_a_zero( ; CHECK-SAME: i32 [[B:%.*]]) { -; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.udot8(i32 0, i32 [[B]], i32 16, i1 false) +; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.amdgcn.udot8(i32 [[B]], i32 0, i32 16, i1 false) ; CHECK-NEXT: ret i32 [[R]] ; %dot = call i32 @llvm.amdgcn.udot8(i32 0, i32 %b, i32 7, i1 false) @@ -532,7 +532,7 @@ define i32 @udot8_a_zero(i32 %b) { define i32 @udot8_const_lhs(i32 %b, i32 %acc) { ; CHECK-LABEL: define i32 @udot8_const_lhs( ; CHECK-SAME: i32 [[B:%.*]], i32 [[ACC:%.*]]) { -; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.udot8(i32 0, i32 [[B]], i32 [[ACC]], i1 false) +; CHECK-NEXT: [[DOT:%.*]] = call i32 @llvm.amdgcn.udot8(i32 [[B]], i32 0, i32 [[ACC]], i1 false) ; CHECK-NEXT: ret i32 [[DOT]] ; %dot = call i32 @llvm.amdgcn.udot8(i32 0, i32 %b, i32 %acc, i1 false) _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
