diff options
Diffstat (limited to 'utils/TableGen/NeonEmitter.cpp')
-rw-r--r-- | utils/TableGen/NeonEmitter.cpp | 60 |
1 files changed, 40 insertions, 20 deletions
diff --git a/utils/TableGen/NeonEmitter.cpp b/utils/TableGen/NeonEmitter.cpp index 5cb688061dcb..9d668a281534 100644 --- a/utils/TableGen/NeonEmitter.cpp +++ b/utils/TableGen/NeonEmitter.cpp @@ -23,6 +23,7 @@ // //===----------------------------------------------------------------------===// +#include "TableGenBackends.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/None.h" @@ -332,6 +333,17 @@ class Intrinsic { NeonEmitter &Emitter; std::stringstream OS; + bool isBigEndianSafe() const { + if (BigEndianSafe) + return true; + + for (const auto &T : Types){ + if (T.isVector() && T.getNumElements() > 1) + return false; + } + return true; + } + public: Intrinsic(Record *R, StringRef Name, StringRef Proto, TypeSpec OutTS, TypeSpec InTS, ClassKind CK, ListInit *Body, NeonEmitter &Emitter, @@ -624,7 +636,7 @@ std::string Type::builtin_str() const { default: llvm_unreachable("Unhandled case!"); } - if (isChar() && !Pointer) + if (isChar() && !Pointer && Signed) // Make chars explicitly signed. S = "S" + S; else if (isInteger() && !Pointer && !Signed) @@ -1293,7 +1305,7 @@ void Intrinsic::emitReverseVariable(Variable &Dest, Variable &Src) { } void Intrinsic::emitArgumentReversal() { - if (BigEndianSafe) + if (isBigEndianSafe()) return; // Reverse all vector arguments. @@ -1314,7 +1326,7 @@ void Intrinsic::emitArgumentReversal() { } void Intrinsic::emitReturnReversal() { - if (BigEndianSafe) + if (isBigEndianSafe()) return; if (!getReturnType().isVector() || getReturnType().isVoid() || getReturnType().getNumElements() == 1) @@ -1401,7 +1413,7 @@ void Intrinsic::emitBodyAsBuiltinCall() { if (T.getNumVectors() > 1) { // Check if an explicit cast is needed. std::string Cast; - if (T.isChar() || T.isPoly() || !T.isSigned()) { + if (LocalCK == ClassB) { Type T2 = T; T2.makeOneVector(); T2.makeInteger(8, /*Signed=*/true); @@ -1430,9 +1442,13 @@ void Intrinsic::emitBodyAsBuiltinCall() { } // Check if an explicit cast is needed. - if (CastToType.isVector()) { + if (CastToType.isVector() && + (LocalCK == ClassB || (T.isHalf() && !T.isScalarForMangling()))) { CastToType.makeInteger(8, true); Arg = "(" + CastToType.str() + ")" + Arg; + } else if (CastToType.isVector() && LocalCK == ClassI) { + CastToType.makeSigned(); + Arg = "(" + CastToType.str() + ")" + Arg; } S += Arg + ", "; @@ -1578,7 +1594,10 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagCall(DagInit *DI) { Intr.Dependencies.insert(&Callee); // Now create the call itself. - std::string S = CallPrefix.str() + Callee.getMangledName(true) + "("; + std::string S = ""; + if (!Callee.isBigEndianSafe()) + S += CallPrefix.str(); + S += Callee.getMangledName(true) + "("; for (unsigned I = 0; I < DI->getNumArgs() - 1; ++I) { if (I != 0) S += ", "; @@ -1732,12 +1751,12 @@ std::pair<Type, std::string> Intrinsic::DagEmitter::emitDagShuffle(DagInit *DI){ SetTheory ST; SetTheory::RecSet Elts; - ST.addOperator("lowhalf", llvm::make_unique<LowHalf>()); - ST.addOperator("highhalf", llvm::make_unique<HighHalf>()); + ST.addOperator("lowhalf", std::make_unique<LowHalf>()); + ST.addOperator("highhalf", std::make_unique<HighHalf>()); ST.addOperator("rev", - llvm::make_unique<Rev>(Arg1.first.getElementSizeInBits())); + std::make_unique<Rev>(Arg1.first.getElementSizeInBits())); ST.addExpander("MaskExpand", - llvm::make_unique<MaskExpander>(Arg1.first.getNumElements())); + std::make_unique<MaskExpander>(Arg1.first.getNumElements())); ST.evaluate(DI->getArg(2), Elts, None); std::string S = "__builtin_shufflevector(" + Arg1.second + ", " + Arg2.second; @@ -1889,6 +1908,11 @@ Intrinsic::DagEmitter::emitDagArg(Init *Arg, std::string ArgName) { } std::string Intrinsic::generate() { + // Avoid duplicated code for big and little endian + if (isBigEndianSafe()) { + generateImpl(false, "", ""); + return OS.str(); + } // Little endian intrinsics are simple and don't require any argument // swapping. OS << "#ifdef __LITTLE_ENDIAN__\n"; @@ -2456,7 +2480,7 @@ void NeonEmitter::run(raw_ostream &OS) { for (auto *I : Defs) I->indexBody(); - llvm::stable_sort(Defs, llvm::less_ptr<Intrinsic>()); + llvm::stable_sort(Defs, llvm::deref<std::less<>>()); // Only emit a def when its requirements have been met. // FIXME: This loop could be made faster, but it's fast enough for now. @@ -2563,7 +2587,7 @@ void NeonEmitter::runFP16(raw_ostream &OS) { for (auto *I : Defs) I->indexBody(); - llvm::stable_sort(Defs, llvm::less_ptr<Intrinsic>()); + llvm::stable_sort(Defs, llvm::deref<std::less<>>()); // Only emit a def when its requirements have been met. // FIXME: This loop could be made faster, but it's fast enough for now. @@ -2610,22 +2634,18 @@ void NeonEmitter::runFP16(raw_ostream &OS) { OS << "#endif /* __ARM_FP16_H */\n"; } -namespace clang { - -void EmitNeon(RecordKeeper &Records, raw_ostream &OS) { +void clang::EmitNeon(RecordKeeper &Records, raw_ostream &OS) { NeonEmitter(Records).run(OS); } -void EmitFP16(RecordKeeper &Records, raw_ostream &OS) { +void clang::EmitFP16(RecordKeeper &Records, raw_ostream &OS) { NeonEmitter(Records).runFP16(OS); } -void EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { +void clang::EmitNeonSema(RecordKeeper &Records, raw_ostream &OS) { NeonEmitter(Records).runHeader(OS); } -void EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { +void clang::EmitNeonTest(RecordKeeper &Records, raw_ostream &OS) { llvm_unreachable("Neon test generation no longer implemented!"); } - -} // end namespace clang |