[llvm] [Hexagon] Use word splats for repeated HVX build-vector words (PR #204808)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 2 08:46:50 PDT 2026
https://github.com/L-roro updated https://github.com/llvm/llvm-project/pull/204808
>From 3dcdcb662865b370c4794030aa4cf586308d6624 Mon Sep 17 00:00:00 2001
From: L-roro <rodriguez at roofline.ai>
Date: Thu, 18 Jun 2026 09:05:29 +0000
Subject: [PATCH] Fix splat granularity bug
---
.../Target/Hexagon/HexagonISelLoweringHVX.cpp | 8 +-
.../autohvx/isel-build-vector-splat-word.ll | 256 ++++++++++++++++++
2 files changed, 263 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/Hexagon/autohvx/isel-build-vector-splat-word.ll
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
index fca33480265ad..b36c0b4e2faaf 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
@@ -1077,7 +1077,13 @@ HexagonTargetLowering::buildHvxVectorReg(ArrayRef<SDValue> Values,
SDValue HalfV = getZero(dl, VecTy, DAG);
if (VecHist[n] > 1) {
- SDValue SplatV = DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Words[n]);
+ // Always splat at word (i32) granularity so that the SPLAT_VECTOR node
+ // is selected as PS_vsplatrw (word broadcast) rather than PS_vsplatrb
+ // (byte broadcast of the low byte only), which would corrupt multi-byte
+ // element types.
+ MVT WordVecTy = MVT::getVectorVT(MVT::i32, HwLen / 4);
+ SDValue WordSplat = DAG.getNode(ISD::SPLAT_VECTOR, dl, WordVecTy, Words[n]);
+ SDValue SplatV = DAG.getBitcast(VecTy, WordSplat);
HalfV = DAG.getNode(HexagonISD::VALIGN, dl, VecTy,
{HalfV, SplatV, DAG.getConstant(HwLen/2, dl, MVT::i32)});
}
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/isel-build-vector-splat-word.ll b/llvm/test/CodeGen/Hexagon/autohvx/isel-build-vector-splat-word.ll
new file mode 100644
index 0000000000000..bc3ffd688cdd9
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/autohvx/isel-build-vector-splat-word.ll
@@ -0,0 +1,256 @@
+; RUN: llc -mtriple=hexagon < %s | FileCheck %s
+
+target triple = "hexagon"
+
+; buildHvxVectorReg packs i8 elements into i32 words before initializing
+; an HVX vector from the most frequent word. That initialization must
+; use a word splat even though the final vector type is i8; a byte
+; splat would broadcast only the low byte of %x.
+define void @splat_i32_word_into_i8_vector(ptr %out, i32 %x, i8 %y) #0 {
+; CHECK-LABEL: splat_i32_word_into_i8_vector:
+; CHECK: v{{[0-9]+}} = vsplat(r{{[0-9]+}})
+; CHECK-NOT: .b = vsplat
+; CHECK: vmem
+entry:
+ %x0 = trunc i32 %x to i8
+ %s1 = lshr i32 %x, 8
+ %x1 = trunc i32 %s1 to i8
+ %s2 = lshr i32 %x, 16
+ %x2 = trunc i32 %s2 to i8
+ %s3 = lshr i32 %x, 24
+ %x3 = trunc i32 %s3 to i8
+
+ %v000 = insertelement <128 x i8> poison, i8 %x0, i32 0
+ %v001 = insertelement <128 x i8> %v000, i8 %x1, i32 1
+ %v002 = insertelement <128 x i8> %v001, i8 %x2, i32 2
+ %v003 = insertelement <128 x i8> %v002, i8 %x3, i32 3
+ %v004 = insertelement <128 x i8> %v003, i8 %x0, i32 4
+ %v005 = insertelement <128 x i8> %v004, i8 %x1, i32 5
+ %v006 = insertelement <128 x i8> %v005, i8 %x2, i32 6
+ %v007 = insertelement <128 x i8> %v006, i8 %x3, i32 7
+ %v008 = insertelement <128 x i8> %v007, i8 %x0, i32 8
+ %v009 = insertelement <128 x i8> %v008, i8 %x1, i32 9
+ %v010 = insertelement <128 x i8> %v009, i8 %x2, i32 10
+ %v011 = insertelement <128 x i8> %v010, i8 %x3, i32 11
+ %v012 = insertelement <128 x i8> %v011, i8 %x0, i32 12
+ %v013 = insertelement <128 x i8> %v012, i8 %x1, i32 13
+ %v014 = insertelement <128 x i8> %v013, i8 %x2, i32 14
+ %v015 = insertelement <128 x i8> %v014, i8 %x3, i32 15
+ %v016 = insertelement <128 x i8> %v015, i8 %x0, i32 16
+ %v017 = insertelement <128 x i8> %v016, i8 %x1, i32 17
+ %v018 = insertelement <128 x i8> %v017, i8 %x2, i32 18
+ %v019 = insertelement <128 x i8> %v018, i8 %x3, i32 19
+ %v020 = insertelement <128 x i8> %v019, i8 %x0, i32 20
+ %v021 = insertelement <128 x i8> %v020, i8 %x1, i32 21
+ %v022 = insertelement <128 x i8> %v021, i8 %x2, i32 22
+ %v023 = insertelement <128 x i8> %v022, i8 %x3, i32 23
+ %v024 = insertelement <128 x i8> %v023, i8 %x0, i32 24
+ %v025 = insertelement <128 x i8> %v024, i8 %x1, i32 25
+ %v026 = insertelement <128 x i8> %v025, i8 %x2, i32 26
+ %v027 = insertelement <128 x i8> %v026, i8 %x3, i32 27
+ %v028 = insertelement <128 x i8> %v027, i8 %x0, i32 28
+ %v029 = insertelement <128 x i8> %v028, i8 %x1, i32 29
+ %v030 = insertelement <128 x i8> %v029, i8 %x2, i32 30
+ %v031 = insertelement <128 x i8> %v030, i8 %x3, i32 31
+ %v032 = insertelement <128 x i8> %v031, i8 %x0, i32 32
+ %v033 = insertelement <128 x i8> %v032, i8 %x1, i32 33
+ %v034 = insertelement <128 x i8> %v033, i8 %x2, i32 34
+ %v035 = insertelement <128 x i8> %v034, i8 %x3, i32 35
+ %v036 = insertelement <128 x i8> %v035, i8 %x0, i32 36
+ %v037 = insertelement <128 x i8> %v036, i8 %x1, i32 37
+ %v038 = insertelement <128 x i8> %v037, i8 %x2, i32 38
+ %v039 = insertelement <128 x i8> %v038, i8 %x3, i32 39
+ %v040 = insertelement <128 x i8> %v039, i8 %x0, i32 40
+ %v041 = insertelement <128 x i8> %v040, i8 %x1, i32 41
+ %v042 = insertelement <128 x i8> %v041, i8 %x2, i32 42
+ %v043 = insertelement <128 x i8> %v042, i8 %x3, i32 43
+ %v044 = insertelement <128 x i8> %v043, i8 %x0, i32 44
+ %v045 = insertelement <128 x i8> %v044, i8 %x1, i32 45
+ %v046 = insertelement <128 x i8> %v045, i8 %x2, i32 46
+ %v047 = insertelement <128 x i8> %v046, i8 %x3, i32 47
+ %v048 = insertelement <128 x i8> %v047, i8 %x0, i32 48
+ %v049 = insertelement <128 x i8> %v048, i8 %x1, i32 49
+ %v050 = insertelement <128 x i8> %v049, i8 %x2, i32 50
+ %v051 = insertelement <128 x i8> %v050, i8 %x3, i32 51
+ %v052 = insertelement <128 x i8> %v051, i8 %x0, i32 52
+ %v053 = insertelement <128 x i8> %v052, i8 %x1, i32 53
+ %v054 = insertelement <128 x i8> %v053, i8 %x2, i32 54
+ %v055 = insertelement <128 x i8> %v054, i8 %x3, i32 55
+ %v056 = insertelement <128 x i8> %v055, i8 %x0, i32 56
+ %v057 = insertelement <128 x i8> %v056, i8 %x1, i32 57
+ %v058 = insertelement <128 x i8> %v057, i8 %x2, i32 58
+ %v059 = insertelement <128 x i8> %v058, i8 %x3, i32 59
+ %v060 = insertelement <128 x i8> %v059, i8 %x0, i32 60
+ %v061 = insertelement <128 x i8> %v060, i8 %x1, i32 61
+ %v062 = insertelement <128 x i8> %v061, i8 %x2, i32 62
+ %v063 = insertelement <128 x i8> %v062, i8 %x3, i32 63
+ %v064 = insertelement <128 x i8> %v063, i8 %y, i32 64
+ %v065 = insertelement <128 x i8> %v064, i8 %x1, i32 65
+ %v066 = insertelement <128 x i8> %v065, i8 %x2, i32 66
+ %v067 = insertelement <128 x i8> %v066, i8 %x3, i32 67
+ %v068 = insertelement <128 x i8> %v067, i8 %x0, i32 68
+ %v069 = insertelement <128 x i8> %v068, i8 %y, i32 69
+ %v070 = insertelement <128 x i8> %v069, i8 %x2, i32 70
+ %v071 = insertelement <128 x i8> %v070, i8 %x3, i32 71
+ %v072 = insertelement <128 x i8> %v071, i8 %x0, i32 72
+ %v073 = insertelement <128 x i8> %v072, i8 %x1, i32 73
+ %v074 = insertelement <128 x i8> %v073, i8 %y, i32 74
+ %v075 = insertelement <128 x i8> %v074, i8 %x3, i32 75
+ %v076 = insertelement <128 x i8> %v075, i8 %x0, i32 76
+ %v077 = insertelement <128 x i8> %v076, i8 %x1, i32 77
+ %v078 = insertelement <128 x i8> %v077, i8 %x2, i32 78
+ %v079 = insertelement <128 x i8> %v078, i8 %y, i32 79
+ %v080 = insertelement <128 x i8> %v079, i8 %x0, i32 80
+ %v081 = insertelement <128 x i8> %v080, i8 %x1, i32 81
+ %v082 = insertelement <128 x i8> %v081, i8 %x2, i32 82
+ %v083 = insertelement <128 x i8> %v082, i8 %x3, i32 83
+ %v084 = insertelement <128 x i8> %v083, i8 %x0, i32 84
+ %v085 = insertelement <128 x i8> %v084, i8 %x1, i32 85
+ %v086 = insertelement <128 x i8> %v085, i8 %x2, i32 86
+ %v087 = insertelement <128 x i8> %v086, i8 %x3, i32 87
+ %v088 = insertelement <128 x i8> %v087, i8 %x0, i32 88
+ %v089 = insertelement <128 x i8> %v088, i8 %x1, i32 89
+ %v090 = insertelement <128 x i8> %v089, i8 %x2, i32 90
+ %v091 = insertelement <128 x i8> %v090, i8 %x3, i32 91
+ %v092 = insertelement <128 x i8> %v091, i8 %x0, i32 92
+ %v093 = insertelement <128 x i8> %v092, i8 %x1, i32 93
+ %v094 = insertelement <128 x i8> %v093, i8 %x2, i32 94
+ %v095 = insertelement <128 x i8> %v094, i8 %x3, i32 95
+ %v096 = insertelement <128 x i8> %v095, i8 %x0, i32 96
+ %v097 = insertelement <128 x i8> %v096, i8 %x1, i32 97
+ %v098 = insertelement <128 x i8> %v097, i8 %x2, i32 98
+ %v099 = insertelement <128 x i8> %v098, i8 %x3, i32 99
+ %v100 = insertelement <128 x i8> %v099, i8 %x0, i32 100
+ %v101 = insertelement <128 x i8> %v100, i8 %x1, i32 101
+ %v102 = insertelement <128 x i8> %v101, i8 %x2, i32 102
+ %v103 = insertelement <128 x i8> %v102, i8 %x3, i32 103
+ %v104 = insertelement <128 x i8> %v103, i8 %x0, i32 104
+ %v105 = insertelement <128 x i8> %v104, i8 %x1, i32 105
+ %v106 = insertelement <128 x i8> %v105, i8 %x2, i32 106
+ %v107 = insertelement <128 x i8> %v106, i8 %x3, i32 107
+ %v108 = insertelement <128 x i8> %v107, i8 %x0, i32 108
+ %v109 = insertelement <128 x i8> %v108, i8 %x1, i32 109
+ %v110 = insertelement <128 x i8> %v109, i8 %x2, i32 110
+ %v111 = insertelement <128 x i8> %v110, i8 %x3, i32 111
+ %v112 = insertelement <128 x i8> %v111, i8 %x0, i32 112
+ %v113 = insertelement <128 x i8> %v112, i8 %x1, i32 113
+ %v114 = insertelement <128 x i8> %v113, i8 %x2, i32 114
+ %v115 = insertelement <128 x i8> %v114, i8 %x3, i32 115
+ %v116 = insertelement <128 x i8> %v115, i8 %x0, i32 116
+ %v117 = insertelement <128 x i8> %v116, i8 %x1, i32 117
+ %v118 = insertelement <128 x i8> %v117, i8 %x2, i32 118
+ %v119 = insertelement <128 x i8> %v118, i8 %x3, i32 119
+ %v120 = insertelement <128 x i8> %v119, i8 %x0, i32 120
+ %v121 = insertelement <128 x i8> %v120, i8 %x1, i32 121
+ %v122 = insertelement <128 x i8> %v121, i8 %x2, i32 122
+ %v123 = insertelement <128 x i8> %v122, i8 %x3, i32 123
+ %v124 = insertelement <128 x i8> %v123, i8 %x0, i32 124
+ %v125 = insertelement <128 x i8> %v124, i8 %x1, i32 125
+ %v126 = insertelement <128 x i8> %v125, i8 %x2, i32 126
+ %v127 = insertelement <128 x i8> %v126, i8 %x3, i32 127
+ store <128 x i8> %v127, ptr %out, align 128
+ ret void
+}
+
+define void @splat_i8_into_i8_vector(ptr %out, i8 %x) #0 {
+; CHECK-LABEL: splat_i8_into_i8_vector:
+; CHECK: v{{[0-9]+}}.b = vsplat(r{{[0-9]+}})
+; CHECK: vmem
+entry:
+ %v0 = insertelement <128 x i8> poison, i8 %x, i32 0
+ %v1 = shufflevector <128 x i8> %v0, <128 x i8> poison, <128 x i32> zeroinitializer
+ store <128 x i8> %v1, ptr %out, align 128
+ ret void
+}
+
+; The same word-splat requirement applies when the final vector type is
+; i16 and the repeated value is a packed i32 containing two halfwords.
+define void @splat_i32_word_into_i16_vector(ptr %out, i32 %x, i16 %y) #0 {
+; CHECK-LABEL: splat_i32_word_into_i16_vector:
+; CHECK: v{{[0-9]+}} = vsplat(r{{[0-9]+}})
+; CHECK-NOT: .h = vsplat
+; CHECK: vmem
+entry:
+ %x0 = trunc i32 %x to i16
+ %s1 = lshr i32 %x, 16
+ %x1 = trunc i32 %s1 to i16
+ %v0 = insertelement <64 x i16> poison, i16 %x0, i32 0
+ %v1 = insertelement <64 x i16> %v0, i16 %x1, i32 1
+ %v2 = insertelement <64 x i16> %v1, i16 %x0, i32 2
+ %v3 = insertelement <64 x i16> %v2, i16 %x1, i32 3
+ %v4 = insertelement <64 x i16> %v3, i16 %x0, i32 4
+ %v5 = insertelement <64 x i16> %v4, i16 %x1, i32 5
+ %v6 = insertelement <64 x i16> %v5, i16 %x0, i32 6
+ %v7 = insertelement <64 x i16> %v6, i16 %x1, i32 7
+ %v8 = insertelement <64 x i16> %v7, i16 %x0, i32 8
+ %v9 = insertelement <64 x i16> %v8, i16 %x1, i32 9
+ %v10 = insertelement <64 x i16> %v9, i16 %x0, i32 10
+ %v11 = insertelement <64 x i16> %v10, i16 %x1, i32 11
+ %v12 = insertelement <64 x i16> %v11, i16 %x0, i32 12
+ %v13 = insertelement <64 x i16> %v12, i16 %x1, i32 13
+ %v14 = insertelement <64 x i16> %v13, i16 %x0, i32 14
+ %v15 = insertelement <64 x i16> %v14, i16 %x1, i32 15
+ %v16 = insertelement <64 x i16> %v15, i16 %x0, i32 16
+ %v17 = insertelement <64 x i16> %v16, i16 %x1, i32 17
+ %v18 = insertelement <64 x i16> %v17, i16 %x0, i32 18
+ %v19 = insertelement <64 x i16> %v18, i16 %x1, i32 19
+ %v20 = insertelement <64 x i16> %v19, i16 %x0, i32 20
+ %v21 = insertelement <64 x i16> %v20, i16 %x1, i32 21
+ %v22 = insertelement <64 x i16> %v21, i16 %x0, i32 22
+ %v23 = insertelement <64 x i16> %v22, i16 %x1, i32 23
+ %v24 = insertelement <64 x i16> %v23, i16 %x0, i32 24
+ %v25 = insertelement <64 x i16> %v24, i16 %x1, i32 25
+ %v26 = insertelement <64 x i16> %v25, i16 %x0, i32 26
+ %v27 = insertelement <64 x i16> %v26, i16 %x1, i32 27
+ %v28 = insertelement <64 x i16> %v27, i16 %x0, i32 28
+ %v29 = insertelement <64 x i16> %v28, i16 %x1, i32 29
+ %v30 = insertelement <64 x i16> %v29, i16 %x0, i32 30
+ %v31 = insertelement <64 x i16> %v30, i16 %x1, i32 31
+ %v32 = insertelement <64 x i16> %v31, i16 %y, i32 32
+ %v33 = insertelement <64 x i16> %v32, i16 %x1, i32 33
+ %v34 = insertelement <64 x i16> %v33, i16 %x0, i32 34
+ %v35 = insertelement <64 x i16> %v34, i16 %x1, i32 35
+ %v36 = insertelement <64 x i16> %v35, i16 %x0, i32 36
+ %v37 = insertelement <64 x i16> %v36, i16 %y, i32 37
+ %v38 = insertelement <64 x i16> %v37, i16 %x0, i32 38
+ %v39 = insertelement <64 x i16> %v38, i16 %x1, i32 39
+ %v40 = insertelement <64 x i16> %v39, i16 %x0, i32 40
+ %v41 = insertelement <64 x i16> %v40, i16 %x1, i32 41
+ %v42 = insertelement <64 x i16> %v41, i16 %y, i32 42
+ %v43 = insertelement <64 x i16> %v42, i16 %x1, i32 43
+ %v44 = insertelement <64 x i16> %v43, i16 %x0, i32 44
+ %v45 = insertelement <64 x i16> %v44, i16 %x1, i32 45
+ %v46 = insertelement <64 x i16> %v45, i16 %x0, i32 46
+ %v47 = insertelement <64 x i16> %v46, i16 %y, i32 47
+ %v48 = insertelement <64 x i16> %v47, i16 %x0, i32 48
+ %v49 = insertelement <64 x i16> %v48, i16 %x1, i32 49
+ %v50 = insertelement <64 x i16> %v49, i16 %x0, i32 50
+ %v51 = insertelement <64 x i16> %v50, i16 %x1, i32 51
+ %v52 = insertelement <64 x i16> %v51, i16 %x0, i32 52
+ %v53 = insertelement <64 x i16> %v52, i16 %x1, i32 53
+ %v54 = insertelement <64 x i16> %v53, i16 %x0, i32 54
+ %v55 = insertelement <64 x i16> %v54, i16 %x1, i32 55
+ %v56 = insertelement <64 x i16> %v55, i16 %x0, i32 56
+ %v57 = insertelement <64 x i16> %v56, i16 %x1, i32 57
+ %v58 = insertelement <64 x i16> %v57, i16 %x0, i32 58
+ %v59 = insertelement <64 x i16> %v58, i16 %x1, i32 59
+ %v60 = insertelement <64 x i16> %v59, i16 %x0, i32 60
+ %v61 = insertelement <64 x i16> %v60, i16 %x1, i32 61
+ %v62 = insertelement <64 x i16> %v61, i16 %x0, i32 62
+ %v63 = insertelement <64 x i16> %v62, i16 %x1, i32 63
+ store <64 x i16> %v63, ptr %out, align 128
+ ret void
+}
+
+define void @splat_i16_into_i16_vector(ptr %out, i16 %x) #0 {
+; CHECK-LABEL: splat_i16_into_i16_vector:
+; CHECK: v{{[0-9]+}}.h = vsplat(r{{[0-9]+}})
+; CHECK: vmem
+entry:
+ %v0 = insertelement <64 x i16> poison, i16 %x, i32 0
+ %v1 = shufflevector <64 x i16> %v0, <64 x i16> poison, <64 x i32> zeroinitializer
+ store <64 x i16> %v1, ptr %out, align 128
+ ret void
+}
+
+attributes #0 = { nounwind "target-cpu"="hexagonv75" "target-features"="+hvxv75,+hvx-length128b" }
More information about the llvm-commits
mailing list