[llvm] 4d68381 - [VectorCombine] Add test cases for scalarizing extracts of extends.
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 5 02:08:45 PDT 2025
Author: Florian Hahn
Date: 2025-06-05T10:08:07+01:00
New Revision: 4d683818a05026cd54af5ae94aaf14e0134a106f
URL: https://github.com/llvm/llvm-project/commit/4d683818a05026cd54af5ae94aaf14e0134a106f
DIFF: https://github.com/llvm/llvm-project/commit/4d683818a05026cd54af5ae94aaf14e0134a106f.diff
LOG: [VectorCombine] Add test cases for scalarizing extracts of extends.
Add test cases where scalarizing extracts of a zext can be profitable.
Added:
llvm/test/Transforms/VectorCombine/AArch64/ext-extract.ll
Modified:
Removed:
################################################################################
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/ext-extract.ll b/llvm/test/Transforms/VectorCombine/AArch64/ext-extract.ll
new file mode 100644
index 0000000000000..09c03991ad7c3
--- /dev/null
+++ b/llvm/test/Transforms/VectorCombine/AArch64/ext-extract.ll
@@ -0,0 +1,268 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -p vector-combine -mtriple=arm64-apple-macosx -S %s | FileCheck %s
+
+declare void @use.i32(i32)
+declare void @use.i64(i64)
+declare void @use.v4i32(<4 x i32>)
+
+define void @zext_v4i8_all_lanes_used(<4 x i8> %src) {
+; CHECK-LABEL: define void @zext_v4i8_all_lanes_used(
+; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
+; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT9]], i64 0
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT9]], i64 1
+; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT9]], i64 2
+; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT9]], i64 3
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_0]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_1]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_2]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_3]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <4 x i8> %src to <4 x i32>
+ %ext.0 = extractelement <4 x i32> %ext9, i64 0
+ %ext.1 = extractelement <4 x i32> %ext9, i64 1
+ %ext.2 = extractelement <4 x i32> %ext9, i64 2
+ %ext.3 = extractelement <4 x i32> %ext9, i64 3
+
+ call void @use.i32(i32 %ext.0)
+ call void @use.i32(i32 %ext.1)
+ call void @use.i32(i32 %ext.2)
+ call void @use.i32(i32 %ext.3)
+ ret void
+}
+
+define void @sext_v4i8_all_lanes_used(<4 x i8> %src) {
+; CHECK-LABEL: define void @sext_v4i8_all_lanes_used(
+; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = sext <4 x i8> [[SRC]] to <4 x i32>
+; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT9]], i64 0
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT9]], i64 1
+; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT9]], i64 2
+; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT9]], i64 3
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_0]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_1]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_2]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_3]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = sext <4 x i8> %src to <4 x i32>
+ %ext.0 = extractelement <4 x i32> %ext9, i64 0
+ %ext.1 = extractelement <4 x i32> %ext9, i64 1
+ %ext.2 = extractelement <4 x i32> %ext9, i64 2
+ %ext.3 = extractelement <4 x i32> %ext9, i64 3
+
+ call void @use.i32(i32 %ext.0)
+ call void @use.i32(i32 %ext.1)
+ call void @use.i32(i32 %ext.2)
+ call void @use.i32(i32 %ext.3)
+ ret void
+}
+
+
+define void @zext_v4i8_3_lanes_used_1(<4 x i8> %src) {
+; CHECK-LABEL: define void @zext_v4i8_3_lanes_used_1(
+; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT9]], i64 1
+; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT9]], i64 2
+; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT9]], i64 3
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_1]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_2]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_3]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <4 x i8> %src to <4 x i32>
+ %ext.1 = extractelement <4 x i32> %ext9, i64 1
+ %ext.2 = extractelement <4 x i32> %ext9, i64 2
+ %ext.3 = extractelement <4 x i32> %ext9, i64 3
+
+ call void @use.i32(i32 %ext.1)
+ call void @use.i32(i32 %ext.2)
+ call void @use.i32(i32 %ext.3)
+ ret void
+}
+
+define void @zext_v4i8_3_lanes_used_2(<4 x i8> %src) {
+; CHECK-LABEL: define void @zext_v4i8_3_lanes_used_2(
+; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
+; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT9]], i64 0
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT9]], i64 1
+; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT9]], i64 3
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_0]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_1]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_3]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <4 x i8> %src to <4 x i32>
+ %ext.0 = extractelement <4 x i32> %ext9, i64 0
+ %ext.1 = extractelement <4 x i32> %ext9, i64 1
+ %ext.3 = extractelement <4 x i32> %ext9, i64 3
+
+ call void @use.i32(i32 %ext.0)
+ call void @use.i32(i32 %ext.1)
+ call void @use.i32(i32 %ext.3)
+ ret void
+}
+
+define void @zext_v4i8_2_lanes_used_1(<4 x i8> %src) {
+; CHECK-LABEL: define void @zext_v4i8_2_lanes_used_1(
+; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT9]], i64 1
+; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT9]], i64 2
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_1]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_2]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <4 x i8> %src to <4 x i32>
+ %ext.1 = extractelement <4 x i32> %ext9, i64 1
+ %ext.2 = extractelement <4 x i32> %ext9, i64 2
+
+ call void @use.i32(i32 %ext.1)
+ call void @use.i32(i32 %ext.2)
+ ret void
+}
+
+define void @zext_v4i8_2_lanes_used_2(<4 x i8> %src) {
+; CHECK-LABEL: define void @zext_v4i8_2_lanes_used_2(
+; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
+; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT9]], i64 0
+; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT9]], i64 2
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_0]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_2]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <4 x i8> %src to <4 x i32>
+ %ext.0 = extractelement <4 x i32> %ext9, i64 0
+ %ext.2 = extractelement <4 x i32> %ext9, i64 2
+
+ call void @use.i32(i32 %ext.0)
+ call void @use.i32(i32 %ext.2)
+ ret void
+}
+
+define void @zext_v4i8_all_lanes_used_noundef(<4 x i8> noundef %src) {
+; CHECK-LABEL: define void @zext_v4i8_all_lanes_used_noundef(
+; CHECK-SAME: <4 x i8> noundef [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
+; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT9]], i64 0
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT9]], i64 1
+; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT9]], i64 2
+; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT9]], i64 3
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_0]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_1]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_2]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_3]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <4 x i8> %src to <4 x i32>
+ %ext.0 = extractelement <4 x i32> %ext9, i64 0
+ %ext.1 = extractelement <4 x i32> %ext9, i64 1
+ %ext.2 = extractelement <4 x i32> %ext9, i64 2
+ %ext.3 = extractelement <4 x i32> %ext9, i64 3
+
+ call void @use.i32(i32 %ext.0)
+ call void @use.i32(i32 %ext.1)
+ call void @use.i32(i32 %ext.2)
+ call void @use.i32(i32 %ext.3)
+ ret void
+}
+
+define void @zext_v4i8_all_lanes_used_zext_other_users(<4 x i8> %src) {
+; CHECK-LABEL: define void @zext_v4i8_all_lanes_used_zext_other_users(
+; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
+; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT9]], i64 0
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT9]], i64 1
+; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT9]], i64 2
+; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT9]], i64 3
+; CHECK-NEXT: call void @use.v4i32(<4 x i32> [[EXT9]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_0]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_1]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_2]])
+; CHECK-NEXT: call void @use.i32(i32 [[EXT_3]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <4 x i8> %src to <4 x i32>
+ %ext.0 = extractelement <4 x i32> %ext9, i64 0
+ %ext.1 = extractelement <4 x i32> %ext9, i64 1
+ %ext.2 = extractelement <4 x i32> %ext9, i64 2
+ %ext.3 = extractelement <4 x i32> %ext9, i64 3
+
+ call void @use.v4i32(<4 x i32> %ext9)
+
+ call void @use.i32(i32 %ext.0)
+ call void @use.i32(i32 %ext.1)
+ call void @use.i32(i32 %ext.2)
+ call void @use.i32(i32 %ext.3)
+ ret void
+}
+
+define void @zext_v4i16_all_lanes_used(<4 x i16> %src) {
+; CHECK-LABEL: define void @zext_v4i16_all_lanes_used(
+; CHECK-SAME: <4 x i16> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <4 x i16> [[SRC]] to <4 x i64>
+; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i64> [[EXT9]], i64 0
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i64> [[EXT9]], i64 1
+; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i64> [[EXT9]], i64 2
+; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i64> [[EXT9]], i64 3
+; CHECK-NEXT: call void @use.i64(i64 [[EXT_0]])
+; CHECK-NEXT: call void @use.i64(i64 [[EXT_1]])
+; CHECK-NEXT: call void @use.i64(i64 [[EXT_2]])
+; CHECK-NEXT: call void @use.i64(i64 [[EXT_3]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <4 x i16> %src to <4 x i64>
+ %ext.0 = extractelement <4 x i64> %ext9, i64 0
+ %ext.1 = extractelement <4 x i64> %ext9, i64 1
+ %ext.2 = extractelement <4 x i64> %ext9, i64 2
+ %ext.3 = extractelement <4 x i64> %ext9, i64 3
+
+ call void @use.i64(i64 %ext.0)
+ call void @use.i64(i64 %ext.1)
+ call void @use.i64(i64 %ext.2)
+ call void @use.i64(i64 %ext.3)
+ ret void
+}
+
+define void @zext_v2i32_all_lanes_used(<2 x i32> %src) {
+; CHECK-LABEL: define void @zext_v2i32_all_lanes_used(
+; CHECK-SAME: <2 x i32> [[SRC:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <2 x i32> [[SRC]] to <2 x i64>
+; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <2 x i64> [[EXT9]], i64 0
+; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <2 x i64> [[EXT9]], i64 1
+; CHECK-NEXT: call void @use.i64(i64 [[EXT_0]])
+; CHECK-NEXT: call void @use.i64(i64 [[EXT_1]])
+; CHECK-NEXT: ret void
+;
+entry:
+ %ext9 = zext nneg <2 x i32> %src to <2 x i64>
+ %ext.0 = extractelement <2 x i64> %ext9, i64 0
+ %ext.1 = extractelement <2 x i64> %ext9, i64 1
+
+ call void @use.i64(i64 %ext.0)
+ call void @use.i64(i64 %ext.1)
+ ret void
+}
More information about the llvm-commits
mailing list