[llvm] sketch idea of getConstantBuildVector (PR #180074)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 8 10:32:32 PST 2026
https://github.com/fbrv updated https://github.com/llvm/llvm-project/pull/180074
>From fc347b3bb95fb31f5acd6797cc591941817eb143 Mon Sep 17 00:00:00 2001
From: fbrv <fabio.baravalle at gmail.com>
Date: Thu, 5 Feb 2026 23:52:36 +0000
Subject: [PATCH 1/5] sketch idea of getConstantBuildVector
---
llvm/include/llvm/CodeGen/SelectionDAG.h | 20 +++
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 21 ++-
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 41 +++++
.../sve-extract-vector-to-predicate-store.ll | 1 +
llvm/test/CodeGen/X86/sext-load.ll | 10 ++
llvm/test/CodeGen/X86/sext-ret-val.ll | 19 ++-
llvm/test/CodeGen/X86/zext-inreg-0.ll | 144 ++++++++++++++++++
7 files changed, 237 insertions(+), 19 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index a208481df0c70..55c88d29da709 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -897,6 +897,26 @@ class SelectionDAG {
return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);
}
+ /// Return a BUILD_VECTOR of constants from an array of APInt values.
+ ///
+ /// \p VT must be a fixed-width integer vector type. \p Ops contains the
+ /// constant value for each element (sized to VT's scalar size in bits).
+ /// Bits set in \p UndefElts indicate elements that should be UNDEF.
+ ///
+ /// When NewNodesMustHaveLegalTypes is true (i.e., after type legalization),
+ /// the element constants are created using a promoted legal type, relying
+ /// on BUILD_VECTOR's implicit truncation semantics. This avoids creating
+ /// nodes with illegal scalar types that would otherwise trigger assertions.
+ LLVM_ABI SDValue getConstantBuildVector(EVT VT, const SDLoc &DL,
+ ArrayRef<APInt> Ops,
+ const APInt &UndefElts);
+
+ /// Convenience overload with no undef elements.
+ SDValue getConstantBuildVector(EVT VT, const SDLoc &DL,
+ ArrayRef<APInt> Ops) {
+ return getConstantBuildVector(VT, DL, Ops, APInt::getZero(Ops.size()));
+ }
+
/// Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all
/// elements. VT must be a vector type. Op's type must be the same as (or,
/// for integers, a type wider than) VT's element type.
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 838da9206ae17..475959abf563c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -14256,37 +14256,36 @@ static SDValue tryToFoldExtendOfConstant(SDNode *N, const SDLoc &DL,
// fold (zext (build_vector AllConstants) -> (build_vector AllConstants)
// fold (aext (build_vector AllConstants) -> (build_vector AllConstants)
EVT SVT = VT.getScalarType();
- if (!(VT.isVector() && (!LegalTypes || TLI.isTypeLegal(SVT)) &&
- ISD::isBuildVectorOfConstantSDNodes(N0.getNode())))
+ if (!(VT.isVector() &&
+ ISD::isBuildVectorOfConstantSDNodes(N0.getNode())))
return SDValue();
// We can fold this node into a build_vector.
unsigned VTBits = SVT.getSizeInBits();
unsigned EVTBits = N0->getValueType(0).getScalarSizeInBits();
- SmallVector<SDValue, 8> Elts;
unsigned NumElts = VT.getVectorNumElements();
+ SmallVector<APInt, 8> Constants;
+ APInt UndefElts = APInt::getZero(NumElts);
for (unsigned i = 0; i != NumElts; ++i) {
SDValue Op = N0.getOperand(i);
if (Op.isUndef()) {
if (Opcode == ISD::ANY_EXTEND || Opcode == ISD::ANY_EXTEND_VECTOR_INREG)
- Elts.push_back(DAG.getUNDEF(SVT));
- else
- Elts.push_back(DAG.getConstant(0, DL, SVT));
+ UndefElts.setBit(i);
+ // For sext/zext, undef -> 0 (matching previous behavior).
+ Constants.push_back(APInt::getZero(VTBits));
continue;
}
-
- SDLoc DL(Op);
// Get the constant value and if needed trunc it to the size of the type.
// Nodes like build_vector might have constants wider than the scalar type.
APInt C = Op->getAsAPIntVal().zextOrTrunc(EVTBits);
if (Opcode == ISD::SIGN_EXTEND || Opcode == ISD::SIGN_EXTEND_VECTOR_INREG)
- Elts.push_back(DAG.getConstant(C.sext(VTBits), DL, SVT));
+ Constants.push_back(C.sext(VTBits));
else
- Elts.push_back(DAG.getConstant(C.zext(VTBits), DL, SVT));
+ Constants.push_back(C.zext(VTBits));
}
- return DAG.getBuildVector(VT, DL, Elts);
+ return DAG.getConstantBuildVector(VT, DL, Constants, UndefElts);
}
// ExtendUsesToFormExtLoad - Trying to extend uses of a load to enable this:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 16a8c264a42b3..eb28ad3ec7b53 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2179,6 +2179,47 @@ SDValue SelectionDAG::getMaskFromElementCount(const SDLoc &DL, EVT DataVT,
getConstant(0, DL, IdxVT), getElementCount(DL, IdxVT, EC));
}
+SDValue SelectionDAG::getConstantBuildVector(EVT VT, const SDLoc &DL,
+ ArrayRef<APInt> Ops,
+ const APInt &UndefElts) {
+ assert(VT.isFixedLengthVector() && "Expected fixed-length vector type");
+ assert(VT.getVectorNumElements() == Ops.size() &&
+ "Mismatch between VT element count and Ops size");
+ assert(UndefElts.getBitWidth() == Ops.size() &&
+ "Mismatch between UndefElts width and Ops size");
+
+ unsigned NumElts = VT.getVectorNumElements();
+ EVT EltVT = VT.getVectorElementType();
+ assert(EltVT.isInteger() && "Expected integer element type");
+
+ // Determine the type to use for the constant elements. After type
+ // legalization, the original scalar element type may be illegal (e.g., i32
+ // on LoongArch64 where only i64 is legal). In that case, we promote to a
+ // legal type and rely on BUILD_VECTOR's implicit truncation.
+ EVT ConstantVT = EltVT;
+ if (NewNodesMustHaveLegalTypes) {
+ auto Action = TLI->getTypeAction(*getContext(), EltVT);
+ if (Action == TargetLowering::TypePromoteInteger)
+ ConstantVT = TLI->getTypeToTransformTo(*getContext(), EltVT);
+ }
+
+ SmallVector<SDValue, 16> BVOps(NumElts);
+ for (unsigned i = 0; i < NumElts; ++i) {
+ if (UndefElts[i]) {
+ BVOps[i] = getUNDEF(ConstantVT);
+ } else {
+ // Zero-extend the APInt to the promoted width if needed, preserving
+ // the original value (BUILD_VECTOR will implicitly truncate).
+ APInt Val = Ops[i];
+ if (ConstantVT.getSizeInBits() > EltVT.getSizeInBits())
+ Val = Val.zextOrTrunc(ConstantVT.getSizeInBits());
+ BVOps[i] = getConstant(Val, DL, ConstantVT);
+ }
+ }
+
+ return getBuildVector(VT, DL, BVOps);
+}
+
SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT) {
APInt One(ResVT.getScalarSizeInBits(), 1);
return getStepVector(DL, ResVT, One);
diff --git a/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll b/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
index e3d368b7b85c6..33b929e6a0d43 100644
--- a/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
+++ b/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -aarch64-sve-intrinsic-opts < %s | FileCheck %s
target triple = "aarch64-unknown-linux-gnu"
diff --git a/llvm/test/CodeGen/X86/sext-load.ll b/llvm/test/CodeGen/X86/sext-load.ll
index 3e51fc2fc6af3..163171afad18e 100644
--- a/llvm/test/CodeGen/X86/sext-load.ll
+++ b/llvm/test/CodeGen/X86/sext-load.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=i686-- | FileCheck %s
; When doing sign extension, use the sext-load lowering to take advantage of
@@ -7,6 +8,10 @@
; CHECK: movsbl {{.*}}, %eax
; CHECK-NEXT: ret
define i32 @test1(i32 %X) nounwind {
+; CHECK-LABEL: test1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: movsbl {{[0-9]+}}(%esp), %eax
+; CHECK-NEXT: retl
entry:
%tmp12 = trunc i32 %X to i8 ; <i8> [#uses=1]
%tmp123 = sext i8 %tmp12 to i32 ; <i32> [#uses=1]
@@ -20,6 +25,11 @@ entry:
; CHECK: movswl {{.*}}, %eax
; CHECK-NEXT: ret
define i32 @test2(ptr %this) {
+; CHECK-LABEL: test2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
+; CHECK-NEXT: movswl 6(%eax), %eax
+; CHECK-NEXT: retl
entry:
%b48 = getelementptr inbounds { i16, [6 x i8] }, ptr %this, i32 0, i32 1
%bf.load = load i48, ptr %b48, align 2
diff --git a/llvm/test/CodeGen/X86/sext-ret-val.ll b/llvm/test/CodeGen/X86/sext-ret-val.ll
index 250d310ebb143..aac4fddd0b6ea 100644
--- a/llvm/test/CodeGen/X86/sext-ret-val.ll
+++ b/llvm/test/CodeGen/X86/sext-ret-val.ll
@@ -1,26 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=i686-unknown-linux-gnu | FileCheck %s
; rdar://6699246
define signext i8 @t1(ptr %A) nounwind readnone ssp {
+; CHECK-LABEL: t1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT: setne %al
+; CHECK-NEXT: retl
entry:
%0 = icmp ne ptr %A, null
%1 = zext i1 %0 to i8
ret i8 %1
-; CHECK-LABEL: t1:
-; CHECK: cmpl
-; CHECK-NEXT: setne
-; CHECK-NEXT: retl
}
define i8 @t2(ptr %A) nounwind readnone ssp {
+; CHECK-LABEL: t2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; CHECK-NEXT: setne %al
+; CHECK-NEXT: retl
entry:
%0 = icmp ne ptr %A, null
%1 = zext i1 %0 to i8
ret i8 %1
-; CHECK-LABEL: t2:
-; CHECK: cmpl
-; CHECK-NEXT: setne
-; CHECK-NEXT: retl
}
diff --git a/llvm/test/CodeGen/X86/zext-inreg-0.ll b/llvm/test/CodeGen/X86/zext-inreg-0.ll
index 72fd6885dcdec..d551a91a9be36 100644
--- a/llvm/test/CodeGen/X86/zext-inreg-0.ll
+++ b/llvm/test/CodeGen/X86/zext-inreg-0.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=i686-- | FileCheck -check-prefix=X86 %s
; RUN: llc < %s -mtriple=x86_64-- | FileCheck -check-prefix=X64 %s
@@ -12,57 +13,200 @@
; This related to not having a ZERO_EXTEND_REG opcode.
define i32 @a(i32 %d) nounwind {
+; X86-LABEL: a:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incl %eax
+; X86-NEXT: movzbl %al, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: a:
+; X64: # %bb.0:
+; X64-NEXT: incl %edi
+; X64-NEXT: movzbl %dil, %eax
+; X64-NEXT: retq
%e = add i32 %d, 1
%retval = and i32 %e, 255
ret i32 %retval
}
define i32 @b(float %d) nounwind {
+; X86-LABEL: b:
+; X86: # %bb.0:
+; X86-NEXT: subl $8, %esp
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: fnstcw {{[0-9]+}}(%esp)
+; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: orl $3072, %eax # imm = 0xC00
+; X86-NEXT: movw %ax, {{[0-9]+}}(%esp)
+; X86-NEXT: fldcw {{[0-9]+}}(%esp)
+; X86-NEXT: fistps {{[0-9]+}}(%esp)
+; X86-NEXT: fldcw {{[0-9]+}}(%esp)
+; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: addl $8, %esp
+; X86-NEXT: retl
+;
+; X64-LABEL: b:
+; X64: # %bb.0:
+; X64-NEXT: cvttss2si %xmm0, %eax
+; X64-NEXT: movzbl %al, %eax
+; X64-NEXT: retq
%tmp12 = fptoui float %d to i8
%retval = zext i8 %tmp12 to i32
ret i32 %retval
}
define i32 @c(i32 %d) nounwind {
+; X86-LABEL: c:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incl %eax
+; X86-NEXT: movzwl %ax, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: c:
+; X64: # %bb.0:
+; X64-NEXT: incl %edi
+; X64-NEXT: movzwl %di, %eax
+; X64-NEXT: retq
%e = add i32 %d, 1
%retval = and i32 %e, 65535
ret i32 %retval
}
define i64 @d(i64 %d) nounwind {
+; X86-LABEL: d:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incl %eax
+; X86-NEXT: movzbl %al, %eax
+; X86-NEXT: xorl %edx, %edx
+; X86-NEXT: retl
+;
+; X64-LABEL: d:
+; X64: # %bb.0:
+; X64-NEXT: incl %edi
+; X64-NEXT: movzbl %dil, %eax
+; X64-NEXT: retq
%e = add i64 %d, 1
%retval = and i64 %e, 255
ret i64 %retval
}
define i64 @e(i64 %d) nounwind {
+; X86-LABEL: e:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incl %eax
+; X86-NEXT: movzwl %ax, %eax
+; X86-NEXT: xorl %edx, %edx
+; X86-NEXT: retl
+;
+; X64-LABEL: e:
+; X64: # %bb.0:
+; X64-NEXT: incl %edi
+; X64-NEXT: movzwl %di, %eax
+; X64-NEXT: retq
%e = add i64 %d, 1
%retval = and i64 %e, 65535
ret i64 %retval
}
define i64 @f(i64 %d) nounwind {
+; X86-LABEL: f:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incl %eax
+; X86-NEXT: xorl %edx, %edx
+; X86-NEXT: retl
+;
+; X64-LABEL: f:
+; X64: # %bb.0:
+; X64-NEXT: leal 1(%rdi), %eax
+; X64-NEXT: retq
%e = add i64 %d, 1
%retval = and i64 %e, 4294967295
ret i64 %retval
}
define i32 @g(i8 %d) nounwind {
+; X86-LABEL: g:
+; X86: # %bb.0:
+; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incb %al
+; X86-NEXT: movzbl %al, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: g:
+; X64: # %bb.0:
+; X64-NEXT: incb %dil
+; X64-NEXT: movzbl %dil, %eax
+; X64-NEXT: retq
%e = add i8 %d, 1
%retval = zext i8 %e to i32
ret i32 %retval
}
define i32 @h(i16 %d) nounwind {
+; X86-LABEL: h:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incl %eax
+; X86-NEXT: movzwl %ax, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: h:
+; X64: # %bb.0:
+; X64-NEXT: incl %edi
+; X64-NEXT: movzwl %di, %eax
+; X64-NEXT: retq
%e = add i16 %d, 1
%retval = zext i16 %e to i32
ret i32 %retval
}
define i64 @i(i8 %d) nounwind {
+; X86-LABEL: i:
+; X86: # %bb.0:
+; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incb %al
+; X86-NEXT: movzbl %al, %eax
+; X86-NEXT: xorl %edx, %edx
+; X86-NEXT: retl
+;
+; X64-LABEL: i:
+; X64: # %bb.0:
+; X64-NEXT: incb %dil
+; X64-NEXT: movzbl %dil, %eax
+; X64-NEXT: retq
%e = add i8 %d, 1
%retval = zext i8 %e to i64
ret i64 %retval
}
define i64 @j(i16 %d) nounwind {
+; X86-LABEL: j:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incl %eax
+; X86-NEXT: movzwl %ax, %eax
+; X86-NEXT: xorl %edx, %edx
+; X86-NEXT: retl
+;
+; X64-LABEL: j:
+; X64: # %bb.0:
+; X64-NEXT: incl %edi
+; X64-NEXT: movzwl %di, %eax
+; X64-NEXT: retq
%e = add i16 %d, 1
%retval = zext i16 %e to i64
ret i64 %retval
}
define i64 @k(i32 %d) nounwind {
+; X86-LABEL: k:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: incl %eax
+; X86-NEXT: xorl %edx, %edx
+; X86-NEXT: retl
+;
+; X64-LABEL: k:
+; X64: # %bb.0:
+; X64-NEXT: # kill: def $edi killed $edi def $rdi
+; X64-NEXT: leal 1(%rdi), %eax
+; X64-NEXT: retq
%e = add i32 %d, 1
%retval = zext i32 %e to i64
ret i64 %retval
>From 36e184cdc9aef96fac91d6b28e67b48df298178c Mon Sep 17 00:00:00 2001
From: fbrv <fabio.baravalle at gmail.com>
Date: Fri, 6 Feb 2026 10:01:21 +0000
Subject: [PATCH 2/5] fmt
---
llvm/include/llvm/CodeGen/SelectionDAG.h | 3 +--
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 55c88d29da709..44b105af0b4d7 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -912,8 +912,7 @@ class SelectionDAG {
const APInt &UndefElts);
/// Convenience overload with no undef elements.
- SDValue getConstantBuildVector(EVT VT, const SDLoc &DL,
- ArrayRef<APInt> Ops) {
+ SDValue getConstantBuildVector(EVT VT, const SDLoc &DL, ArrayRef<APInt> Ops) {
return getConstantBuildVector(VT, DL, Ops, APInt::getZero(Ops.size()));
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 475959abf563c..46cb2c64927da 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -14256,8 +14256,7 @@ static SDValue tryToFoldExtendOfConstant(SDNode *N, const SDLoc &DL,
// fold (zext (build_vector AllConstants) -> (build_vector AllConstants)
// fold (aext (build_vector AllConstants) -> (build_vector AllConstants)
EVT SVT = VT.getScalarType();
- if (!(VT.isVector() &&
- ISD::isBuildVectorOfConstantSDNodes(N0.getNode())))
+ if (!(VT.isVector() && ISD::isBuildVectorOfConstantSDNodes(N0.getNode())))
return SDValue();
// We can fold this node into a build_vector.
>From fa438c9ef8b1423ffc63f8b3c177fdfbfee422db Mon Sep 17 00:00:00 2001
From: fbrv <fabio.baravalle at gmail.com>
Date: Sun, 8 Feb 2026 18:20:17 +0000
Subject: [PATCH 3/5] use isSExtCheaperThanZExt
---
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index eb28ad3ec7b53..72a6c3b33e1a6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2187,11 +2187,9 @@ SDValue SelectionDAG::getConstantBuildVector(EVT VT, const SDLoc &DL,
"Mismatch between VT element count and Ops size");
assert(UndefElts.getBitWidth() == Ops.size() &&
"Mismatch between UndefElts width and Ops size");
-
unsigned NumElts = VT.getVectorNumElements();
EVT EltVT = VT.getVectorElementType();
assert(EltVT.isInteger() && "Expected integer element type");
-
// Determine the type to use for the constant elements. After type
// legalization, the original scalar element type may be illegal (e.g., i32
// on LoongArch64 where only i64 is legal). In that case, we promote to a
@@ -2202,21 +2200,22 @@ SDValue SelectionDAG::getConstantBuildVector(EVT VT, const SDLoc &DL,
if (Action == TargetLowering::TypePromoteInteger)
ConstantVT = TLI->getTypeToTransformTo(*getContext(), EltVT);
}
-
SmallVector<SDValue, 16> BVOps(NumElts);
for (unsigned i = 0; i < NumElts; ++i) {
if (UndefElts[i]) {
BVOps[i] = getUNDEF(ConstantVT);
} else {
- // Zero-extend the APInt to the promoted width if needed, preserving
- // the original value (BUILD_VECTOR will implicitly truncate).
+
APInt Val = Ops[i];
- if (ConstantVT.getSizeInBits() > EltVT.getSizeInBits())
- Val = Val.zextOrTrunc(ConstantVT.getSizeInBits());
+ if (ConstantVT.getSizeInBits() > EltVT.getSizeInBits()) {
+ if (TLI->isSExtCheaperThanZExt(EltVT, ConstantVT))
+ Val = Val.sextOrTrunc(ConstantVT.getSizeInBits());
+ else
+ Val = Val.zextOrTrunc(ConstantVT.getSizeInBits());
+ }
BVOps[i] = getConstant(Val, DL, ConstantVT);
}
}
-
return getBuildVector(VT, DL, BVOps);
}
>From 3295b29eeb8832e4eef4b145c62eb288b23c14d5 Mon Sep 17 00:00:00 2001
From: fbrv <fabio.baravalle at gmail.com>
Date: Sun, 8 Feb 2026 18:28:10 +0000
Subject: [PATCH 4/5] revert test changes
---
.../sve-extract-vector-to-predicate-store.ll | 1 -
llvm/test/CodeGen/X86/sext-load.ll | 10 ----------
llvm/test/CodeGen/X86/sext-ret-val.ll | 19 ++++++++-----------
3 files changed, 8 insertions(+), 22 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll b/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
index 33b929e6a0d43..e3d368b7b85c6 100644
--- a/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
+++ b/llvm/test/CodeGen/AArch64/sve-extract-vector-to-predicate-store.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: opt -S -aarch64-sve-intrinsic-opts < %s | FileCheck %s
target triple = "aarch64-unknown-linux-gnu"
diff --git a/llvm/test/CodeGen/X86/sext-load.ll b/llvm/test/CodeGen/X86/sext-load.ll
index 163171afad18e..3e51fc2fc6af3 100644
--- a/llvm/test/CodeGen/X86/sext-load.ll
+++ b/llvm/test/CodeGen/X86/sext-load.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=i686-- | FileCheck %s
; When doing sign extension, use the sext-load lowering to take advantage of
@@ -8,10 +7,6 @@
; CHECK: movsbl {{.*}}, %eax
; CHECK-NEXT: ret
define i32 @test1(i32 %X) nounwind {
-; CHECK-LABEL: test1:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: movsbl {{[0-9]+}}(%esp), %eax
-; CHECK-NEXT: retl
entry:
%tmp12 = trunc i32 %X to i8 ; <i8> [#uses=1]
%tmp123 = sext i8 %tmp12 to i32 ; <i32> [#uses=1]
@@ -25,11 +20,6 @@ entry:
; CHECK: movswl {{.*}}, %eax
; CHECK-NEXT: ret
define i32 @test2(ptr %this) {
-; CHECK-LABEL: test2:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
-; CHECK-NEXT: movswl 6(%eax), %eax
-; CHECK-NEXT: retl
entry:
%b48 = getelementptr inbounds { i16, [6 x i8] }, ptr %this, i32 0, i32 1
%bf.load = load i48, ptr %b48, align 2
diff --git a/llvm/test/CodeGen/X86/sext-ret-val.ll b/llvm/test/CodeGen/X86/sext-ret-val.ll
index aac4fddd0b6ea..250d310ebb143 100644
--- a/llvm/test/CodeGen/X86/sext-ret-val.ll
+++ b/llvm/test/CodeGen/X86/sext-ret-val.ll
@@ -1,29 +1,26 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=i686-unknown-linux-gnu | FileCheck %s
; rdar://6699246
define signext i8 @t1(ptr %A) nounwind readnone ssp {
-; CHECK-LABEL: t1:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; CHECK-NEXT: setne %al
-; CHECK-NEXT: retl
entry:
%0 = icmp ne ptr %A, null
%1 = zext i1 %0 to i8
ret i8 %1
+; CHECK-LABEL: t1:
+; CHECK: cmpl
+; CHECK-NEXT: setne
+; CHECK-NEXT: retl
}
define i8 @t2(ptr %A) nounwind readnone ssp {
-; CHECK-LABEL: t2:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; CHECK-NEXT: setne %al
-; CHECK-NEXT: retl
entry:
%0 = icmp ne ptr %A, null
%1 = zext i1 %0 to i8
ret i8 %1
+; CHECK-LABEL: t2:
+; CHECK: cmpl
+; CHECK-NEXT: setne
+; CHECK-NEXT: retl
}
>From 5124c6aad08d20a0ac5ebe59b085bfe29b6caf23 Mon Sep 17 00:00:00 2001
From: fbrv <fabio.baravalle at gmail.com>
Date: Sun, 8 Feb 2026 18:32:19 +0000
Subject: [PATCH 5/5] revert zext-inreg-0.ll changes
---
llvm/test/CodeGen/X86/zext-inreg-0.ll | 144 --------------------------
1 file changed, 144 deletions(-)
diff --git a/llvm/test/CodeGen/X86/zext-inreg-0.ll b/llvm/test/CodeGen/X86/zext-inreg-0.ll
index d551a91a9be36..72fd6885dcdec 100644
--- a/llvm/test/CodeGen/X86/zext-inreg-0.ll
+++ b/llvm/test/CodeGen/X86/zext-inreg-0.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s -mtriple=i686-- | FileCheck -check-prefix=X86 %s
; RUN: llc < %s -mtriple=x86_64-- | FileCheck -check-prefix=X64 %s
@@ -13,200 +12,57 @@
; This related to not having a ZERO_EXTEND_REG opcode.
define i32 @a(i32 %d) nounwind {
-; X86-LABEL: a:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incl %eax
-; X86-NEXT: movzbl %al, %eax
-; X86-NEXT: retl
-;
-; X64-LABEL: a:
-; X64: # %bb.0:
-; X64-NEXT: incl %edi
-; X64-NEXT: movzbl %dil, %eax
-; X64-NEXT: retq
%e = add i32 %d, 1
%retval = and i32 %e, 255
ret i32 %retval
}
define i32 @b(float %d) nounwind {
-; X86-LABEL: b:
-; X86: # %bb.0:
-; X86-NEXT: subl $8, %esp
-; X86-NEXT: flds {{[0-9]+}}(%esp)
-; X86-NEXT: fnstcw {{[0-9]+}}(%esp)
-; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: orl $3072, %eax # imm = 0xC00
-; X86-NEXT: movw %ax, {{[0-9]+}}(%esp)
-; X86-NEXT: fldcw {{[0-9]+}}(%esp)
-; X86-NEXT: fistps {{[0-9]+}}(%esp)
-; X86-NEXT: fldcw {{[0-9]+}}(%esp)
-; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: addl $8, %esp
-; X86-NEXT: retl
-;
-; X64-LABEL: b:
-; X64: # %bb.0:
-; X64-NEXT: cvttss2si %xmm0, %eax
-; X64-NEXT: movzbl %al, %eax
-; X64-NEXT: retq
%tmp12 = fptoui float %d to i8
%retval = zext i8 %tmp12 to i32
ret i32 %retval
}
define i32 @c(i32 %d) nounwind {
-; X86-LABEL: c:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incl %eax
-; X86-NEXT: movzwl %ax, %eax
-; X86-NEXT: retl
-;
-; X64-LABEL: c:
-; X64: # %bb.0:
-; X64-NEXT: incl %edi
-; X64-NEXT: movzwl %di, %eax
-; X64-NEXT: retq
%e = add i32 %d, 1
%retval = and i32 %e, 65535
ret i32 %retval
}
define i64 @d(i64 %d) nounwind {
-; X86-LABEL: d:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incl %eax
-; X86-NEXT: movzbl %al, %eax
-; X86-NEXT: xorl %edx, %edx
-; X86-NEXT: retl
-;
-; X64-LABEL: d:
-; X64: # %bb.0:
-; X64-NEXT: incl %edi
-; X64-NEXT: movzbl %dil, %eax
-; X64-NEXT: retq
%e = add i64 %d, 1
%retval = and i64 %e, 255
ret i64 %retval
}
define i64 @e(i64 %d) nounwind {
-; X86-LABEL: e:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incl %eax
-; X86-NEXT: movzwl %ax, %eax
-; X86-NEXT: xorl %edx, %edx
-; X86-NEXT: retl
-;
-; X64-LABEL: e:
-; X64: # %bb.0:
-; X64-NEXT: incl %edi
-; X64-NEXT: movzwl %di, %eax
-; X64-NEXT: retq
%e = add i64 %d, 1
%retval = and i64 %e, 65535
ret i64 %retval
}
define i64 @f(i64 %d) nounwind {
-; X86-LABEL: f:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incl %eax
-; X86-NEXT: xorl %edx, %edx
-; X86-NEXT: retl
-;
-; X64-LABEL: f:
-; X64: # %bb.0:
-; X64-NEXT: leal 1(%rdi), %eax
-; X64-NEXT: retq
%e = add i64 %d, 1
%retval = and i64 %e, 4294967295
ret i64 %retval
}
define i32 @g(i8 %d) nounwind {
-; X86-LABEL: g:
-; X86: # %bb.0:
-; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incb %al
-; X86-NEXT: movzbl %al, %eax
-; X86-NEXT: retl
-;
-; X64-LABEL: g:
-; X64: # %bb.0:
-; X64-NEXT: incb %dil
-; X64-NEXT: movzbl %dil, %eax
-; X64-NEXT: retq
%e = add i8 %d, 1
%retval = zext i8 %e to i32
ret i32 %retval
}
define i32 @h(i16 %d) nounwind {
-; X86-LABEL: h:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incl %eax
-; X86-NEXT: movzwl %ax, %eax
-; X86-NEXT: retl
-;
-; X64-LABEL: h:
-; X64: # %bb.0:
-; X64-NEXT: incl %edi
-; X64-NEXT: movzwl %di, %eax
-; X64-NEXT: retq
%e = add i16 %d, 1
%retval = zext i16 %e to i32
ret i32 %retval
}
define i64 @i(i8 %d) nounwind {
-; X86-LABEL: i:
-; X86: # %bb.0:
-; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incb %al
-; X86-NEXT: movzbl %al, %eax
-; X86-NEXT: xorl %edx, %edx
-; X86-NEXT: retl
-;
-; X64-LABEL: i:
-; X64: # %bb.0:
-; X64-NEXT: incb %dil
-; X64-NEXT: movzbl %dil, %eax
-; X64-NEXT: retq
%e = add i8 %d, 1
%retval = zext i8 %e to i64
ret i64 %retval
}
define i64 @j(i16 %d) nounwind {
-; X86-LABEL: j:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incl %eax
-; X86-NEXT: movzwl %ax, %eax
-; X86-NEXT: xorl %edx, %edx
-; X86-NEXT: retl
-;
-; X64-LABEL: j:
-; X64: # %bb.0:
-; X64-NEXT: incl %edi
-; X64-NEXT: movzwl %di, %eax
-; X64-NEXT: retq
%e = add i16 %d, 1
%retval = zext i16 %e to i64
ret i64 %retval
}
define i64 @k(i32 %d) nounwind {
-; X86-LABEL: k:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: incl %eax
-; X86-NEXT: xorl %edx, %edx
-; X86-NEXT: retl
-;
-; X64-LABEL: k:
-; X64: # %bb.0:
-; X64-NEXT: # kill: def $edi killed $edi def $rdi
-; X64-NEXT: leal 1(%rdi), %eax
-; X64-NEXT: retq
%e = add i32 %d, 1
%retval = zext i32 %e to i64
ret i64 %retval
More information about the llvm-commits
mailing list