diff --git a/clang/include/clang/Basic/arm_mve.td b/clang/include/clang/Basic/arm_mve.td --- a/clang/include/clang/Basic/arm_mve.td +++ b/clang/include/clang/Basic/arm_mve.td @@ -192,6 +192,10 @@ let params = T.Signed in { defm vqdmulhq : VectorVectorArithmetic<"qdmulh_predicated", (?), 0>; defm vqrdmulhq : VectorVectorArithmetic<"qrdmulh_predicated", (?), 0>; + def vminaq_m: Intrinsic $a, $b, $pred)>; + def vmaxaq_m: Intrinsic $a, $b, $pred)>; } let params = T.Poly, overrideKindLetter = "p" in { @@ -203,6 +207,10 @@ let params = T.Float in { defm vminnmq : VectorVectorArithmetic<"min_predicated", (? (u32 0))>; defm vmaxnmq : VectorVectorArithmetic<"max_predicated", (? (u32 0))>; + def vminnmaq_m: Intrinsic $a, $b, $pred)>; + def vmaxnmaq_m: Intrinsic $a, $b, $pred)>; } let params = T.Int in { @@ -275,6 +283,14 @@ (select (icmp_sle $a, $b), $a, $b)>; def vmaxq: Intrinsic; + def vminaq: Intrinsic; + def vmaxaq: Intrinsic; } let params = T.Unsigned in { def vminqu: Intrinsic $a, $b)>; + (IRIntBase<"minnum", [Vector]> $a, $b)>; def vmaxnmq: Intrinsic $a, $b)>; + (IRIntBase<"maxnum", [Vector]> $a, $b)>; + def vminnmaq: Intrinsic + $a, (IRIntBase<"fabs", [Vector]> $b))>; + def vmaxnmaq: Intrinsic + $a, (IRIntBase<"fabs", [Vector]> $b))>; } def vpselq: Intrinsic + +// CHECK-LABEL: @test_vmaxaq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <16 x i8> [[B:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <16 x i8> zeroinitializer, [[B]] +// CHECK-NEXT: [[TMP2:%.*]] = select <16 x i1> [[TMP0]], <16 x i8> [[TMP1]], <16 x i8> [[B]] +// CHECK-NEXT: [[TMP3:%.*]] = icmp ugt <16 x i8> [[TMP2]], [[A:%.*]] +// CHECK-NEXT: [[TMP4:%.*]] = select <16 x i1> [[TMP3]], <16 x i8> [[TMP2]], <16 x i8> [[A]] +// CHECK-NEXT: ret <16 x i8> [[TMP4]] +// +uint8x16_t test_vmaxaq_s8(uint8x16_t a, int8x16_t b) +{ +#ifdef POLYMORPHIC + return vmaxaq(a, b); +#else /* POLYMORPHIC */ + return vmaxaq_s8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmaxaq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <8 x i16> [[B:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <8 x i16> zeroinitializer, [[B]] +// CHECK-NEXT: [[TMP2:%.*]] = select <8 x i1> [[TMP0]], <8 x i16> [[TMP1]], <8 x i16> [[B]] +// CHECK-NEXT: [[TMP3:%.*]] = icmp ugt <8 x i16> [[TMP2]], [[A:%.*]] +// CHECK-NEXT: [[TMP4:%.*]] = select <8 x i1> [[TMP3]], <8 x i16> [[TMP2]], <8 x i16> [[A]] +// CHECK-NEXT: ret <8 x i16> [[TMP4]] +// +uint16x8_t test_vmaxaq_s16(uint16x8_t a, int16x8_t b) +{ +#ifdef POLYMORPHIC + return vmaxaq(a, b); +#else /* POLYMORPHIC */ + return vmaxaq_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmaxaq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i32> [[B:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <4 x i32> zeroinitializer, [[B]] +// CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[TMP1]], <4 x i32> [[B]] +// CHECK-NEXT: [[TMP3:%.*]] = icmp ugt <4 x i32> [[TMP2]], [[A:%.*]] +// CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP3]], <4 x i32> [[TMP2]], <4 x i32> [[A]] +// CHECK-NEXT: ret <4 x i32> [[TMP4]] +// +uint32x4_t test_vmaxaq_s32(uint32x4_t a, int32x4_t b) +{ +#ifdef POLYMORPHIC + return vmaxaq(a, b); +#else /* POLYMORPHIC */ + return vmaxaq_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmaxaq_m_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.arm.mve.vmaxa.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], <16 x i1> [[TMP1]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +uint8x16_t test_vmaxaq_m_s8(uint8x16_t a, int8x16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmaxaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vmaxaq_m_s8(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmaxaq_m_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.arm.mve.vmaxa.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], <8 x i1> [[TMP1]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vmaxaq_m_s16(uint16x8_t a, int16x8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmaxaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vmaxaq_m_s16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmaxaq_m_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.arm.mve.vmaxa.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i1> [[TMP1]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +uint32x4_t test_vmaxaq_m_s32(uint32x4_t a, int32x4_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmaxaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vmaxaq_m_s32(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vmaxnmaq.c b/clang/test/CodeGen/arm-mve-intrinsics/vmaxnmaq.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vmaxnmaq.c @@ -0,0 +1,67 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O3 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O3 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vmaxnmaq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call <8 x half> @llvm.fabs.v8f16(<8 x half> [[B:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x half> @llvm.maxnum.v8f16(<8 x half> [[A:%.*]], <8 x half> [[TMP0]]) +// CHECK-NEXT: ret <8 x half> [[TMP1]] +// +float16x8_t test_vmaxnmaq_f16(float16x8_t a, float16x8_t b) +{ +#ifdef POLYMORPHIC + return vmaxnmaq(a, b); +#else /* POLYMORPHIC */ + return vmaxnmaq_f16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmaxnmaq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x float> @llvm.fabs.v4f32(<4 x float> [[B:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.maxnum.v4f32(<4 x float> [[A:%.*]], <4 x float> [[TMP0]]) +// CHECK-NEXT: ret <4 x float> [[TMP1]] +// +float32x4_t test_vmaxnmaq_f32(float32x4_t a, float32x4_t b) +{ +#ifdef POLYMORPHIC + return vmaxnmaq(a, b); +#else /* POLYMORPHIC */ + return vmaxnmaq_f32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmaxnmaq_m_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x half> @llvm.arm.mve.vmaxnma.predicated.v8f16.v8i1(<8 x half> [[A:%.*]], <8 x half> [[B:%.*]], <8 x i1> [[TMP1]]) +// CHECK-NEXT: ret <8 x half> [[TMP2]] +// +float16x8_t test_vmaxnmaq_m_f16(float16x8_t a, float16x8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmaxnmaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vmaxnmaq_m_f16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vmaxnmaq_m_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.arm.mve.vmaxnma.predicated.v4f32.v4i1(<4 x float> [[A:%.*]], <4 x float> [[B:%.*]], <4 x i1> [[TMP1]]) +// CHECK-NEXT: ret <4 x float> [[TMP2]] +// +float32x4_t test_vmaxnmaq_m_f32(float32x4_t a, float32x4_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vmaxnmaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vmaxnmaq_m_f32(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vminaq.c b/clang/test/CodeGen/arm-mve-intrinsics/vminaq.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vminaq.c @@ -0,0 +1,107 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O3 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O3 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vminaq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <16 x i8> [[B:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <16 x i8> zeroinitializer, [[B]] +// CHECK-NEXT: [[TMP2:%.*]] = select <16 x i1> [[TMP0]], <16 x i8> [[TMP1]], <16 x i8> [[B]] +// CHECK-NEXT: [[TMP3:%.*]] = icmp ult <16 x i8> [[TMP2]], [[A:%.*]] +// CHECK-NEXT: [[TMP4:%.*]] = select <16 x i1> [[TMP3]], <16 x i8> [[TMP2]], <16 x i8> [[A]] +// CHECK-NEXT: ret <16 x i8> [[TMP4]] +// +uint8x16_t test_vminaq_s8(uint8x16_t a, int8x16_t b) +{ +#ifdef POLYMORPHIC + return vminaq(a, b); +#else /* POLYMORPHIC */ + return vminaq_s8(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vminaq_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <8 x i16> [[B:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <8 x i16> zeroinitializer, [[B]] +// CHECK-NEXT: [[TMP2:%.*]] = select <8 x i1> [[TMP0]], <8 x i16> [[TMP1]], <8 x i16> [[B]] +// CHECK-NEXT: [[TMP3:%.*]] = icmp ult <8 x i16> [[TMP2]], [[A:%.*]] +// CHECK-NEXT: [[TMP4:%.*]] = select <8 x i1> [[TMP3]], <8 x i16> [[TMP2]], <8 x i16> [[A]] +// CHECK-NEXT: ret <8 x i16> [[TMP4]] +// +uint16x8_t test_vminaq_s16(uint16x8_t a, int16x8_t b) +{ +#ifdef POLYMORPHIC + return vminaq(a, b); +#else /* POLYMORPHIC */ + return vminaq_s16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vminaq_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i32> [[B:%.*]], zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = sub <4 x i32> zeroinitializer, [[B]] +// CHECK-NEXT: [[TMP2:%.*]] = select <4 x i1> [[TMP0]], <4 x i32> [[TMP1]], <4 x i32> [[B]] +// CHECK-NEXT: [[TMP3:%.*]] = icmp ult <4 x i32> [[TMP2]], [[A:%.*]] +// CHECK-NEXT: [[TMP4:%.*]] = select <4 x i1> [[TMP3]], <4 x i32> [[TMP2]], <4 x i32> [[A]] +// CHECK-NEXT: ret <4 x i32> [[TMP4]] +// +uint32x4_t test_vminaq_s32(uint32x4_t a, int32x4_t b) +{ +#ifdef POLYMORPHIC + return vminaq(a, b); +#else /* POLYMORPHIC */ + return vminaq_s32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vminaq_m_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <16 x i8> @llvm.arm.mve.vmina.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], <16 x i1> [[TMP1]]) +// CHECK-NEXT: ret <16 x i8> [[TMP2]] +// +uint8x16_t test_vminaq_m_s8(uint8x16_t a, int8x16_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vminaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vminaq_m_s8(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vminaq_m_s16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x i16> @llvm.arm.mve.vmina.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]], <8 x i1> [[TMP1]]) +// CHECK-NEXT: ret <8 x i16> [[TMP2]] +// +uint16x8_t test_vminaq_m_s16(uint16x8_t a, int16x8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vminaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vminaq_m_s16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vminaq_m_s32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x i32> @llvm.arm.mve.vmina.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]], <4 x i1> [[TMP1]]) +// CHECK-NEXT: ret <4 x i32> [[TMP2]] +// +uint32x4_t test_vminaq_m_s32(uint32x4_t a, int32x4_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vminaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vminaq_m_s32(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/clang/test/CodeGen/arm-mve-intrinsics/vminnmaq.c b/clang/test/CodeGen/arm-mve-intrinsics/vminnmaq.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/arm-mve-intrinsics/vminnmaq.c @@ -0,0 +1,67 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O3 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s +// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O3 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s + +#include + +// CHECK-LABEL: @test_vminnmaq_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call <8 x half> @llvm.fabs.v8f16(<8 x half> [[B:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x half> @llvm.minnum.v8f16(<8 x half> [[A:%.*]], <8 x half> [[TMP0]]) +// CHECK-NEXT: ret <8 x half> [[TMP1]] +// +float16x8_t test_vminnmaq_f16(float16x8_t a, float16x8_t b) +{ +#ifdef POLYMORPHIC + return vminnmaq(a, b); +#else /* POLYMORPHIC */ + return vminnmaq_f16(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vminnmaq_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call <4 x float> @llvm.fabs.v4f32(<4 x float> [[B:%.*]]) +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x float> @llvm.minnum.v4f32(<4 x float> [[A:%.*]], <4 x float> [[TMP0]]) +// CHECK-NEXT: ret <4 x float> [[TMP1]] +// +float32x4_t test_vminnmaq_f32(float32x4_t a, float32x4_t b) +{ +#ifdef POLYMORPHIC + return vminnmaq(a, b); +#else /* POLYMORPHIC */ + return vminnmaq_f32(a, b); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vminnmaq_m_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <8 x half> @llvm.arm.mve.vminnma.predicated.v8f16.v8i1(<8 x half> [[A:%.*]], <8 x half> [[B:%.*]], <8 x i1> [[TMP1]]) +// CHECK-NEXT: ret <8 x half> [[TMP2]] +// +float16x8_t test_vminnmaq_m_f16(float16x8_t a, float16x8_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vminnmaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vminnmaq_m_f16(a, b, p); +#endif /* POLYMORPHIC */ +} + +// CHECK-LABEL: @test_vminnmaq_m_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32 +// CHECK-NEXT: [[TMP1:%.*]] = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = tail call <4 x float> @llvm.arm.mve.vminnma.predicated.v4f32.v4i1(<4 x float> [[A:%.*]], <4 x float> [[B:%.*]], <4 x i1> [[TMP1]]) +// CHECK-NEXT: ret <4 x float> [[TMP2]] +// +float32x4_t test_vminnmaq_m_f32(float32x4_t a, float32x4_t b, mve_pred16_t p) +{ +#ifdef POLYMORPHIC + return vminnmaq_m(a, b, p); +#else /* POLYMORPHIC */ + return vminnmaq_m_f32(a, b, p); +#endif /* POLYMORPHIC */ +} diff --git a/llvm/include/llvm/IR/IntrinsicsARM.td b/llvm/include/llvm/IR/IntrinsicsARM.td --- a/llvm/include/llvm/IR/IntrinsicsARM.td +++ b/llvm/include/llvm/IR/IntrinsicsARM.td @@ -876,6 +876,18 @@ def int_arm_mve_hsub_predicated: Intrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty /* unsigned */, llvm_anyvector_ty, LLVMMatchType<0>], [IntrNoMem]>; +def int_arm_mve_vmina_predicated: Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; +def int_arm_mve_vmaxa_predicated: Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; +def int_arm_mve_vminnma_predicated: Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; +def int_arm_mve_vmaxnma_predicated: Intrinsic<[llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyvector_ty], + [IntrNoMem]>; defm int_arm_mve_minv: IntrinsicSignSuffix<[llvm_i32_ty], [llvm_i32_ty, llvm_anyvector_ty], [IntrNoMem]>; diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td --- a/llvm/lib/Target/ARM/ARMInstrMVE.td +++ b/llvm/lib/Target/ARM/ARMInstrMVE.td @@ -2291,13 +2291,37 @@ let validForTailPredication = 1; } -def MVE_VMAXAs8 : MVE_VMINMAXA<"vmaxa", "s8", 0b00, 0b0>; -def MVE_VMAXAs16 : MVE_VMINMAXA<"vmaxa", "s16", 0b01, 0b0>; -def MVE_VMAXAs32 : MVE_VMINMAXA<"vmaxa", "s32", 0b10, 0b0>; +multiclass MVE_VMINMAXA_m { + def "" : MVE_VMINMAXA; + defvar Inst = !cast(NAME); + + let Predicates = [HasMVEInt] in { + // Unpredicated v(min|max)a + def : Pat<(VTI.Vec (unpred_op (VTI.Vec MQPR:$Qd), (abs (VTI.Vec MQPR:$Qm)))), + (VTI.Vec (Inst (VTI.Vec MQPR:$Qd), (VTI.Vec MQPR:$Qm)))>; -def MVE_VMINAs8 : MVE_VMINMAXA<"vmina", "s8", 0b00, 0b1>; -def MVE_VMINAs16 : MVE_VMINMAXA<"vmina", "s16", 0b01, 0b1>; -def MVE_VMINAs32 : MVE_VMINMAXA<"vmina", "s32", 0b10, 0b1>; + // Predicated v(min|max)a + def : Pat<(VTI.Vec (pred_int (VTI.Vec MQPR:$Qd), (VTI.Vec MQPR:$Qm), + (VTI.Pred VCCR:$mask))), + (VTI.Vec (Inst (VTI.Vec MQPR:$Qd), (VTI.Vec MQPR:$Qm), + ARMVCCThen, (VTI.Pred VCCR:$mask)))>; + } +} + +multiclass MVE_VMINA + : MVE_VMINMAXA_m<"vmina", VTI, umin, int_arm_mve_vmina_predicated, 0b1>; + +defm MVE_VMAXAs8 : MVE_VMINA; +defm MVE_VMAXAs16 : MVE_VMINA; +defm MVE_VMAXAs32 : MVE_VMINA; + +multiclass MVE_VMAXA + : MVE_VMINMAXA_m<"vmaxa", VTI, umax, int_arm_mve_vmaxa_predicated, 0b0>; + +defm MVE_VMINAs8 : MVE_VMAXA; +defm MVE_VMINAs16 : MVE_VMAXA; +defm MVE_VMINAs32 : MVE_VMAXA; // end of MVE Integer instructions @@ -3623,11 +3647,36 @@ let Inst{0} = 0b1; } -def MVE_VMAXNMAf32 : MVE_VMAXMINNMA<"vmaxnma", "f32", 0b0, 0b0>; -def MVE_VMAXNMAf16 : MVE_VMAXMINNMA<"vmaxnma", "f16", 0b1, 0b0>; +multiclass MVE_VMAXMINNMA_m { + def "" : MVE_VMAXMINNMA; + defvar Inst = !cast(NAME); + + let Predicates = [HasMVEInt] in { + // Unpredicated v(max|min)nma + def : Pat<(VTI.Vec (unpred_op (VTI.Vec MQPR:$Qd), (fabs (VTI.Vec MQPR:$Qm)))), + (VTI.Vec (Inst (VTI.Vec MQPR:$Qd), (VTI.Vec MQPR:$Qm)))>; + + // Predicated v(max|min)nma + def : Pat<(VTI.Vec (pred_int (VTI.Vec MQPR:$Qd), (VTI.Vec MQPR:$Qm), + (VTI.Pred VCCR:$mask))), + (VTI.Vec (Inst (VTI.Vec MQPR:$Qd), (VTI.Vec MQPR:$Qm), + ARMVCCThen, (VTI.Pred VCCR:$mask)))>; + } +} + +multiclass MVE_VMAXNMA + : MVE_VMAXMINNMA_m<"vmaxnma", VTI, fmaxnum, int_arm_mve_vmaxnma_predicated, bit_12>; + +defm MVE_VMAXNMAf32 : MVE_VMAXNMA; +defm MVE_VMAXNMAf16 : MVE_VMAXNMA; + +multiclass MVE_VMINNMA + : MVE_VMAXMINNMA_m<"vminnma", VTI, fminnum, int_arm_mve_vminnma_predicated, bit_12>; -def MVE_VMINNMAf32 : MVE_VMAXMINNMA<"vminnma", "f32", 0b0, 0b1>; -def MVE_VMINNMAf16 : MVE_VMAXMINNMA<"vminnma", "f16", 0b1, 0b1>; +defm MVE_VMINNMAf32 : MVE_VMINNMA; +defm MVE_VMINNMAf16 : MVE_VMINNMA; // end of MVE Floating Point instructions diff --git a/llvm/test/CodeGen/Thumb2/mve-intrinsics/vmaxaq.ll b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vmaxaq.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vmaxaq.ll @@ -0,0 +1,98 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve.fp -verify-machineinstrs -o - %s | FileCheck %s + +define arm_aapcs_vfpcc <16 x i8> @test_vmaxaq_s8(<16 x i8> %a, <16 x i8> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vmaxaq_s8: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmaxa.s8 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = icmp slt <16 x i8> %b, zeroinitializer + %1 = sub <16 x i8> zeroinitializer, %b + %2 = select <16 x i1> %0, <16 x i8> %1, <16 x i8> %b + %3 = icmp ugt <16 x i8> %2, %a + %4 = select <16 x i1> %3, <16 x i8> %2, <16 x i8> %a + ret <16 x i8> %4 +} + +define arm_aapcs_vfpcc <8 x i16> @test_vmaxaq_s16(<8 x i16> %a, <8 x i16> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vmaxaq_s16: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmaxa.s16 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = icmp slt <8 x i16> %b, zeroinitializer + %1 = sub <8 x i16> zeroinitializer, %b + %2 = select <8 x i1> %0, <8 x i16> %1, <8 x i16> %b + %3 = icmp ugt <8 x i16> %2, %a + %4 = select <8 x i1> %3, <8 x i16> %2, <8 x i16> %a + ret <8 x i16> %4 +} + +define arm_aapcs_vfpcc <4 x i32> @test_vmaxaq_s32(<4 x i32> %a, <4 x i32> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vmaxaq_s32: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmaxa.s32 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = icmp slt <4 x i32> %b, zeroinitializer + %1 = sub <4 x i32> zeroinitializer, %b + %2 = select <4 x i1> %0, <4 x i32> %1, <4 x i32> %b + %3 = icmp ugt <4 x i32> %2, %a + %4 = select <4 x i1> %3, <4 x i32> %2, <4 x i32> %a + ret <4 x i32> %4 +} + +define arm_aapcs_vfpcc <16 x i8> @test_vmaxaq_m_s8(<16 x i8> %a, <16 x i8> %b, i16 zeroext %p) local_unnamed_addr #1 { +; CHECK-LABEL: test_vmaxaq_m_s8: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vmaxat.s8 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0) + %2 = tail call <16 x i8> @llvm.arm.mve.vmaxa.predicated.v16i8.v16i1(<16 x i8> %a, <16 x i8> %b, <16 x i1> %1) + ret <16 x i8> %2 +} + +declare <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32) #2 + +declare <16 x i8> @llvm.arm.mve.vmaxa.predicated.v16i8.v16i1(<16 x i8>, <16 x i8>, <16 x i1>) #2 + +define arm_aapcs_vfpcc <8 x i16> @test_vmaxaq_m_s16(<8 x i16> %a, <8 x i16> %b, i16 zeroext %p) local_unnamed_addr #1 { +; CHECK-LABEL: test_vmaxaq_m_s16: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vmaxat.s16 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0) + %2 = tail call <8 x i16> @llvm.arm.mve.vmaxa.predicated.v8i16.v8i1(<8 x i16> %a, <8 x i16> %b, <8 x i1> %1) + ret <8 x i16> %2 +} + +declare <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32) #2 + +declare <8 x i16> @llvm.arm.mve.vmaxa.predicated.v8i16.v8i1(<8 x i16>, <8 x i16>, <8 x i1>) #2 + +define arm_aapcs_vfpcc <4 x i32> @test_vmaxaq_m_s32(<4 x i32> %a, <4 x i32> %b, i16 zeroext %p) local_unnamed_addr #1 { +; CHECK-LABEL: test_vmaxaq_m_s32: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vmaxat.s32 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0) + %2 = tail call <4 x i32> @llvm.arm.mve.vmaxa.predicated.v4i32.v4i1(<4 x i32> %a, <4 x i32> %b, <4 x i1> %1) + ret <4 x i32> %2 +} + +declare <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32) #2 + +declare <4 x i32> @llvm.arm.mve.vmaxa.predicated.v4i32.v4i1(<4 x i32>, <4 x i32>, <4 x i1>) #2 diff --git a/llvm/test/CodeGen/Thumb2/mve-intrinsics/vmaxnmaq.ll b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vmaxnmaq.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vmaxnmaq.ll @@ -0,0 +1,68 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve.fp -verify-machineinstrs -o - %s | FileCheck %s + +define arm_aapcs_vfpcc <8 x half> @test_vmaxnmaq_f16(<8 x half> %a, <8 x half> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vmaxnmaq_f16: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmaxnma.f16 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = tail call <8 x half> @llvm.fabs.v8f16(<8 x half> %b) + %1 = tail call <8 x half> @llvm.maxnum.v8f16(<8 x half> %a, <8 x half> %0) + ret <8 x half> %1 +} + +declare <8 x half> @llvm.fabs.v8f16(<8 x half>) #1 + +declare <8 x half> @llvm.maxnum.v8f16(<8 x half>, <8 x half>) #1 + +define arm_aapcs_vfpcc <4 x float> @test_vmaxnmaq_f32(<4 x float> %a, <4 x float> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vmaxnmaq_f32: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmaxnma.f32 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = tail call <4 x float> @llvm.fabs.v4f32(<4 x float> %b) + %1 = tail call <4 x float> @llvm.maxnum.v4f32(<4 x float> %a, <4 x float> %0) + ret <4 x float> %1 +} + +declare <4 x float> @llvm.fabs.v4f32(<4 x float>) #1 + +declare <4 x float> @llvm.maxnum.v4f32(<4 x float>, <4 x float>) #1 + +define arm_aapcs_vfpcc <8 x half> @test_vmaxnmaq_m_f16(<8 x half> %a, <8 x half> %b, i16 zeroext %p) local_unnamed_addr #0 { +; CHECK-LABEL: test_vmaxnmaq_m_f16: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vmaxnmat.f16 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0) + %2 = tail call <8 x half> @llvm.arm.mve.vmaxnma.predicated.v8f16.v8i1(<8 x half> %a, <8 x half> %b, <8 x i1> %1) + ret <8 x half> %2 +} + +declare <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32) #2 + +declare <8 x half> @llvm.arm.mve.vmaxnma.predicated.v8f16.v8i1(<8 x half>, <8 x half>, <8 x i1>) #2 + +define arm_aapcs_vfpcc <4 x float> @test_vmaxnmaq_m_f32(<4 x float> %a, <4 x float> %b, i16 zeroext %p) local_unnamed_addr #0 { +; CHECK-LABEL: test_vmaxnmaq_m_f32: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vmaxnmat.f32 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0) + %2 = tail call <4 x float> @llvm.arm.mve.vmaxnma.predicated.v4f32.v4i1(<4 x float> %a, <4 x float> %b, <4 x i1> %1) + ret <4 x float> %2 +} + +declare <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32) #2 + +declare <4 x float> @llvm.arm.mve.vmaxnma.predicated.v4f32.v4i1(<4 x float>, <4 x float>, <4 x i1>) #2 diff --git a/llvm/test/CodeGen/Thumb2/mve-intrinsics/vminaq.ll b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vminaq.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vminaq.ll @@ -0,0 +1,98 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve.fp -verify-machineinstrs -o - %s | FileCheck %s + +define arm_aapcs_vfpcc <16 x i8> @test_vminaq_s8(<16 x i8> %a, <16 x i8> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vminaq_s8: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmina.s8 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = icmp slt <16 x i8> %b, zeroinitializer + %1 = sub <16 x i8> zeroinitializer, %b + %2 = select <16 x i1> %0, <16 x i8> %1, <16 x i8> %b + %3 = icmp ult <16 x i8> %2, %a + %4 = select <16 x i1> %3, <16 x i8> %2, <16 x i8> %a + ret <16 x i8> %4 +} + +define arm_aapcs_vfpcc <8 x i16> @test_vminaq_s16(<8 x i16> %a, <8 x i16> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vminaq_s16: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmina.s16 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = icmp slt <8 x i16> %b, zeroinitializer + %1 = sub <8 x i16> zeroinitializer, %b + %2 = select <8 x i1> %0, <8 x i16> %1, <8 x i16> %b + %3 = icmp ult <8 x i16> %2, %a + %4 = select <8 x i1> %3, <8 x i16> %2, <8 x i16> %a + ret <8 x i16> %4 +} + +define arm_aapcs_vfpcc <4 x i32> @test_vminaq_s32(<4 x i32> %a, <4 x i32> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vminaq_s32: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmina.s32 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = icmp slt <4 x i32> %b, zeroinitializer + %1 = sub <4 x i32> zeroinitializer, %b + %2 = select <4 x i1> %0, <4 x i32> %1, <4 x i32> %b + %3 = icmp ult <4 x i32> %2, %a + %4 = select <4 x i1> %3, <4 x i32> %2, <4 x i32> %a + ret <4 x i32> %4 +} + +define arm_aapcs_vfpcc <16 x i8> @test_vminaq_m_s8(<16 x i8> %a, <16 x i8> %b, i16 zeroext %p) local_unnamed_addr #1 { +; CHECK-LABEL: test_vminaq_m_s8: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vminat.s8 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0) + %2 = tail call <16 x i8> @llvm.arm.mve.vmina.predicated.v16i8.v16i1(<16 x i8> %a, <16 x i8> %b, <16 x i1> %1) + ret <16 x i8> %2 +} + +declare <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32) #2 + +declare <16 x i8> @llvm.arm.mve.vmina.predicated.v16i8.v16i1(<16 x i8>, <16 x i8>, <16 x i1>) #2 + +define arm_aapcs_vfpcc <8 x i16> @test_vminaq_m_s16(<8 x i16> %a, <8 x i16> %b, i16 zeroext %p) local_unnamed_addr #1 { +; CHECK-LABEL: test_vminaq_m_s16: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vminat.s16 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0) + %2 = tail call <8 x i16> @llvm.arm.mve.vmina.predicated.v8i16.v8i1(<8 x i16> %a, <8 x i16> %b, <8 x i1> %1) + ret <8 x i16> %2 +} + +declare <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32) #2 + +declare <8 x i16> @llvm.arm.mve.vmina.predicated.v8i16.v8i1(<8 x i16>, <8 x i16>, <8 x i1>) #2 + +define arm_aapcs_vfpcc <4 x i32> @test_vminaq_m_s32(<4 x i32> %a, <4 x i32> %b, i16 zeroext %p) local_unnamed_addr #1 { +; CHECK-LABEL: test_vminaq_m_s32: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vminat.s32 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0) + %2 = tail call <4 x i32> @llvm.arm.mve.vmina.predicated.v4i32.v4i1(<4 x i32> %a, <4 x i32> %b, <4 x i1> %1) + ret <4 x i32> %2 +} + +declare <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32) #2 + +declare <4 x i32> @llvm.arm.mve.vmina.predicated.v4i32.v4i1(<4 x i32>, <4 x i32>, <4 x i1>) #2 diff --git a/llvm/test/CodeGen/Thumb2/mve-intrinsics/vminnmaq.ll b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vminnmaq.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vminnmaq.ll @@ -0,0 +1,68 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve.fp -verify-machineinstrs -o - %s | FileCheck %s + +define arm_aapcs_vfpcc <8 x half> @test_vminnmaq_f16(<8 x half> %a, <8 x half> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vminnmaq_f16: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vminnma.f16 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = tail call <8 x half> @llvm.fabs.v8f16(<8 x half> %b) + %1 = tail call <8 x half> @llvm.minnum.v8f16(<8 x half> %a, <8 x half> %0) + ret <8 x half> %1 +} + +declare <8 x half> @llvm.fabs.v8f16(<8 x half>) #1 + +declare <8 x half> @llvm.minnum.v8f16(<8 x half>, <8 x half>) #1 + +define arm_aapcs_vfpcc <4 x float> @test_vminnmaq_f32(<4 x float> %a, <4 x float> %b) local_unnamed_addr #0 { +; CHECK-LABEL: test_vminnmaq_f32: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vminnma.f32 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = tail call <4 x float> @llvm.fabs.v4f32(<4 x float> %b) + %1 = tail call <4 x float> @llvm.minnum.v4f32(<4 x float> %a, <4 x float> %0) + ret <4 x float> %1 +} + +declare <4 x float> @llvm.fabs.v4f32(<4 x float>) #1 + +declare <4 x float> @llvm.minnum.v4f32(<4 x float>, <4 x float>) #1 + +define arm_aapcs_vfpcc <8 x half> @test_vminnmaq_m_f16(<8 x half> %a, <8 x half> %b, i16 zeroext %p) local_unnamed_addr #0 { +; CHECK-LABEL: test_vminnmaq_m_f16: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vminnmat.f16 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0) + %2 = tail call <8 x half> @llvm.arm.mve.vminnma.predicated.v8f16.v8i1(<8 x half> %a, <8 x half> %b, <8 x i1> %1) + ret <8 x half> %2 +} + +declare <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32) #2 + +declare <8 x half> @llvm.arm.mve.vminnma.predicated.v8f16.v8i1(<8 x half>, <8 x half>, <8 x i1>) #2 + +define arm_aapcs_vfpcc <4 x float> @test_vminnmaq_m_f32(<4 x float> %a, <4 x float> %b, i16 zeroext %p) local_unnamed_addr #0 { +; CHECK-LABEL: test_vminnmaq_m_f32: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: vmsr p0, r0 +; CHECK-NEXT: vpst +; CHECK-NEXT: vminnmat.f32 q0, q1 +; CHECK-NEXT: bx lr +entry: + %0 = zext i16 %p to i32 + %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0) + %2 = tail call <4 x float> @llvm.arm.mve.vminnma.predicated.v4f32.v4i1(<4 x float> %a, <4 x float> %b, <4 x i1> %1) + ret <4 x float> %2 +} + +declare <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32) #2 + +declare <4 x float> @llvm.arm.mve.vminnma.predicated.v4f32.v4i1(<4 x float>, <4 x float>, <4 x i1>) #2