[llvm-branch-commits] [llvm] release/23.x: [SelectionDAG] Fix result index and vector width in unrollExpandedOp (#225886) (PR #226607)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Sep 25 16:48:42 PDT 2026
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/226607
Backport 5cab2963e13496c272a482145b11796e9e26eeb4
Requested by: @anun333
>From 5171836cfe0f73905d48659406dc2fe5caabfbde Mon Sep 17 00:00:00 2001
From: Demetrios Chiuratto Agourakis <demetrios at agourakis.med.br>
Date: Fri, 25 Sep 2026 19:53:05 -0300
Subject: [PATCH] [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>
(cherry picked from commit 5cab2963e13496c272a482145b11796e9e26eeb4)
---
.../SelectionDAG/LegalizeVectorTypes.cpp | 13 +-
llvm/test/CodeGen/X86/llvm.frexp.ll | 144 ++++++++++++++++--
2 files changed, 137 insertions(+), 20 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index c0fab69cb518a5..e0a44144f6a165 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -5242,13 +5242,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 3410fd5169c9a4..d849670e98fa4c 100644
--- a/llvm/test/CodeGen/X86/llvm.frexp.ll
+++ b/llvm/test/CodeGen/X86/llvm.frexp.ll
@@ -590,22 +590,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-branch-commits
mailing list