[llvm] [AArch64][GlobalISel] Don't crash when legalising vector G_SHL (PR #168848)
Nathan Corbyn via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 1 08:39:13 PST 2025
https://github.com/cofibrant updated https://github.com/llvm/llvm-project/pull/168848
>From 7683b54ca4bd1248fbeee3735f1de59722e14e4e Mon Sep 17 00:00:00 2001
From: Nathan Corbyn <n_corbyn at apple.com>
Date: Thu, 20 Nov 2025 10:50:21 +0000
Subject: [PATCH 1/4] [AArch64][GlobalISel] Don't crash when legalising vector
G_SHL
---
.../AArch64/GISel/AArch64LegalizerInfo.cpp | 8 ++---
.../AArch64/GlobalISel/legalize-shl-crash.ll | 29 +++++++++++++++++++
2 files changed, 33 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/legalize-shl-crash.ll
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 089b0b2feb231..c0c8ceb0122b9 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -216,15 +216,15 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.widenScalarToNextPow2(0)
.clampScalar(1, s32, s64)
.clampScalar(0, s32, s64)
+ .minScalarSameAs(1, 0)
+ .minScalarEltSameAsIf(isVector(0), 1, 0)
+ .maxScalarEltSameAsIf(isVector(0), 1, 0)
.clampNumElements(0, v8s8, v16s8)
.clampNumElements(0, v4s16, v8s16)
.clampNumElements(0, v2s32, v4s32)
.clampNumElements(0, v2s64, v2s64)
.moreElementsToNextPow2(0)
- .minScalarSameAs(1, 0)
- .scalarizeIf(scalarOrEltWiderThan(0, 64), 0)
- .minScalarEltSameAsIf(isVector(0), 1, 0)
- .maxScalarEltSameAsIf(isVector(0), 1, 0);
+ .scalarizeIf(scalarOrEltWiderThan(0, 64), 0);
getActionDefinitionsBuilder(G_PTR_ADD)
.legalFor({{p0, s64}, {v2p0, v2s64}})
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shl-crash.ll b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shl-crash.ll
new file mode 100644
index 0000000000000..b7a5cdc77aa35
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shl-crash.ll
@@ -0,0 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -global-isel -o - %s | FileCheck %s
+
+target triple = "aarch64-unknown-unknown"
+
+; Check we don't crash here.
+
+define <2 x i8> @test() {
+; CHECK-LABEL: test:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov w8, #1 // =0x1
+; CHECK-NEXT: mov w9, #0 // =0x0
+; CHECK-NEXT: fmov s0, w8
+; CHECK-NEXT: fmov s1, w9
+; CHECK-NEXT: mov v0.b[1], w8
+; CHECK-NEXT: mov v1.b[1], w9
+; CHECK-NEXT: ushl v0.8b, v0.8b, v1.8b
+; CHECK-NEXT: umov w8, v0.b[0]
+; CHECK-NEXT: umov w9, v0.b[1]
+; CHECK-NEXT: fmov s0, w8
+; CHECK-NEXT: mov v0.s[1], w9
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+entry:
+ %zeroes = zext <2 x i1> zeroinitializer to <2 x i32>
+ %ones = shl <2 x i32> splat (i32 1), %zeroes
+ %ones.trunc = trunc <2 x i32> %ones to <2 x i8>
+ ret <2 x i8> %ones.trunc
+}
>From 92db3f75ebe9413662f3c061a5eff823ee5abe29 Mon Sep 17 00:00:00 2001
From: Nathan Corbyn <n_corbyn at apple.com>
Date: Mon, 1 Dec 2025 15:43:34 +0000
Subject: [PATCH 2/4] Modify handling of `G_*SH*` opcodes in
`LegalizerHelper::moreElementsVector()`
---
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 21 +++++++++++++------
.../AArch64/GISel/AArch64LegalizerInfo.cpp | 8 +++----
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 120c38ab8404c..1aa1d465d8da6 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -6684,13 +6684,24 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
case TargetOpcode::G_FMAXIMUMNUM:
case TargetOpcode::G_STRICT_FADD:
case TargetOpcode::G_STRICT_FSUB:
- case TargetOpcode::G_STRICT_FMUL:
+ case TargetOpcode::G_STRICT_FMUL: {
+ Observer.changingInstr(MI);
+ moreElementsVectorSrc(MI, MoreTy, 1);
+ moreElementsVectorSrc(MI, MoreTy, 2);
+ moreElementsVectorDst(MI, MoreTy, 0);
+ Observer.changedInstr(MI);
+ return Legalized;
+ }
case TargetOpcode::G_SHL:
case TargetOpcode::G_ASHR:
case TargetOpcode::G_LSHR: {
Observer.changingInstr(MI);
moreElementsVectorSrc(MI, MoreTy, 1);
- moreElementsVectorSrc(MI, MoreTy, 2);
+ // The shift operand may have a different scalar type from the source and
+ // destination operands.
+ LLT ShiftMoreTy = MoreTy.changeElementType(
+ MRI.getType(MI.getOperand(2).getReg()).getElementType());
+ moreElementsVectorSrc(MI, ShiftMoreTy, 2);
moreElementsVectorDst(MI, MoreTy, 0);
Observer.changedInstr(MI);
return Legalized;
@@ -6806,12 +6817,10 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
LLT DstExtTy;
if (TypeIdx == 0) {
DstExtTy = MoreTy;
- SrcExtTy = LLT::fixed_vector(
- MoreTy.getNumElements(),
+ SrcExtTy = MoreTy.changeElementType(
MRI.getType(MI.getOperand(1).getReg()).getElementType());
} else {
- DstExtTy = LLT::fixed_vector(
- MoreTy.getNumElements(),
+ DstExtTy = MoreTy.changeElementType(
MRI.getType(MI.getOperand(0).getReg()).getElementType());
SrcExtTy = MoreTy;
}
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index c0c8ceb0122b9..089b0b2feb231 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -216,15 +216,15 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
.widenScalarToNextPow2(0)
.clampScalar(1, s32, s64)
.clampScalar(0, s32, s64)
- .minScalarSameAs(1, 0)
- .minScalarEltSameAsIf(isVector(0), 1, 0)
- .maxScalarEltSameAsIf(isVector(0), 1, 0)
.clampNumElements(0, v8s8, v16s8)
.clampNumElements(0, v4s16, v8s16)
.clampNumElements(0, v2s32, v4s32)
.clampNumElements(0, v2s64, v2s64)
.moreElementsToNextPow2(0)
- .scalarizeIf(scalarOrEltWiderThan(0, 64), 0);
+ .minScalarSameAs(1, 0)
+ .scalarizeIf(scalarOrEltWiderThan(0, 64), 0)
+ .minScalarEltSameAsIf(isVector(0), 1, 0)
+ .maxScalarEltSameAsIf(isVector(0), 1, 0);
getActionDefinitionsBuilder(G_PTR_ADD)
.legalFor({{p0, s64}, {v2p0, v2s64}})
>From 8e7ad6589016f38fe4a9aaeaae25b5c64a85a51a Mon Sep 17 00:00:00 2001
From: Nathan Corbyn <n_corbyn at apple.com>
Date: Mon, 1 Dec 2025 15:48:02 +0000
Subject: [PATCH 3/4] Relocate test case
---
.../AArch64/GlobalISel/legalize-shl-crash.ll | 29 -------------------
llvm/test/CodeGen/AArch64/shift.ll | 28 ++++++++++++++++++
2 files changed, 28 insertions(+), 29 deletions(-)
delete mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/legalize-shl-crash.ll
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shl-crash.ll b/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shl-crash.ll
deleted file mode 100644
index b7a5cdc77aa35..0000000000000
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalize-shl-crash.ll
+++ /dev/null
@@ -1,29 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -global-isel -o - %s | FileCheck %s
-
-target triple = "aarch64-unknown-unknown"
-
-; Check we don't crash here.
-
-define <2 x i8> @test() {
-; CHECK-LABEL: test:
-; CHECK: // %bb.0: // %entry
-; CHECK-NEXT: mov w8, #1 // =0x1
-; CHECK-NEXT: mov w9, #0 // =0x0
-; CHECK-NEXT: fmov s0, w8
-; CHECK-NEXT: fmov s1, w9
-; CHECK-NEXT: mov v0.b[1], w8
-; CHECK-NEXT: mov v1.b[1], w9
-; CHECK-NEXT: ushl v0.8b, v0.8b, v1.8b
-; CHECK-NEXT: umov w8, v0.b[0]
-; CHECK-NEXT: umov w9, v0.b[1]
-; CHECK-NEXT: fmov s0, w8
-; CHECK-NEXT: mov v0.s[1], w9
-; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
-; CHECK-NEXT: ret
-entry:
- %zeroes = zext <2 x i1> zeroinitializer to <2 x i32>
- %ones = shl <2 x i32> splat (i32 1), %zeroes
- %ones.trunc = trunc <2 x i32> %ones to <2 x i8>
- ret <2 x i8> %ones.trunc
-}
diff --git a/llvm/test/CodeGen/AArch64/shift.ll b/llvm/test/CodeGen/AArch64/shift.ll
index 9827cb3526f99..f67ccc0af9501 100644
--- a/llvm/test/CodeGen/AArch64/shift.ll
+++ b/llvm/test/CodeGen/AArch64/shift.ll
@@ -1033,6 +1033,34 @@ define <2 x i128> @lshr_v2i128(<2 x i128> %0, <2 x i128> %1){
ret <2 x i128> %3
}
+define <2 x i8> @pr168848() {
+; CHECK-SD-LABEL: pr168848:
+; CHECK-SD: // %bb.0: // %entry
+; CHECK-SD-NEXT: movi v0.2s, #1
+; CHECK-SD-NEXT: ret
+;
+; CHECK-GI-LABEL: pr168848:
+; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: mov w8, #1 // =0x1
+; CHECK-GI-NEXT: mov w9, #0 // =0x0
+; CHECK-GI-NEXT: fmov s0, w8
+; CHECK-GI-NEXT: fmov s1, w9
+; CHECK-GI-NEXT: mov v0.b[1], w8
+; CHECK-GI-NEXT: mov v1.b[1], w9
+; CHECK-GI-NEXT: ushl v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: umov w8, v0.b[0]
+; CHECK-GI-NEXT: umov w9, v0.b[1]
+; CHECK-GI-NEXT: fmov s0, w8
+; CHECK-GI-NEXT: mov v0.s[1], w9
+; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT: ret
+entry:
+ %zeroes = zext <2 x i1> zeroinitializer to <2 x i32>
+ %ones = shl <2 x i32> splat (i32 1), %zeroes
+ %ones.trunc = trunc <2 x i32> %ones to <2 x i8>
+ ret <2 x i8> %ones.trunc
+}
+
; ===== Vector with Non-Pow 2 Width =====
define <3 x i8> @shl_v3i8(<3 x i8> %0, <3 x i8> %1){
>From 0425039642d0d2804c90f15c97b4566dcf899d19 Mon Sep 17 00:00:00 2001
From: Nathan Corbyn <n_corbyn at apple.com>
Date: Mon, 1 Dec 2025 16:38:59 +0000
Subject: [PATCH 4/4] Make sure the test case won't be optimised out
---
llvm/test/CodeGen/AArch64/shift.ll | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/shift.ll b/llvm/test/CodeGen/AArch64/shift.ll
index f67ccc0af9501..98c7f673ecd01 100644
--- a/llvm/test/CodeGen/AArch64/shift.ll
+++ b/llvm/test/CodeGen/AArch64/shift.ll
@@ -1033,21 +1033,24 @@ define <2 x i128> @lshr_v2i128(<2 x i128> %0, <2 x i128> %1){
ret <2 x i128> %3
}
-define <2 x i8> @pr168848() {
+define <2 x i8> @pr168848(<2 x i1> %shift) {
; CHECK-SD-LABEL: pr168848:
; CHECK-SD: // %bb.0: // %entry
-; CHECK-SD-NEXT: movi v0.2s, #1
+; CHECK-SD-NEXT: movi v1.2s, #1
+; CHECK-SD-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-SD-NEXT: ushl v0.2s, v1.2s, v0.2s
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: pr168848:
; CHECK-GI: // %bb.0: // %entry
+; CHECK-GI-NEXT: movi v1.2s, #1
; CHECK-GI-NEXT: mov w8, #1 // =0x1
-; CHECK-GI-NEXT: mov w9, #0 // =0x0
-; CHECK-GI-NEXT: fmov s0, w8
-; CHECK-GI-NEXT: fmov s1, w9
-; CHECK-GI-NEXT: mov v0.b[1], w8
-; CHECK-GI-NEXT: mov v1.b[1], w9
-; CHECK-GI-NEXT: ushl v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: and v0.8b, v0.8b, v1.8b
+; CHECK-GI-NEXT: fmov s1, w8
+; CHECK-GI-NEXT: uzp1 v0.4h, v0.4h, v0.4h
+; CHECK-GI-NEXT: mov v1.b[1], w8
+; CHECK-GI-NEXT: uzp1 v0.8b, v0.8b, v0.8b
+; CHECK-GI-NEXT: ushl v0.8b, v1.8b, v0.8b
; CHECK-GI-NEXT: umov w8, v0.b[0]
; CHECK-GI-NEXT: umov w9, v0.b[1]
; CHECK-GI-NEXT: fmov s0, w8
@@ -1055,8 +1058,8 @@ define <2 x i8> @pr168848() {
; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0
; CHECK-GI-NEXT: ret
entry:
- %zeroes = zext <2 x i1> zeroinitializer to <2 x i32>
- %ones = shl <2 x i32> splat (i32 1), %zeroes
+ %shift.zext = zext <2 x i1> %shift to <2 x i32>
+ %ones = shl <2 x i32> splat (i32 1), %shift.zext
%ones.trunc = trunc <2 x i32> %ones to <2 x i8>
ret <2 x i8> %ones.trunc
}
More information about the llvm-commits
mailing list