blob: 26d7647e5afdeb74d28429e7b6c57fac03d226d1 [file]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=vector-combine -mtriple=aarch64 < %s | FileCheck %s
define i1 @or_eq_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_eq_0(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
%cmp = icmp eq i32 %red, 0
ret i1 %cmp
}
define i1 @or_ne_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_ne_0(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
%cmp = icmp ne i32 %red, 0
ret i1 %cmp
}
define i1 @or_slt_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_slt_0(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
%cmp = icmp slt i32 %red, 0
ret i1 %cmp
}
define i1 @or_sgt_m1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_sgt_m1(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
%cmp = icmp sgt i32 %red, -1
ret i1 %cmp
}
define i1 @and_eq_allones(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_eq_allones(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %x)
%cmp = icmp eq i32 %red, -1
ret i1 %cmp
}
define i1 @and_ne_allones(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_ne_allones(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP1]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %x)
%cmp = icmp ne i32 %red, -1
ret i1 %cmp
}
define i1 @and_slt_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_slt_0(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %x)
%cmp = icmp slt i32 %red, 0
ret i1 %cmp
}
define i1 @and_sgt_m1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_sgt_m1(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %x)
%cmp = icmp sgt i32 %red, -1
ret i1 %cmp
}
define i1 @or_slt_1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_slt_1(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
%cmp = icmp slt i32 %red, 1
ret i1 %cmp
}
define i1 @and_sgt_m2(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_sgt_m2(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -2
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %x)
%cmp = icmp sgt i32 %red, -2
ret i1 %cmp
}
define i1 @umax_eq_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umax_eq_0(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> %x)
%cmp = icmp eq i32 %red, 0
ret i1 %cmp
}
define i1 @umax_ne_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umax_ne_0(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[RED]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> %x)
%cmp = icmp ne i32 %red, 0
ret i1 %cmp
}
define i1 @umax_slt_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umax_slt_0(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[RED]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> %x)
%cmp = icmp slt i32 %red, 0
ret i1 %cmp
}
define i1 @umax_sgt_m1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umax_sgt_m1(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[RED]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> %x)
%cmp = icmp sgt i32 %red, -1
ret i1 %cmp
}
define i1 @umin_eq_allones(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umin_eq_allones(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> %x)
%cmp = icmp eq i32 %red, -1
ret i1 %cmp
}
define i1 @umin_ne_allones(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umin_ne_allones(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[RED]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> %x)
%cmp = icmp ne i32 %red, -1
ret i1 %cmp
}
define i1 @umin_slt_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umin_slt_0(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[RED]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> %x)
%cmp = icmp slt i32 %red, 0
ret i1 %cmp
}
define i1 @umin_sgt_m1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umin_sgt_m1(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[RED]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> %x)
%cmp = icmp sgt i32 %red, -1
ret i1 %cmp
}
define i1 @or_eq_0_i8(<16 x i8> %x) {
; CHECK-LABEL: define i1 @or_eq_0_i8(
; CHECK-SAME: <16 x i8> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.vector.reduce.umax.v16i8(<16 x i8> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i8 @llvm.vector.reduce.or.v16i8(<16 x i8> %x)
%cmp = icmp eq i8 %red, 0
ret i1 %cmp
}
define i1 @or_eq_0_i64(<2 x i64> %x) {
; CHECK-LABEL: define i1 @or_eq_0_i64(
; CHECK-SAME: <2 x i64> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.umax.v2i64(<2 x i64> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i64 @llvm.vector.reduce.or.v2i64(<2 x i64> %x)
%cmp = icmp eq i64 %red, 0
ret i1 %cmp
}
define i1 @or_eq_1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_eq_1(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
%cmp = icmp eq i32 %red, 1
ret i1 %cmp
}
define i1 @and_eq_minus2(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_eq_minus2(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], -2
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %x)
%cmp = icmp eq i32 %red, -2
ret i1 %cmp
}
define i1 @or_slt_2(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_slt_2(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
%cmp = icmp slt i32 %red, 2
ret i1 %cmp
}
define i1 @and_sgt_m3(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_sgt_m3(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -3
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %x)
%cmp = icmp sgt i32 %red, -3
ret i1 %cmp
}
define i1 @and_eq_0_negative(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_eq_0_negative(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.and.v4i32(<4 x i32> %x)
%cmp = icmp eq i32 %red, 0
ret i1 %cmp
}
define i1 @or_ult_0_negative(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_ult_0_negative(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[RED]], 1
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
%cmp = icmp ult i32 %red, 1
ret i1 %cmp
}
define i1 @or_eq_0_multiuse_negative(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_eq_0_multiuse_negative(
; CHECK-SAME: <4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[X]])
; CHECK-NEXT: call void @use(i32 [[RED]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> %x)
call void @use(i32 %red)
%cmp = icmp eq i32 %red, 0
ret i1 %cmp
}
define i1 @or_eq_0_scalable_negative(<vscale x 4 x i32> %x) {
; CHECK-LABEL: define i1 @or_eq_0_scalable_negative(
; CHECK-SAME: <vscale x 4 x i32> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.or.nxv4i32(<vscale x 4 x i32> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i32 @llvm.vector.reduce.or.nxv4i32(<vscale x 4 x i32> %x)
%cmp = icmp eq i32 %red, 0
ret i1 %cmp
}
; i1 vector tests - for i1, or===umax and and===umin
define i1 @or_eq_0_v4i1(<4 x i1> %x) {
; CHECK-LABEL: define i1 @or_eq_0_v4i1(
; CHECK-SAME: <4 x i1> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1 [[RED]], false
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> %x)
%cmp = icmp eq i1 %red, 0
ret i1 %cmp
}
define i1 @or_ne_0_v4i1(<4 x i1> %x) {
; CHECK-LABEL: define i1 @or_ne_0_v4i1(
; CHECK-SAME: <4 x i1> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i1 [[RED]], false
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> %x)
%cmp = icmp ne i1 %red, 0
ret i1 %cmp
}
define i1 @and_eq_allones_v4i1(<4 x i1> %x) {
; CHECK-LABEL: define i1 @and_eq_allones_v4i1(
; CHECK-SAME: <4 x i1> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1 [[RED]], true
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> %x)
%cmp = icmp eq i1 %red, -1
ret i1 %cmp
}
define i1 @and_ne_allones_v4i1(<4 x i1> %x) {
; CHECK-LABEL: define i1 @and_ne_allones_v4i1(
; CHECK-SAME: <4 x i1> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i1 [[RED]], true
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> %x)
%cmp = icmp ne i1 %red, -1
ret i1 %cmp
}
define i1 @umax_eq_0_v4i1(<4 x i1> %x) {
; CHECK-LABEL: define i1 @umax_eq_0_v4i1(
; CHECK-SAME: <4 x i1> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.umax.v4i1(<4 x i1> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1 [[RED]], false
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i1 @llvm.vector.reduce.umax.v4i1(<4 x i1> %x)
%cmp = icmp eq i1 %red, 0
ret i1 %cmp
}
define i1 @umin_eq_allones_v4i1(<4 x i1> %x) {
; CHECK-LABEL: define i1 @umin_eq_allones_v4i1(
; CHECK-SAME: <4 x i1> [[X:%.*]]) {
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.umin.v4i1(<4 x i1> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1 [[RED]], true
; CHECK-NEXT: ret i1 [[CMP]]
;
%red = call i1 @llvm.vector.reduce.umin.v4i1(<4 x i1> %x)
%cmp = icmp eq i1 %red, -1
ret i1 %cmp
}
declare void @use(i32)