diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -64,9 +64,10 @@ case OverloadKind::VOID: case OverloadKind::ObjectType: case OverloadKind::UserDefineType: - llvm_unreachable("invalid overload type for name"); - return "void"; + break; } + llvm_unreachable("invalid overload type for name"); + return "void"; } static OverloadKind getOverloadKind(Type *Ty) { @@ -233,13 +234,17 @@ static bool lowerIntrinsics(Module &M) { bool Updated = false; - static SmallDenseMap LowerMap = { - {Intrinsic::sin, DXIL::OpCode::Sin}, - {Intrinsic::umax, DXIL::OpCode::UMax}}; + +#define DXIL_OP_INTRINSIC_MAP +#include "DXILOperation.inc" +#undef DXIL_OP_INTRINSIC_MAP + for (Function &F : make_early_inc_range(M.functions())) { if (!F.isDeclaration()) continue; Intrinsic::ID ID = F.getIntrinsicID(); + if (ID == Intrinsic::not_intrinsic) + continue; auto LowerIt = LowerMap.find(ID); if (LowerIt == LowerMap.end()) continue; diff --git a/llvm/utils/TableGen/DXILEmitter.cpp b/llvm/utils/TableGen/DXILEmitter.cpp --- a/llvm/utils/TableGen/DXILEmitter.cpp +++ b/llvm/utils/TableGen/DXILEmitter.cpp @@ -59,8 +59,10 @@ SmallVector Params; // the operands that this instruction takes StringRef OverloadTypes; // overload types if applicable StringRef FnAttr; // attribute shorthands: rn=does not access - // memory,ro=only reads from memory, - bool IsDeriv; // whether this is some kind of derivative + // memory,ro=only reads from memory + StringRef Intrinsic; // The llvm intrinsic map to DXILOp. Default is "" which + // means no map exist + bool IsDeriv; // whether this is some kind of derivative bool IsGradient; // whether this requires a gradient calculation bool IsFeedback; // whether this is a sampler feedback op bool IsWave; // whether this requires in-wave, cross-lane functionality @@ -79,7 +81,16 @@ DXILClass = R->getValueAsDef("op_class")->getValueAsString("name"); Category = R->getValueAsDef("category")->getValueAsString("name"); + if (R->getValue("llvm_intrinsic")) { + auto *IntrinsicDef = R->getValueAsDef("llvm_intrinsic"); + auto DefName = IntrinsicDef->getName(); + assert(DefName.startswith("int_") && "invalid intrinsic name"); + // Remove the int_ from intrinsic name. + Intrinsic = DefName.substr(4); + } + Doc = R->getValueAsString("doc"); + ListInit *ParamList = R->getValueAsListInit("ops"); for (unsigned i = 0; i < ParamList->size(); ++i) { Record *Param = ParamList->getElementAsRecord(i); @@ -179,6 +190,24 @@ OS << "\n};\n\n"; } +// Emit map from llvm intrinsic to DXIL operation. +static void EmitDXILIntrinsicMap(std::vector &DXILOps, + raw_ostream &OS) { + OS << "\n"; + // FIXME: use array instead of SmallDenseMap. + OS << "static const SmallDenseMap LowerMap = " + "{\n"; + for (auto &DXILOp : DXILOps) { + if (DXILOp.Intrinsic.empty()) + continue; + // {Intrinsic::sin, DXIL::OpCode::Sin}, + OS << " { Intrinsic::" << DXILOp.Intrinsic + << ", DXIL::OpCode::" << DXILOp.DXILOp << "},\n"; + } + OS << "};\n"; + OS << "\n"; +} + namespace llvm { void EmitDXILOperation(RecordKeeper &Records, raw_ostream &OS) { @@ -196,6 +225,11 @@ emitDXILEnums(DXILOps, OS); OS << "#endif\n\n"; + OS << "#ifdef DXIL_OP_INTRINSIC_MAP\n"; + EmitDXILIntrinsicMap(DXILOps, OS); + OS << "#endif\n\n"; + + OS << "\n"; }