[llvm-branch-commits] [llvm] [AMDGPU][InstCombine] Fold zero dot operands to accumulator (PR #225003)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Sep 20 22:45:38 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Harrison Hao (harrisonGPU)

<details>
<summary>Changes</summary>

Fold AMDGPU dot intrinsics when either operand is zero.

`dot(a, 0) = 0` and `dot(0, b) = 0`, so replace the intrinsic with its accumulator.
This avoids unrelated clamp and add/sub reassociation cases.

---

<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>

---
Full diff: https://github.com/llvm/llvm-project/pull/225003.diff


2 Files Affected:

- (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+4) 
- (modified) llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dot.ll (+12-24) 


``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 6bfbfd189c1da..2f485b3667d87 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -1974,6 +1974,10 @@ GCNTTIImpl::instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const {
   case Intrinsic::amdgcn_udot4:
   case Intrinsic::amdgcn_sdot8:
   case Intrinsic::amdgcn_udot8: {
+    if (match(II.getArgOperand(0), m_Zero()) ||
+        match(II.getArgOperand(1), m_Zero()))
+      return IC.replaceInstUsesWith(II, II.getArgOperand(2));
+
     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 c002c5ebecc27..017896248970c 100644
--- a/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dot.ll
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/llvm.amdgcn.dot.ll
@@ -26,8 +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:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.sdot2(<2 x i16> zeroinitializer, <2 x i16> %b, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -37,8 +36,7 @@ define i32 @sdot2_a_zero(<2 x i16> %b) {
 define i32 @sdot2_b_zero(<2 x i16> %a) {
 ; CHECK-LABEL: define i32 @sdot2_b_zero(
 ; CHECK-SAME: <2 x i16> [[A:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call i32 @llvm.amdgcn.sdot2(<2 x i16> [[A]], <2 x i16> zeroinitializer, i32 16, i1 false)
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.sdot2(<2 x i16> %a, <2 x i16> zeroinitializer, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -119,8 +117,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:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.udot2(<2 x i16> zeroinitializer, <2 x i16> %b, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -130,8 +127,7 @@ define i32 @udot2_a_zero(<2 x i16> %b) {
 define i32 @udot2_b_zero(<2 x i16> %a) {
 ; CHECK-LABEL: define i32 @udot2_b_zero(
 ; CHECK-SAME: <2 x i16> [[A:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call i32 @llvm.amdgcn.udot2(<2 x i16> [[A]], <2 x i16> zeroinitializer, i32 16, i1 false)
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.udot2(<2 x i16> %a, <2 x i16> zeroinitializer, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -197,8 +193,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:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.sdot4(i32 0, i32 %b, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -208,8 +203,7 @@ define i32 @sdot4_a_zero(i32 %b) {
 define i32 @sdot4_b_zero(i32 %a) {
 ; CHECK-LABEL: define i32 @sdot4_b_zero(
 ; CHECK-SAME: i32 [[A:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call i32 @llvm.amdgcn.sdot4(i32 [[A]], i32 0, i32 16, i1 false)
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.sdot4(i32 %a, i32 0, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -337,8 +331,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:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.udot4(i32 0, i32 %b, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -348,8 +341,7 @@ define i32 @udot4_a_zero(i32 %b) {
 define i32 @udot4_b_zero(i32 %a) {
 ; CHECK-LABEL: define i32 @udot4_b_zero(
 ; CHECK-SAME: i32 [[A:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call i32 @llvm.amdgcn.udot4(i32 [[A]], i32 0, i32 16, i1 false)
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.udot4(i32 %a, i32 0, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -404,8 +396,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:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.sdot8(i32 0, i32 %b, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -415,8 +406,7 @@ define i32 @sdot8_a_zero(i32 %b) {
 define i32 @sdot8_b_zero(i32 %a) {
 ; CHECK-LABEL: define i32 @sdot8_b_zero(
 ; CHECK-SAME: i32 [[A:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call i32 @llvm.amdgcn.sdot8(i32 [[A]], i32 0, i32 16, i1 false)
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.sdot8(i32 %a, i32 0, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -471,8 +461,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:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.udot8(i32 0, i32 %b, i32 7, i1 false)
   %r = add i32 %dot, 9
@@ -482,8 +471,7 @@ define i32 @udot8_a_zero(i32 %b) {
 define i32 @udot8_b_zero(i32 %a) {
 ; CHECK-LABEL: define i32 @udot8_b_zero(
 ; CHECK-SAME: i32 [[A:%.*]]) {
-; CHECK-NEXT:    [[R:%.*]] = call i32 @llvm.amdgcn.udot8(i32 [[A]], i32 0, i32 16, i1 false)
-; CHECK-NEXT:    ret i32 [[R]]
+; CHECK-NEXT:    ret i32 16
 ;
   %dot = call i32 @llvm.amdgcn.udot8(i32 %a, i32 0, i32 7, i1 false)
   %r = add i32 %dot, 9

``````````

</details>


https://github.com/llvm/llvm-project/pull/225003


More information about the llvm-branch-commits mailing list