diff options
Diffstat (limited to 'clang/utils/TableGen')
-rw-r--r-- | clang/utils/TableGen/MveEmitter.cpp | 122 |
1 files changed, 101 insertions, 21 deletions
diff --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp index aa3b475ea7b..2941cb6ec08 100644 --- a/clang/utils/TableGen/MveEmitter.cpp +++ b/clang/utils/TableGen/MveEmitter.cpp @@ -283,12 +283,9 @@ class VectorType : public CRegularNamedType { unsigned Lanes; public: - VectorType(const ScalarType *Element) - : CRegularNamedType(TypeKind::Vector), Element(Element) { - // MVE has a fixed 128-bit vector size - Lanes = 128 / Element->sizeInBits(); - } - unsigned sizeInBits() const override { return 128; } + VectorType(const ScalarType *Element, unsigned Lanes) + : CRegularNamedType(TypeKind::Vector), Element(Element), Lanes(Lanes) {} + unsigned sizeInBits() const override { return Lanes * Element->sizeInBits(); } unsigned lanes() const { return Lanes; } bool requiresFloat() const override { return Element->requiresFloat(); } std::string cNameBase() const override { @@ -609,24 +606,41 @@ public: } }; +// Result subclass representing a cast between different pointer types. +class PointerCastResult : public Result { +public: + const PointerType *PtrType; + Ptr V; + PointerCastResult(const PointerType *PtrType, Ptr V) + : PtrType(PtrType), V(V) {} + void genCode(raw_ostream &OS, + CodeGenParamAllocator &ParamAlloc) const override { + OS << "Builder.CreatePointerCast(" << V->asValue() << ", " + << ParamAlloc.allocParam("llvm::Type *", PtrType->llvmName()) << ")"; + } + void morePrerequisites(std::vector<Ptr> &output) const override { + output.push_back(V); + } +}; + // Result subclass representing a call to an IRBuilder method. Each IRBuilder // method we want to use will have a Tablegen record giving the method name and // describing any important details of how to call it, such as whether a // particular argument should be an integer constant instead of an llvm::Value. class IRBuilderResult : public Result { public: - StringRef BuilderMethod; + StringRef CallPrefix; std::vector<Ptr> Args; std::set<unsigned> AddressArgs; std::set<unsigned> IntConstantArgs; - IRBuilderResult(StringRef BuilderMethod, std::vector<Ptr> Args, + IRBuilderResult(StringRef CallPrefix, std::vector<Ptr> Args, std::set<unsigned> AddressArgs, std::set<unsigned> IntConstantArgs) - : BuilderMethod(BuilderMethod), Args(Args), AddressArgs(AddressArgs), + : CallPrefix(CallPrefix), Args(Args), AddressArgs(AddressArgs), IntConstantArgs(IntConstantArgs) {} void genCode(raw_ostream &OS, CodeGenParamAllocator &ParamAlloc) const override { - OS << "Builder." << BuilderMethod << "("; + OS << CallPrefix; const char *Sep = ""; for (unsigned i = 0, e = Args.size(); i < e; ++i) { Ptr Arg = Args[i]; @@ -652,6 +666,25 @@ public: } }; +// Result subclass representing making an Address out of a Value. +class AddressResult : public Result { +public: + Ptr Arg; + unsigned Align; + AddressResult(Ptr Arg, unsigned Align) : Arg(Arg), Align(Align) {} + void genCode(raw_ostream &OS, + CodeGenParamAllocator &ParamAlloc) const override { + OS << "Address(" << Arg->varname() << ", CharUnits::fromQuantity(" + << Align << "))"; + } + std::string typeName() const override { + return "Address"; + } + void morePrerequisites(std::vector<Ptr> &output) const override { + output.push_back(Arg); + } +}; + // Result subclass representing a call to an IR intrinsic, which we first have // to look up using an Intrinsic::ID constant and an array of types. class IRIntrinsicResult : public Result { @@ -665,7 +698,7 @@ public: void genCode(raw_ostream &OS, CodeGenParamAllocator &ParamAlloc) const override { std::string IntNo = ParamAlloc.allocParam( - "Intrinsic::ID", "Intrinsic::arm_mve_" + IntrinsicID); + "Intrinsic::ID", "Intrinsic::" + IntrinsicID); OS << "Builder.CreateCall(CGM.getIntrinsic(" << IntNo; if (!ParamTypes.empty()) { OS << ", llvm::SmallVector<llvm::Type *, " << ParamTypes.size() << "> {"; @@ -689,6 +722,20 @@ public: } }; +// Result subclass that specifies a type, for use in IRBuilder operations such +// as CreateBitCast that take a type argument. +class TypeResult : public Result { +public: + const Type *T; + TypeResult(const Type *T) : T(T) {} + void genCode(raw_ostream &OS, CodeGenParamAllocator &) const override { + OS << T->llvmName(); + } + std::string typeName() const override { + return "llvm::Type *"; + } +}; + // ----------------------------------------------------------------------------- // Class that describes a single ACLE intrinsic. // @@ -852,7 +899,8 @@ class MveEmitter { // MveEmitter holds a collection of all the types we've instantiated. VoidType Void; std::map<std::string, std::unique_ptr<ScalarType>> ScalarTypes; - std::map<std::pair<ScalarTypeKind, unsigned>, std::unique_ptr<VectorType>> + std::map<std::tuple<ScalarTypeKind, unsigned, unsigned>, + std::unique_ptr<VectorType>> VectorTypes; std::map<std::pair<std::string, unsigned>, std::unique_ptr<MultiVectorType>> MultiVectorTypes; @@ -872,12 +920,16 @@ public: const ScalarType *getScalarType(Record *R) { return getScalarType(R->getName()); } - const VectorType *getVectorType(const ScalarType *ST) { - std::pair<ScalarTypeKind, unsigned> key(ST->kind(), ST->sizeInBits()); + const VectorType *getVectorType(const ScalarType *ST, unsigned Lanes) { + std::tuple<ScalarTypeKind, unsigned, unsigned> key(ST->kind(), + ST->sizeInBits(), Lanes); if (VectorTypes.find(key) == VectorTypes.end()) - VectorTypes[key] = std::make_unique<VectorType>(ST); + VectorTypes[key] = std::make_unique<VectorType>(ST, Lanes); return VectorTypes[key].get(); } + const VectorType *getVectorType(const ScalarType *ST) { + return getVectorType(ST, 128 / ST->sizeInBits()); + } const MultiVectorType *getMultiVectorType(unsigned Registers, const VectorType *VT) { std::pair<std::string, unsigned> key(VT->cNameBase(), Registers); @@ -969,7 +1021,13 @@ const Type *MveEmitter::getType(DagInit *D, const Type *Param) { if (Op->getName() == "CTO_Vec") { const Type *Element = getType(D->getArg(0), Param); - return getVectorType(cast<ScalarType>(Element)); + if (D->getNumArgs() == 1) { + return getVectorType(cast<ScalarType>(Element)); + } else { + const Type *ExistingVector = getType(D->getArg(1), Param); + return getVectorType(cast<ScalarType>(Element), + cast<VectorType>(ExistingVector)->lanes()); + } } if (Op->getName() == "CTO_Pred") { @@ -1035,8 +1093,21 @@ Result::Ptr MveEmitter::getCodeForDag(DagInit *D, const Result::Scope &Scope, else return std::make_shared<IntCastResult>(ST, Arg); } + } else if (const auto *PT = dyn_cast<PointerType>(CastType)) { + return std::make_shared<PointerCastResult>(PT, Arg); } PrintFatalError("Unsupported type cast"); + } else if (Op->getName() == "address") { + if (D->getNumArgs() != 2) + PrintFatalError("'address' should have two arguments"); + Result::Ptr Arg = getCodeForDagArg(D, 0, Scope, Param); + unsigned Alignment; + if (auto *II = dyn_cast<IntInit>(D->getArg(1))) { + Alignment = II->getValue(); + } else { + PrintFatalError("'address' alignment argument should be an integer"); + } + return std::make_shared<AddressResult>(Arg, Alignment); } else if (Op->getName() == "unsignedflag") { if (D->getNumArgs() != 1) PrintFatalError("unsignedflag should have exactly one argument"); @@ -1053,7 +1124,7 @@ Result::Ptr MveEmitter::getCodeForDag(DagInit *D, const Result::Scope &Scope, std::vector<Result::Ptr> Args; for (unsigned i = 0, e = D->getNumArgs(); i < e; ++i) Args.push_back(getCodeForDagArg(D, i, Scope, Param)); - if (Op->isSubClassOf("IRBuilder")) { + if (Op->isSubClassOf("IRBuilderBase")) { std::set<unsigned> AddressArgs; for (unsigned i : Op->getValueAsListOfInts("address_params")) AddressArgs.insert(i); @@ -1061,8 +1132,8 @@ Result::Ptr MveEmitter::getCodeForDag(DagInit *D, const Result::Scope &Scope, for (unsigned i : Op->getValueAsListOfInts("int_constant_params")) IntConstantArgs.insert(i); return std::make_shared<IRBuilderResult>( - Op->getValueAsString("func"), Args, AddressArgs, IntConstantArgs); - } else if (Op->isSubClassOf("IRInt")) { + Op->getValueAsString("prefix"), Args, AddressArgs, IntConstantArgs); + } else if (Op->isSubClassOf("IRIntBase")) { std::vector<const Type *> ParamTypes; for (Record *RParam : Op->getValueAsListOfDefs("params")) ParamTypes.push_back(getType(RParam, Param)); @@ -1099,6 +1170,14 @@ Result::Ptr MveEmitter::getCodeForDagArg(DagInit *D, unsigned ArgNum, if (auto *DI = dyn_cast<DagInit>(Arg)) return getCodeForDag(DI, Scope, Param); + if (auto *DI = dyn_cast<DefInit>(Arg)) { + Record *Rec = DI->getDef(); + if (Rec->isSubClassOf("Type")) { + const Type *T = getType(Rec, Param); + return std::make_shared<TypeResult>(T); + } + } + PrintFatalError("bad dag argument type for code generation"); } @@ -1111,8 +1190,9 @@ Result::Ptr MveEmitter::getCodeForArg(unsigned ArgNum, const Type *ArgType) { V = std::make_shared<IntCastResult>(getScalarType("u32"), V); } else if (const auto *PT = dyn_cast<PredicateType>(ArgType)) { V = std::make_shared<IntCastResult>(getScalarType("u32"), V); - V = std::make_shared<IRIntrinsicResult>( - "pred_i2v", std::vector<const Type *>{PT}, std::vector<Result::Ptr>{V}); + V = std::make_shared<IRIntrinsicResult>("arm_mve_pred_i2v", + std::vector<const Type *>{PT}, + std::vector<Result::Ptr>{V}); } return V; |