| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=aarch64 | FileCheck %s --check-prefixes=CHECK |
| |
| define <1 x float> @dup_v1i32_oeq(float %a, float %b) { |
| ; CHECK-LABEL: dup_v1i32_oeq: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmeq s0, s0, s1 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan oeq float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_ogt(float %a, float %b) { |
| ; CHECK-LABEL: dup_v1i32_ogt: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmgt s0, s0, s1 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ogt float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_oge(float %a, float %b) { |
| ; CHECK-LABEL: dup_v1i32_oge: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmge s0, s0, s1 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan oge float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_olt(float %a, float %b) { |
| ; CHECK-LABEL: dup_v1i32_olt: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmgt s0, s1, s0 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan olt float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_ole(float %a, float %b) { |
| ; CHECK-LABEL: dup_v1i32_ole: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmge s0, s1, s0 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ole float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_one(float %a, float %b) { |
| ; |
| ; |
| ; CHECK-LABEL: dup_v1i32_one: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmeq s0, s0, s1 |
| ; CHECK-NEXT: mvn v0.8b, v0.8b |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan one float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_ord(float %a, float %b) { |
| ; CHECK-LABEL: dup_v1i32_ord: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmge s2, s0, s1 |
| ; CHECK-NEXT: fcmgt s0, s1, s0 |
| ; CHECK-NEXT: orr v0.16b, v0.16b, v2.16b |
| ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ord float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_ueq(float %a, float %b) { |
| ; |
| ; |
| ; CHECK-LABEL: dup_v1i32_ueq: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmeq s0, s0, s1 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ueq float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_ugt(float %a, float %b) { |
| ; |
| ; |
| ; CHECK-LABEL: dup_v1i32_ugt: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmgt s0, s0, s1 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ugt float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_uge(float %a, float %b) { |
| ; |
| ; |
| ; CHECK-LABEL: dup_v1i32_uge: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmge s0, s0, s1 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan uge float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_ult(float %a, float %b) { |
| ; |
| ; |
| ; CHECK-LABEL: dup_v1i32_ult: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmgt s0, s1, s0 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ult float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_ule(float %a, float %b) { |
| ; |
| ; |
| ; CHECK-LABEL: dup_v1i32_ule: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmge s0, s1, s0 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ule float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_une(float %a, float %b) { |
| ; CHECK-LABEL: dup_v1i32_une: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmeq s0, s0, s1 |
| ; CHECK-NEXT: mvn v0.8b, v0.8b |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan une float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <1 x float> @dup_v1i32_uno(float %a, float %b) { |
| ; CHECK-LABEL: dup_v1i32_uno: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmge s2, s0, s1 |
| ; CHECK-NEXT: fcmgt s0, s1, s0 |
| ; CHECK-NEXT: orr v0.16b, v0.16b, v2.16b |
| ; CHECK-NEXT: mvn v0.8b, v0.8b |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan uno float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <1 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <1 x i32> %vecinit.i to <1 x float> |
| ret <1 x float> %1 |
| } |
| |
| define <4 x float> @dup_v4i32(float %a, float %b) { |
| ; CHECK-LABEL: dup_v4i32: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmge s0, s0, s1 |
| ; CHECK-NEXT: dup v0.4s, v0.s[0] |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan oge float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <4 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <4 x i32> %vecinit.i to <4 x float> |
| %2 = shufflevector <4 x float> %1, <4 x float> poison, <4 x i32> zeroinitializer |
| ret <4 x float> %2 |
| } |
| |
| define <4 x float> @dup_v4i32_reversed(float %a, float %b) { |
| ; CHECK-LABEL: dup_v4i32_reversed: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmgt s0, s1, s0 |
| ; CHECK-NEXT: dup v0.4s, v0.s[0] |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ogt float %b, %a |
| %vcmpd.i = sext i1 %0 to i32 |
| %vecinit.i = insertelement <4 x i32> poison, i32 %vcmpd.i, i64 0 |
| %1 = bitcast <4 x i32> %vecinit.i to <4 x float> |
| %2 = shufflevector <4 x float> %1, <4 x float> poison, <4 x i32> zeroinitializer |
| ret <4 x float> %2 |
| } |
| |
| define <2 x double> @dup_v2i64(double %a, double %b) { |
| ; CHECK-LABEL: dup_v2i64: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmgt d0, d0, d1 |
| ; CHECK-NEXT: dup v0.2d, v0.d[0] |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan ogt double %a, %b |
| %vcmpd.i = sext i1 %0 to i64 |
| %vecinit.i = insertelement <2 x i64> poison, i64 %vcmpd.i, i64 0 |
| %1 = bitcast <2 x i64> %vecinit.i to <2 x double> |
| %2 = shufflevector <2 x double> %1, <2 x double> poison, <2 x i32> zeroinitializer |
| ret <2 x double> %2 |
| } |
| |
| define <8 x half> @dup_v8i16(half %a, half %b) { |
| ; |
| ; |
| ; FIXME: Could be replaced with fcmeq + dup but the type of the former is |
| ; promoted to i32 during selection and then the optimization does not apply. |
| ; CHECK-LABEL: dup_v8i16: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcvt s1, h1 |
| ; CHECK-NEXT: fcvt s0, h0 |
| ; CHECK-NEXT: fcmeq s0, s0, s1 |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan oeq half %a, %b |
| %vcmpd.i = sext i1 %0 to i16 |
| %vecinit.i = insertelement <8 x i16> poison, i16 %vcmpd.i, i64 0 |
| %1 = bitcast <8 x i16> %vecinit.i to <8 x half> |
| ret <8 x half> %1 |
| } |
| |
| define i32 @mask_i32(float %a, float %b) { |
| ; CHECK-LABEL: mask_i32: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmp s0, s1 |
| ; CHECK-NEXT: csetm w0, eq |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan oeq float %a, %b |
| %vcmpd.i = sext i1 %0 to i32 |
| ret i32 %vcmpd.i |
| } |
| |
| ; Verify that a mask is not emitted when (allOnes, allZeros) are not the |
| ; operands for the SELECT_CC. |
| define i32 @bool_i32(float %a, float %b) { |
| ; CHECK-LABEL: bool_i32: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fcmp s0, s1 |
| ; CHECK-NEXT: cset w0, eq |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = fcmp nnan oeq float %a, %b |
| %vcmpd.i = zext i1 %0 to i32 |
| ret i32 %vcmpd.i |
| } |