diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h index 2e99c9e2ee3e6f..fcd3a1025ac135 100644 --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -707,8 +707,7 @@ class VPBinOpIntrinsic : public VPIntrinsic { /// This is the common base class for constrained floating point intrinsics. class ConstrainedFPIntrinsic : public IntrinsicInst { public: - bool isUnaryOp() const; - bool isTernaryOp() const; + unsigned getNonMetadataArgCount() const; std::optional getRoundingMode() const; std::optional getExceptionBehavior() const; bool isDefaultFPEnvironment() const; diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h index 340c1c326d0665..f79df522dc8056 100644 --- a/llvm/include/llvm/IR/Intrinsics.h +++ b/llvm/include/llvm/IR/Intrinsics.h @@ -109,6 +109,10 @@ namespace Intrinsic { /// Floating-Point Intrinsics". bool isConstrainedFPIntrinsic(ID QID); + /// Returns true if the intrinsic ID is for one of the "Constrained + /// Floating-Point Intrinsics" that take rounding mode metadata. + bool hasConstrainedFPRoundingModeOperand(ID QID); + /// This is a type descriptor which explains the type requirements of an /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index e26c6ca3d61692..77ee5e645288b1 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2053,11 +2053,8 @@ bool IRTranslator::translateConstrainedFPIntrinsic( Flags |= MachineInstr::NoFPExcept; SmallVector VRegs; - VRegs.push_back(getOrCreateVReg(*FPI.getArgOperand(0))); - if (!FPI.isUnaryOp()) - VRegs.push_back(getOrCreateVReg(*FPI.getArgOperand(1))); - if (FPI.isTernaryOp()) - VRegs.push_back(getOrCreateVReg(*FPI.getArgOperand(2))); + for (unsigned I = 0, E = FPI.getNonMetadataArgCount(); I != E; ++I) + VRegs.push_back(getOrCreateVReg(*FPI.getArgOperand(I))); MIRBuilder.buildInstr(Opcode, {getOrCreateVReg(FPI)}, VRegs, Flags); return true; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index cfd82a342433fa..f47aea29625f6a 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7962,16 +7962,8 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic( SDValue Chain = DAG.getRoot(); SmallVector Opers; Opers.push_back(Chain); - if (FPI.isUnaryOp()) { - Opers.push_back(getValue(FPI.getArgOperand(0))); - } else if (FPI.isTernaryOp()) { - Opers.push_back(getValue(FPI.getArgOperand(0))); - Opers.push_back(getValue(FPI.getArgOperand(1))); - Opers.push_back(getValue(FPI.getArgOperand(2))); - } else { - Opers.push_back(getValue(FPI.getArgOperand(0))); - Opers.push_back(getValue(FPI.getArgOperand(1))); - } + for (unsigned I = 0, E = FPI.getNonMetadataArgCount(); I != E; ++I) + Opers.push_back(getValue(FPI.getArgOperand(I))); auto pushOutChain = [this](SDValue Result, fp::ExceptionBehavior EB) { assert(Result.getNode()->getNumValues() == 2); diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index e42248da17422b..7f1e832f8597cb 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1493,7 +1493,19 @@ bool Intrinsic::isConstrainedFPIntrinsic(ID QID) { #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ case Intrinsic::INTRINSIC: #include "llvm/IR/ConstrainedOps.def" +#undef INSTRUCTION return true; + default: + return false; + } +} + +bool Intrinsic::hasConstrainedFPRoundingModeOperand(Intrinsic::ID QID) { + switch (QID) { +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ + case Intrinsic::INTRINSIC: \ + return ROUND_MODE == 1; +#include "llvm/IR/ConstrainedOps.def" #undef INSTRUCTION default: return false; diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 9ec5a7deeec632..c6f20af0f1dfbe 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -1029,17 +1029,7 @@ CallInst *IRBuilderBase::CreateConstrainedFPCast( UseFMF = FMFSource->getFastMathFlags(); CallInst *C; - bool HasRoundingMD = false; - switch (ID) { - default: - break; -#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: \ - HasRoundingMD = ROUND_MODE; \ - break; -#include "llvm/IR/ConstrainedOps.def" - } - if (HasRoundingMD) { + if (Intrinsic::hasConstrainedFPRoundingModeOperand(ID)) { Value *RoundingV = getConstrainedFPRounding(Rounding); C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, RoundingV, ExceptV}, nullptr, Name); @@ -1088,17 +1078,8 @@ CallInst *IRBuilderBase::CreateConstrainedFPCall( llvm::SmallVector UseArgs; append_range(UseArgs, Args); - bool HasRoundingMD = false; - switch (Callee->getIntrinsicID()) { - default: - break; -#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: \ - HasRoundingMD = ROUND_MODE; \ - break; -#include "llvm/IR/ConstrainedOps.def" - } - if (HasRoundingMD) + + if (Intrinsic::hasConstrainedFPRoundingModeOperand(Callee->getIntrinsicID())) UseArgs.push_back(getConstrainedFPRounding(Rounding)); UseArgs.push_back(getConstrainedFPExcept(Except)); diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp index 6743b315c74a55..e17755c8ad57b7 100644 --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -365,37 +365,23 @@ FCmpInst::Predicate ConstrainedFPCmpIntrinsic::getPredicate() const { return getFPPredicateFromMD(getArgOperand(2)); } -bool ConstrainedFPIntrinsic::isUnaryOp() const { - switch (getIntrinsicID()) { - default: - return false; -#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: \ - return NARG == 1; -#include "llvm/IR/ConstrainedOps.def" - } -} +unsigned ConstrainedFPIntrinsic::getNonMetadataArgCount() const { + // All constrained fp intrinsics have "fpexcept" metadata. + unsigned NumArgs = arg_size() - 1; -bool ConstrainedFPIntrinsic::isTernaryOp() const { - switch (getIntrinsicID()) { - default: - return false; -#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: \ - return NARG == 3; -#include "llvm/IR/ConstrainedOps.def" - } + // Some intrinsics have "round" metadata. + if (Intrinsic::hasConstrainedFPRoundingModeOperand(getIntrinsicID())) + NumArgs -= 1; + + // Compare intrinsics take their predicate as metadata. + if (isa(this)) + NumArgs -= 1; + + return NumArgs; } bool ConstrainedFPIntrinsic::classof(const IntrinsicInst *I) { - switch (I->getIntrinsicID()) { -#define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: -#include "llvm/IR/ConstrainedOps.def" - return true; - default: - return false; - } + return Intrinsic::isConstrainedFPIntrinsic(I->getIntrinsicID()); } ElementCount VPIntrinsic::getStaticVectorLength() const { diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 41d3fce7eef776..aa8160d18edd48 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5384,11 +5384,13 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { } #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID: #include "llvm/IR/VPIntrinsics.def" +#undef BEGIN_REGISTER_VP_INTRINSIC visitVPIntrinsic(cast(Call)); break; #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ case Intrinsic::INTRINSIC: #include "llvm/IR/ConstrainedOps.def" +#undef INSTRUCTION visitConstrainedFPIntrinsic(cast(Call)); break; case Intrinsic::dbg_declare: // llvm.dbg.declare @@ -6527,19 +6529,13 @@ void Verifier::visitVPIntrinsic(VPIntrinsic &VPI) { } void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { - unsigned NumOperands; - bool HasRoundingMD; - switch (FPI.getIntrinsicID()) { -#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: \ - NumOperands = NARG; \ - HasRoundingMD = ROUND_MODE; \ - break; -#include "llvm/IR/ConstrainedOps.def" - default: - llvm_unreachable("Invalid constrained FP intrinsic!"); - } + unsigned NumOperands = FPI.getNonMetadataArgCount(); + bool HasRoundingMD = + Intrinsic::hasConstrainedFPRoundingModeOperand(FPI.getIntrinsicID()); + + // Add the expected number of metadata operands. NumOperands += (1 + HasRoundingMD); + // Compare intrinsics carry an extra predicate metadata operand. if (isa(FPI)) NumOperands += 1; @@ -6553,8 +6549,8 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { Type *ResultTy = FPI.getType(); Check(!ValTy->isVectorTy() && !ResultTy->isVectorTy(), "Intrinsic does not support vectors", &FPI); - } break; + } case Intrinsic::experimental_constrained_lround: case Intrinsic::experimental_constrained_llround: { @@ -6593,8 +6589,8 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { "Intrinsic first argument and result vector lengths must be equal", &FPI); } - } break; + } case Intrinsic::experimental_constrained_sitofp: case Intrinsic::experimental_constrained_uitofp: { @@ -6616,7 +6612,8 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { "Intrinsic first argument and result vector lengths must be equal", &FPI); } - } break; + break; + } case Intrinsic::experimental_constrained_fptrunc: case Intrinsic::experimental_constrained_fpext: { @@ -6645,8 +6642,8 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { "Intrinsic first argument's type must be smaller than result type", &FPI); } - } break; + } default: break; diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index 6f6dc63653c173..6a3b3faac77dfa 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -386,18 +386,6 @@ struct PruningFunctionCloner { }; } // namespace -static bool hasRoundingModeOperand(Intrinsic::ID CIID) { - switch (CIID) { -#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: \ - return ROUND_MODE == 1; -#define FUNCTION INSTRUCTION -#include "llvm/IR/ConstrainedOps.def" - default: - llvm_unreachable("Unexpected constrained intrinsic id"); - } -} - Instruction * PruningFunctionCloner::cloneInstruction(BasicBlock::const_iterator II) { const Instruction &OldInst = *II; @@ -455,7 +443,7 @@ PruningFunctionCloner::cloneInstruction(BasicBlock::const_iterator II) { // The last arguments of a constrained intrinsic are metadata that // represent rounding mode (absents in some intrinsics) and exception // behavior. The inlined function uses default settings. - if (hasRoundingModeOperand(CIID)) + if (Intrinsic::hasConstrainedFPRoundingModeOperand(CIID)) Args.push_back( MetadataAsValue::get(Ctx, MDString::get(Ctx, "round.tonearest"))); Args.push_back(