[llvm] [SelectionDAG] Scalarize one-lane intrinsic results (PR #223622)

Bastian Hagedorn via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 15 01:34:34 PDT 2026


https://github.com/bastianhagedorn updated https://github.com/llvm/llvm-project/pull/223622

>From e2c3a769fff39ebbc53b119f830496640b48bf4b Mon Sep 17 00:00:00 2001
From: Bastian Hagedorn <bhagedorn at nvidia.com>
Date: Tue, 15 Sep 2026 07:16:19 +0000
Subject: [PATCH 1/2] [SelectionDAG] Scalarize one-lane intrinsic results

---
 llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h |  1 +
 .../SelectionDAG/LegalizeVectorTypes.cpp      | 29 +++++++++++++++++++
 llvm/test/CodeGen/NVPTX/f32-ex2.ll            | 20 +++++++++++++
 3 files changed, 50 insertions(+)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 6fc6d61c6a38d..ccff9a07a4d29 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -826,6 +826,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
   SDValue ScalarizeVecRes_TernaryOp(SDNode *N);
   SDValue ScalarizeVecRes_UnaryOp(SDNode *N);
   SDValue ScalarizeVecRes_StrictFPOp(SDNode *N);
+  SDValue ScalarizeVecRes_INTRINSIC_WO_CHAIN(SDNode *N);
   SDValue ScalarizeVecRes_OverflowOp(SDNode *N, unsigned ResNo);
   SDValue ScalarizeVecRes_InregOp(SDNode *N);
   SDValue ScalarizeVecRes_VecInregOp(SDNode *N);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index f6e7feab57ee9..71d1f7c632cee 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -83,6 +83,8 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
     R = ScalarizeVecRes_ATOMIC_LOAD(cast<AtomicSDNode>(N));
     break;
   case ISD::LOAD:           R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
+  case ISD::INTRINSIC_WO_CHAIN:
+    R = ScalarizeVecRes_INTRINSIC_WO_CHAIN(N); break;
   case ISD::SCALAR_TO_VECTOR:  R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
   case ISD::VECTOR_DEINTERLEAVE:
   case ISD::VECTOR_INTERLEAVE:
@@ -586,6 +588,33 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
   return Result;
 }
 
+SDValue DAGTypeLegalizer::ScalarizeVecRes_INTRINSIC_WO_CHAIN(SDNode *N) {
+  assert(N->getValueType(0).getVectorNumElements() == 1 &&
+         "Unexpected vector type");
+
+  SDLoc DL(N);
+  SmallVector<SDValue, 4> Ops{N->getOperand(0)};
+  for (unsigned I = 1; I < N->getNumOperands(); ++I) {
+    SDValue Operand = N->getOperand(I);
+    EVT OperandVT = Operand.getValueType();
+    if (OperandVT.isVector()) {
+      assert(OperandVT.getVectorNumElements() == 1 &&
+             "Unexpected vector operand type");
+      if (getTypeAction(OperandVT) == TargetLowering::TypeScalarizeVector) {
+        Operand = GetScalarizedVector(Operand);
+      } else {
+        Operand = DAG.getExtractVectorElt(DL, OperandVT.getVectorElementType(),
+                                          Operand, 0);
+      }
+    }
+    Ops.push_back(Operand);
+  }
+
+  return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL,
+                     N->getValueType(0).getVectorElementType(), Ops,
+                     N->getFlags());
+}
+
 SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
   // Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
   EVT DestVT = N->getValueType(0).getVectorElementType();
diff --git a/llvm/test/CodeGen/NVPTX/f32-ex2.ll b/llvm/test/CodeGen/NVPTX/f32-ex2.ll
index db3dd4a9e6011..523e681c9ea9e 100644
--- a/llvm/test/CodeGen/NVPTX/f32-ex2.ll
+++ b/llvm/test/CodeGen/NVPTX/f32-ex2.ll
@@ -5,6 +5,8 @@ target triple = "nvptx-nvidia-cuda"
 
 declare float @llvm.nvvm.ex2.approx.f32(float)
 declare float @llvm.nvvm.ex2.approx.ftz.f32(float)
+declare <1 x float> @llvm.nvvm.ex2.approx.v1f32(<1 x float>)
+declare <1 x float> @llvm.nvvm.ex2.approx.ftz.v1f32(<1 x float>)
 
 ; CHECK-LABEL: ex2_float
 define float @ex2_float(float %0) {
@@ -35,3 +37,21 @@ define float @ex2_float_ftz(float %0) {
   %res = call float @llvm.nvvm.ex2.approx.ftz.f32(float %0)
   ret float %res
 }
+
+; CHECK-LABEL: ex2_float_v1
+define <1 x float> @ex2_float_v1(<1 x float> %0) {
+; CHECK-LABEL: ex2_float_v1(
+; CHECK:       {
+; CHECK:         ex2.approx.f32
+  %res = call <1 x float> @llvm.nvvm.ex2.approx.v1f32(<1 x float> %0)
+  ret <1 x float> %res
+}
+
+; CHECK-LABEL: ex2_float_v1_ftz
+define <1 x float> @ex2_float_v1_ftz(<1 x float> %0) {
+; CHECK-LABEL: ex2_float_v1_ftz(
+; CHECK:       {
+; CHECK:         ex2.approx.ftz.f32
+  %res = call <1 x float> @llvm.nvvm.ex2.approx.ftz.v1f32(<1 x float> %0)
+  ret <1 x float> %res
+}

>From 14fa1393b2e645a6aae1185d43317018a397814c Mon Sep 17 00:00:00 2001
From: Bastian Hagedorn <bhagedorn at nvidia.com>
Date: Tue, 15 Sep 2026 08:33:20 +0000
Subject: [PATCH 2/2] [SelectionDAG] Fix formatting

---
 llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 71d1f7c632cee..487854fa3f4fd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -84,7 +84,8 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
     break;
   case ISD::LOAD:           R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
   case ISD::INTRINSIC_WO_CHAIN:
-    R = ScalarizeVecRes_INTRINSIC_WO_CHAIN(N); break;
+    R = ScalarizeVecRes_INTRINSIC_WO_CHAIN(N);
+    break;
   case ISD::SCALAR_TO_VECTOR:  R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
   case ISD::VECTOR_DEINTERLEAVE:
   case ISD::VECTOR_INTERLEAVE:



More information about the llvm-commits mailing list