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,10 @@ (select (icmp_sle $a, $b), $a, $b)>; def vmaxq: Intrinsic; + def vminaq: Intrinsic $a, $b)>; + def vmaxaq: Intrinsic $a, $b)>; } 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, $b)>; + def vmaxnmaq: Intrinsic $a, $b)>; } def vpselq: Intrinsic + +// CHECK-LABEL: @test_vmaxaq_s8( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call <16 x i8> @llvm.arm.mve.vmaxa.v16i8.v16i8(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +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:%.*]] = tail call <8 x i16> @llvm.arm.mve.vmaxa.v8i16.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +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:%.*]] = tail call <4 x i32> @llvm.arm.mve.vmaxa.v4i32.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +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,65 @@ +// 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.arm.mve.vmaxnma.v8f16(<8 x half> [[A:%.*]], <8 x half> [[B:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +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.arm.mve.vmaxnma.v4f32(<4 x float> [[A:%.*]], <4 x float> [[B:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +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,95 @@ +// 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:%.*]] = tail call <16 x i8> @llvm.arm.mve.vmina.v16i8.v16i8(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]]) +// CHECK-NEXT: ret <16 x i8> [[TMP0]] +// +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:%.*]] = tail call <8 x i16> @llvm.arm.mve.vmina.v8i16.v8i16(<8 x i16> [[A:%.*]], <8 x i16> [[B:%.*]]) +// CHECK-NEXT: ret <8 x i16> [[TMP0]] +// +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:%.*]] = tail call <4 x i32> @llvm.arm.mve.vmina.v4i32.v4i32(<4 x i32> [[A:%.*]], <4 x i32> [[B:%.*]]) +// CHECK-NEXT: ret <4 x i32> [[TMP0]] +// +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,65 @@ +// 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.arm.mve.vminnma.v8f16(<8 x half> [[A:%.*]], <8 x half> [[B:%.*]]) +// CHECK-NEXT: ret <8 x half> [[TMP0]] +// +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.arm.mve.vminnma.v4f32(<4 x float> [[A:%.*]], <4 x float> [[B:%.*]]) +// CHECK-NEXT: ret <4 x float> [[TMP0]] +// +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]>; @@ -1029,6 +1041,18 @@ def int_arm_mve_vmull_poly: Intrinsic< [llvm_anyvector_ty], [llvm_anyvector_ty, LLVMMatchType<1>, llvm_i32_ty], [IntrNoMem]>; +def int_arm_mve_vmina: Intrinsic< + [llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], [IntrNoMem]>; +def int_arm_mve_vmaxa: Intrinsic< + [llvm_anyvector_ty], + [LLVMMatchType<0>, llvm_anyvector_ty], [IntrNoMem]>; +def int_arm_mve_vminnma: Intrinsic< + [llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; +def int_arm_mve_vmaxnma: Intrinsic< + [llvm_anyvector_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; // Intrinsic with a predicated and a non-predicated case. The predicated case // has two additional parameters: inactive (the value for inactive lanes, can 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), (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, int_arm_mve_vmina, 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, int_arm_mve_vmaxa, 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), (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, int_arm_mve_vmaxnma, 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, int_arm_mve_vminnma, 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,92 @@ +; 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 = tail call <16 x i8> @llvm.arm.mve.vmaxa.v16i8.v16i8(<16 x i8> %a, <16 x i8> %b) + ret <16 x i8> %0 +} + +declare <16 x i8> @llvm.arm.mve.vmaxa.v16i8.v16i8(<16 x i8>, <16 x i8>) #1 + +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 = tail call <8 x i16> @llvm.arm.mve.vmaxa.v8i16.v8i16(<8 x i16> %a, <8 x i16> %b) + ret <8 x i16> %0 +} + +declare <8 x i16> @llvm.arm.mve.vmaxa.v8i16.v8i16(<8 x i16>, <8 x i16>) #1 + +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 = tail call <4 x i32> @llvm.arm.mve.vmaxa.v4i32.v4i32(<4 x i32> %a, <4 x i32> %b) + ret <4 x i32> %0 +} + +declare <4 x i32> @llvm.arm.mve.vmaxa.v4i32.v4i32(<4 x i32>, <4 x i32>) #1 + +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 #0 { +; 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) #1 + +declare <16 x i8> @llvm.arm.mve.vmaxa.predicated.v16i8.v16i1(<16 x i8>, <16 x i8>, <16 x i1>) #1 + +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 #0 { +; 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) #1 + +declare <8 x i16> @llvm.arm.mve.vmaxa.predicated.v8i16.v8i1(<8 x i16>, <8 x i16>, <8 x i1>) #1 + +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 #0 { +; 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) #1 + +declare <4 x i32> @llvm.arm.mve.vmaxa.predicated.v4i32.v4i1(<4 x i32>, <4 x i32>, <4 x i1>) #1 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,62 @@ +; 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.arm.mve.vmaxnma.v8f16(<8 x half> %a, <8 x half> %b) + ret <8 x half> %0 +} + +declare <8 x half> @llvm.arm.mve.vmaxnma.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.arm.mve.vmaxnma.v4f32(<4 x float> %a, <4 x float> %b) + ret <4 x float> %0 +} + +declare <4 x float> @llvm.arm.mve.vmaxnma.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) #1 + +declare <8 x half> @llvm.arm.mve.vmaxnma.predicated.v8f16.v8i1(<8 x half>, <8 x half>, <8 x i1>) #1 + +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) #1 + +declare <4 x float> @llvm.arm.mve.vmaxnma.predicated.v4f32.v4i1(<4 x float>, <4 x float>, <4 x i1>) #1 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,92 @@ +; 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 = tail call <16 x i8> @llvm.arm.mve.vmina.v16i8.v16i8(<16 x i8> %a, <16 x i8> %b) + ret <16 x i8> %0 +} + +declare <16 x i8> @llvm.arm.mve.vmina.v16i8.v16i8(<16 x i8>, <16 x i8>) #1 + +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 = tail call <8 x i16> @llvm.arm.mve.vmina.v8i16.v8i16(<8 x i16> %a, <8 x i16> %b) + ret <8 x i16> %0 +} + +declare <8 x i16> @llvm.arm.mve.vmina.v8i16.v8i16(<8 x i16>, <8 x i16>) #1 + +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 = tail call <4 x i32> @llvm.arm.mve.vmina.v4i32.v4i32(<4 x i32> %a, <4 x i32> %b) + ret <4 x i32> %0 +} + +declare <4 x i32> @llvm.arm.mve.vmina.v4i32.v4i32(<4 x i32>, <4 x i32>) #1 + +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 #0 { +; 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) #1 + +declare <16 x i8> @llvm.arm.mve.vmina.predicated.v16i8.v16i1(<16 x i8>, <16 x i8>, <16 x i1>) #1 + +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 #0 { +; 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) #1 + +declare <8 x i16> @llvm.arm.mve.vmina.predicated.v8i16.v8i1(<8 x i16>, <8 x i16>, <8 x i1>) #1 + +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 #0 { +; 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) #1 + +declare <4 x i32> @llvm.arm.mve.vmina.predicated.v4i32.v4i1(<4 x i32>, <4 x i32>, <4 x i1>) #1 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,62 @@ +; 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.arm.mve.vminnma.v8f16(<8 x half> %a, <8 x half> %b) + ret <8 x half> %0 +} + +declare <8 x half> @llvm.arm.mve.vminnma.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.arm.mve.vminnma.v4f32(<4 x float> %a, <4 x float> %b) + ret <4 x float> %0 +} + +declare <4 x float> @llvm.arm.mve.vminnma.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) #1 + +declare <8 x half> @llvm.arm.mve.vminnma.predicated.v8f16.v8i1(<8 x half>, <8 x half>, <8 x i1>) #1 + +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) #1 + +declare <4 x float> @llvm.arm.mve.vminnma.predicated.v4f32.v4i1(<4 x float>, <4 x float>, <4 x i1>) #1