This change aims to avoid inserting a freeze instruction between the load and bitcast when scalarizing extend-extract. This is particularly useful in combination with https://github.com/llvm/llvm-project/pull/164682, which can then potentially further scalarize, provided there is no freeze. alive2 proof: https://alive2.llvm.org/ce/z/W-GD88
535 lines
22 KiB
LLVM
535 lines
22 KiB
LLVM
; 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: [[TMP0:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[TMP0]] to i32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 24
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP1]], 16
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 255
|
|
; CHECK-NEXT: [[TMP6:%.*]] = lshr i32 [[TMP1]], 8
|
|
; CHECK-NEXT: [[TMP7:%.*]] = and i32 [[TMP6]], 255
|
|
; CHECK-NEXT: [[TMP9:%.*]] = and i32 [[TMP1]], 255
|
|
; 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 [[TMP9]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP7]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP5]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP2]])
|
|
; 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: [[TMP0:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[TMP0]] to i32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 24
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP1]], 16
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 255
|
|
; CHECK-NEXT: [[TMP6:%.*]] = lshr i32 [[TMP1]], 8
|
|
; CHECK-NEXT: [[TMP7:%.*]] = and i32 [[TMP6]], 255
|
|
; 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 [[TMP7]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP5]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP2]])
|
|
; 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: [[TMP0:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[TMP0]] to i32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 24
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP1]], 8
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 255
|
|
; CHECK-NEXT: [[TMP7:%.*]] = and i32 [[TMP1]], 255
|
|
; 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 [[TMP7]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP5]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP2]])
|
|
; 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: [[TMP0:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[TMP0]] to i32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 255
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP1]], 8
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 255
|
|
; 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 [[TMP5]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP3]])
|
|
; 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: [[TMP0:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[TMP0]] to i32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 16
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 255
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP1]], 255
|
|
; 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 [[TMP5]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP3]])
|
|
; 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: [[TMP0:%.*]] = bitcast <4 x i8> [[SRC]] to i32
|
|
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[TMP0]], 24
|
|
; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[TMP0]], 16
|
|
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 255
|
|
; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP0]], 8
|
|
; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 255
|
|
; CHECK-NEXT: [[TMP8:%.*]] = and i32 [[TMP0]], 255
|
|
; 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 [[TMP8]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP6]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP4]])
|
|
; CHECK-NEXT: call void @use.i32(i32 [[TMP1]])
|
|
; 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: [[TMP0:%.*]] = freeze <4 x i16> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to i64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 48
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i64 [[TMP1]], 32
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP4]], 65535
|
|
; CHECK-NEXT: [[TMP6:%.*]] = lshr i64 [[TMP1]], 16
|
|
; CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], 65535
|
|
; CHECK-NEXT: [[TMP9:%.*]] = and i64 [[TMP1]], 65535
|
|
; 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 [[TMP9]])
|
|
; CHECK-NEXT: call void @use.i64(i64 [[TMP7]])
|
|
; CHECK-NEXT: call void @use.i64(i64 [[TMP5]])
|
|
; CHECK-NEXT: call void @use.i64(i64 [[TMP2]])
|
|
; 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: [[TMP0:%.*]] = freeze <2 x i32> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[TMP0]] to i64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 32
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i64 [[TMP1]], 4294967295
|
|
; 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 [[TMP5]])
|
|
; CHECK-NEXT: call void @use.i64(i64 [[TMP2]])
|
|
; 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
|
|
}
|
|
|
|
define void @zext_nxv4i8_all_lanes_used(<vscale x 4 x i8> %src) {
|
|
; CHECK-LABEL: define void @zext_nxv4i8_all_lanes_used(
|
|
; CHECK-SAME: <vscale x 4 x i8> [[SRC:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*:]]
|
|
; CHECK-NEXT: [[EXT9:%.*]] = zext nneg <vscale x 4 x i8> [[SRC]] to <vscale x 4 x i32>
|
|
; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <vscale x 4 x i32> [[EXT9]], i64 0
|
|
; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <vscale x 4 x i32> [[EXT9]], i64 1
|
|
; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <vscale x 4 x i32> [[EXT9]], i64 2
|
|
; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <vscale x 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 <vscale x 4 x i8> %src to <vscale x 4 x i32>
|
|
%ext.0 = extractelement <vscale x 4 x i32> %ext9, i64 0
|
|
%ext.1 = extractelement <vscale x 4 x i32> %ext9, i64 1
|
|
%ext.2 = extractelement <vscale x 4 x i32> %ext9, i64 2
|
|
%ext.3 = extractelement <vscale x 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 noundef i32 @zext_v4i8_all_lanes_used_no_freeze(<4 x i8> %src) {
|
|
; CHECK-LABEL: define noundef i32 @zext_v4i8_all_lanes_used_no_freeze(
|
|
; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*:]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i8> [[SRC]] to i32
|
|
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[TMP0]], 24
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0]], 16
|
|
; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 255
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP0]], 8
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 255
|
|
; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP0]], 255
|
|
; CHECK-NEXT: [[EXT:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
|
|
; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT]], i64 0
|
|
; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT]], i64 1
|
|
; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT]], i64 2
|
|
; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT]], i64 3
|
|
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[TMP6]], [[TMP5]]
|
|
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], [[TMP3]]
|
|
; CHECK-NEXT: [[ADD3:%.*]] = add i32 [[ADD2]], [[TMP1]]
|
|
; CHECK-NEXT: ret i32 [[ADD3]]
|
|
;
|
|
entry:
|
|
%ext = zext nneg <4 x i8> %src to <4 x i32>
|
|
%ext.0 = extractelement <4 x i32> %ext, i64 0
|
|
%ext.1 = extractelement <4 x i32> %ext, i64 1
|
|
%ext.2 = extractelement <4 x i32> %ext, i64 2
|
|
%ext.3 = extractelement <4 x i32> %ext, i64 3
|
|
|
|
%add1 = add i32 %ext.0, %ext.1
|
|
%add2 = add i32 %add1, %ext.2
|
|
%add3 = add i32 %add2, %ext.3
|
|
ret i32 %add3
|
|
}
|
|
|
|
define noundef i32 @zext_v4i8_not_all_lanes_used(<4 x i8> %src) {
|
|
; CHECK-LABEL: define noundef i32 @zext_v4i8_not_all_lanes_used(
|
|
; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*:]]
|
|
; CHECK-NEXT: [[TMP2:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i8> [[TMP2]] to i32
|
|
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[TMP0]], 24
|
|
; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 [[TMP0]], 8
|
|
; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 255
|
|
; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP0]], 255
|
|
; CHECK-NEXT: [[EXT:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
|
|
; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT]], i64 0
|
|
; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT]], i64 1
|
|
; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT]], i64 3
|
|
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[TMP6]], [[TMP5]]
|
|
; CHECK-NEXT: [[ADD3:%.*]] = add i32 [[ADD2]], [[TMP1]]
|
|
; CHECK-NEXT: ret i32 [[ADD3]]
|
|
;
|
|
entry:
|
|
%ext = zext nneg <4 x i8> %src to <4 x i32>
|
|
%ext.0 = extractelement <4 x i32> %ext, i64 0
|
|
%ext.1 = extractelement <4 x i32> %ext, i64 1
|
|
%ext.3 = extractelement <4 x i32> %ext, i64 3
|
|
|
|
%add1 = add i32 %ext.0, %ext.1
|
|
%add2 = add i32 %add1, %ext.3
|
|
ret i32 %add2
|
|
}
|
|
|
|
define i32 @zext_v4i8_all_lanes_used_no_ub(<4 x i8> %src) {
|
|
; CHECK-LABEL: define i32 @zext_v4i8_all_lanes_used_no_ub(
|
|
; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*:]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[TMP0]] to i32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 24
|
|
; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[TMP1]], 16
|
|
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 255
|
|
; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP1]], 8
|
|
; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 255
|
|
; CHECK-NEXT: [[TMP7:%.*]] = and i32 [[TMP1]], 255
|
|
; CHECK-NEXT: [[EXT:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
|
|
; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT]], i64 0
|
|
; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT]], i64 1
|
|
; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT]], i64 2
|
|
; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT]], i64 3
|
|
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[TMP7]], [[TMP6]]
|
|
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], [[TMP4]]
|
|
; CHECK-NEXT: [[ADD3:%.*]] = add i32 [[ADD2]], [[TMP2]]
|
|
; CHECK-NEXT: ret i32 [[ADD3]]
|
|
;
|
|
entry:
|
|
%ext = zext nneg <4 x i8> %src to <4 x i32>
|
|
%ext.0 = extractelement <4 x i32> %ext, i64 0
|
|
%ext.1 = extractelement <4 x i32> %ext, i64 1
|
|
%ext.2 = extractelement <4 x i32> %ext, i64 2
|
|
%ext.3 = extractelement <4 x i32> %ext, i64 3
|
|
|
|
%add1 = add i32 %ext.0, %ext.1
|
|
%add2 = add i32 %add1, %ext.2
|
|
%add3 = add i32 %add2, %ext.3
|
|
ret i32 %add3
|
|
}
|
|
|
|
define noundef i32 @zext_v4i8_extracts_different_blocks(<4 x i8> %src, i1 %cond) {
|
|
; CHECK-LABEL: define noundef i32 @zext_v4i8_extracts_different_blocks(
|
|
; CHECK-SAME: <4 x i8> [[SRC:%.*]], i1 [[COND:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*:]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[TMP0]] to i32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 24
|
|
; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[TMP1]], 16
|
|
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 255
|
|
; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP1]], 8
|
|
; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 255
|
|
; CHECK-NEXT: [[TMP7:%.*]] = and i32 [[TMP1]], 255
|
|
; CHECK-NEXT: [[EXT:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
|
|
; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT]], i64 0
|
|
; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT]], i64 1
|
|
; CHECK-NEXT: br i1 [[COND]], label %[[THEN:.*]], label %[[ELSE:.*]]
|
|
; CHECK: [[THEN]]:
|
|
; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT]], i64 2
|
|
; CHECK-NEXT: br label %[[EXIT:.*]]
|
|
; CHECK: [[ELSE]]:
|
|
; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT]], i64 3
|
|
; CHECK-NEXT: br label %[[EXIT]]
|
|
; CHECK: [[EXIT]]:
|
|
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[TMP4]], %[[THEN]] ], [ [[TMP2]], %[[ELSE]] ]
|
|
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[TMP7]], [[TMP6]]
|
|
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], [[PHI]]
|
|
; CHECK-NEXT: ret i32 [[ADD2]]
|
|
;
|
|
entry:
|
|
%ext = zext nneg <4 x i8> %src to <4 x i32>
|
|
%ext.0 = extractelement <4 x i32> %ext, i64 0
|
|
%ext.1 = extractelement <4 x i32> %ext, i64 1
|
|
br i1 %cond, label %then, label %else
|
|
|
|
then:
|
|
%ext.2 = extractelement <4 x i32> %ext, i64 2
|
|
br label %exit
|
|
|
|
else:
|
|
%ext.3 = extractelement <4 x i32> %ext, i64 3
|
|
br label %exit
|
|
|
|
exit:
|
|
%phi = phi i32 [ %ext.2, %then ], [ %ext.3, %else ]
|
|
%add1 = add i32 %ext.0, %ext.1
|
|
%add2 = add i32 %add1, %phi
|
|
ret i32 %add2
|
|
}
|
|
|
|
|
|
declare void @may_throw() willreturn
|
|
|
|
define noundef i32 @zext_v4i8_throwing_call_between(<4 x i8> %src) {
|
|
; CHECK-LABEL: define noundef i32 @zext_v4i8_throwing_call_between(
|
|
; CHECK-SAME: <4 x i8> [[SRC:%.*]]) {
|
|
; CHECK-NEXT: [[ENTRY:.*:]]
|
|
; CHECK-NEXT: [[TMP0:%.*]] = freeze <4 x i8> [[SRC]]
|
|
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i8> [[TMP0]] to i32
|
|
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP1]], 24
|
|
; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[TMP1]], 16
|
|
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 255
|
|
; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP1]], 8
|
|
; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 255
|
|
; CHECK-NEXT: [[TMP7:%.*]] = and i32 [[TMP1]], 255
|
|
; CHECK-NEXT: [[EXT:%.*]] = zext nneg <4 x i8> [[SRC]] to <4 x i32>
|
|
; CHECK-NEXT: [[EXT_0:%.*]] = extractelement <4 x i32> [[EXT]], i64 0
|
|
; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <4 x i32> [[EXT]], i64 1
|
|
; CHECK-NEXT: [[EXT_2:%.*]] = extractelement <4 x i32> [[EXT]], i64 2
|
|
; CHECK-NEXT: call void @may_throw()
|
|
; CHECK-NEXT: [[EXT_3:%.*]] = extractelement <4 x i32> [[EXT]], i64 3
|
|
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[TMP7]], [[TMP6]]
|
|
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], [[TMP4]]
|
|
; CHECK-NEXT: [[ADD3:%.*]] = add i32 [[ADD2]], [[TMP2]]
|
|
; CHECK-NEXT: ret i32 [[ADD3]]
|
|
;
|
|
entry:
|
|
%ext = zext nneg <4 x i8> %src to <4 x i32>
|
|
%ext.0 = extractelement <4 x i32> %ext, i64 0
|
|
%ext.1 = extractelement <4 x i32> %ext, i64 1
|
|
%ext.2 = extractelement <4 x i32> %ext, i64 2
|
|
call void @may_throw()
|
|
%ext.3 = extractelement <4 x i32> %ext, i64 3
|
|
%add1 = add i32 %ext.0, %ext.1
|
|
%add2 = add i32 %add1, %ext.2
|
|
%add3 = add i32 %add2, %ext.3
|
|
ret i32 %add3
|
|
}
|