[llvm] f7ce52f - [AMDGPU] Fix FDOT2 fold for non-constant lane indices (#217646)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 7 14:59:28 PDT 2026
Author: Arseniy Obolenskiy
Date: 2026-09-07T21:59:23Z
New Revision: f7ce52f0f4ec943bfdc749bc67de00a1e3ece6bc
URL: https://github.com/llvm/llvm-project/commit/f7ce52f0f4ec943bfdc749bc67de00a1e3ece6bc
DIFF: https://github.com/llvm/llvm-project/commit/f7ce52f0f4ec943bfdc749bc67de00a1e3ece6bc.diff
LOG: [AMDGPU] Fix FDOT2 fold for non-constant lane indices (#217646)
The fold only checked that the two lane index nodes were not the same
SDValue, but distinct nodes can still be equal at runtime, silently
picking the wrong lanes
Require both indices to be constant and distinct
Added:
Modified:
llvm/lib/Target/AMDGPU/SIISelLowering.cpp
llvm/test/CodeGen/AMDGPU/fdot2.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 5fb904aa4970f..1ec23da794bca 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -18394,8 +18394,10 @@ SDValue SITargetLowering::performFMACombine(SDNode *N,
SDValue Vec4 = FMAOp2.getOperand(0);
SDValue Idx2 = FMAOp1.getOperand(1);
- if (Idx1 != Op2.getOperand(1) || Idx2 != FMAOp2.getOperand(1) ||
- // Idx1 and Idx2 cannot be the same.
+ if (Idx1 != Op2.getOperand(1) || Idx2 != FMAOp2.getOperand(1))
+ return SDValue();
+
+ if (!isa<ConstantSDNode>(Idx1) || !isa<ConstantSDNode>(Idx2) ||
Idx1 == Idx2)
return SDValue();
diff --git a/llvm/test/CodeGen/AMDGPU/fdot2.ll b/llvm/test/CodeGen/AMDGPU/fdot2.ll
index a9665ba607936..c03e41052535e 100644
--- a/llvm/test/CodeGen/AMDGPU/fdot2.ll
+++ b/llvm/test/CodeGen/AMDGPU/fdot2.ll
@@ -493,4 +493,52 @@ define amdgpu_kernel void @dotproduct_f16_f32_afn(<2 x half> %a, <2 x half> %b,
ret void
}
+; fdot2 hardwires lanes 0/1, so it must not fold when %i == %j at runtime.
+; GCN-LABEL: {{^}}Var_Idx_NotAdotproductContract
+; GFX906-DENORM-CONTRACT-NOT: v_dot2
+; GFX906-DENORM-CONTRACT: v_fma_mix_f32
+; GFX90A-PS-NOT: v_dot2
+; GFX90A-PS: v_fma_mix_f32
+define float @Var_Idx_NotAdotproductContract(<2 x half> %src1, <2 x half> %src2, float %acc, i32 %i, i32 %j) {
+ %src1.eli = extractelement <2 x half> %src1, i32 %i
+ %csrc1.eli = fpext half %src1.eli to float
+ %src2.eli = extractelement <2 x half> %src2, i32 %i
+ %csrc2.eli = fpext half %src2.eli to float
+
+ %src1.elj = extractelement <2 x half> %src1, i32 %j
+ %csrc1.elj = fpext half %src1.elj to float
+ %src2.elj = extractelement <2 x half> %src2, i32 %j
+ %csrc2.elj = fpext half %src2.elj to float
+
+ %mul2 = fmul contract float %csrc1.elj, %csrc2.elj
+ %mul1 = fmul contract float %csrc1.eli, %csrc2.eli
+ %acc1 = fadd contract float %mul2, %acc
+ %acc2 = fadd contract float %mul1, %acc1
+ ret float %acc2
+}
+
+; A mix of a constant and a variable index must not fold either.
+; GCN-LABEL: {{^}}Mixed_Idx_NotAdotproductContract
+; GFX906-DENORM-CONTRACT-NOT: v_dot2
+; GFX906-DENORM-CONTRACT: v_fma_mix_f32
+; GFX90A-PS-NOT: v_dot2
+; GFX90A-PS: v_fma_mix_f32
+define float @Mixed_Idx_NotAdotproductContract(<2 x half> %src1, <2 x half> %src2, float %acc, i32 %j) {
+ %src1.el0 = extractelement <2 x half> %src1, i32 0
+ %csrc1.el0 = fpext half %src1.el0 to float
+ %src2.el0 = extractelement <2 x half> %src2, i32 0
+ %csrc2.el0 = fpext half %src2.el0 to float
+
+ %src1.elj = extractelement <2 x half> %src1, i32 %j
+ %csrc1.elj = fpext half %src1.elj to float
+ %src2.elj = extractelement <2 x half> %src2, i32 %j
+ %csrc2.elj = fpext half %src2.elj to float
+
+ %mul2 = fmul contract float %csrc1.elj, %csrc2.elj
+ %mul1 = fmul contract float %csrc1.el0, %csrc2.el0
+ %acc1 = fadd contract float %mul2, %acc
+ %acc2 = fadd contract float %mul1, %acc1
+ ret float %acc2
+}
+
attributes #0 = { denormal_fpenv(float: dynamic) }
More information about the llvm-commits
mailing list