[llvm] [X86] fold-signbit-reduction-cmp.ll - test for each x86-64 cpu level (PR #210051)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 16 06:08:45 PDT 2026
https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/210051
None
>From dae4eed1f61ecaa41e394eafec5f948681c9b8a3 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Thu, 16 Jul 2026 14:07:52 +0100
Subject: [PATCH] [X86] fold-signbit-reduction-cmp.ll - test for each x86-64
cpu level
---
.../X86/fold-signbit-reduction-cmp.ll | 388 ++++++++++++------
1 file changed, 271 insertions(+), 117 deletions(-)
diff --git a/llvm/test/Transforms/VectorCombine/X86/fold-signbit-reduction-cmp.ll b/llvm/test/Transforms/VectorCombine/X86/fold-signbit-reduction-cmp.ll
index 74d651e91871c..910e585e7b528 100644
--- a/llvm/test/Transforms/VectorCombine/X86/fold-signbit-reduction-cmp.ll
+++ b/llvm/test/Transforms/VectorCombine/X86/fold-signbit-reduction-cmp.ll
@@ -1,9 +1,12 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -passes=vector-combine -mtriple=x86_64-- < %s | FileCheck %s
+; RUN: opt < %s -S -passes=vector-combine -mtriple=x86_64-- -mcpu=x86-64 | FileCheck %s --check-prefixes=CHECK,SSE,SSE2
+; RUN: opt < %s -S -passes=vector-combine -mtriple=x86_64-- -mcpu=x86-64-v2 | FileCheck %s --check-prefixes=CHECK,SSE,SSE4
+; RUN: opt < %s -S -passes=vector-combine -mtriple=x86_64-- -mcpu=x86-64-v3 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2
+; RUN: opt < %s -S -passes=vector-combine -mtriple=x86_64-- -mcpu=x86-64-v4 | FileCheck %s --check-prefixes=CHECK,AVX,AVX512
define i1 @or_eq_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_eq_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0:[0-9]+]] {
; 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]]
@@ -16,7 +19,7 @@ define i1 @or_eq_0(<4 x i32> %x) {
define i1 @or_ne_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_ne_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -29,7 +32,7 @@ define i1 @or_ne_0(<4 x i32> %x) {
define i1 @or_eq_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_eq_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -42,7 +45,7 @@ define i1 @or_eq_max(<4 x i32> %x) {
define i1 @or_ne_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @or_ne_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -55,7 +58,7 @@ define i1 @or_ne_max(<4 x i32> %x) {
define i1 @umax_eq_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umax_eq_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -68,7 +71,7 @@ define i1 @umax_eq_0(<4 x i32> %x) {
define i1 @umax_ne_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umax_ne_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -81,7 +84,7 @@ define i1 @umax_ne_0(<4 x i32> %x) {
define i1 @umax_eq_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umax_eq_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -94,7 +97,7 @@ define i1 @umax_eq_max(<4 x i32> %x) {
define i1 @umax_ne_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umax_ne_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -107,7 +110,7 @@ define i1 @umax_ne_max(<4 x i32> %x) {
define i1 @and_eq_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_eq_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -120,7 +123,7 @@ define i1 @and_eq_0(<4 x i32> %x) {
define i1 @and_ne_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_ne_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -133,7 +136,7 @@ define i1 @and_ne_0(<4 x i32> %x) {
define i1 @and_eq_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_eq_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -146,7 +149,7 @@ define i1 @and_eq_max(<4 x i32> %x) {
define i1 @and_ne_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @and_ne_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -159,7 +162,7 @@ define i1 @and_ne_max(<4 x i32> %x) {
define i1 @umin_eq_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umin_eq_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -172,7 +175,7 @@ define i1 @umin_eq_0(<4 x i32> %x) {
define i1 @umin_ne_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umin_ne_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -185,7 +188,7 @@ define i1 @umin_ne_0(<4 x i32> %x) {
define i1 @umin_eq_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umin_eq_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -198,7 +201,7 @@ define i1 @umin_eq_max(<4 x i32> %x) {
define i1 @umin_ne_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @umin_ne_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -211,7 +214,7 @@ define i1 @umin_ne_max(<4 x i32> %x) {
define i1 @add_eq_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @add_eq_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -224,7 +227,7 @@ define i1 @add_eq_0(<4 x i32> %x) {
define i1 @add_ne_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @add_ne_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -237,7 +240,7 @@ define i1 @add_ne_0(<4 x i32> %x) {
define i1 @add_eq_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @add_eq_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -250,7 +253,7 @@ define i1 @add_eq_max(<4 x i32> %x) {
define i1 @add_ne_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @add_ne_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -263,7 +266,7 @@ define i1 @add_ne_max(<4 x i32> %x) {
define i1 @add_ult_max(<4 x i32> %x) {
; CHECK-LABEL: define i1 @add_ult_max(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -276,7 +279,7 @@ define i1 @add_ult_max(<4 x i32> %x) {
define i1 @add_ugt_max_minus_1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @add_ugt_max_minus_1(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -289,7 +292,7 @@ define i1 @add_ugt_max_minus_1(<4 x i32> %x) {
define i1 @ashr_add_eq_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @ashr_add_eq_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -302,7 +305,7 @@ define i1 @ashr_add_eq_0(<4 x i32> %x) {
define i1 @or_eq_0_v8i16(<8 x i16> %x) {
; CHECK-LABEL: define i1 @or_eq_0_v8i16(
-; CHECK-SAME: <8 x i16> [[X:%.*]]) {
+; CHECK-SAME: <8 x i16> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.vector.reduce.umax.v8i16(<8 x i16> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[TMP1]], -1
; CHECK-NEXT: ret i1 [[CMP]]
@@ -314,11 +317,23 @@ define i1 @or_eq_0_v8i16(<8 x i16> %x) {
}
define i1 @and_eq_max_v2i64(<2 x i64> %x) {
-; CHECK-LABEL: define i1 @and_eq_max_v2i64(
-; CHECK-SAME: <2 x i64> [[X:%.*]]) {
-; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.and.v2i64(<2 x i64> [[X]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[TMP1]], 0
-; CHECK-NEXT: ret i1 [[CMP]]
+; SSE-LABEL: define i1 @and_eq_max_v2i64(
+; SSE-SAME: <2 x i64> [[X:%.*]]) #[[ATTR0]] {
+; SSE-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.and.v2i64(<2 x i64> [[X]])
+; SSE-NEXT: [[CMP:%.*]] = icmp slt i64 [[TMP1]], 0
+; SSE-NEXT: ret i1 [[CMP]]
+;
+; AVX2-LABEL: define i1 @and_eq_max_v2i64(
+; AVX2-SAME: <2 x i64> [[X:%.*]]) #[[ATTR0]] {
+; AVX2-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.and.v2i64(<2 x i64> [[X]])
+; AVX2-NEXT: [[CMP:%.*]] = icmp slt i64 [[TMP1]], 0
+; AVX2-NEXT: ret i1 [[CMP]]
+;
+; AVX512-LABEL: define i1 @and_eq_max_v2i64(
+; AVX512-SAME: <2 x i64> [[X:%.*]]) #[[ATTR0]] {
+; AVX512-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.umin.v2i64(<2 x i64> [[X]])
+; AVX512-NEXT: [[CMP:%.*]] = icmp slt i64 [[TMP1]], 0
+; AVX512-NEXT: ret i1 [[CMP]]
;
%shr = lshr <2 x i64> %x, splat (i64 63)
%red = call i64 @llvm.vector.reduce.and.v2i64(<2 x i64> %shr)
@@ -328,12 +343,33 @@ define i1 @and_eq_max_v2i64(<2 x i64> %x) {
; negative: shift amount is not bitwidth-1
define i1 @negative_wrong_shift(<4 x i32> %x) {
-; CHECK-LABEL: define i1 @negative_wrong_shift(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
-; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 30)
-; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
-; CHECK-NEXT: ret i1 [[CMP]]
+; SSE2-LABEL: define i1 @negative_wrong_shift(
+; SSE2-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
+; SSE2-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 30)
+; SSE2-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
+; SSE2-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
+; SSE2-NEXT: ret i1 [[CMP]]
+;
+; SSE4-LABEL: define i1 @negative_wrong_shift(
+; SSE4-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
+; SSE4-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 30)
+; SSE4-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[SHR]], zeroinitializer
+; SSE4-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
+; SSE4-NEXT: ret i1 [[CMP]]
+;
+; AVX2-LABEL: define i1 @negative_wrong_shift(
+; AVX2-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
+; AVX2-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 30)
+; AVX2-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[SHR]], zeroinitializer
+; AVX2-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
+; AVX2-NEXT: ret i1 [[CMP]]
+;
+; AVX512-LABEL: define i1 @negative_wrong_shift(
+; AVX512-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
+; AVX512-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 30)
+; AVX512-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[SHR]])
+; AVX512-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; AVX512-NEXT: ret i1 [[CMP]]
;
%shr = lshr <4 x i32> %x, splat (i32 30)
%red = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %shr)
@@ -344,7 +380,7 @@ define i1 @negative_wrong_shift(<4 x i32> %x) {
; negative: comparison constant is neither 0 nor max
define i1 @negative_wrong_cmp_const(<4 x i32> %x) {
; CHECK-LABEL: define i1 @negative_wrong_cmp_const(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 31)
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 2
@@ -358,13 +394,37 @@ define i1 @negative_wrong_cmp_const(<4 x i32> %x) {
; negative: shift has multiple uses
define i1 @negative_multi_use_shift(<4 x i32> %x, ptr %p) {
-; CHECK-LABEL: define i1 @negative_multi_use_shift(
-; CHECK-SAME: <4 x i32> [[X:%.*]], ptr [[P:%.*]]) {
-; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 31)
-; CHECK-NEXT: store <4 x i32> [[SHR]], ptr [[P]], align 16
-; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
-; CHECK-NEXT: ret i1 [[CMP]]
+; SSE2-LABEL: define i1 @negative_multi_use_shift(
+; SSE2-SAME: <4 x i32> [[X:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; SSE2-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 31)
+; SSE2-NEXT: store <4 x i32> [[SHR]], ptr [[P]], align 16
+; SSE2-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
+; SSE2-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
+; SSE2-NEXT: ret i1 [[CMP]]
+;
+; SSE4-LABEL: define i1 @negative_multi_use_shift(
+; SSE4-SAME: <4 x i32> [[X:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; SSE4-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 31)
+; SSE4-NEXT: store <4 x i32> [[SHR]], ptr [[P]], align 16
+; SSE4-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[SHR]], zeroinitializer
+; SSE4-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
+; SSE4-NEXT: ret i1 [[CMP]]
+;
+; AVX2-LABEL: define i1 @negative_multi_use_shift(
+; AVX2-SAME: <4 x i32> [[X:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; AVX2-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 31)
+; AVX2-NEXT: store <4 x i32> [[SHR]], ptr [[P]], align 16
+; AVX2-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[SHR]], zeroinitializer
+; AVX2-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
+; AVX2-NEXT: ret i1 [[CMP]]
+;
+; AVX512-LABEL: define i1 @negative_multi_use_shift(
+; AVX512-SAME: <4 x i32> [[X:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; AVX512-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 31)
+; AVX512-NEXT: store <4 x i32> [[SHR]], ptr [[P]], align 16
+; AVX512-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[SHR]])
+; AVX512-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; AVX512-NEXT: ret i1 [[CMP]]
;
%shr = lshr <4 x i32> %x, splat (i32 31)
store <4 x i32> %shr, ptr %p
@@ -376,7 +436,7 @@ define i1 @negative_multi_use_shift(<4 x i32> %x, ptr %p) {
; negative: sgt with wrong constant (not 0 or max-1)
define i1 @negative_sgt_wrong_const(<4 x i32> %x) {
; CHECK-LABEL: define i1 @negative_sgt_wrong_const(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 31)
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[RED]], 1
@@ -391,7 +451,7 @@ define i1 @negative_sgt_wrong_const(<4 x i32> %x) {
; negative: slt with wrong constant (not 1 or max)
define i1 @negative_slt_wrong_const(<4 x i32> %x) {
; CHECK-LABEL: define i1 @negative_slt_wrong_const(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i32> [[X]], splat (i32 31)
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[RED]], 2
@@ -406,7 +466,7 @@ define i1 @negative_slt_wrong_const(<4 x i32> %x) {
; negative: if reduce.add can wrap, transformation is incorrect
define i1 @negative_add_numelts_overflow(<8 x i2> %x) {
; CHECK-LABEL: define i1 @negative_add_numelts_overflow(
-; CHECK-SAME: <8 x i2> [[X:%.*]]) {
+; CHECK-SAME: <8 x i2> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <8 x i2> [[X]], splat (i2 1)
; CHECK-NEXT: [[RED:%.*]] = call i2 @llvm.vector.reduce.add.v8i2(<8 x i2> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i2 [[RED]], 0
@@ -420,7 +480,7 @@ define i1 @negative_add_numelts_overflow(<8 x i2> %x) {
define i1 @ashr_add_eq_allneg(<4 x i32> %x) {
; CHECK-LABEL: define i1 @ashr_add_eq_allneg(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -433,7 +493,7 @@ define i1 @ashr_add_eq_allneg(<4 x i32> %x) {
define i1 @ashr_add_ne_allneg(<4 x i32> %x) {
; CHECK-LABEL: define i1 @ashr_add_ne_allneg(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -446,7 +506,7 @@ define i1 @ashr_add_ne_allneg(<4 x i32> %x) {
define i1 @ashr_add_sgt_minus1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @ashr_add_sgt_minus1(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -459,7 +519,7 @@ define i1 @ashr_add_sgt_minus1(<4 x i32> %x) {
define i1 @ashr_add_slt_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @ashr_add_slt_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -472,7 +532,7 @@ define i1 @ashr_add_slt_0(<4 x i32> %x) {
define i1 @ashr_add_slt_minus3(<4 x i32> %x) {
; CHECK-LABEL: define i1 @ashr_add_slt_minus3(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -485,7 +545,7 @@ define i1 @ashr_add_slt_minus3(<4 x i32> %x) {
define i1 @ashr_add_sgt_minus4(<4 x i32> %x) {
; CHECK-LABEL: define i1 @ashr_add_sgt_minus4(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; 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]]
@@ -498,7 +558,7 @@ define i1 @ashr_add_sgt_minus4(<4 x i32> %x) {
define i1 @ashr_add_eq_allneg_v8i16(<8 x i16> %x) {
; CHECK-LABEL: define i1 @ashr_add_eq_allneg_v8i16(
-; CHECK-SAME: <8 x i16> [[X:%.*]]) {
+; CHECK-SAME: <8 x i16> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.vector.reduce.umin.v8i16(<8 x i16> [[X]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[TMP1]], 0
; CHECK-NEXT: ret i1 [[CMP]]
@@ -512,7 +572,7 @@ define i1 @ashr_add_eq_allneg_v8i16(<8 x i16> %x) {
; negative: NumElts=2 doesn't fit as signed in i2
define i1 @add_eq_0_v2i2(<2 x i2> %x) {
; CHECK-LABEL: define i1 @add_eq_0_v2i2(
-; CHECK-SAME: <2 x i2> [[X:%.*]]) {
+; CHECK-SAME: <2 x i2> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <2 x i2> [[X]], splat (i2 1)
; CHECK-NEXT: [[RED:%.*]] = call i2 @llvm.vector.reduce.add.v2i2(<2 x i2> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i2 [[RED]], 0
@@ -527,7 +587,7 @@ define i1 @add_eq_0_v2i2(<2 x i2> %x) {
; negative: NumElts=3 doesn't fit as signed in i2
define i1 @add_eq_max_v3i2(<3 x i2> %x) {
; CHECK-LABEL: define i1 @add_eq_max_v3i2(
-; CHECK-SAME: <3 x i2> [[X:%.*]]) {
+; CHECK-SAME: <3 x i2> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <3 x i2> [[X]], splat (i2 1)
; CHECK-NEXT: [[RED:%.*]] = call i2 @llvm.vector.reduce.add.v3i2(<3 x i2> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i2 [[RED]], -1
@@ -541,7 +601,7 @@ define i1 @add_eq_max_v3i2(<3 x i2> %x) {
define i1 @negative_add_v4i2(<4 x i2> %x) {
; CHECK-LABEL: define i1 @negative_add_v4i2(
-; CHECK-SAME: <4 x i2> [[X:%.*]]) {
+; CHECK-SAME: <4 x i2> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i2> [[X]], splat (i2 1)
; CHECK-NEXT: [[RED:%.*]] = call i2 @llvm.vector.reduce.add.v4i2(<4 x i2> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i2 [[RED]], 0
@@ -556,7 +616,7 @@ define i1 @negative_add_v4i2(<4 x i2> %x) {
; negative: ashr with NumElts=5 causes -5 to wrap to 3 (positive),
define i1 @negative_ashr_add_sgt_0(<5 x i3> %x) {
; CHECK-LABEL: define i1 @negative_ashr_add_sgt_0(
-; CHECK-SAME: <5 x i3> [[X:%.*]]) {
+; CHECK-SAME: <5 x i3> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = ashr <5 x i3> [[X]], splat (i3 2)
; CHECK-NEXT: [[RED:%.*]] = call i3 @llvm.vector.reduce.add.v5i3(<5 x i3> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i3 [[RED]], 0
@@ -570,7 +630,7 @@ define i1 @negative_ashr_add_sgt_0(<5 x i3> %x) {
define i1 @i1_or_eq_0(<4 x i1> %x) {
; CHECK-LABEL: define i1 @i1_or_eq_0(
-; CHECK-SAME: <4 x i1> [[X:%.*]]) {
+; CHECK-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i1> [[SHR]], zeroinitializer
; CHECK-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
@@ -583,12 +643,25 @@ define i1 @i1_or_eq_0(<4 x i1> %x) {
}
define i1 @i1_or_ne_0(<4 x i1> %x) {
-; CHECK-LABEL: define i1 @i1_or_ne_0(
-; CHECK-SAME: <4 x i1> [[X:%.*]]) {
-; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
-; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[SHR]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp ne i1 [[RED]], false
-; CHECK-NEXT: ret i1 [[CMP]]
+; SSE-LABEL: define i1 @i1_or_ne_0(
+; SSE-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
+; SSE-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
+; SSE-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[SHR]])
+; SSE-NEXT: [[CMP:%.*]] = icmp ne i1 [[RED]], false
+; SSE-NEXT: ret i1 [[CMP]]
+;
+; AVX2-LABEL: define i1 @i1_or_ne_0(
+; AVX2-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
+; AVX2-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
+; AVX2-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[SHR]])
+; AVX2-NEXT: [[CMP:%.*]] = icmp ne i1 [[RED]], false
+; AVX2-NEXT: ret i1 [[CMP]]
+;
+; AVX512-LABEL: define i1 @i1_or_ne_0(
+; AVX512-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
+; AVX512-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
+; AVX512-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> [[SHR]])
+; AVX512-NEXT: ret i1 [[CMP]]
;
%shr = lshr <4 x i1> %x, splat (i1 0)
%red = call i1 @llvm.vector.reduce.or.v4i1(<4 x i1> %shr)
@@ -598,7 +671,7 @@ define i1 @i1_or_ne_0(<4 x i1> %x) {
define i1 @i1_and_eq_0(<4 x i1> %x) {
; CHECK-LABEL: define i1 @i1_and_eq_0(
-; CHECK-SAME: <4 x i1> [[X:%.*]]) {
+; CHECK-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1 [[RED]], false
@@ -612,7 +685,7 @@ define i1 @i1_and_eq_0(<4 x i1> %x) {
define i1 @i1_and_ne_0(<4 x i1> %x) {
; CHECK-LABEL: define i1 @i1_and_ne_0(
-; CHECK-SAME: <4 x i1> [[X:%.*]]) {
+; CHECK-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i1 [[RED]], false
@@ -626,7 +699,7 @@ define i1 @i1_and_ne_0(<4 x i1> %x) {
define i1 @i1_umax_eq_0(<4 x i1> %x) {
; CHECK-LABEL: define i1 @i1_umax_eq_0(
-; CHECK-SAME: <4 x i1> [[X:%.*]]) {
+; CHECK-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i1> [[SHR]], zeroinitializer
; CHECK-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
@@ -639,11 +712,24 @@ define i1 @i1_umax_eq_0(<4 x i1> %x) {
}
define i1 @i1_umin_ne_0(<4 x i1> %x) {
-; CHECK-LABEL: define i1 @i1_umin_ne_0(
-; CHECK-SAME: <4 x i1> [[X:%.*]]) {
-; CHECK-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
-; CHECK-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[SHR]])
-; CHECK-NEXT: ret i1 [[CMP]]
+; SSE-LABEL: define i1 @i1_umin_ne_0(
+; SSE-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
+; SSE-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
+; SSE-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[SHR]])
+; SSE-NEXT: ret i1 [[CMP]]
+;
+; AVX2-LABEL: define i1 @i1_umin_ne_0(
+; AVX2-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
+; AVX2-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
+; AVX2-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.umin.v4i1(<4 x i1> [[SHR]])
+; AVX2-NEXT: [[CMP:%.*]] = icmp ne i1 [[RED]], false
+; AVX2-NEXT: ret i1 [[CMP]]
+;
+; AVX512-LABEL: define i1 @i1_umin_ne_0(
+; AVX512-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
+; AVX512-NEXT: [[SHR:%.*]] = lshr <4 x i1> [[X]], zeroinitializer
+; AVX512-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[SHR]])
+; AVX512-NEXT: ret i1 [[CMP]]
;
%shr = lshr <4 x i1> %x, splat (i1 0)
%red = call i1 @llvm.vector.reduce.umin.v4i1(<4 x i1> %shr)
@@ -653,7 +739,7 @@ define i1 @i1_umin_ne_0(<4 x i1> %x) {
define i1 @i1_ashr_or_eq_0(<4 x i1> %x) {
; CHECK-LABEL: define i1 @i1_ashr_or_eq_0(
-; CHECK-SAME: <4 x i1> [[X:%.*]]) {
+; CHECK-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i1> [[X]], zeroinitializer
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <4 x i1> [[SHR]], zeroinitializer
; CHECK-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
@@ -667,7 +753,7 @@ define i1 @i1_ashr_or_eq_0(<4 x i1> %x) {
define i1 @i1_ashr_and_ne_0(<4 x i1> %x) {
; CHECK-LABEL: define i1 @i1_ashr_and_ne_0(
-; CHECK-SAME: <4 x i1> [[X:%.*]]) {
+; CHECK-SAME: <4 x i1> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i1> [[X]], zeroinitializer
; CHECK-NEXT: [[RED:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i1 [[RED]], false
@@ -681,7 +767,7 @@ define i1 @i1_ashr_and_ne_0(<4 x i1> %x) {
define i1 @negative_ashr_add_ult_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @negative_ashr_add_ult_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i32> [[X]], splat (i32 31)
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[RED]], 0
@@ -695,7 +781,7 @@ define i1 @negative_ashr_add_ult_0(<4 x i32> %x) {
define i1 @negative_ashr_add_ugt_minus1(<4 x i32> %x) {
; CHECK-LABEL: define i1 @negative_ashr_add_ugt_minus1(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i32> [[X]], splat (i32 31)
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[RED]], -1
@@ -709,7 +795,7 @@ define i1 @negative_ashr_add_ugt_minus1(<4 x i32> %x) {
define i1 @negative_ashr_add_ult_minus3(<4 x i32> %x) {
; CHECK-LABEL: define i1 @negative_ashr_add_ult_minus3(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i32> [[X]], splat (i32 31)
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[RED]], -3
@@ -723,7 +809,7 @@ define i1 @negative_ashr_add_ult_minus3(<4 x i32> %x) {
define i1 @negative_ashr_or_ult_0(<4 x i32> %x) {
; CHECK-LABEL: define i1 @negative_ashr_or_ult_0(
-; CHECK-SAME: <4 x i32> [[X:%.*]]) {
+; CHECK-SAME: <4 x i32> [[X:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SHR:%.*]] = ashr <4 x i32> [[X]], splat (i32 31)
; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[SHR]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[RED]], 0
@@ -737,7 +823,7 @@ define i1 @negative_ashr_or_ult_0(<4 x i32> %x) {
define i1 @multi_add_lshr_eq_0(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_add_lshr_eq_0(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = or <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], -1
@@ -753,7 +839,7 @@ define i1 @multi_add_lshr_eq_0(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_add_lshr_ne_0(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_add_lshr_ne_0(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = or <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP2]], 0
@@ -769,7 +855,7 @@ define i1 @multi_add_lshr_ne_0(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_add_lshr_eq_8(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_add_lshr_eq_8(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP2]], 0
@@ -785,7 +871,7 @@ define i1 @multi_add_lshr_eq_8(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_add_lshr_ne_8(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_add_lshr_ne_8(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], -1
@@ -801,7 +887,7 @@ define i1 @multi_add_lshr_ne_8(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_or_lshr_eq_0(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_or_lshr_eq_0(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = or <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], -1
@@ -817,7 +903,7 @@ define i1 @multi_or_lshr_eq_0(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_and_lshr_eq_1(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_and_lshr_eq_1(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP2]], 0
@@ -833,7 +919,7 @@ define i1 @multi_and_lshr_eq_1(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_triple_add_lshr_eq_0(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
; CHECK-LABEL: define i1 @multi_triple_add_lshr_eq_0(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = or <4 x i32> [[C]], [[B]]
; CHECK-NEXT: [[TMP2:%.*]] = or <4 x i32> [[TMP1]], [[A]]
; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP2]])
@@ -852,7 +938,7 @@ define i1 @multi_triple_add_lshr_eq_0(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c)
define i1 @multi_triple_add_lshr_eq_12(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
; CHECK-LABEL: define i1 @multi_triple_add_lshr_eq_12(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[C]], [[B]]
; CHECK-NEXT: [[TMP2:%.*]] = and <4 x i32> [[TMP1]], [[A]]
; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[TMP2]])
@@ -871,7 +957,7 @@ define i1 @multi_triple_add_lshr_eq_12(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c)
define i1 @multi_add_ashr_eq_0(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_add_ashr_eq_0(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = or <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], -1
@@ -887,7 +973,7 @@ define i1 @multi_add_ashr_eq_0(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_add_ashr_eq_minus8(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_add_ashr_eq_minus8(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP2]], 0
@@ -903,7 +989,7 @@ define i1 @multi_add_ashr_eq_minus8(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_add_ashr_sgt_minus1(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_add_ashr_sgt_minus1(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = or <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], -1
@@ -919,7 +1005,7 @@ define i1 @multi_add_ashr_sgt_minus1(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_add_ashr_slt_minus7(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_add_ashr_slt_minus7(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP2]], 0
@@ -935,7 +1021,7 @@ define i1 @multi_add_ashr_slt_minus7(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_umax_or_tree_eq_0(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_umax_or_tree_eq_0(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = or <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP2]], -1
@@ -951,7 +1037,7 @@ define i1 @multi_umax_or_tree_eq_0(<4 x i32> %a, <4 x i32> %b) {
define i1 @multi_umin_and_tree_eq_1(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @multi_umin_and_tree_eq_1(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = and <4 x i32> [[B]], [[A]]
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.umin.v4i32(<4 x i32> [[TMP1]])
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP2]], 0
@@ -968,7 +1054,7 @@ define i1 @multi_umin_and_tree_eq_1(<4 x i32> %a, <4 x i32> %b) {
; negative: mixed lshr/ashr shifts
define i1 @negative_multi_mixed_shifts(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @negative_multi_mixed_shifts(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
; CHECK-NEXT: [[SB:%.*]] = ashr <4 x i32> [[B]], splat (i32 31)
; CHECK-NEXT: [[SUM:%.*]] = add <4 x i32> [[SA]], [[SB]]
@@ -987,7 +1073,7 @@ define i1 @negative_multi_mixed_shifts(<4 x i32> %a, <4 x i32> %b) {
; negative: overflow with two vectors (2*8 = 16 > max for i2)
define i1 @negative_multi_overflow(<8 x i2> %a, <8 x i2> %b) {
; CHECK-LABEL: define i1 @negative_multi_overflow(
-; CHECK-SAME: <8 x i2> [[A:%.*]], <8 x i2> [[B:%.*]]) {
+; CHECK-SAME: <8 x i2> [[A:%.*]], <8 x i2> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SA:%.*]] = lshr <8 x i2> [[A]], splat (i2 1)
; CHECK-NEXT: [[SB:%.*]] = lshr <8 x i2> [[B]], splat (i2 1)
; CHECK-NEXT: [[SUM:%.*]] = add <8 x i2> [[SA]], [[SB]]
@@ -1005,15 +1091,45 @@ define i1 @negative_multi_overflow(<8 x i2> %a, <8 x i2> %b) {
; negative: shift has multiple uses
define i1 @negative_multi_shift_multiuse(<4 x i32> %a, <4 x i32> %b, ptr %p) {
-; CHECK-LABEL: define i1 @negative_multi_shift_multiuse(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], ptr [[P:%.*]]) {
-; CHECK-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
-; CHECK-NEXT: store <4 x i32> [[SA]], ptr [[P]], align 16
-; CHECK-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
-; CHECK-NEXT: [[SUM:%.*]] = add <4 x i32> [[SA]], [[SB]]
-; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SUM]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
-; CHECK-NEXT: ret i1 [[CMP]]
+; SSE2-LABEL: define i1 @negative_multi_shift_multiuse(
+; SSE2-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; SSE2-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
+; SSE2-NEXT: store <4 x i32> [[SA]], ptr [[P]], align 16
+; SSE2-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
+; SSE2-NEXT: [[SUM:%.*]] = add <4 x i32> [[SA]], [[SB]]
+; SSE2-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[SUM]])
+; SSE2-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
+; SSE2-NEXT: ret i1 [[CMP]]
+;
+; SSE4-LABEL: define i1 @negative_multi_shift_multiuse(
+; SSE4-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; SSE4-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
+; SSE4-NEXT: store <4 x i32> [[SA]], ptr [[P]], align 16
+; SSE4-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
+; SSE4-NEXT: [[SUM:%.*]] = add <4 x i32> [[SA]], [[SB]]
+; SSE4-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[SUM]], zeroinitializer
+; SSE4-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
+; SSE4-NEXT: ret i1 [[CMP]]
+;
+; AVX2-LABEL: define i1 @negative_multi_shift_multiuse(
+; AVX2-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; AVX2-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
+; AVX2-NEXT: store <4 x i32> [[SA]], ptr [[P]], align 16
+; AVX2-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
+; AVX2-NEXT: [[SUM:%.*]] = add <4 x i32> [[SA]], [[SB]]
+; AVX2-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[SUM]], zeroinitializer
+; AVX2-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
+; AVX2-NEXT: ret i1 [[CMP]]
+;
+; AVX512-LABEL: define i1 @negative_multi_shift_multiuse(
+; AVX512-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; AVX512-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
+; AVX512-NEXT: store <4 x i32> [[SA]], ptr [[P]], align 16
+; AVX512-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
+; AVX512-NEXT: [[SUM:%.*]] = add <4 x i32> [[SA]], [[SB]]
+; AVX512-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[SUM]])
+; AVX512-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; AVX512-NEXT: ret i1 [[CMP]]
;
%sa = lshr <4 x i32> %a, splat (i32 31)
store <4 x i32> %sa, ptr %p
@@ -1024,19 +1140,55 @@ define i1 @negative_multi_shift_multiuse(<4 x i32> %a, <4 x i32> %b, ptr %p) {
ret i1 %cmp
}
-; negative: internal tree node has multiple uses
+; negative: internal tree node has multiple uses (cost driven)
define i1 @negative_multi_tree_node_multiuse(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c, ptr %p) {
-; CHECK-LABEL: define i1 @negative_multi_tree_node_multiuse(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]], ptr [[P:%.*]]) {
-; CHECK-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
-; CHECK-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
-; CHECK-NEXT: [[SC:%.*]] = lshr <4 x i32> [[C]], splat (i32 31)
-; CHECK-NEXT: [[AB:%.*]] = add <4 x i32> [[SA]], [[SB]]
-; CHECK-NEXT: store <4 x i32> [[AB]], ptr [[P]], align 16
-; CHECK-NEXT: [[ABC:%.*]] = add <4 x i32> [[AB]], [[SC]]
-; CHECK-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[ABC]])
-; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
-; CHECK-NEXT: ret i1 [[CMP]]
+; SSE2-LABEL: define i1 @negative_multi_tree_node_multiuse(
+; SSE2-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; SSE2-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
+; SSE2-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
+; SSE2-NEXT: [[SC:%.*]] = lshr <4 x i32> [[C]], splat (i32 31)
+; SSE2-NEXT: [[AB:%.*]] = add <4 x i32> [[SA]], [[SB]]
+; SSE2-NEXT: store <4 x i32> [[AB]], ptr [[P]], align 16
+; SSE2-NEXT: [[ABC:%.*]] = add <4 x i32> [[AB]], [[SC]]
+; SSE2-NEXT: [[RED:%.*]] = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> [[ABC]])
+; SSE2-NEXT: [[CMP:%.*]] = icmp eq i32 [[RED]], 0
+; SSE2-NEXT: ret i1 [[CMP]]
+;
+; SSE4-LABEL: define i1 @negative_multi_tree_node_multiuse(
+; SSE4-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; SSE4-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
+; SSE4-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
+; SSE4-NEXT: [[SC:%.*]] = lshr <4 x i32> [[C]], splat (i32 31)
+; SSE4-NEXT: [[AB:%.*]] = add <4 x i32> [[SA]], [[SB]]
+; SSE4-NEXT: store <4 x i32> [[AB]], ptr [[P]], align 16
+; SSE4-NEXT: [[ABC:%.*]] = add <4 x i32> [[AB]], [[SC]]
+; SSE4-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[ABC]], zeroinitializer
+; SSE4-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
+; SSE4-NEXT: ret i1 [[CMP]]
+;
+; AVX2-LABEL: define i1 @negative_multi_tree_node_multiuse(
+; AVX2-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; AVX2-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
+; AVX2-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
+; AVX2-NEXT: [[SC:%.*]] = lshr <4 x i32> [[C]], splat (i32 31)
+; AVX2-NEXT: [[AB:%.*]] = add <4 x i32> [[SA]], [[SB]]
+; AVX2-NEXT: store <4 x i32> [[AB]], ptr [[P]], align 16
+; AVX2-NEXT: [[ABC:%.*]] = add <4 x i32> [[AB]], [[SC]]
+; AVX2-NEXT: [[TMP1:%.*]] = icmp eq <4 x i32> [[ABC]], zeroinitializer
+; AVX2-NEXT: [[CMP:%.*]] = call i1 @llvm.vector.reduce.and.v4i1(<4 x i1> [[TMP1]])
+; AVX2-NEXT: ret i1 [[CMP]]
+;
+; AVX512-LABEL: define i1 @negative_multi_tree_node_multiuse(
+; AVX512-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i32> [[C:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; AVX512-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
+; AVX512-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
+; AVX512-NEXT: [[SC:%.*]] = lshr <4 x i32> [[C]], splat (i32 31)
+; AVX512-NEXT: [[AB:%.*]] = add <4 x i32> [[SA]], [[SB]]
+; AVX512-NEXT: store <4 x i32> [[AB]], ptr [[P]], align 16
+; AVX512-NEXT: [[ABC:%.*]] = add <4 x i32> [[AB]], [[SC]]
+; AVX512-NEXT: [[TMP1:%.*]] = call i32 @llvm.vector.reduce.umax.v4i32(<4 x i32> [[ABC]])
+; AVX512-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
+; AVX512-NEXT: ret i1 [[CMP]]
;
%sa = lshr <4 x i32> %a, splat (i32 31)
%sb = lshr <4 x i32> %b, splat (i32 31)
@@ -1052,7 +1204,7 @@ define i1 @negative_multi_tree_node_multiuse(<4 x i32> %a, <4 x i32> %b, <4 x i3
; negative: tree op (add) doesn't match reduction (or/umax expects or tree)
define i1 @negative_multi_op_mismatch(<4 x i32> %a, <4 x i32> %b) {
; CHECK-LABEL: define i1 @negative_multi_op_mismatch(
-; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) {
+; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[SA:%.*]] = lshr <4 x i32> [[A]], splat (i32 31)
; CHECK-NEXT: [[SB:%.*]] = lshr <4 x i32> [[B]], splat (i32 31)
; CHECK-NEXT: [[SUM:%.*]] = add <4 x i32> [[SA]], [[SB]]
@@ -1067,3 +1219,5 @@ define i1 @negative_multi_op_mismatch(<4 x i32> %a, <4 x i32> %b) {
%cmp = icmp eq i32 %red, 0
ret i1 %cmp
}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; AVX: {{.*}}
More information about the llvm-commits
mailing list