[llvm-branch-commits] [llvm] release/23.x: [SPARC] Lower dynamic v2i32 vector extracts on 32-bit SPARC (#222348) (PR #232099)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Oct 14 14:49:19 PDT 2026


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/232099

Backport fc264e6ba8b4c65abb716882826e3adccc3bbf1a

Requested by: @brad0

>From a8aa34d108928df0addd5ef2aa7c24f414d7544f Mon Sep 17 00:00:00 2001
From: Daniel Cederman <cederman at gaisler.com>
Date: Tue, 13 Oct 2026 17:22:57 +0200
Subject: [PATCH] [SPARC] Lower dynamic v2i32 vector extracts on 32-bit SPARC
 (#222348)

Lower dynamically indexed extracts after vector legalization so that
instruction selection never receives a variable index.

Constant indexes use the existing TableGen patterns.

Fixes the following error:

LLVM ERROR: Cannot select: 0x5e7e87e5b590: i32 = extract_vector_elt
0x5e7e87e5b910, 0x5e7e87e5b0c0
  0x5e7e87e5b910: v2i32 = BUILD_VECTOR 0x5e7e87e5af70, 0x5e7e87e5b6e0
    0x5e7e87e5af70: i32,ch = CopyFromReg 0x5e7e87e24840, Register:i32 %0
      0x5e7e87e5b750: i32 = Register %0
    0x5e7e87e5b6e0: i32,ch = CopyFromReg 0x5e7e87e24840, Register:i32 %1
      0x5e7e87e5b7c0: i32 = Register %1
  0x5e7e87e5b0c0: i32,ch = CopyFromReg 0x5e7e87e24840, Register:i32 %2
    0x5e7e87e5afe0: i32 = Register %2
In function: extract_v2i8

Assisted-by: Codex
(cherry picked from commit fc264e6ba8b4c65abb716882826e3adccc3bbf1a)
---
 llvm/lib/Target/Sparc/SparcISelLowering.cpp   | 24 +++++++++++++++-
 llvm/test/CodeGen/SPARC/vector-extract-elt.ll | 28 ++++++++++++++++---
 2 files changed, 47 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index c45babaec5dc2e..829e31f5143000 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1681,7 +1681,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
     // However, load and store *are* legal.
     setOperationAction(ISD::LOAD, MVT::v2i32, Legal);
     setOperationAction(ISD::STORE, MVT::v2i32, Legal);
-    setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Legal);
+    setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Custom);
     setOperationAction(ISD::BUILD_VECTOR, MVT::v2i32, Legal);
 
     // And we need to promote i64 loads/stores into vector load/store
@@ -3163,6 +3163,26 @@ static SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) {
   return Op;
 }
 
+static SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
+  SDLoc DL(Op);
+  SDValue Vec = Op.getOperand(0);
+  SDValue Idx = Op.getOperand(1);
+  assert(Vec.getSimpleValueType() == MVT::v2i32 && "Unexpected vector type");
+
+  // Constant indices are handled by the TableGen patterns.
+  if (isa<ConstantSDNode>(Idx))
+    return Op;
+
+  EVT VT = Op.getValueType();
+  EVT IdxVT = Idx.getValueType();
+  SDValue Elt0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Vec,
+                             DAG.getConstant(0, DL, IdxVT));
+  SDValue Elt1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Vec,
+                             DAG.getConstant(1, DL, IdxVT));
+  return DAG.getSelectCC(DL, Idx, DAG.getConstant(0, DL, IdxVT), Elt0, Elt1,
+                         ISD::SETEQ);
+}
+
 SDValue SparcTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
                                                      SelectionDAG &DAG) const {
   unsigned IntNo = Op.getConstantOperandVal(0);
@@ -3233,6 +3253,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
   case ISD::FP_ROUND:           return LowerF128_FPROUND(Op, DAG, *this);
   case ISD::ATOMIC_LOAD:
   case ISD::ATOMIC_STORE:       return LowerATOMIC_LOAD_STORE(Op, DAG);
+  case ISD::EXTRACT_VECTOR_ELT:
+    return LowerEXTRACT_VECTOR_ELT(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
   }
 }
diff --git a/llvm/test/CodeGen/SPARC/vector-extract-elt.ll b/llvm/test/CodeGen/SPARC/vector-extract-elt.ll
index ef2a4323accce4..fd2d6ce95b149d 100644
--- a/llvm/test/CodeGen/SPARC/vector-extract-elt.ll
+++ b/llvm/test/CodeGen/SPARC/vector-extract-elt.ll
@@ -1,13 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc -mtriple=sparc < %s | FileCheck %s
 
 
 ; If computeKnownSignBits (in SelectionDAG) can do a simple
 ; look-thru for extractelement then we know that the add will yield a
 ; non-negative result.
-define i1 @test1(ptr %in) {
-; CHECK-LABEL: ! %bb.0:
-; CHECK-NEXT:        retl
-; CHECK-NEXT:        mov %g0, %o0
+define i1 @test1(ptr %in) nounwind {
+; CHECK-LABEL: test1:
+; CHECK:       ! %bb.0:
+; CHECK-NEXT:    retl
+; CHECK-NEXT:    mov %g0, %o0
   %vec2 = load <4 x i16>, ptr %in, align 1
   %vec3 = lshr <4 x i16> %vec2, <i16 2, i16 2, i16 2, i16 2>
   %vec4 = sext <4 x i16> %vec3 to <4 x i32>
@@ -17,3 +19,21 @@ define i1 @test1(ptr %in) {
   %bool = icmp slt i32 %sum, 0
   ret i1 %bool
 }
+
+; v2i32 is legal on 32-bit SPARC to represent 64-bit integer register pairs.
+; Make sure a dynamic extract does not reach instruction selection, which
+; only handles constant indices.
+define i32 @extract_v2i32(<2 x i32> %v, i32 %idx) nounwind {
+; CHECK-LABEL: extract_v2i32:
+; CHECK:       ! %bb.0:
+; CHECK-NEXT:    cmp %o2, 0
+; CHECK-NEXT:    be .LBB1_2
+; CHECK-NEXT:    nop
+; CHECK-NEXT:  ! %bb.1:
+; CHECK-NEXT:    mov %o1, %o0
+; CHECK-NEXT:  .LBB1_2:
+; CHECK-NEXT:    retl
+; CHECK-NEXT:    nop
+  %elt = extractelement <2 x i32> %v, i32 %idx
+  ret i32 %elt
+}



More information about the llvm-branch-commits mailing list