diff --git a/llvm/include/llvm/IR/ConstrainedOps.def b/llvm/include/llvm/IR/ConstrainedOps.def new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/IR/ConstrainedOps.def @@ -0,0 +1,64 @@ +//===- llvm/IR/ConstrainedOps.def - Constrained intrinsics ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Defines properties of constrained intrinsics, in particular corresponding +// floating point operations and DAG nodes. +// +//===----------------------------------------------------------------------===// + +#ifndef INSTRUCTION +#define INSTRUCTION(N,A,R,I,D) +#endif + +#ifndef FUNCTION +#define FUNCTION(F,A,R,I,D) +#endif + +// Arguments of the entries are: +// - instruction of intrinsic function name. +// - Number of original instruction/intrinsic arguments. +// - 1 if the corresponding constrained intrinsic has rounding mode argument. +// - name of the constrained intrinsic to represent this instruction/function. +// - DAG node corresponding to the constrained intrinsic. + +INSTRUCTION(FAdd, 2, 1, experimental_constrained_fadd, STRICT_FADD) +INSTRUCTION(FSub, 2, 1, experimental_constrained_fsub, STRICT_FSUB) +INSTRUCTION(FMul, 2, 1, experimental_constrained_fmul, STRICT_FMUL) +INSTRUCTION(FDiv, 2, 1, experimental_constrained_fdiv, STRICT_FDIV) +INSTRUCTION(FRem, 2, 1, experimental_constrained_frem, STRICT_FREM) +INSTRUCTION(FPExt, 1, 0, experimental_constrained_fpext, STRICT_FP_EXTEND) +INSTRUCTION(FPToSI, 1, 0, experimental_constrained_fptosi, STRICT_FP_TO_SINT) +INSTRUCTION(FPToUI, 1, 0, experimental_constrained_fptoui, STRICT_FP_TO_UINT) +INSTRUCTION(FPTrunc, 1, 1, experimental_constrained_fptrunc, STRICT_FP_ROUND) + +FUNCTION(ceil, 1, 1, experimental_constrained_ceil, STRICT_FCEIL) +FUNCTION(cos, 1, 1, experimental_constrained_cos, STRICT_FCOS) +FUNCTION(exp, 1, 1, experimental_constrained_exp, STRICT_FEXP) +FUNCTION(exp2, 1, 1, experimental_constrained_exp2, STRICT_FEXP2) +FUNCTION(floor, 1, 1, experimental_constrained_floor, STRICT_FFLOOR) +FUNCTION(fma, 3, 1, experimental_constrained_fma, STRICT_FMA) +FUNCTION(log, 1, 1, experimental_constrained_log, STRICT_FLOG) +FUNCTION(log10, 1, 1, experimental_constrained_log10, STRICT_FLOG10) +FUNCTION(log2, 1, 1, experimental_constrained_log2, STRICT_FLOG2) +FUNCTION(lrint, 1, 1, experimental_constrained_lrint, STRICT_LRINT) +FUNCTION(llrint, 1, 1, experimental_constrained_llrint, STRICT_LLRINT) +FUNCTION(lround, 1, 0, experimental_constrained_lround, STRICT_LROUND) +FUNCTION(llround, 1, 0, experimental_constrained_llround, STRICT_LLROUND) +FUNCTION(maxnum, 2, 1, experimental_constrained_maxnum, STRICT_FMAXNUM) +FUNCTION(minnum, 2, 1, experimental_constrained_minnum, STRICT_FMINNUM) +FUNCTION(nearbyint, 1, 1, experimental_constrained_nearbyint, STRICT_FNEARBYINT) +FUNCTION(pow, 2, 1, experimental_constrained_pow, STRICT_FPOW) +FUNCTION(powi, 2, 1, experimental_constrained_powi, STRICT_FPOWI) +FUNCTION(rint, 1, 1, experimental_constrained_rint, STRICT_FRINT) +FUNCTION(round, 1, 1, experimental_constrained_round, STRICT_FROUND) +FUNCTION(sin, 1, 1, experimental_constrained_sin, STRICT_FSIN) +FUNCTION(sqrt, 1, 1, experimental_constrained_sqrt, STRICT_FSQRT) +FUNCTION(trunc, 1, 1, experimental_constrained_trunc, STRICT_FTRUNC) + +#undef INSTRUCTION +#undef FUNCTION diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -251,44 +251,7 @@ static Optional ExceptionBehaviorToStr(ExceptionBehavior); // Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { - case Intrinsic::experimental_constrained_fadd: - case Intrinsic::experimental_constrained_fsub: - case Intrinsic::experimental_constrained_fmul: - case Intrinsic::experimental_constrained_fdiv: - case Intrinsic::experimental_constrained_frem: - case Intrinsic::experimental_constrained_fma: - case Intrinsic::experimental_constrained_fptosi: - case Intrinsic::experimental_constrained_fptoui: - case Intrinsic::experimental_constrained_fptrunc: - case Intrinsic::experimental_constrained_fpext: - case Intrinsic::experimental_constrained_sqrt: - case Intrinsic::experimental_constrained_pow: - case Intrinsic::experimental_constrained_powi: - case Intrinsic::experimental_constrained_sin: - case Intrinsic::experimental_constrained_cos: - case Intrinsic::experimental_constrained_exp: - case Intrinsic::experimental_constrained_exp2: - case Intrinsic::experimental_constrained_log: - case Intrinsic::experimental_constrained_log10: - case Intrinsic::experimental_constrained_log2: - case Intrinsic::experimental_constrained_lrint: - case Intrinsic::experimental_constrained_llrint: - case Intrinsic::experimental_constrained_rint: - case Intrinsic::experimental_constrained_nearbyint: - case Intrinsic::experimental_constrained_maxnum: - case Intrinsic::experimental_constrained_minnum: - case Intrinsic::experimental_constrained_ceil: - case Intrinsic::experimental_constrained_floor: - case Intrinsic::experimental_constrained_lround: - case Intrinsic::experimental_constrained_llround: - case Intrinsic::experimental_constrained_round: - case Intrinsic::experimental_constrained_trunc: - return true; - default: return false; - } - } + static bool classof(const IntrinsicInst *I); static bool classof(const Value *V) { return isa(V) && classof(cast(V)); } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6120,38 +6120,10 @@ getValue(I.getArgOperand(1)), getValue(I.getArgOperand(2)))); return; - case Intrinsic::experimental_constrained_fadd: - case Intrinsic::experimental_constrained_fsub: - case Intrinsic::experimental_constrained_fmul: - case Intrinsic::experimental_constrained_fdiv: - case Intrinsic::experimental_constrained_frem: - case Intrinsic::experimental_constrained_fma: - case Intrinsic::experimental_constrained_fptosi: - case Intrinsic::experimental_constrained_fptoui: - case Intrinsic::experimental_constrained_fptrunc: - case Intrinsic::experimental_constrained_fpext: - case Intrinsic::experimental_constrained_sqrt: - case Intrinsic::experimental_constrained_pow: - case Intrinsic::experimental_constrained_powi: - case Intrinsic::experimental_constrained_sin: - case Intrinsic::experimental_constrained_cos: - case Intrinsic::experimental_constrained_exp: - case Intrinsic::experimental_constrained_exp2: - case Intrinsic::experimental_constrained_log: - case Intrinsic::experimental_constrained_log10: - case Intrinsic::experimental_constrained_log2: - case Intrinsic::experimental_constrained_lrint: - case Intrinsic::experimental_constrained_llrint: - case Intrinsic::experimental_constrained_rint: - case Intrinsic::experimental_constrained_nearbyint: - case Intrinsic::experimental_constrained_maxnum: - case Intrinsic::experimental_constrained_minnum: - case Intrinsic::experimental_constrained_ceil: - case Intrinsic::experimental_constrained_floor: - case Intrinsic::experimental_constrained_lround: - case Intrinsic::experimental_constrained_llround: - case Intrinsic::experimental_constrained_round: - case Intrinsic::experimental_constrained_trunc: +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ + case Intrinsic::INTRINSIC: +#define FUNCTION INSTRUCTION +#include "llvm/IR/ConstrainedOps.def" visitConstrainedFPIntrinsic(cast(I)); return; case Intrinsic::fmuladd: { @@ -6917,106 +6889,18 @@ unsigned Opcode; switch (FPI.getIntrinsicID()) { default: llvm_unreachable("Impossible intrinsic"); // Can't reach here. - case Intrinsic::experimental_constrained_fadd: - Opcode = ISD::STRICT_FADD; - break; - case Intrinsic::experimental_constrained_fsub: - Opcode = ISD::STRICT_FSUB; - break; - case Intrinsic::experimental_constrained_fmul: - Opcode = ISD::STRICT_FMUL; - break; - case Intrinsic::experimental_constrained_fdiv: - Opcode = ISD::STRICT_FDIV; - break; - case Intrinsic::experimental_constrained_frem: - Opcode = ISD::STRICT_FREM; - break; - case Intrinsic::experimental_constrained_fma: - Opcode = ISD::STRICT_FMA; - break; - case Intrinsic::experimental_constrained_fptosi: - Opcode = ISD::STRICT_FP_TO_SINT; - break; - case Intrinsic::experimental_constrained_fptoui: - Opcode = ISD::STRICT_FP_TO_UINT; - break; - case Intrinsic::experimental_constrained_fptrunc: - Opcode = ISD::STRICT_FP_ROUND; - Opers.push_back(DAG.getTargetConstant(0, sdl, - TLI.getPointerTy(DAG.getDataLayout()))); - break; - case Intrinsic::experimental_constrained_fpext: - Opcode = ISD::STRICT_FP_EXTEND; - break; - case Intrinsic::experimental_constrained_sqrt: - Opcode = ISD::STRICT_FSQRT; - break; - case Intrinsic::experimental_constrained_pow: - Opcode = ISD::STRICT_FPOW; - break; - case Intrinsic::experimental_constrained_powi: - Opcode = ISD::STRICT_FPOWI; - break; - case Intrinsic::experimental_constrained_sin: - Opcode = ISD::STRICT_FSIN; - break; - case Intrinsic::experimental_constrained_cos: - Opcode = ISD::STRICT_FCOS; - break; - case Intrinsic::experimental_constrained_exp: - Opcode = ISD::STRICT_FEXP; - break; - case Intrinsic::experimental_constrained_exp2: - Opcode = ISD::STRICT_FEXP2; - break; - case Intrinsic::experimental_constrained_log: - Opcode = ISD::STRICT_FLOG; - break; - case Intrinsic::experimental_constrained_log10: - Opcode = ISD::STRICT_FLOG10; - break; - case Intrinsic::experimental_constrained_log2: - Opcode = ISD::STRICT_FLOG2; - break; - case Intrinsic::experimental_constrained_lrint: - Opcode = ISD::STRICT_LRINT; - break; - case Intrinsic::experimental_constrained_llrint: - Opcode = ISD::STRICT_LLRINT; - break; - case Intrinsic::experimental_constrained_rint: - Opcode = ISD::STRICT_FRINT; - break; - case Intrinsic::experimental_constrained_nearbyint: - Opcode = ISD::STRICT_FNEARBYINT; - break; - case Intrinsic::experimental_constrained_maxnum: - Opcode = ISD::STRICT_FMAXNUM; - break; - case Intrinsic::experimental_constrained_minnum: - Opcode = ISD::STRICT_FMINNUM; - break; - case Intrinsic::experimental_constrained_ceil: - Opcode = ISD::STRICT_FCEIL; - break; - case Intrinsic::experimental_constrained_floor: - Opcode = ISD::STRICT_FFLOOR; - break; - case Intrinsic::experimental_constrained_lround: - Opcode = ISD::STRICT_LROUND; - break; - case Intrinsic::experimental_constrained_llround: - Opcode = ISD::STRICT_LLROUND; - break; - case Intrinsic::experimental_constrained_round: - Opcode = ISD::STRICT_FROUND; - break; - case Intrinsic::experimental_constrained_trunc: - Opcode = ISD::STRICT_FTRUNC; +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ + case Intrinsic::INTRINSIC: \ + Opcode = ISD::DAGN; \ break; +#define FUNCTION INSTRUCTION +#include "llvm/IR/ConstrainedOps.def" } + if (Opcode == ISD::STRICT_FP_ROUND) + Opers.push_back( + DAG.getTargetConstant(0, sdl, TLI.getPointerTy(DAG.getDataLayout()))); + SDVTList VTs = DAG.getVTList(ValueVTs); SDValue Result = DAG.getNode(Opcode, sdl, VTs, Opers); diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -188,29 +188,11 @@ switch (getIntrinsicID()) { default: return false; - case Intrinsic::experimental_constrained_fptosi: - case Intrinsic::experimental_constrained_fptoui: - case Intrinsic::experimental_constrained_fptrunc: - case Intrinsic::experimental_constrained_fpext: - case Intrinsic::experimental_constrained_sqrt: - case Intrinsic::experimental_constrained_sin: - case Intrinsic::experimental_constrained_cos: - case Intrinsic::experimental_constrained_exp: - case Intrinsic::experimental_constrained_exp2: - case Intrinsic::experimental_constrained_log: - case Intrinsic::experimental_constrained_log10: - case Intrinsic::experimental_constrained_log2: - case Intrinsic::experimental_constrained_lrint: - case Intrinsic::experimental_constrained_llrint: - case Intrinsic::experimental_constrained_rint: - case Intrinsic::experimental_constrained_nearbyint: - case Intrinsic::experimental_constrained_ceil: - case Intrinsic::experimental_constrained_floor: - case Intrinsic::experimental_constrained_lround: - case Intrinsic::experimental_constrained_llround: - case Intrinsic::experimental_constrained_round: - case Intrinsic::experimental_constrained_trunc: - return true; +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ + case Intrinsic::INTRINSIC: \ + return NARG == 1; +#define FUNCTION INSTRUCTION +#include "llvm/IR/ConstrainedOps.def" } } @@ -223,6 +205,18 @@ } } +bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { +#define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC, DAGN) \ + case Intrinsic::INTRINSIC: +#define FUNCTION INSTRUCTION +#include "llvm/IR/ConstrainedOps.def" + return true; + default: + return false; + } +} + Instruction::BinaryOps BinaryOpIntrinsic::getBinaryOp() const { switch (getIntrinsicID()) { case Intrinsic::uadd_with_overflow: diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4300,38 +4300,10 @@ "an array"); break; } - case Intrinsic::experimental_constrained_fadd: - case Intrinsic::experimental_constrained_fsub: - case Intrinsic::experimental_constrained_fmul: - case Intrinsic::experimental_constrained_fdiv: - case Intrinsic::experimental_constrained_frem: - case Intrinsic::experimental_constrained_fma: - case Intrinsic::experimental_constrained_fptosi: - case Intrinsic::experimental_constrained_fptoui: - case Intrinsic::experimental_constrained_fptrunc: - case Intrinsic::experimental_constrained_fpext: - case Intrinsic::experimental_constrained_sqrt: - case Intrinsic::experimental_constrained_pow: - case Intrinsic::experimental_constrained_powi: - case Intrinsic::experimental_constrained_sin: - case Intrinsic::experimental_constrained_cos: - case Intrinsic::experimental_constrained_exp: - case Intrinsic::experimental_constrained_exp2: - case Intrinsic::experimental_constrained_log: - case Intrinsic::experimental_constrained_log10: - case Intrinsic::experimental_constrained_log2: - case Intrinsic::experimental_constrained_lrint: - case Intrinsic::experimental_constrained_llrint: - case Intrinsic::experimental_constrained_rint: - case Intrinsic::experimental_constrained_nearbyint: - case Intrinsic::experimental_constrained_maxnum: - case Intrinsic::experimental_constrained_minnum: - case Intrinsic::experimental_constrained_ceil: - case Intrinsic::experimental_constrained_floor: - case Intrinsic::experimental_constrained_lround: - case Intrinsic::experimental_constrained_llround: - case Intrinsic::experimental_constrained_round: - case Intrinsic::experimental_constrained_trunc: +#define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC, DAGN) \ + case Intrinsic::INTRINSIC: +#define FUNCTION INSTRUCTION +#include "llvm/IR/ConstrainedOps.def" visitConstrainedFPIntrinsic(cast(Call)); break; case Intrinsic::dbg_declare: // llvm.dbg.declare @@ -4758,83 +4730,45 @@ } void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { - unsigned NumOperands = FPI.getNumArgOperands(); - bool HasExceptionMD = false; - bool HasRoundingMD = false; + unsigned NumOperands; + bool HasRoundingMD; switch (FPI.getIntrinsicID()) { - case Intrinsic::experimental_constrained_sqrt: - case Intrinsic::experimental_constrained_sin: - case Intrinsic::experimental_constrained_cos: - case Intrinsic::experimental_constrained_exp: - case Intrinsic::experimental_constrained_exp2: - case Intrinsic::experimental_constrained_log: - case Intrinsic::experimental_constrained_log10: - case Intrinsic::experimental_constrained_log2: - case Intrinsic::experimental_constrained_rint: - case Intrinsic::experimental_constrained_nearbyint: - case Intrinsic::experimental_constrained_ceil: - case Intrinsic::experimental_constrained_floor: - case Intrinsic::experimental_constrained_round: - case Intrinsic::experimental_constrained_trunc: - Assert((NumOperands == 3), "invalid arguments for constrained FP intrinsic", - &FPI); - HasExceptionMD = true; - HasRoundingMD = true; +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN) \ + case Intrinsic::INTRINSIC: \ + NumOperands = NARG; \ + HasRoundingMD = ROUND_MODE; \ break; +#define FUNCTION INSTRUCTION +#include "llvm/IR/ConstrainedOps.def" + default: + llvm_unreachable("Invalid constrained FP intrinsic!"); + } + NumOperands += (1 + HasRoundingMD); + unsigned ActualNumOperands = FPI.getNumArgOperands(); + Assert((NumOperands == ActualNumOperands), + "invalid arguments for constrained FP intrinsic", &FPI); + switch (FPI.getIntrinsicID()) { case Intrinsic::experimental_constrained_lrint: case Intrinsic::experimental_constrained_llrint: { - Assert((NumOperands == 3), "invalid arguments for constrained FP intrinsic", - &FPI); Type *ValTy = FPI.getArgOperand(0)->getType(); Type *ResultTy = FPI.getType(); Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(), "Intrinsic does not support vectors", &FPI); - HasExceptionMD = true; - HasRoundingMD = true; } break; case Intrinsic::experimental_constrained_lround: case Intrinsic::experimental_constrained_llround: { - Assert((NumOperands == 2), "invalid arguments for constrained FP intrinsic", - &FPI); Type *ValTy = FPI.getArgOperand(0)->getType(); Type *ResultTy = FPI.getType(); Assert(!ValTy->isVectorTy() && !ResultTy->isVectorTy(), "Intrinsic does not support vectors", &FPI); - HasExceptionMD = true; break; } - case Intrinsic::experimental_constrained_fma: - Assert((NumOperands == 5), "invalid arguments for constrained FP intrinsic", - &FPI); - HasExceptionMD = true; - HasRoundingMD = true; - break; - - case Intrinsic::experimental_constrained_fadd: - case Intrinsic::experimental_constrained_fsub: - case Intrinsic::experimental_constrained_fmul: - case Intrinsic::experimental_constrained_fdiv: - case Intrinsic::experimental_constrained_frem: - case Intrinsic::experimental_constrained_pow: - case Intrinsic::experimental_constrained_powi: - case Intrinsic::experimental_constrained_maxnum: - case Intrinsic::experimental_constrained_minnum: - Assert((NumOperands == 4), "invalid arguments for constrained FP intrinsic", - &FPI); - HasExceptionMD = true; - HasRoundingMD = true; - break; - case Intrinsic::experimental_constrained_fptosi: case Intrinsic::experimental_constrained_fptoui: { - Assert((NumOperands == 2), - "invalid arguments for constrained FP intrinsic", &FPI); - HasExceptionMD = true; - Value *Operand = FPI.getArgOperand(0); uint64_t NumSrcElem = 0; Assert(Operand->getType()->isFPOrFPVectorTy(), @@ -4858,16 +4792,6 @@ case Intrinsic::experimental_constrained_fptrunc: case Intrinsic::experimental_constrained_fpext: { - if (FPI.getIntrinsicID() == Intrinsic::experimental_constrained_fptrunc) { - Assert((NumOperands == 3), - "invalid arguments for constrained FP intrinsic", &FPI); - HasRoundingMD = true; - } else { - Assert((NumOperands == 2), - "invalid arguments for constrained FP intrinsic", &FPI); - } - HasExceptionMD = true; - Value *Operand = FPI.getArgOperand(0); Type *OperandTy = Operand->getType(); Value *Result = &FPI; @@ -4898,7 +4822,7 @@ break; default: - llvm_unreachable("Invalid constrained FP intrinsic!"); + break; } // If a non-metadata argument is passed in a metadata slot then the @@ -4906,10 +4830,8 @@ // match the specification in the intrinsic call table. Thus, no // argument type check is needed here. - if (HasExceptionMD) { - Assert(FPI.getExceptionBehavior().hasValue(), - "invalid exception behavior argument", &FPI); - } + Assert(FPI.getExceptionBehavior().hasValue(), + "invalid exception behavior argument", &FPI); if (HasRoundingMD) { Assert(FPI.getRoundingMode().hasValue(), "invalid rounding mode argument", &FPI);