[llvm] 5cab296 - [SelectionDAG] Fix result index and vector width in unrollExpandedOp (#225886)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 25 15:53:11 PDT 2026
Author: Demetrios Chiuratto Agourakis
Date: 2026-09-25T15:53:05-07:00
New Revision: 5cab2963e13496c272a482145b11796e9e26eeb4
URL: https://github.com/llvm/llvm-project/commit/5cab2963e13496c272a482145b11796e9e26eeb4
DIFF: https://github.com/llvm/llvm-project/commit/5cab2963e13496c272a482145b11796e9e26eeb4.diff
LOG: [SelectionDAG] Fix result index and vector width in unrollExpandedOp (#225886)
Fixes #224127.
In `DAGTypeLegalizer::WidenVectorResult`, `unrollExpandedOp` computes
the unroll count and widened vector type from the result being legalized
(`ResNo`) rather than unconditionally using result 0. For multi-result
nodes where result types differ (e.g. `ISD::FFREXP`), this prevents
mismatched vector widths and preserves the correct result index from
`DAG.UnrollVectorOp`.
Assisted-by: Claude
---------
Co-authored-by: Demetrios Chiuratto Agourakis <agourakis82 at gmail.com>
Added:
Modified:
llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
llvm/test/CodeGen/X86/llvm.frexp.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 2e78858d422b9..913aa4536bc81 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -5262,13 +5262,16 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
// elements. If the wide vector op is eventually going to be expanded to
// scalar libcalls, then unroll into scalar ops now to avoid unnecessary
// libcalls on the undef elements.
- EVT VT = N->getValueType(0);
- EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
+ EVT ResVT = N->getValueType(ResNo);
+ EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
+ EVT VT0 = N->getValueType(0);
if (!TLI.isOperationLegalOrCustomOrPromote(N->getOpcode(), WideVecVT) &&
- TLI.isOperationExpandOrLibCall(N->getOpcode(), VT.getScalarType())) {
- Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
+ TLI.isOperationExpandOrLibCall(N->getOpcode(), VT0.getScalarType())) {
+ SDValue Unrolled =
+ DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
+ Res = Unrolled.getValue(ResNo);
if (N->getNumValues() > 1)
- ReplaceOtherWidenResults(N, Res.getNode(), ResNo);
+ ReplaceOtherWidenResults(N, Unrolled.getNode(), ResNo);
return true;
}
return false;
diff --git a/llvm/test/CodeGen/X86/llvm.frexp.ll b/llvm/test/CodeGen/X86/llvm.frexp.ll
index fb778add339fb..079c1504ca50f 100644
--- a/llvm/test/CodeGen/X86/llvm.frexp.ll
+++ b/llvm/test/CodeGen/X86/llvm.frexp.ll
@@ -588,22 +588,136 @@ define { float, i32 } @pr160981() {
ret { float, i32 } %ret
}
-; FIXME: Widen vector result
-; define { <2 x double>, <2 x i32> } @test_frexp_v2f64_v2i32(<2 x double> %a) nounwind {
-; %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
-; ret { <2 x double>, <2 x i32> } %result
-; }
+define { <2 x double>, <2 x i32> } @test_frexp_v2f64_v2i32(<2 x double> %a) nounwind {
+; X64-LABEL: test_frexp_v2f64_v2i32:
+; X64: # %bb.0:
+; X64-NEXT: subq $56, %rsp
+; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT: callq frexp at PLT
+; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; X64-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]
+; X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT: callq frexp at PLT
+; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 # 16-byte Reload
+; X64-NEXT: movlhps {{.*#+}} xmm2 = xmm2[0],xmm0[0]
+; X64-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; X64-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X64-NEXT: unpcklps {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
+; X64-NEXT: movaps %xmm2, %xmm0
+; X64-NEXT: addq $56, %rsp
+; X64-NEXT: retq
+;
+; WIN32-LABEL: test_frexp_v2f64_v2i32:
+; WIN32: # %bb.0:
+; WIN32-NEXT: subl $36, %esp
+; WIN32-NEXT: fldl {{[0-9]+}}(%esp)
+; WIN32-NEXT: fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
+; WIN32-NEXT: fldl {{[0-9]+}}(%esp)
+; WIN32-NEXT: leal {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT: fstpl (%esp)
+; WIN32-NEXT: calll _frexp
+; WIN32-NEXT: fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
+; WIN32-NEXT: leal {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT: fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
+; WIN32-NEXT: fstpl (%esp)
+; WIN32-NEXT: calll _frexp
+; WIN32-NEXT: movl {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT: movl {{[0-9]+}}(%esp), %edx
+; WIN32-NEXT: fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
+; WIN32-NEXT: addl $36, %esp
+; WIN32-NEXT: retl
+ %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
+ ret { <2 x double>, <2 x i32> } %result
+}
-; define <2 x double> @test_frexp_v2f64_v2i32_only_use_fract(<2 x double> %a) nounwind {
-; %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
-; %result.0 = extractvalue { <2 x double>, <2 x i32> } %result, 0
-; ret <2 x double> %result.0
-; }
+define <2 x double> @test_frexp_v2f64_v2i32_only_use_fract(<2 x double> %a) nounwind {
+; X64-LABEL: test_frexp_v2f64_v2i32_only_use_fract:
+; X64: # %bb.0:
+; X64-NEXT: subq $56, %rsp
+; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT: callq frexp at PLT
+; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; X64-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]
+; X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT: callq frexp at PLT
+; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 16-byte Reload
+; X64-NEXT: movlhps {{.*#+}} xmm1 = xmm1[0],xmm0[0]
+; X64-NEXT: movaps %xmm1, %xmm0
+; X64-NEXT: addq $56, %rsp
+; X64-NEXT: retq
+;
+; WIN32-LABEL: test_frexp_v2f64_v2i32_only_use_fract:
+; WIN32: # %bb.0:
+; WIN32-NEXT: subl $36, %esp
+; WIN32-NEXT: fldl {{[0-9]+}}(%esp)
+; WIN32-NEXT: fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
+; WIN32-NEXT: fldl {{[0-9]+}}(%esp)
+; WIN32-NEXT: leal {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT: fstpl (%esp)
+; WIN32-NEXT: calll _frexp
+; WIN32-NEXT: fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
+; WIN32-NEXT: leal {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT: fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
+; WIN32-NEXT: fstpl (%esp)
+; WIN32-NEXT: calll _frexp
+; WIN32-NEXT: fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
+; WIN32-NEXT: fxch %st(1)
+; WIN32-NEXT: addl $36, %esp
+; WIN32-NEXT: retl
+ %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
+ %result.0 = extractvalue { <2 x double>, <2 x i32> } %result, 0
+ ret <2 x double> %result.0
+}
-; define <2 x i32> @test_frexp_v2f64_v2i32_only_use_exp(<2 x double> %a) nounwind {
-; %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
-; %result.1 = extractvalue { <2 x double>, <2 x i32> } %result, 1
-; ret <2 x i32> %result.1
-; }
+define <2 x i32> @test_frexp_v2f64_v2i32_only_use_exp(<2 x double> %a) nounwind {
+; X64-LABEL: test_frexp_v2f64_v2i32_only_use_exp:
+; X64: # %bb.0:
+; X64-NEXT: subq $40, %rsp
+; X64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 16-byte Spill
+; X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT: callq frexp at PLT
+; X64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 16-byte Reload
+; X64-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]
+; X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi
+; X64-NEXT: callq frexp at PLT
+; X64-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X64-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; X64-NEXT: unpcklps {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
+; X64-NEXT: addq $40, %rsp
+; X64-NEXT: retq
+;
+; WIN32-LABEL: test_frexp_v2f64_v2i32_only_use_exp:
+; WIN32: # %bb.0:
+; WIN32-NEXT: subl $28, %esp
+; WIN32-NEXT: fldl {{[0-9]+}}(%esp)
+; WIN32-NEXT: fstpl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Spill
+; WIN32-NEXT: fldl {{[0-9]+}}(%esp)
+; WIN32-NEXT: leal {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT: fstpl (%esp)
+; WIN32-NEXT: calll _frexp
+; WIN32-NEXT: fstp %st(0)
+; WIN32-NEXT: leal {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT: movl %eax, {{[0-9]+}}(%esp)
+; WIN32-NEXT: fldl {{[-0-9]+}}(%e{{[sb]}}p) # 8-byte Folded Reload
+; WIN32-NEXT: fstpl (%esp)
+; WIN32-NEXT: calll _frexp
+; WIN32-NEXT: fstp %st(0)
+; WIN32-NEXT: movl {{[0-9]+}}(%esp), %eax
+; WIN32-NEXT: movl {{[0-9]+}}(%esp), %edx
+; WIN32-NEXT: addl $28, %esp
+; WIN32-NEXT: retl
+ %result = call { <2 x double>, <2 x i32> } @llvm.frexp.v2f64.v2i32(<2 x double> %a)
+ %result.1 = extractvalue { <2 x double>, <2 x i32> } %result, 1
+ ret <2 x i32> %result.1
+}
attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
More information about the llvm-commits
mailing list