[llvm] [LLVM][CodeGen][SVE] Add lowering for single type constrained operations. (PR #215232)
Paul Walker via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 10 03:10:03 PDT 2026
https://github.com/paulwalker-arm created https://github.com/llvm/llvm-project/pull/215232
This formalises a long standing requirement of SVE instructions selection to not introduce new faulting behaviour. This is why the strict and non-strict ops are combined to the existing ops (e.g. AArch64fadd_p). That means other than not crashing when trying to select these constrained operations the PR is NFC like. Following work will relax patterns that are currently restricted to all-active predicates by using the new _nonstrict ops that have no no-new-faults requirement.
NOTE: Excludes bfloat16 support because most lowerings require cast operations.
NOTE: Streaming mode has a different fp environment, specifically FP exceptions are disabled, but given things like rounding modes are still in play I figure it makes sense to match the non-streaming mode lowering.
>From 1ca95b78ccad30dbb12f81edecb614831968b91f Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Tue, 10 Mar 2026 11:08:55 +0000
Subject: [PATCH] [LLVM][CodeGen][SVE] Add lowering for single type constrained
operations.
NOTE: Excludes bfloat16 support because most lowerings require cast
operations.
NOTE: Streaming mode has a different fp environment, specifically FP
exceptions are disabled, but given things like rounding modes are still
in play I figure it makes sense to match the non-streaming mode
lowering.
---
.../Target/AArch64/AArch64ISelLowering.cpp | 151 ++-
.../lib/Target/AArch64/AArch64SVEInstrInfo.td | 55 +-
.../AArch64/sve-fp-constrained-intrinsics.ll | 1084 +++++++++++++++++
3 files changed, 1237 insertions(+), 53 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/sve-fp-constrained-intrinsics.ll
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index b01dc35531f4b..6c9627ee7711a 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -364,6 +364,13 @@ static bool isMergePassthruOpcode(unsigned Opc) {
case AArch64ISD::FSQRT_MERGE_PASSTHRU:
case AArch64ISD::FRECPX_MERGE_PASSTHRU:
case AArch64ISD::FABS_MERGE_PASSTHRU:
+ case AArch64ISD::STRICT_FCEIL_MERGE_PASSTHRU:
+ case AArch64ISD::STRICT_FFLOOR_MERGE_PASSTHRU:
+ case AArch64ISD::STRICT_FNEARBYINT_MERGE_PASSTHRU:
+ case AArch64ISD::STRICT_FROUND_MERGE_PASSTHRU:
+ case AArch64ISD::STRICT_FROUNDEVEN_MERGE_PASSTHRU:
+ case AArch64ISD::STRICT_FTRUNC_MERGE_PASSTHRU:
+ case AArch64ISD::STRICT_FSQRT_MERGE_PASSTHRU:
return true;
}
}
@@ -1826,30 +1833,30 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SPLAT_VECTOR, VT, Legal);
setOperationAction(ISD::SELECT, VT, Custom);
setOperationAction(ISD::SETCC, VT, Custom);
- setOperationAction(ISD::FADD, VT, Custom);
+ setOperationAction({ISD::FADD, ISD::STRICT_FADD}, VT, Custom);
setOperationAction(ISD::FCANONICALIZE, VT, Custom);
setOperationAction(ISD::FCOPYSIGN, VT, Custom);
- setOperationAction(ISD::FDIV, VT, Custom);
- setOperationAction(ISD::FMA, VT, Custom);
- setOperationAction(ISD::FMAXIMUM, VT, Custom);
- setOperationAction(ISD::FMAXNUM, VT, Custom);
+ setOperationAction({ISD::FDIV, ISD::STRICT_FDIV}, VT, Custom);
+ setOperationAction({ISD::FMA, ISD::STRICT_FMA}, VT, Custom);
+ setOperationAction({ISD::FMAXIMUM, ISD::STRICT_FMAXIMUM}, VT, Custom);
+ setOperationAction({ISD::FMAXNUM, ISD::STRICT_FMAXNUM}, VT, Custom);
setOperationAction(ISD::FMAXNUM_IEEE, VT, Custom);
- setOperationAction(ISD::FMINIMUM, VT, Custom);
- setOperationAction(ISD::FMINNUM, VT, Custom);
+ setOperationAction({ISD::FMINIMUM, ISD::STRICT_FMINIMUM}, VT, Custom);
+ setOperationAction({ISD::FMINNUM, ISD::STRICT_FMINNUM}, VT, Custom);
setOperationAction(ISD::FMINNUM_IEEE, VT, Custom);
- setOperationAction(ISD::FMUL, VT, Custom);
+ setOperationAction({ISD::FMUL, ISD::STRICT_FMUL}, VT, Custom);
setOperationAction(ISD::FNEG, VT, Custom);
- setOperationAction(ISD::FSUB, VT, Custom);
- setOperationAction(ISD::FCEIL, VT, Custom);
- setOperationAction(ISD::FFLOOR, VT, Custom);
- setOperationAction(ISD::FNEARBYINT, VT, Custom);
+ setOperationAction({ISD::FSUB, ISD::STRICT_FSUB}, VT, Custom);
+ setOperationAction({ISD::FCEIL, ISD::STRICT_FCEIL}, VT, Custom);
+ setOperationAction({ISD::FFLOOR, ISD::STRICT_FFLOOR}, VT, Custom);
+ setOperationAction({ISD::FNEARBYINT, ISD::STRICT_FNEARBYINT}, VT, Custom);
setOperationAction(ISD::FRINT, VT, Custom);
setOperationAction(ISD::LRINT, VT, Custom);
setOperationAction(ISD::LLRINT, VT, Custom);
- setOperationAction(ISD::FROUND, VT, Custom);
- setOperationAction(ISD::FROUNDEVEN, VT, Custom);
- setOperationAction(ISD::FTRUNC, VT, Custom);
- setOperationAction(ISD::FSQRT, VT, Custom);
+ setOperationAction({ISD::FROUND, ISD::STRICT_FROUND}, VT, Custom);
+ setOperationAction({ISD::FROUNDEVEN, ISD::STRICT_FROUNDEVEN}, VT, Custom);
+ setOperationAction({ISD::FTRUNC, ISD::STRICT_FTRUNC}, VT, Custom);
+ setOperationAction({ISD::FSQRT, ISD::STRICT_FSQRT}, VT, Custom);
setOperationAction(ISD::FABS, VT, Custom);
setOperationAction(ISD::FP_EXTEND, VT, Custom);
setOperationAction(ISD::FP_ROUND, VT, Custom);
@@ -1865,27 +1872,45 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setOperationAction(ISD::VECTOR_INTERLEAVE, VT, Custom);
setOperationAction(ISD::SELECT_CC, VT, Expand);
- setOperationAction(ISD::FREM, VT, Expand);
- setOperationAction(ISD::FPOW, VT, Expand);
- setOperationAction(ISD::FPOWI, VT, Expand);
+ setOperationAction({ISD::FREM, ISD::STRICT_FREM}, VT, Expand);
+ setOperationAction({ISD::FPOW, ISD::STRICT_FPOW}, VT, Expand);
+ setOperationAction({ISD::FPOWI, ISD::STRICT_FPOWI}, VT, Expand);
setOperationAction(ISD::FCBRT, VT, Expand);
- setOperationAction(ISD::FCOS, VT, Expand);
- setOperationAction(ISD::FSIN, VT, Expand);
+ setOperationAction({ISD::FCOS, ISD::STRICT_FCOS}, VT, Expand);
+ setOperationAction({ISD::FSIN, ISD::STRICT_FSIN}, VT, Expand);
setOperationAction(ISD::FSINCOS, VT, Expand);
- setOperationAction(ISD::FTAN, VT, Expand);
- setOperationAction(ISD::FACOS, VT, Expand);
- setOperationAction(ISD::FASIN, VT, Expand);
- setOperationAction(ISD::FATAN, VT, Expand);
- setOperationAction(ISD::FATAN2, VT, Expand);
- setOperationAction(ISD::FCOSH, VT, Expand);
- setOperationAction(ISD::FSINH, VT, Expand);
- setOperationAction(ISD::FTANH, VT, Expand);
- setOperationAction(ISD::FEXP, VT, Expand);
- setOperationAction(ISD::FEXP2, VT, Expand);
+ setOperationAction({ISD::FTAN, ISD::STRICT_FTAN}, VT, Expand);
+ setOperationAction({ISD::FACOS, ISD::STRICT_FACOS}, VT, Expand);
+ setOperationAction({ISD::FASIN, ISD::STRICT_FASIN}, VT, Expand);
+ setOperationAction({ISD::FATAN, ISD::STRICT_FATAN}, VT, Expand);
+ setOperationAction({ISD::FATAN2, ISD::STRICT_FATAN2}, VT, Expand);
+ setOperationAction({ISD::FCOSH, ISD::STRICT_FCOSH}, VT, Expand);
+ setOperationAction({ISD::FSINH, ISD::STRICT_FSINH}, VT, Expand);
+ setOperationAction({ISD::FTANH, ISD::STRICT_FTANH}, VT, Expand);
+ setOperationAction({ISD::FEXP, ISD::STRICT_FEXP}, VT, Expand);
+ setOperationAction({ISD::FEXP2, ISD::STRICT_FEXP2}, VT, Expand);
setOperationAction(ISD::FEXP10, VT, Expand);
- setOperationAction(ISD::FLOG, VT, Expand);
- setOperationAction(ISD::FLOG2, VT, Expand);
- setOperationAction(ISD::FLOG10, VT, Expand);
+ setOperationAction({ISD::FLOG, ISD::STRICT_FLOG}, VT, Expand);
+ setOperationAction({ISD::FLOG2, ISD::STRICT_FLOG2}, VT, Expand);
+ setOperationAction({ISD::FLOG10, ISD::STRICT_FLOG10}, VT, Expand);
+
+ // TODO: These require custom lowering.
+ setOperationAction(ISD::STRICT_FLDEXP, VT, Expand);
+ setOperationAction(ISD::STRICT_FRINT, VT, Expand);
+ setOperationAction(ISD::STRICT_PSEUDO_FMIN, VT, Expand);
+ setOperationAction(ISD::STRICT_PSEUDO_FMAX, VT, Expand);
+ setOperationAction(ISD::STRICT_LROUND, VT, Expand);
+ setOperationAction(ISD::STRICT_LLROUND, VT, Expand);
+ setOperationAction(ISD::STRICT_LRINT, VT, Expand);
+ setOperationAction(ISD::STRICT_LLRINT, VT, Expand);
+ setOperationAction(ISD::STRICT_FP_TO_SINT, VT, Expand);
+ setOperationAction(ISD::STRICT_FP_TO_UINT, VT, Expand);
+ setOperationAction(ISD::STRICT_SINT_TO_FP, VT, Expand);
+ setOperationAction(ISD::STRICT_UINT_TO_FP, VT, Expand);
+ setOperationAction(ISD::STRICT_FP_ROUND, VT, Expand);
+ setOperationAction(ISD::STRICT_FP_EXTEND, VT, Expand);
+ setOperationAction(ISD::STRICT_FSETCC, VT, Expand);
+ setOperationAction(ISD::STRICT_FSETCCS, VT, Expand);
setCondCodeAction(ISD::SETO, VT, Expand);
setCondCodeAction(ISD::SETOLT, VT, Expand);
@@ -8595,32 +8620,63 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
return LowerXALUO(Op, DAG);
case ISD::FADD:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FADD_PRED);
+ case ISD::STRICT_FADD:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FADD_PRED);
case ISD::FSUB:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FSUB_PRED);
+ case ISD::STRICT_FSUB:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FSUB_PRED);
case ISD::FMUL:
return LowerFMUL(Op, DAG);
+ case ISD::STRICT_FMUL:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMUL_PRED);
case ISD::FMA:
return LowerFMA(Op, DAG);
+ case ISD::STRICT_FMA:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMA_PRED);
case ISD::FDIV:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FDIV_PRED);
+ case ISD::STRICT_FDIV:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FDIV_PRED);
case ISD::FNEG:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FNEG_MERGE_PASSTHRU);
case ISD::FCEIL:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FCEIL_MERGE_PASSTHRU);
+ case ISD::STRICT_FCEIL:
+ return LowerToPredicatedOp(Op, DAG,
+ AArch64ISD::STRICT_FCEIL_MERGE_PASSTHRU);
case ISD::FFLOOR:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FFLOOR_MERGE_PASSTHRU);
+ case ISD::STRICT_FFLOOR:
+ return LowerToPredicatedOp(Op, DAG,
+ AArch64ISD::STRICT_FFLOOR_MERGE_PASSTHRU);
case ISD::FNEARBYINT:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FNEARBYINT_MERGE_PASSTHRU);
+ case ISD::STRICT_FNEARBYINT:
+ return LowerToPredicatedOp(Op, DAG,
+ AArch64ISD::STRICT_FNEARBYINT_MERGE_PASSTHRU);
case ISD::FRINT:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FRINT_MERGE_PASSTHRU);
case ISD::FROUND:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FROUND_MERGE_PASSTHRU);
+ case ISD::STRICT_FROUND:
+ return LowerToPredicatedOp(Op, DAG,
+ AArch64ISD::STRICT_FROUND_MERGE_PASSTHRU);
case ISD::FROUNDEVEN:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU);
+ case ISD::STRICT_FROUNDEVEN:
+ return LowerToPredicatedOp(Op, DAG,
+ AArch64ISD::STRICT_FROUNDEVEN_MERGE_PASSTHRU);
case ISD::FTRUNC:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FTRUNC_MERGE_PASSTHRU);
+ case ISD::STRICT_FTRUNC:
+ return LowerToPredicatedOp(Op, DAG,
+ AArch64ISD::STRICT_FTRUNC_MERGE_PASSTHRU);
case ISD::FSQRT:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FSQRT_MERGE_PASSTHRU);
+ case ISD::STRICT_FSQRT:
+ return LowerToPredicatedOp(Op, DAG,
+ AArch64ISD::STRICT_FSQRT_MERGE_PASSTHRU);
case ISD::FABS:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FABS_MERGE_PASSTHRU);
case ISD::FP_ROUND:
@@ -8795,14 +8851,22 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
return LowerToScalableOp(Op, DAG);
case ISD::FMAXIMUM:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMAX_PRED);
+ case ISD::STRICT_FMAXIMUM:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMAX_PRED);
case ISD::FMAXNUM:
case ISD::FMAXNUM_IEEE:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMAXNM_PRED);
+ case ISD::STRICT_FMAXNUM:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMAXNM_PRED);
case ISD::FMINIMUM:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMIN_PRED);
+ case ISD::STRICT_FMINIMUM:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMIN_PRED);
case ISD::FMINNUM:
case ISD::FMINNUM_IEEE:
return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMINNM_PRED);
+ case ISD::STRICT_FMINNUM:
+ return LowerToPredicatedOp(Op, DAG, AArch64ISD::STRICT_FMINNM_PRED);
case ISD::VSELECT:
return LowerFixedLengthVectorSelectToSVE(Op, DAG);
case ISD::ABS:
@@ -33923,6 +33987,9 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
SDLoc DL(Op);
auto Pg = getPredicateForVector(DAG, DL, VT);
+ bool IsStrictFP = Op->isStrictFPOpcode();
+ unsigned OpStartIdx = IsStrictFP ? 1 : 0;
+
if (VT.isFixedLengthVector()) {
assert(isTypeLegal(VT) && "Expected only legal fixed-width types");
EVT ContainerVT = getContainerForFixedLengthVector(DAG, VT);
@@ -33957,8 +34024,18 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
assert(VT.isScalableVector() && "Only expect to lower scalable vector op!");
- SmallVector<SDValue, 4> Operands = {Pg};
- for (const SDValue &V : Op->op_values()) {
+ SmallVector<SDValue, 4> Operands;
+
+ // Chain
+ if (IsStrictFP)
+ Operands.push_back(Op.getOperand(0));
+
+ // Predicate
+ Operands.push_back(Pg);
+
+ // Regular operands
+ for (unsigned OpIdx = OpStartIdx; OpIdx < Op.getNumOperands(); OpIdx++) {
+ SDValue V = Op.getOperand(OpIdx);
assert((!V.getValueType().isVector() ||
V.getValueType().isScalableVector()) &&
"Only scalable vectors are supported!");
@@ -33968,7 +34045,7 @@ SDValue AArch64TargetLowering::LowerToPredicatedOp(SDValue Op,
if (isMergePassthruOpcode(NewOp))
Operands.push_back(DAG.getPOISON(VT));
- return DAG.getNode(NewOp, DL, VT, Operands, Op->getFlags());
+ return DAG.getNode(NewOp, DL, Op->getVTList(), Operands, Op->getFlags());
}
// If a fixed length vector operation has no side effects when applied to
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index bc9fa998cea8f..01c834355d2a2 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -236,15 +236,6 @@ def SDT_AArch64FMA : SDTypeProfile<1, 4, [
// Predicated operations with the result of inactive lanes being unspecified.
def AArch64asr_p : SDNode<"AArch64ISD::SRA_PRED", SDT_AArch64Arith>;
-def AArch64fadd_p : SDNode<"AArch64ISD::FADD_PRED", SDT_AArch64Arith>;
-def AArch64fdiv_p : SDNode<"AArch64ISD::FDIV_PRED", SDT_AArch64Arith>;
-def AArch64fma_p : SDNode<"AArch64ISD::FMA_PRED", SDT_AArch64FMA>;
-def AArch64fmax_p : SDNode<"AArch64ISD::FMAX_PRED", SDT_AArch64Arith>;
-def AArch64fmaxnm_p : SDNode<"AArch64ISD::FMAXNM_PRED", SDT_AArch64Arith>;
-def AArch64fmin_p : SDNode<"AArch64ISD::FMIN_PRED", SDT_AArch64Arith>;
-def AArch64fminnm_p : SDNode<"AArch64ISD::FMINNM_PRED", SDT_AArch64Arith>;
-def AArch64fmul_p : SDNode<"AArch64ISD::FMUL_PRED", SDT_AArch64Arith>;
-def AArch64fsub_p : SDNode<"AArch64ISD::FSUB_PRED", SDT_AArch64Arith>;
def AArch64lsl_p : SDNode<"AArch64ISD::SHL_PRED", SDT_AArch64Arith>;
def AArch64lsr_p : SDNode<"AArch64ISD::SRL_PRED", SDT_AArch64Arith>;
def AArch64mul_p : SDNode<"AArch64ISD::MUL_PRED", SDT_AArch64Arith>;
@@ -261,6 +252,37 @@ def AArch64umax_p : SDNode<"AArch64ISD::UMAX_PRED", SDT_AArch64Arith>;
def AArch64umin_p : SDNode<"AArch64ISD::UMIN_PRED", SDT_AArch64Arith>;
def AArch64umulh_p : SDNode<"AArch64ISD::MULHU_PRED", SDT_AArch64Arith>;
+multiclass def_strict_fp_op<string short_opcode, SDTypeProfile typeprof> {
+ def _nonstrict : SDNode<"AArch64ISD::" # short_opcode, typeprof>;
+ def _strict : SDNode<"AArch64ISD::STRICT_" # short_opcode, typeprof, [SDNPHasChain]>;
+}
+
+multiclass def_strict_fp_3op<string short_opcode, SDTypeProfile typeprof>
+: def_strict_fp_op<short_opcode, typeprof> {
+ def NAME : PatFrags<
+ (ops node:$op1, node:$op2, node:$op3),
+ [(!cast<SDPatternOperator>(NAME # "_nonstrict") node:$op1, node:$op2, node:$op3),
+ (!cast<SDPatternOperator>(NAME # "_strict") node:$op1, node:$op2, node:$op3)]>;
+}
+
+multiclass def_strict_fp_4op<string short_opcode, SDTypeProfile typeprof>
+: def_strict_fp_op<short_opcode, typeprof> {
+ def NAME : PatFrags<
+ (ops node:$op1, node:$op2, node:$op3, node:$op4),
+ [(!cast<SDPatternOperator>(NAME # "_nonstrict") node:$op1, node:$op2, node:$op3, node:$op4),
+ (!cast<SDPatternOperator>(NAME # "_strict") node:$op1, node:$op2, node:$op3, node:$op4)]>;
+}
+
+defm AArch64fadd_p : def_strict_fp_3op<"FADD_PRED", SDT_AArch64Arith>;
+defm AArch64fdiv_p : def_strict_fp_3op<"FDIV_PRED", SDT_AArch64Arith>;
+defm AArch64fma_p : def_strict_fp_4op<"FMA_PRED", SDT_AArch64FMA>;
+defm AArch64fmax_p : def_strict_fp_3op<"FMAX_PRED", SDT_AArch64Arith>;
+defm AArch64fmaxnm_p : def_strict_fp_3op<"FMAXNM_PRED", SDT_AArch64Arith>;
+defm AArch64fmin_p : def_strict_fp_3op<"FMIN_PRED", SDT_AArch64Arith>;
+defm AArch64fminnm_p : def_strict_fp_3op<"FMINNM_PRED", SDT_AArch64Arith>;
+defm AArch64fmul_p : def_strict_fp_3op<"FMUL_PRED", SDT_AArch64Arith>;
+defm AArch64fsub_p : def_strict_fp_3op<"FSUB_PRED", SDT_AArch64Arith>;
+
def AArch64fadd_p_contract : PatFrag<(ops node:$op1, node:$op2, node:$op3),
(AArch64fadd_p node:$op1, node:$op2, node:$op3), [{
return N->getFlags().hasAllowContract();
@@ -313,18 +335,11 @@ def AArch64abs_mt : SDNode<"AArch64ISD::ABS_MERGE_PASSTHRU", SDT_AArch64Arith
def AArch64neg_mt : SDNode<"AArch64ISD::NEG_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64sxt_mt : SDNode<"AArch64ISD::SIGN_EXTEND_INREG_MERGE_PASSTHRU", SDT_AArch64IntExtend>;
def AArch64uxt_mt : SDNode<"AArch64ISD::ZERO_EXTEND_INREG_MERGE_PASSTHRU", SDT_AArch64IntExtend>;
-def AArch64frintp_mt : SDNode<"AArch64ISD::FCEIL_MERGE_PASSTHRU", SDT_AArch64Arith>;
-def AArch64frintm_mt : SDNode<"AArch64ISD::FFLOOR_MERGE_PASSTHRU", SDT_AArch64Arith>;
-def AArch64frinti_mt : SDNode<"AArch64ISD::FNEARBYINT_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64frintx_mt : SDNode<"AArch64ISD::FRINT_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64frint32x_mt : SDNode<"AArch64ISD::FRINT32_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64frint64x_mt : SDNode<"AArch64ISD::FRINT64_MERGE_PASSTHRU", SDT_AArch64Arith>;
-def AArch64frinta_mt : SDNode<"AArch64ISD::FROUND_MERGE_PASSTHRU", SDT_AArch64Arith>;
-def AArch64frintn_mt : SDNode<"AArch64ISD::FROUNDEVEN_MERGE_PASSTHRU", SDT_AArch64Arith>;
-def AArch64frintz_mt : SDNode<"AArch64ISD::FTRUNC_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64frint32z_mt : SDNode<"AArch64ISD::FTRUNC32_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64frint64z_mt : SDNode<"AArch64ISD::FTRUNC64_MERGE_PASSTHRU", SDT_AArch64Arith>;
-def AArch64fsqrt_mt : SDNode<"AArch64ISD::FSQRT_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64frecpx_mt : SDNode<"AArch64ISD::FRECPX_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64rbit_mt : SDNode<"AArch64ISD::BITREVERSE_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64revb_mt : SDNode<"AArch64ISD::BSWAP_MERGE_PASSTHRU", SDT_AArch64Arith>;
@@ -332,6 +347,14 @@ def AArch64revh_mt : SDNode<"AArch64ISD::REVH_MERGE_PASSTHRU", SDT_AArch64Arit
def AArch64revw_mt : SDNode<"AArch64ISD::REVW_MERGE_PASSTHRU", SDT_AArch64Arith>;
def AArch64revd_mt : SDNode<"AArch64ISD::REVD_MERGE_PASSTHRU", SDT_AArch64Arith>;
+defm AArch64frintp_mt : def_strict_fp_3op<"FCEIL_MERGE_PASSTHRU", SDT_AArch64Arith>;
+defm AArch64frintm_mt : def_strict_fp_3op<"FFLOOR_MERGE_PASSTHRU", SDT_AArch64Arith>;
+defm AArch64frinti_mt : def_strict_fp_3op<"FNEARBYINT_MERGE_PASSTHRU", SDT_AArch64Arith>;
+defm AArch64frinta_mt : def_strict_fp_3op<"FROUND_MERGE_PASSTHRU", SDT_AArch64Arith>;
+defm AArch64frintn_mt : def_strict_fp_3op<"FROUNDEVEN_MERGE_PASSTHRU", SDT_AArch64Arith>;
+defm AArch64frintz_mt : def_strict_fp_3op<"FTRUNC_MERGE_PASSTHRU", SDT_AArch64Arith>;
+defm AArch64fsqrt_mt : def_strict_fp_3op<"FSQRT_MERGE_PASSTHRU", SDT_AArch64Arith>;
+
def AArch64fneg_mt_nsz : PatFrag<(ops node:$pred, node:$op, node:$pt),
(AArch64fneg_mt node:$pred, node:$op, node:$pt), [{
return N->getFlags().hasNoSignedZeros();
diff --git a/llvm/test/CodeGen/AArch64/sve-fp-constrained-intrinsics.ll b/llvm/test/CodeGen/AArch64/sve-fp-constrained-intrinsics.ll
new file mode 100644
index 0000000000000..b1e1ebdf5b094
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve-fp-constrained-intrinsics.ll
@@ -0,0 +1,1084 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mattr=+sve < %s -o - | FileCheck %s
+; RUN: llc -mattr=+sme --force-streaming < %s -o - | FileCheck %s
+
+target triple = "aarch64-unknown-linux-gnu"
+
+;
+; constrained.ceil
+;
+
+define <vscale x 2 x half> @ceil_nxv2f16(<vscale x 2 x half> %a) {
+; CHECK-LABEL: ceil_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintp z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.ceil(<vscale x 2 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @ceil_nxv4f16(<vscale x 4 x half> %a) {
+; CHECK-LABEL: ceil_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frintp z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.ceil(<vscale x 4 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @ceil_nxv8f16(<vscale x 8 x half> %a) {
+; CHECK-LABEL: ceil_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: frintp z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.ceil(<vscale x 8 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @ceil_nxv2f32(<vscale x 2 x float> %a) {
+; CHECK-LABEL: ceil_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintp z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.ceil(<vscale x 2 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @ceil_nxv4f32(<vscale x 4 x float> %a) {
+; CHECK-LABEL: ceil_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frintp z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.ceil(<vscale x 4 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @ceil_nxv2f64(<vscale x 2 x double> %a) {
+; CHECK-LABEL: ceil_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintp z0.d, p0/m, z0.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.ceil(<vscale x 2 x double> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.fadd
+;
+
+define <vscale x 2 x half> @fadd_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b) {
+; CHECK-LABEL: fadd_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fadd z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.fadd(<vscale x 2 x half> %a, <vscale x 2 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @fadd_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b) {
+; CHECK-LABEL: fadd_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fadd z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.fadd(<vscale x 4 x half> %a, <vscale x 4 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @fadd_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b) {
+; CHECK-LABEL: fadd_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fadd z0.h, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.fadd(<vscale x 8 x half> %a, <vscale x 8 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @fadd_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b) {
+; CHECK-LABEL: fadd_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fadd z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.fadd(<vscale x 2 x float> %a, <vscale x 2 x float> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @fadd_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: fadd_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fadd z0.s, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.fadd(<vscale x 4 x float> %a, <vscale x 4 x float> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @fadd_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b) {
+; CHECK-LABEL: fadd_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fadd z0.d, z0.d, z1.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.fadd(<vscale x 2 x double> %a, <vscale x 2 x double> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.fcmp (TODO)
+;
+
+;
+; constrained.fcmps (TODO)
+;
+
+;
+; constrained.fdiv
+;
+
+define <vscale x 2 x half> @fdiv_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b) {
+; CHECK-LABEL: fdiv_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fdiv z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.fdiv(<vscale x 2 x half> %a, <vscale x 2 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @fdiv_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b) {
+; CHECK-LABEL: fdiv_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fdiv z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.fdiv(<vscale x 4 x half> %a, <vscale x 4 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @fdiv_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b) {
+; CHECK-LABEL: fdiv_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: fdiv z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.fdiv(<vscale x 8 x half> %a, <vscale x 8 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @fdiv_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b) {
+; CHECK-LABEL: fdiv_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fdiv z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.fdiv(<vscale x 2 x float> %a, <vscale x 2 x float> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @fdiv_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: fdiv_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fdiv z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.fdiv(<vscale x 4 x float> %a, <vscale x 4 x float> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @fdiv_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b) {
+; CHECK-LABEL: fdiv_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fdiv z0.d, p0/m, z0.d, z1.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.fdiv(<vscale x 2 x double> %a, <vscale x 2 x double> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.floor
+;
+
+define <vscale x 2 x half> @floor_nxv2f16(<vscale x 2 x half> %a) {
+; CHECK-LABEL: floor_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintm z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.floor(<vscale x 2 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @floor_nxv4f16(<vscale x 4 x half> %a) {
+; CHECK-LABEL: floor_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frintm z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.floor(<vscale x 4 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @floor_nxv8f16(<vscale x 8 x half> %a) {
+; CHECK-LABEL: floor_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: frintm z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.floor(<vscale x 8 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @floor_nxv2f32(<vscale x 2 x float> %a) {
+; CHECK-LABEL: floor_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintm z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.floor(<vscale x 2 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @floor_nxv4f32(<vscale x 4 x float> %a) {
+; CHECK-LABEL: floor_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frintm z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.floor(<vscale x 4 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @floor_nxv2f64(<vscale x 2 x double> %a) {
+; CHECK-LABEL: floor_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintm z0.d, p0/m, z0.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.floor(<vscale x 2 x double> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.fma
+;
+
+define <vscale x 2 x half> @fma_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b, <vscale x 2 x half> %c) {
+; CHECK-LABEL: fma_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmad z0.h, p0/m, z1.h, z2.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.fma(<vscale x 2 x half> %a, <vscale x 2 x half> %b, <vscale x 2 x half> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @fma_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b, <vscale x 4 x half> %c) {
+; CHECK-LABEL: fma_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmad z0.h, p0/m, z1.h, z2.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.fma(<vscale x 4 x half> %a, <vscale x 4 x half> %b, <vscale x 4 x half> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @fma_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b, <vscale x 8 x half> %c) {
+; CHECK-LABEL: fma_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: fmad z0.h, p0/m, z1.h, z2.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.fma(<vscale x 8 x half> %a, <vscale x 8 x half> %b, <vscale x 8 x half> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @fma_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b, <vscale x 2 x float> %c) {
+; CHECK-LABEL: fma_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmad z0.s, p0/m, z1.s, z2.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.fma(<vscale x 2 x float> %a, <vscale x 2 x float> %b, <vscale x 2 x float> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @fma_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b, <vscale x 4 x float> %c) {
+; CHECK-LABEL: fma_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmad z0.s, p0/m, z1.s, z2.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.fma(<vscale x 4 x float> %a, <vscale x 4 x float> %b, <vscale x 4 x float> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @fma_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b, <vscale x 2 x double> %c) {
+; CHECK-LABEL: fma_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmad z0.d, p0/m, z1.d, z2.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.fma(<vscale x 2 x double> %a, <vscale x 2 x double> %b, <vscale x 2 x double> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.fmuladd
+;
+
+define <vscale x 2 x half> @fmuladd_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b, <vscale x 2 x half> %c) {
+; CHECK-LABEL: fmuladd_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmad z0.h, p0/m, z1.h, z2.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.fmuladd(<vscale x 2 x half> %a, <vscale x 2 x half> %b, <vscale x 2 x half> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @fmuladd_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b, <vscale x 4 x half> %c) {
+; CHECK-LABEL: fmuladd_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmad z0.h, p0/m, z1.h, z2.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.fmuladd(<vscale x 4 x half> %a, <vscale x 4 x half> %b, <vscale x 4 x half> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @fmuladd_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b, <vscale x 8 x half> %c) {
+; CHECK-LABEL: fmuladd_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: fmad z0.h, p0/m, z1.h, z2.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.fmuladd(<vscale x 8 x half> %a, <vscale x 8 x half> %b, <vscale x 8 x half> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @fmuladd_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b, <vscale x 2 x float> %c) {
+; CHECK-LABEL: fmuladd_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmad z0.s, p0/m, z1.s, z2.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.fmuladd(<vscale x 2 x float> %a, <vscale x 2 x float> %b, <vscale x 2 x float> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @fmuladd_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b, <vscale x 4 x float> %c) {
+; CHECK-LABEL: fmuladd_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmad z0.s, p0/m, z1.s, z2.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.fmuladd(<vscale x 4 x float> %a, <vscale x 4 x float> %b, <vscale x 4 x float> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @fmuladd_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b, <vscale x 2 x double> %c) {
+; CHECK-LABEL: fmuladd_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmad z0.d, p0/m, z1.d, z2.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.fmuladd(<vscale x 2 x double> %a, <vscale x 2 x double> %b, <vscale x 2 x double> %c, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+;constrained.fpext (TODO)
+;
+
+;
+;constrained.fptosi (TODO)
+;
+
+;
+;constrained.fptoui (TODO)
+;
+
+;
+;constrained.fptrunc (TODO)
+;
+
+;
+; constrained.frem (TODO)
+;
+
+;
+; constrained.fsub
+;
+
+define <vscale x 2 x half> @fsub_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b) {
+; CHECK-LABEL: fsub_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fsub z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.fsub(<vscale x 2 x half> %a, <vscale x 2 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @fsub_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b) {
+; CHECK-LABEL: fsub_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fsub z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.fsub(<vscale x 4 x half> %a, <vscale x 4 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @fsub_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b) {
+; CHECK-LABEL: fsub_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fsub z0.h, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.fsub(<vscale x 8 x half> %a, <vscale x 8 x half> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @fsub_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b) {
+; CHECK-LABEL: fsub_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fsub z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.fsub(<vscale x 2 x float> %a, <vscale x 2 x float> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @fsub_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: fsub_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fsub z0.s, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.fsub(<vscale x 4 x float> %a, <vscale x 4 x float> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @fsub_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b) {
+; CHECK-LABEL: fsub_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fsub z0.d, z0.d, z1.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.fsub(<vscale x 2 x double> %a, <vscale x 2 x double> %b, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.ldexp (TODO)
+;
+
+;
+; constrained.llrint (TODO)
+;
+
+;
+; constrained.llround (TODO)
+;
+
+;
+; constrained.lrint (TODO)
+;
+
+;
+; constrained.lround (TODO)
+;
+
+;
+; constrained.maximum
+;
+
+define <vscale x 2 x half> @maximum_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b) {
+; CHECK-LABEL: maximum_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmax z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.maximum(<vscale x 2 x half> %a, <vscale x 2 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @maximum_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b) {
+; CHECK-LABEL: maximum_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmax z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.maximum(<vscale x 4 x half> %a, <vscale x 4 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @maximum_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b) {
+; CHECK-LABEL: maximum_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: fmax z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.maximum(<vscale x 8 x half> %a, <vscale x 8 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @maximum_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b) {
+; CHECK-LABEL: maximum_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmax z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.maximum(<vscale x 2 x float> %a, <vscale x 2 x float> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @maximum_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: maximum_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmax z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.maximum(<vscale x 4 x float> %a, <vscale x 4 x float> %b, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @maximum_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b) {
+; CHECK-LABEL: maximum_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmax z0.d, p0/m, z0.d, z1.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.maximum(<vscale x 2 x double> %a, <vscale x 2 x double> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.maxnum
+;
+
+define <vscale x 2 x half> @maxnum_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b) {
+; CHECK-LABEL: maxnum_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmaxnm z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.maxnum(<vscale x 2 x half> %a, <vscale x 2 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @maxnum_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b) {
+; CHECK-LABEL: maxnum_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmaxnm z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.maxnum(<vscale x 4 x half> %a, <vscale x 4 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @maxnum_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b) {
+; CHECK-LABEL: maxnum_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: fmaxnm z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.maxnum(<vscale x 8 x half> %a, <vscale x 8 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @maxnum_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b) {
+; CHECK-LABEL: maxnum_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmaxnm z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.maxnum(<vscale x 2 x float> %a, <vscale x 2 x float> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @maxnum_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: maxnum_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmaxnm z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.maxnum(<vscale x 4 x float> %a, <vscale x 4 x float> %b, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @maxnum_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b) {
+; CHECK-LABEL: maxnum_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmaxnm z0.d, p0/m, z0.d, z1.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.maxnum(<vscale x 2 x double> %a, <vscale x 2 x double> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.minimum
+;
+
+define <vscale x 2 x half> @minimum_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b) {
+; CHECK-LABEL: minimum_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmin z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.minimum(<vscale x 2 x half> %a, <vscale x 2 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @minimum_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b) {
+; CHECK-LABEL: minimum_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmin z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.minimum(<vscale x 4 x half> %a, <vscale x 4 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @minimum_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b) {
+; CHECK-LABEL: minimum_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: fmin z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.minimum(<vscale x 8 x half> %a, <vscale x 8 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @minimum_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b) {
+; CHECK-LABEL: minimum_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmin z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.minimum(<vscale x 2 x float> %a, <vscale x 2 x float> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @minimum_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: minimum_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fmin z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.minimum(<vscale x 4 x float> %a, <vscale x 4 x float> %b, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @minimum_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b) {
+; CHECK-LABEL: minimum_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fmin z0.d, p0/m, z0.d, z1.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.minimum(<vscale x 2 x double> %a, <vscale x 2 x double> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.minnum
+;
+
+define <vscale x 2 x half> @minnum_nxv2f16(<vscale x 2 x half> %a, <vscale x 2 x half> %b) {
+; CHECK-LABEL: minnum_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fminnm z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.minnum(<vscale x 2 x half> %a, <vscale x 2 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @minnum_nxv4f16(<vscale x 4 x half> %a, <vscale x 4 x half> %b) {
+; CHECK-LABEL: minnum_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fminnm z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.minnum(<vscale x 4 x half> %a, <vscale x 4 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @minnum_nxv8f16(<vscale x 8 x half> %a, <vscale x 8 x half> %b) {
+; CHECK-LABEL: minnum_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: fminnm z0.h, p0/m, z0.h, z1.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.minnum(<vscale x 8 x half> %a, <vscale x 8 x half> %b, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @minnum_nxv2f32(<vscale x 2 x float> %a, <vscale x 2 x float> %b) {
+; CHECK-LABEL: minnum_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fminnm z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.minnum(<vscale x 2 x float> %a, <vscale x 2 x float> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @minnum_nxv4f32(<vscale x 4 x float> %a, <vscale x 4 x float> %b) {
+; CHECK-LABEL: minnum_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fminnm z0.s, p0/m, z0.s, z1.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.minnum(<vscale x 4 x float> %a, <vscale x 4 x float> %b, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @minnum_nxv2f64(<vscale x 2 x double> %a, <vscale x 2 x double> %b) {
+; CHECK-LABEL: minnum_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fminnm z0.d, p0/m, z0.d, z1.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.minnum(<vscale x 2 x double> %a, <vscale x 2 x double> %b, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.nearbyint
+;
+
+define <vscale x 2 x half> @nearbyint_nxv2f16(<vscale x 2 x half> %a) {
+; CHECK-LABEL: nearbyint_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frinti z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.nearbyint(<vscale x 2 x half> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @nearbyint_nxv4f16(<vscale x 4 x half> %a) {
+; CHECK-LABEL: nearbyint_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frinti z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.nearbyint(<vscale x 4 x half> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @nearbyint_nxv8f16(<vscale x 8 x half> %a) {
+; CHECK-LABEL: nearbyint_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: frinti z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.nearbyint(<vscale x 8 x half> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @nearbyint_nxv2f32(<vscale x 2 x float> %a) {
+; CHECK-LABEL: nearbyint_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frinti z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.nearbyint(<vscale x 2 x float> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @nearbyint_nxv4f32(<vscale x 4 x float> %a) {
+; CHECK-LABEL: nearbyint_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frinti z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.nearbyint(<vscale x 4 x float> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @nearbyint_nxv2f64(<vscale x 2 x double> %a) {
+; CHECK-LABEL: nearbyint_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frinti z0.d, p0/m, z0.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.nearbyint(<vscale x 2 x double> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.rint (TODO)
+;
+
+;
+; constrained.round
+;
+
+define <vscale x 2 x half> @round_nxv2f16(<vscale x 2 x half> %a) {
+; CHECK-LABEL: round_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frinta z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.round(<vscale x 2 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @round_nxv4f16(<vscale x 4 x half> %a) {
+; CHECK-LABEL: round_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frinta z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.round(<vscale x 4 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @round_nxv8f16(<vscale x 8 x half> %a) {
+; CHECK-LABEL: round_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: frinta z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.round(<vscale x 8 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @round_nxv2f32(<vscale x 2 x float> %a) {
+; CHECK-LABEL: round_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frinta z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.round(<vscale x 2 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @round_nxv4f32(<vscale x 4 x float> %a) {
+; CHECK-LABEL: round_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frinta z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.round(<vscale x 4 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @round_nxv2f64(<vscale x 2 x double> %a) {
+; CHECK-LABEL: round_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frinta z0.d, p0/m, z0.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.round(<vscale x 2 x double> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.roundeven
+;
+
+define <vscale x 2 x half> @roundeven_nxv2f16(<vscale x 2 x half> %a) {
+; CHECK-LABEL: roundeven_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintn z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.roundeven(<vscale x 2 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @roundeven_nxv4f16(<vscale x 4 x half> %a) {
+; CHECK-LABEL: roundeven_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frintn z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.roundeven(<vscale x 4 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @roundeven_nxv8f16(<vscale x 8 x half> %a) {
+; CHECK-LABEL: roundeven_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: frintn z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.roundeven(<vscale x 8 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @roundeven_nxv2f32(<vscale x 2 x float> %a) {
+; CHECK-LABEL: roundeven_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintn z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.roundeven(<vscale x 2 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @roundeven_nxv4f32(<vscale x 4 x float> %a) {
+; CHECK-LABEL: roundeven_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frintn z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.roundeven(<vscale x 4 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @roundeven_nxv2f64(<vscale x 2 x double> %a) {
+; CHECK-LABEL: roundeven_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintn z0.d, p0/m, z0.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.roundeven(<vscale x 2 x double> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained.sqrt
+;
+
+define <vscale x 2 x half> @sqrt_nxv2f16(<vscale x 2 x half> %a) {
+; CHECK-LABEL: sqrt_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fsqrt z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.sqrt(<vscale x 2 x half> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @sqrt_nxv4f16(<vscale x 4 x half> %a) {
+; CHECK-LABEL: sqrt_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fsqrt z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.sqrt(<vscale x 4 x half> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @sqrt_nxv8f16(<vscale x 8 x half> %a) {
+; CHECK-LABEL: sqrt_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: fsqrt z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.sqrt(<vscale x 8 x half> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @sqrt_nxv2f32(<vscale x 2 x float> %a) {
+; CHECK-LABEL: sqrt_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fsqrt z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.sqrt(<vscale x 2 x float> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @sqrt_nxv4f32(<vscale x 4 x float> %a) {
+; CHECK-LABEL: sqrt_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: fsqrt z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.sqrt(<vscale x 4 x float> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @sqrt_nxv2f64(<vscale x 2 x double> %a) {
+; CHECK-LABEL: sqrt_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: fsqrt z0.d, p0/m, z0.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.sqrt(<vscale x 2 x double> %a, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained_sitofp (TODO)
+;
+
+;
+; constrained.trunc
+;
+
+define <vscale x 2 x half> @trunc_nxv2f16(<vscale x 2 x half> %a) {
+; CHECK-LABEL: trunc_nxv2f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintz z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x half> @llvm.experimental.constrained.trunc(<vscale x 2 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x half> %r
+}
+
+define <vscale x 4 x half> @trunc_nxv4f16(<vscale x 4 x half> %a) {
+; CHECK-LABEL: trunc_nxv4f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frintz z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x half> @llvm.experimental.constrained.trunc(<vscale x 4 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x half> %r
+}
+
+define <vscale x 8 x half> @trunc_nxv8f16(<vscale x 8 x half> %a) {
+; CHECK-LABEL: trunc_nxv8f16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.h
+; CHECK-NEXT: frintz z0.h, p0/m, z0.h
+; CHECK-NEXT: ret
+ %r = call <vscale x 8 x half> @llvm.experimental.constrained.trunc(<vscale x 8 x half> %a, metadata !"fpexcept.strict")
+ ret <vscale x 8 x half> %r
+}
+
+define <vscale x 2 x float> @trunc_nxv2f32(<vscale x 2 x float> %a) {
+; CHECK-LABEL: trunc_nxv2f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintz z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x float> @llvm.experimental.constrained.trunc(<vscale x 2 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x float> %r
+}
+
+define <vscale x 4 x float> @trunc_nxv4f32(<vscale x 4 x float> %a) {
+; CHECK-LABEL: trunc_nxv4f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.s
+; CHECK-NEXT: frintz z0.s, p0/m, z0.s
+; CHECK-NEXT: ret
+ %r = call <vscale x 4 x float> @llvm.experimental.constrained.trunc(<vscale x 4 x float> %a, metadata !"fpexcept.strict")
+ ret <vscale x 4 x float> %r
+}
+
+define <vscale x 2 x double> @trunc_nxv2f64(<vscale x 2 x double> %a) {
+; CHECK-LABEL: trunc_nxv2f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: ptrue p0.d
+; CHECK-NEXT: frintz z0.d, p0/m, z0.d
+; CHECK-NEXT: ret
+ %r = call <vscale x 2 x double> @llvm.experimental.constrained.trunc(<vscale x 2 x double> %a, metadata !"fpexcept.strict")
+ ret <vscale x 2 x double> %r
+}
+
+;
+; constrained_uitofp (TODO)
+;
+
More information about the llvm-commits
mailing list