aboutsummaryrefslogtreecommitdiff
path: root/utils/TableGen/NeonEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen/NeonEmitter.cpp')
-rw-r--r--utils/TableGen/NeonEmitter.cpp60
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