| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 |
| ; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=sse2 | FileCheck %s |
| ; RUN: opt < %s -passes=vector-combine -S -mtriple=x86_64-- -mattr=avx2 | FileCheck %s |
| |
| ; Fold "shuffle (binop (shuffle, shuffle)), undef" --> "binop (shuffle), (shuffle)" |
| |
| declare void @use_v4f64(<4 x double>) |
| |
| define <4 x double> @fadd_v4f64(<4 x double> %a, <4 x double> %b) { |
| ; CHECK-LABEL: define <4 x double> @fadd_v4f64( |
| ; CHECK-SAME: <4 x double> [[A:%.*]], <4 x double> [[B:%.*]]) #[[ATTR0:[0-9]+]] { |
| ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[A]], <4 x double> poison, <4 x i32> <i32 2, i32 3, i32 0, i32 1> |
| ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x double> [[B]], <4 x double> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1> |
| ; CHECK-NEXT: [[POST:%.*]] = fadd <4 x double> [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret <4 x double> [[POST]] |
| ; |
| %a1 = shufflevector <4 x double> %a, <4 x double> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| %b1 = shufflevector <4 x double> %b, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| %op = fadd <4 x double> %a1, %b1 |
| %post = shufflevector <4 x double> %op, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> |
| ret <4 x double> %post |
| } |
| |
| define <4 x double> @fadd_v4f64_poison_idx(<4 x double> %a, <4 x double> %b) { |
| ; CHECK-LABEL: define <4 x double> @fadd_v4f64_poison_idx( |
| ; CHECK-SAME: <4 x double> [[A:%.*]], <4 x double> [[B:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[A]], <4 x double> poison, <4 x i32> <i32 2, i32 3, i32 0, i32 poison> |
| ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x double> [[B]], <4 x double> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 poison> |
| ; CHECK-NEXT: [[POST:%.*]] = fadd <4 x double> [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret <4 x double> [[POST]] |
| ; |
| %a1 = shufflevector <4 x double> %a, <4 x double> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| %b1 = shufflevector <4 x double> %b, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| %op = fadd <4 x double> %a1, %b1 |
| %post = shufflevector <4 x double> %op, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 4> |
| ret <4 x double> %post |
| } |
| |
| define <4 x double> @fadd_v4f64_mixed_types(<4 x double> %a, <2 x double> %b) { |
| ; CHECK-LABEL: define <4 x double> @fadd_v4f64_mixed_types( |
| ; CHECK-SAME: <4 x double> [[A:%.*]], <2 x double> [[B:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[A]], <4 x double> poison, <4 x i32> <i32 2, i32 3, i32 0, i32 1> |
| ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <2 x double> [[B]], <2 x double> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1> |
| ; CHECK-NEXT: [[POST:%.*]] = fadd <4 x double> [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret <4 x double> [[POST]] |
| ; |
| %a1 = shufflevector <4 x double> %a, <4 x double> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| %b1 = shufflevector <2 x double> %b, <2 x double> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| %op = fadd <4 x double> %a1, %b1 |
| %post = shufflevector <4 x double> %op, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> |
| ret <4 x double> %post |
| } |
| |
| define <4 x float> @fadd_v4f32_mixed_types(<4 x float> %a0) { |
| ; CHECK-LABEL: define <4 x float> @fadd_v4f32_mixed_types( |
| ; CHECK-SAME: <4 x float> [[A0:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[A0]], <4 x float> zeroinitializer, <4 x i32> <i32 1, i32 5, i32 poison, i32 poison> |
| ; CHECK-NEXT: [[POST:%.*]] = fmul <4 x float> [[TMP1]], <float 0.000000e+00, float 0.000000e+00, float undef, float undef> |
| ; CHECK-NEXT: ret <4 x float> [[POST]] |
| ; |
| %pre = shufflevector <4 x float> %a0, <4 x float> zeroinitializer, <2 x i32> <i32 1, i32 5> |
| %op = fmul <2 x float> %pre, zeroinitializer |
| %post = shufflevector <2 x float> %op, <2 x float> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison> |
| ret <4 x float> %post |
| } |
| |
| ; Negative test - multiple use of fadd |
| define <4 x double> @fadd_v4f64_multiuse_op(<4 x double> %a, <4 x double> %b) { |
| ; CHECK-LABEL: define <4 x double> @fadd_v4f64_multiuse_op( |
| ; CHECK-SAME: <4 x double> [[A:%.*]], <4 x double> [[B:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[A1:%.*]] = shufflevector <4 x double> [[A]], <4 x double> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| ; CHECK-NEXT: [[B1:%.*]] = shufflevector <4 x double> [[B]], <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| ; CHECK-NEXT: [[OP:%.*]] = fadd <4 x double> [[A1]], [[B1]] |
| ; CHECK-NEXT: [[POST:%.*]] = shufflevector <4 x double> [[OP]], <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> |
| ; CHECK-NEXT: call void @use_v4f64(<4 x double> [[OP]]) |
| ; CHECK-NEXT: ret <4 x double> [[POST]] |
| ; |
| %a1 = shufflevector <4 x double> %a, <4 x double> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| %b1 = shufflevector <4 x double> %b, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| %op = fadd <4 x double> %a1, %b1 |
| %post = shufflevector <4 x double> %op, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> |
| call void @use_v4f64(<4 x double> %op) |
| ret <4 x double> %post |
| } |
| |
| define <4 x double> @fadd_v4f64_multiuse_shuffle(<4 x double> %a, <4 x double> %b) { |
| ; CHECK-LABEL: define <4 x double> @fadd_v4f64_multiuse_shuffle( |
| ; CHECK-SAME: <4 x double> [[A:%.*]], <4 x double> [[B:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[A1:%.*]] = shufflevector <4 x double> [[A]], <4 x double> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x double> [[A]], <4 x double> poison, <4 x i32> <i32 2, i32 3, i32 0, i32 1> |
| ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x double> [[B]], <4 x double> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1> |
| ; CHECK-NEXT: [[POST:%.*]] = fadd <4 x double> [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: call void @use_v4f64(<4 x double> [[A1]]) |
| ; CHECK-NEXT: ret <4 x double> [[POST]] |
| ; |
| %a1 = shufflevector <4 x double> %a, <4 x double> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| %b1 = shufflevector <4 x double> %b, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| %op = fadd <4 x double> %a1, %b1 |
| %post = shufflevector <4 x double> %op, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2> |
| call void @use_v4f64(<4 x double> %a1) |
| ret <4 x double> %post |
| } |
| |
| define <4 x i32> @sdiv_v4i32(<4 x i32> %a, <4 x i32> %b) { |
| ; CHECK-LABEL: define <4 x i32> @sdiv_v4i32( |
| ; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> poison, <4 x i32> <i32 2, i32 3, i32 0, i32 3> |
| ; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 1> |
| ; CHECK-NEXT: [[POST:%.*]] = sdiv <4 x i32> [[TMP1]], [[TMP2]] |
| ; CHECK-NEXT: ret <4 x i32> [[POST]] |
| ; |
| %a1 = shufflevector <4 x i32> %a, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| %b1 = shufflevector <4 x i32> %b, <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| %op = sdiv <4 x i32> %a1, %b1 |
| %post = shufflevector <4 x i32> %op, <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 0> |
| ret <4 x i32> %post |
| } |
| |
| ; Negative test - don't introduce poison element into div/rem instruction |
| define <4 x i32> @sdiv_v4i32_poison(<4 x i32> %a, <4 x i32> %b) { |
| ; CHECK-LABEL: define <4 x i32> @sdiv_v4i32_poison( |
| ; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[A1:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| ; CHECK-NEXT: [[B1:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| ; CHECK-NEXT: [[OP:%.*]] = sdiv <4 x i32> [[A1]], [[B1]] |
| ; CHECK-NEXT: [[POST:%.*]] = shufflevector <4 x i32> [[OP]], <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 poison> |
| ; CHECK-NEXT: ret <4 x i32> [[POST]] |
| ; |
| %a1 = shufflevector <4 x i32> %a, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| %b1 = shufflevector <4 x i32> %b, <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| %op = sdiv <4 x i32> %a1, %b1 |
| %post = shufflevector <4 x i32> %op, <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 poison> |
| ret <4 x i32> %post |
| } |
| |
| ; Negative test - don't introduce poison element into div/rem instruction |
| define <4 x i32> @sdiv_v4i32_poison_idx(<4 x i32> %a, <4 x i32> %b) { |
| ; CHECK-LABEL: define <4 x i32> @sdiv_v4i32_poison_idx( |
| ; CHECK-SAME: <4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) #[[ATTR0]] { |
| ; CHECK-NEXT: [[A1:%.*]] = shufflevector <4 x i32> [[A]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| ; CHECK-NEXT: [[B1:%.*]] = shufflevector <4 x i32> [[B]], <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| ; CHECK-NEXT: [[OP:%.*]] = sdiv <4 x i32> [[A1]], [[B1]] |
| ; CHECK-NEXT: [[POST:%.*]] = shufflevector <4 x i32> [[OP]], <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 4> |
| ; CHECK-NEXT: ret <4 x i32> [[POST]] |
| ; |
| %a1 = shufflevector <4 x i32> %a, <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0> |
| %b1 = shufflevector <4 x i32> %b, <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 1, i32 0> |
| %op = sdiv <4 x i32> %a1, %b1 |
| %post = shufflevector <4 x i32> %op, <4 x i32> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 4> |
| ret <4 x i32> %post |
| } |