https://github.com/harrisonGPU updated https://github.com/llvm/llvm-project/pull/225003
>From 101bff3557366932314462d1b32abc9fd257d10f Mon Sep 17 00:00:00 2001 From: Harrison Hao <[email protected]> Date: Mon, 21 Sep 2026 13:19:30 +0800 Subject: [PATCH] [AMDGPU][InstCombine] Fold zero dot operands to accumulator 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. --- .../AMDGPU/AMDGPUInstCombineIntrinsic.cpp | 4 +++ .../InstCombine/AMDGPU/llvm.amdgcn.dot.ll | 36 +++++++------------ 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp index dcbdde6ccbdfa..7a82f35a85ba6 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
