diff options
Diffstat (limited to 'utils/TableGen/NeonEmitter.cpp')
| -rw-r--r-- | utils/TableGen/NeonEmitter.cpp | 98 |
1 files changed, 63 insertions, 35 deletions
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index b5313a073d16..49c1edce3220 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -24,24 +24,32 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/SetTheory.h" -#include "llvm/TableGen/TableGenBackend.h" #include <algorithm> +#include <cassert> +#include <cctype> +#include <cstddef> +#include <cstdint> #include <deque> #include <map> +#include <set> #include <sstream> #include <string> #include <utility> #include <vector> + using namespace llvm; namespace { @@ -76,6 +84,7 @@ enum ClassKind { /// builtins. These must be kept in sync with the flags in /// include/clang/Basic/TargetBuiltins.h. namespace NeonTypeFlags { + enum { EltTypeMask = 0xf, UnsignedFlag = 0x10, QuadFlag = 0x20 }; enum EltType { @@ -91,12 +100,10 @@ enum EltType { Float32, Float64 }; -} -class Intrinsic; +} // end namespace NeonTypeFlags + class NeonEmitter; -class Type; -class Variable; //===----------------------------------------------------------------------===// // TypeSpec @@ -192,6 +199,7 @@ public: // void makeUnsigned() { Signed = false; } void makeSigned() { Signed = true; } + void makeInteger(unsigned ElemWidth, bool Sign) { Float = false; Poly = false; @@ -199,6 +207,7 @@ public: Immediate = false; ElementBitwidth = ElemWidth; } + void makeImmediate(unsigned ElemWidth) { Float = false; Poly = false; @@ -206,18 +215,22 @@ public: Immediate = true; ElementBitwidth = ElemWidth; } + void makeScalar() { Bitwidth = ElementBitwidth; NumVectors = 0; } + void makeOneVector() { assert(isVector()); NumVectors = 1; } + void doubleLanes() { assert_with_loc(Bitwidth != 128, "Can't get bigger than 128!"); Bitwidth = 128; } + void halveLanes() { assert_with_loc(Bitwidth != 64, "Can't get smaller than 64!"); Bitwidth = 64; @@ -369,6 +382,7 @@ public: bool hasImmediate() const { return Proto.find('i') != std::string::npos; } + /// Return the parameter index of the immediate operand. unsigned getImmediateIdx() const { assert(hasImmediate()); @@ -379,6 +393,7 @@ public: /// Return true if the intrinsic takes an splat operand. bool hasSplat() const { return Proto.find('a') != std::string::npos; } + /// Return the parameter index of the splat operand. unsigned getSplatIdx() const { assert(hasSplat()); @@ -414,7 +429,7 @@ public: return Idx; } - bool hasBody() const { return Body && Body->getValues().size() > 0; } + bool hasBody() const { return Body && !Body->getValues().empty(); } void setNeededEarly() { NeededEarly = true; } @@ -487,7 +502,6 @@ private: std::pair<Type, std::string> emitDagOp(DagInit *DI); std::pair<Type, std::string> emitDag(DagInit *DI); }; - }; //===----------------------------------------------------------------------===// @@ -1071,7 +1085,7 @@ std::string Intrinsic::mangleName(std::string Name, ClassKind LocalCK) const { Name == "vcvt_f32_f64" || Name == "vcvt_f64_f32") return Name; - if (typeCode.size() > 0) { + if (!typeCode.empty()) { // If the name ends with _xN (N = 2,3,4), insert the typeCode before _xN. if (Name.size() >= 3 && isdigit(Name.back()) && Name[Name.length() - 2] == 'x' && Name[Name.length() - 3] == '_') @@ -1246,7 +1260,6 @@ void Intrinsic::emitReturnReversal() { emitReverseVariable(RetVar, RetVar); } - void Intrinsic::emitShadowedArgs() { // Macro arguments are not type-checked like inline function arguments, // so assign them to local temporaries to get the right type checking. @@ -1397,7 +1410,7 @@ void Intrinsic::emitBody(StringRef CallPrefix) { emitNewLine(); } - if (!Body || Body->getValues().size() == 0) { + if (!Body || Body->getValues().empty()) { // Nothing specific to output - must output a builtin. emitBodyAsBuiltinCall(); return; @@ -1465,14 +1478,14 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagOp(DagInit *DI) { if (DI->getNumArgs() == 2) { // Unary op. std::pair<Type, std::string> R = - emitDagArg(DI->getArg(1), DI->getArgName(1)); + emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); return std::make_pair(R.first, Op + R.second); } else { assert(DI->getNumArgs() == 3 && "Can only handle unary and binary ops!"); std::pair<Type, std::string> R1 = - emitDagArg(DI->getArg(1), DI->getArgName(1)); + emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); std::pair<Type, std::string> R2 = - emitDagArg(DI->getArg(2), DI->getArgName(2)); + emitDagArg(DI->getArg(2), DI->getArgNameStr(2)); assert_with_loc(R1.first == R2.first, "Argument type mismatch!"); return std::make_pair(R1.first, R1.second + " " + Op + " " + R2.second); } @@ -1483,7 +1496,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) { std::vector<std::string> Values; for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { std::pair<Type, std::string> R = - emitDagArg(DI->getArg(I + 1), DI->getArgName(I + 1)); + emitDagArg(DI->getArg(I + 1), DI->getArgNameStr(I + 1)); Types.push_back(R.first); Values.push_back(R.second); } @@ -1516,7 +1529,8 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI, bool IsBitCast){ // (cast MOD* VAL) -> cast VAL to type given by MOD. std::pair<Type, std::string> R = emitDagArg( - DI->getArg(DI->getNumArgs() - 1), DI->getArgName(DI->getNumArgs() - 1)); + DI->getArg(DI->getNumArgs() - 1), + DI->getArgNameStr(DI->getNumArgs() - 1)); Type castToType = R.first; for (unsigned ArgIdx = 0; ArgIdx < DI->getNumArgs() - 1; ++ArgIdx) { @@ -1527,11 +1541,11 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCast(DagInit *DI, // 4. The value "U" or "S" to switch the signedness. // 5. The value "H" or "D" to half or double the bitwidth. // 6. The value "8" to convert to 8-bit (signed) integer lanes. - if (DI->getArgName(ArgIdx).size()) { - assert_with_loc(Intr.Variables.find(DI->getArgName(ArgIdx)) != + if (!DI->getArgNameStr(ArgIdx).empty()) { + assert_with_loc(Intr.Variables.find(DI->getArgNameStr(ArgIdx)) != Intr.Variables.end(), "Variable not found"); - castToType = Intr.Variables[DI->getArgName(ArgIdx)].getType(); + castToType = Intr.Variables[DI->getArgNameStr(ArgIdx)].getType(); } else { StringInit *SI = dyn_cast<StringInit>(DI->getArg(ArgIdx)); assert_with_loc(SI, "Expected string type or $Name for cast type"); @@ -1589,6 +1603,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ Elts.insert(Elts2.begin(), Elts2.begin() + (Elts2.size() / 2)); } }; + class HighHalf : public SetTheory::Operator { public: void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, @@ -1598,11 +1613,13 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ Elts.insert(Elts2.begin() + (Elts2.size() / 2), Elts2.end()); } }; + class Rev : public SetTheory::Operator { unsigned ElementSize; public: Rev(unsigned ElementSize) : ElementSize(ElementSize) {} + void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, ArrayRef<SMLoc> Loc) override { SetTheory::RecSet Elts2; @@ -1621,11 +1638,13 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ Elts.insert(Revved.begin(), Revved.end()); } }; + class MaskExpander : public SetTheory::Expander { unsigned N; public: MaskExpander(unsigned N) : N(N) {} + void expand(SetTheory &ST, Record *R, SetTheory::RecSet &Elts) override { unsigned Addend = 0; if (R->getName() == "mask0") @@ -1641,9 +1660,9 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ // (shuffle arg1, arg2, sequence) std::pair<Type, std::string> Arg1 = - emitDagArg(DI->getArg(0), DI->getArgName(0)); + emitDagArg(DI->getArg(0), DI->getArgNameStr(0)); std::pair<Type, std::string> Arg2 = - emitDagArg(DI->getArg(1), DI->getArgName(1)); + emitDagArg(DI->getArg(1), DI->getArgNameStr(1)); assert_with_loc(Arg1.first == Arg2.first, "Different types in arguments to shuffle!"); @@ -1685,7 +1704,8 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) { assert_with_loc(DI->getNumArgs() == 1, "dup() expects one argument"); - std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0)); + std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), + DI->getArgNameStr(0)); assert_with_loc(A.first.isScalar(), "dup() expects a scalar argument"); Type T = Intr.getBaseType(); @@ -1703,8 +1723,10 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagDup(DagInit *DI) { std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) { assert_with_loc(DI->getNumArgs() == 2, "splat() expects two arguments"); - std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), DI->getArgName(0)); - std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), DI->getArgName(1)); + std::pair<Type, std::string> A = emitDagArg(DI->getArg(0), + DI->getArgNameStr(0)); + std::pair<Type, std::string> B = emitDagArg(DI->getArg(1), + DI->getArgNameStr(1)); assert_with_loc(B.first.isScalar(), "splat() requires a scalar int as the second argument"); @@ -1720,13 +1742,15 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSplat(DagInit *DI) { std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagSaveTemp(DagInit *DI) { assert_with_loc(DI->getNumArgs() == 2, "save_temp() expects two arguments"); - std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), DI->getArgName(1)); + std::pair<Type, std::string> A = emitDagArg(DI->getArg(1), + DI->getArgNameStr(1)); assert_with_loc(!A.first.isVoid(), "Argument to save_temp() must have non-void type!"); - std::string N = DI->getArgName(0); - assert_with_loc(N.size(), "save_temp() expects a name as the first argument"); + std::string N = DI->getArgNameStr(0); + assert_with_loc(!N.empty(), + "save_temp() expects a name as the first argument"); assert_with_loc(Intr.Variables.find(N) == Intr.Variables.end(), "Variable already defined!"); @@ -1762,7 +1786,7 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagLiteral(DagInit *DI){ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) { - if (ArgName.size()) { + if (!ArgName.empty()) { assert_with_loc(!Arg->isComplete(), "Arguments must either be DAGs or names, not both!"); assert_with_loc(Intr.Variables.find(ArgName) != Intr.Variables.end(), @@ -1900,7 +1924,7 @@ Intrinsic &NeonEmitter::getIntrinsic(StringRef Name, ArrayRef<Type> Types) { GoodVec.push_back(&I); } - assert_with_loc(GoodVec.size() > 0, + assert_with_loc(!GoodVec.empty(), "No compatible intrinsic found - " + ErrMsg); assert_with_loc(GoodVec.size() == 1, "Multiple overloads found - " + ErrMsg); @@ -2157,9 +2181,9 @@ NeonEmitter::genIntrinsicRangeCheckCode(raw_ostream &OS, OS << "case NEON::BI__builtin_neon_" << Def->getMangledName() << ": " << "i = " << Idx << ";"; - if (LowerBound.size()) + if (!LowerBound.empty()) OS << " l = " << LowerBound << ";"; - if (UpperBound.size()) + if (!UpperBound.empty()) OS << " u = " << UpperBound << ";"; OS << " break;\n"; @@ -2350,7 +2374,7 @@ void NeonEmitter::run(raw_ostream &OS) { // Only emit a def when its requirements have been met. // FIXME: This loop could be made faster, but it's fast enough for now. bool MadeProgress = true; - std::string InGuard = ""; + std::string InGuard; while (!Defs.empty() && MadeProgress) { MadeProgress = false; @@ -2393,13 +2417,17 @@ void NeonEmitter::run(raw_ostream &OS) { } namespace clang { + void EmitNeon(RecordKeeper &Records, raw_ostream &OS) { NeonEmitter(Records).run(OS); } + void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { NeonEmitter(Records).runHeader(OS); } + void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { llvm_unreachable("Neon test generation no longer implemented!"); } -} // End namespace clang + +} // end namespace clang |
