blob: 9c75e114ee9f40167c1d74d1df370ceedc6fb99c [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -passes=slp-vectorizer -slp-threshold=-99999 -S -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
; umax is the main opcode. x2/x3 are copyable and vectorize as umax with 0.
define void @test_umax(ptr %dst, i32 %x0, i32 %x1, i32 %x2, i32 %x3) {
; CHECK-LABEL: define void @test_umax(
; CHECK-SAME: ptr [[DST:%.*]], i32 [[X0:%.*]], i32 [[X1:%.*]], i32 [[X2:%.*]], i32 [[X3:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[X0]], i64 0
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> [[TMP0]], i32 [[X1]], i64 1
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x i32> [[TMP1]], i32 [[X2]], i64 2
; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i32> [[TMP2]], i32 [[X3]], i64 3
; CHECK-NEXT: [[TMP4:%.*]] = call <4 x i32> @llvm.umax.v4i32(<4 x i32> [[TMP3]], <4 x i32> <i32 1, i32 2, i32 0, i32 0>)
; CHECK-NEXT: store <4 x i32> [[TMP4]], ptr [[DST]], align 4
; CHECK-NEXT: ret void
;
entry:
%umax0 = call i32 @llvm.umax.i32(i32 %x0, i32 1)
%umax1 = call i32 @llvm.umax.i32(i32 %x1, i32 2)
store i32 %umax0, ptr %dst, align 4
%p1 = getelementptr i32, ptr %dst, i32 1
store i32 %umax1, ptr %p1, align 4
%p2 = getelementptr i32, ptr %dst, i32 2
store i32 %x2, ptr %p2, align 4
%p3 = getelementptr i32, ptr %dst, i32 3
store i32 %x3, ptr %p3, align 4
ret void
}
; umin is the main opcode. x2/x3 are copyable and vectorize as umin with -1
; (all-ones), the identity for umin.
define void @test_umin(ptr %dst, i32 %x0, i32 %x1, i32 %x2, i32 %x3) {
; CHECK-LABEL: define void @test_umin(
; CHECK-SAME: ptr [[DST:%.*]], i32 [[X0:%.*]], i32 [[X1:%.*]], i32 [[X2:%.*]], i32 [[X3:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[X0]], i64 0
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> [[TMP0]], i32 [[X1]], i64 1
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x i32> [[TMP1]], i32 [[X2]], i64 2
; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i32> [[TMP2]], i32 [[X3]], i64 3
; CHECK-NEXT: [[TMP4:%.*]] = call <4 x i32> @llvm.umin.v4i32(<4 x i32> [[TMP3]], <4 x i32> <i32 1, i32 2, i32 -1, i32 -1>)
; CHECK-NEXT: store <4 x i32> [[TMP4]], ptr [[DST]], align 4
; CHECK-NEXT: ret void
;
entry:
%umin0 = call i32 @llvm.umin.i32(i32 %x0, i32 1)
%umin1 = call i32 @llvm.umin.i32(i32 %x1, i32 2)
store i32 %umin0, ptr %dst, align 4
%p1 = getelementptr i32, ptr %dst, i32 1
store i32 %umin1, ptr %p1, align 4
%p2 = getelementptr i32, ptr %dst, i32 2
store i32 %x2, ptr %p2, align 4
%p3 = getelementptr i32, ptr %dst, i32 3
store i32 %x3, ptr %p3, align 4
ret void
}
; smax is the main opcode. x2/x3 are copyable and vectorize as smax with
; -2147483648 (signed min), the identity for smax.
define void @test_smax(ptr %dst, i32 %x0, i32 %x1, i32 %x2, i32 %x3) {
; CHECK-LABEL: define void @test_smax(
; CHECK-SAME: ptr [[DST:%.*]], i32 [[X0:%.*]], i32 [[X1:%.*]], i32 [[X2:%.*]], i32 [[X3:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[X0]], i64 0
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> [[TMP0]], i32 [[X1]], i64 1
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x i32> [[TMP1]], i32 [[X2]], i64 2
; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i32> [[TMP2]], i32 [[X3]], i64 3
; CHECK-NEXT: [[TMP4:%.*]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[TMP3]], <4 x i32> <i32 1, i32 2, i32 -2147483648, i32 -2147483648>)
; CHECK-NEXT: store <4 x i32> [[TMP4]], ptr [[DST]], align 4
; CHECK-NEXT: ret void
;
entry:
%smax0 = call i32 @llvm.smax.i32(i32 %x0, i32 1)
%smax1 = call i32 @llvm.smax.i32(i32 %x1, i32 2)
store i32 %smax0, ptr %dst, align 4
%p1 = getelementptr i32, ptr %dst, i32 1
store i32 %smax1, ptr %p1, align 4
%p2 = getelementptr i32, ptr %dst, i32 2
store i32 %x2, ptr %p2, align 4
%p3 = getelementptr i32, ptr %dst, i32 3
store i32 %x3, ptr %p3, align 4
ret void
}
; smin is the main opcode. x2/x3 are copyable and vectorize as smin with
; 2147483647 (signed max), the identity for smin.
define void @test_smin(ptr %dst, i32 %x0, i32 %x1, i32 %x2, i32 %x3) {
; CHECK-LABEL: define void @test_smin(
; CHECK-SAME: ptr [[DST:%.*]], i32 [[X0:%.*]], i32 [[X1:%.*]], i32 [[X2:%.*]], i32 [[X3:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x i32> poison, i32 [[X0]], i64 0
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x i32> [[TMP0]], i32 [[X1]], i64 1
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x i32> [[TMP1]], i32 [[X2]], i64 2
; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x i32> [[TMP2]], i32 [[X3]], i64 3
; CHECK-NEXT: [[TMP4:%.*]] = call <4 x i32> @llvm.smin.v4i32(<4 x i32> [[TMP3]], <4 x i32> <i32 1, i32 2, i32 2147483647, i32 2147483647>)
; CHECK-NEXT: store <4 x i32> [[TMP4]], ptr [[DST]], align 4
; CHECK-NEXT: ret void
;
entry:
%smin0 = call i32 @llvm.smin.i32(i32 %x0, i32 1)
%smin1 = call i32 @llvm.smin.i32(i32 %x1, i32 2)
store i32 %smin0, ptr %dst, align 4
%p1 = getelementptr i32, ptr %dst, i32 1
store i32 %smin1, ptr %p1, align 4
%p2 = getelementptr i32, ptr %dst, i32 2
store i32 %x2, ptr %p2, align 4
%p3 = getelementptr i32, ptr %dst, i32 3
store i32 %x3, ptr %p3, align 4
ret void
}
; smax main opcode with copyables and trunc users, to exercise the
; minbitwidth (collectValuesToDemote) copyable path for min/max intrinsics.
define void @test_minbitwidth_trunc(ptr %dst, ptr %src) {
; CHECK-LABEL: define void @test_minbitwidth_trunc(
; CHECK-SAME: ptr [[DST:%.*]], ptr [[SRC:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[SRC]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SRC]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[SRC]], align 4
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[SRC]], align 4
; CHECK-NEXT: [[TMP4:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i64 0
; CHECK-NEXT: [[TMP5:%.*]] = insertelement <4 x i32> [[TMP4]], i32 [[TMP1]], i64 1
; CHECK-NEXT: [[TMP11:%.*]] = insertelement <4 x i32> [[TMP5]], i32 [[TMP2]], i64 2
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i32> [[TMP11]], i32 [[TMP3]], i64 3
; CHECK-NEXT: [[TMP8:%.*]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[TMP7]], <4 x i32> <i32 100, i32 200, i32 -2147483648, i32 -2147483648>)
; CHECK-NEXT: [[TMP9:%.*]] = trunc <4 x i32> [[TMP8]] to <4 x i16>
; CHECK-NEXT: store <4 x i16> [[TMP9]], ptr [[DST]], align 2
; CHECK-NEXT: ret void
;
entry:
%0 = load i32, ptr %src, align 4
%1 = load i32, ptr %src, align 4
%2 = load i32, ptr %src, align 4
%3 = load i32, ptr %src, align 4
%smax0 = call i32 @llvm.smax.i32(i32 %0, i32 100)
%smax1 = call i32 @llvm.smax.i32(i32 %1, i32 200)
%trunc0 = trunc i32 %smax0 to i16
%trunc1 = trunc i32 %smax1 to i16
%trunc2 = trunc i32 %2 to i16
%trunc3 = trunc i32 %3 to i16
store i16 %trunc0, ptr %dst, align 2
%p1 = getelementptr i16, ptr %dst, i32 1
store i16 %trunc1, ptr %p1, align 2
%p2 = getelementptr i16, ptr %dst, i32 2
store i16 %trunc2, ptr %p2, align 2
%p3 = getelementptr i16, ptr %dst, i32 3
store i16 %trunc3, ptr %p3, align 2
ret void
}