This patch adds: 1. Support to recognize bf16 type in the frontend and isel/abi support for scalar bf16 programs Limitations: fp_to_bf16 is being generated with a tablegen pattern instead of lowering via expansion. This is because we do not have support for fcanonincalize instruction which should prevent an SNaN being converted to an infinity due to truncation. 2. Vector codegen support for bf16 Patch By: Fateme Hosseini Co-authored-by: Muntasir Mallick <quic_mallick@quicinc.com> Co-authored-by: Muntasir Mallick <mallick@qti.qualcomm.com> Co-authored-by: Kaushik Kulkarni <quic_kauskulk@quicinc.com>
296 lines
10 KiB
C++
296 lines
10 KiB
C++
//===--- Hexagon.cpp - Implement Hexagon target feature support -----------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements Hexagon TargetInfo objects.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Hexagon.h"
|
|
#include "clang/Basic/MacroBuilder.h"
|
|
#include "clang/Basic/TargetBuiltins.h"
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
|
|
using namespace clang;
|
|
using namespace clang::targets;
|
|
|
|
void HexagonTargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
MacroBuilder &Builder) const {
|
|
Builder.defineMacro("__qdsp6__", "1");
|
|
Builder.defineMacro("__hexagon__", "1");
|
|
|
|
// The macro __HVXDBL__ is deprecated.
|
|
bool DefineHvxDbl = false;
|
|
|
|
if (CPU == "hexagonv5") {
|
|
Builder.defineMacro("__HEXAGON_V5__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "5");
|
|
if (Opts.HexagonQdsp6Compat) {
|
|
Builder.defineMacro("__QDSP6_V5__");
|
|
Builder.defineMacro("__QDSP6_ARCH__", "5");
|
|
}
|
|
} else if (CPU == "hexagonv55") {
|
|
Builder.defineMacro("__HEXAGON_V55__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "55");
|
|
Builder.defineMacro("__QDSP6_V55__");
|
|
Builder.defineMacro("__QDSP6_ARCH__", "55");
|
|
} else if (CPU == "hexagonv60") {
|
|
DefineHvxDbl = true;
|
|
Builder.defineMacro("__HEXAGON_V60__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "60");
|
|
Builder.defineMacro("__QDSP6_V60__");
|
|
Builder.defineMacro("__QDSP6_ARCH__", "60");
|
|
} else if (CPU == "hexagonv62") {
|
|
DefineHvxDbl = true;
|
|
Builder.defineMacro("__HEXAGON_V62__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "62");
|
|
} else if (CPU == "hexagonv65") {
|
|
DefineHvxDbl = true;
|
|
Builder.defineMacro("__HEXAGON_V65__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "65");
|
|
} else if (CPU == "hexagonv66") {
|
|
DefineHvxDbl = true;
|
|
Builder.defineMacro("__HEXAGON_V66__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "66");
|
|
} else if (CPU == "hexagonv67") {
|
|
Builder.defineMacro("__HEXAGON_V67__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "67");
|
|
} else if (CPU == "hexagonv67t") {
|
|
Builder.defineMacro("__HEXAGON_V67T__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "67");
|
|
} else if (CPU == "hexagonv68") {
|
|
Builder.defineMacro("__HEXAGON_V68__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "68");
|
|
} else if (CPU == "hexagonv69") {
|
|
Builder.defineMacro("__HEXAGON_V69__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "69");
|
|
} else if (CPU == "hexagonv71") {
|
|
Builder.defineMacro("__HEXAGON_V71__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "71");
|
|
} else if (CPU == "hexagonv71t") {
|
|
Builder.defineMacro("__HEXAGON_V71T__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "71");
|
|
} else if (CPU == "hexagonv73") {
|
|
Builder.defineMacro("__HEXAGON_V73__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "73");
|
|
} else if (CPU == "hexagonv75") {
|
|
Builder.defineMacro("__HEXAGON_V75__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "75");
|
|
} else if (CPU == "hexagonv79") {
|
|
Builder.defineMacro("__HEXAGON_V79__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "79");
|
|
} else if (CPU == "hexagonv81") {
|
|
Builder.defineMacro("__HEXAGON_V81__");
|
|
Builder.defineMacro("__HEXAGON_ARCH__", "81");
|
|
}
|
|
|
|
if (hasFeature("hvx-length64b")) {
|
|
Builder.defineMacro("__HVX__");
|
|
Builder.defineMacro("__HVX_ARCH__", HVXVersion);
|
|
Builder.defineMacro("__HVX_LENGTH__", "64");
|
|
}
|
|
|
|
if (hasFeature("hvx-length128b")) {
|
|
Builder.defineMacro("__HVX__");
|
|
Builder.defineMacro("__HVX_ARCH__", HVXVersion);
|
|
Builder.defineMacro("__HVX_LENGTH__", "128");
|
|
if (DefineHvxDbl)
|
|
Builder.defineMacro("__HVXDBL__");
|
|
}
|
|
|
|
if (hasFeature("audio")) {
|
|
Builder.defineMacro("__HEXAGON_AUDIO__");
|
|
}
|
|
|
|
std::string NumPhySlots = isTinyCore() ? "3" : "4";
|
|
Builder.defineMacro("__HEXAGON_PHYSICAL_SLOTS__", NumPhySlots);
|
|
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
|
|
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
|
|
}
|
|
|
|
bool HexagonTargetInfo::initFeatureMap(
|
|
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
|
|
const std::vector<std::string> &FeaturesVec) const {
|
|
if (isTinyCore())
|
|
Features["audio"] = true;
|
|
|
|
StringRef CPUFeature = CPU;
|
|
CPUFeature.consume_front("hexagon");
|
|
CPUFeature.consume_back("t");
|
|
if (!CPUFeature.empty())
|
|
Features[CPUFeature] = true;
|
|
|
|
Features["long-calls"] = false;
|
|
|
|
return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec);
|
|
}
|
|
|
|
bool HexagonTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
|
DiagnosticsEngine &Diags) {
|
|
for (auto &F : Features) {
|
|
if (F == "+hvx-length64b")
|
|
HasHVX = HasHVX64B = true;
|
|
else if (F == "+hvx-length128b")
|
|
HasHVX = HasHVX128B = true;
|
|
else if (F.find("+hvxv") != std::string::npos) {
|
|
HasHVX = true;
|
|
HVXVersion = F.substr(std::string("+hvxv").length());
|
|
} else if (F == "-hvx")
|
|
HasHVX = HasHVX64B = HasHVX128B = false;
|
|
else if (F == "+long-calls")
|
|
UseLongCalls = true;
|
|
else if (F == "-long-calls")
|
|
UseLongCalls = false;
|
|
else if (F == "+audio")
|
|
HasAudio = true;
|
|
}
|
|
if (CPU.compare("hexagonv68") >= 0) {
|
|
HasFastHalfType = true;
|
|
HasFloat16 = true;
|
|
}
|
|
if (CPU.compare("hexagonv81") >= 0)
|
|
HasBFloat16 = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool HexagonTargetInfo::hasBFloat16Type() const { return HasBFloat16; }
|
|
|
|
const char *const HexagonTargetInfo::GCCRegNames[] = {
|
|
// Scalar registers:
|
|
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
|
|
"r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
|
|
"r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
|
|
"r1:0", "r3:2", "r5:4", "r7:6", "r9:8", "r11:10", "r13:12", "r15:14",
|
|
"r17:16", "r19:18", "r21:20", "r23:22", "r25:24", "r27:26", "r29:28",
|
|
"r31:30",
|
|
// Predicate registers:
|
|
"p0", "p1", "p2", "p3",
|
|
// Control registers:
|
|
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "c10", "c11",
|
|
"c12", "c13", "c14", "c15", "c16", "c17", "c18", "c19", "c20", "c21",
|
|
"c22", "c23", "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31",
|
|
"c1:0", "c3:2", "c5:4", "c7:6", "c9:8", "c11:10", "c13:12", "c15:14",
|
|
"c17:16", "c19:18", "c21:20", "c23:22", "c25:24", "c27:26", "c29:28",
|
|
"c31:30",
|
|
// Control register aliases:
|
|
"sa0", "lc0", "sa1", "lc1", "p3:0", "m0", "m1", "usr", "pc", "ugp",
|
|
"gp", "cs0", "cs1", "upcyclelo", "upcyclehi", "framelimit", "framekey",
|
|
"pktcountlo", "pktcounthi", "utimerlo", "utimerhi",
|
|
"upcycle", "pktcount", "utimer",
|
|
// HVX vector registers:
|
|
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", "v11",
|
|
"v12", "v13", "v14", "v15", "v16", "v17", "v18", "v19", "v20", "v21",
|
|
"v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
|
|
"v1:0", "v3:2", "v5:4", "v7:6", "v9:8", "v11:10", "v13:12", "v15:14",
|
|
"v17:16", "v19:18", "v21:20", "v23:22", "v25:24", "v27:26", "v29:28",
|
|
"v31:30",
|
|
"v3:0", "v7:4", "v11:8", "v15:12", "v19:16", "v23:20", "v27:24", "v31:28",
|
|
// HVX vector predicates:
|
|
"q0", "q1", "q2", "q3",
|
|
};
|
|
|
|
ArrayRef<const char *> HexagonTargetInfo::getGCCRegNames() const {
|
|
return llvm::ArrayRef(GCCRegNames);
|
|
}
|
|
|
|
const TargetInfo::GCCRegAlias HexagonTargetInfo::GCCRegAliases[] = {
|
|
{{"sp"}, "r29"},
|
|
{{"fp"}, "r30"},
|
|
{{"lr"}, "r31"},
|
|
};
|
|
|
|
ArrayRef<TargetInfo::GCCRegAlias> HexagonTargetInfo::getGCCRegAliases() const {
|
|
return llvm::ArrayRef(GCCRegAliases);
|
|
}
|
|
|
|
static constexpr int NumBuiltins =
|
|
clang::Hexagon::LastTSBuiltin - Builtin::FirstTSBuiltin;
|
|
|
|
#define GET_BUILTIN_STR_TABLE
|
|
#include "clang/Basic/BuiltinsHexagon.inc"
|
|
#undef GET_BUILTIN_STR_TABLE
|
|
|
|
static constexpr Builtin::Info BuiltinInfos[] = {
|
|
#define GET_BUILTIN_INFOS
|
|
#include "clang/Basic/BuiltinsHexagon.inc"
|
|
#undef GET_BUILTIN_INFOS
|
|
};
|
|
|
|
static constexpr Builtin::Info PrefixedBuiltinInfos[] = {
|
|
#define GET_BUILTIN_PREFIXED_INFOS
|
|
#include "clang/Basic/BuiltinsHexagon.inc"
|
|
#undef GET_BUILTIN_PREFIXED_INFOS
|
|
};
|
|
static_assert((std::size(BuiltinInfos) + std::size(PrefixedBuiltinInfos)) ==
|
|
NumBuiltins);
|
|
|
|
bool HexagonTargetInfo::hasFeature(StringRef Feature) const {
|
|
std::string VS = "hvxv" + HVXVersion;
|
|
if (Feature == VS)
|
|
return true;
|
|
|
|
return llvm::StringSwitch<bool>(Feature)
|
|
.Case("hexagon", true)
|
|
.Case("hvx", HasHVX)
|
|
.Case("hvx-length64b", HasHVX64B)
|
|
.Case("hvx-length128b", HasHVX128B)
|
|
.Case("long-calls", UseLongCalls)
|
|
.Case("audio", HasAudio)
|
|
.Default(false);
|
|
}
|
|
|
|
struct CPUSuffix {
|
|
llvm::StringLiteral Name;
|
|
llvm::StringLiteral Suffix;
|
|
};
|
|
|
|
static constexpr CPUSuffix Suffixes[] = {
|
|
{{"hexagonv5"}, {"5"}}, {{"hexagonv55"}, {"55"}},
|
|
{{"hexagonv60"}, {"60"}}, {{"hexagonv62"}, {"62"}},
|
|
{{"hexagonv65"}, {"65"}}, {{"hexagonv66"}, {"66"}},
|
|
{{"hexagonv67"}, {"67"}}, {{"hexagonv67t"}, {"67t"}},
|
|
{{"hexagonv68"}, {"68"}}, {{"hexagonv69"}, {"69"}},
|
|
{{"hexagonv71"}, {"71"}}, {{"hexagonv71t"}, {"71t"}},
|
|
{{"hexagonv73"}, {"73"}}, {{"hexagonv75"}, {"75"}},
|
|
{{"hexagonv79"}, {"79"}}, {{"hexagonv81"}, {"81"}}};
|
|
|
|
std::optional<unsigned> HexagonTargetInfo::getHexagonCPURev(StringRef Name) {
|
|
StringRef Arch = Name;
|
|
Arch.consume_front("hexagonv");
|
|
Arch.consume_back("t");
|
|
|
|
unsigned Val;
|
|
if (!Arch.getAsInteger(0, Val))
|
|
return Val;
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
const char *HexagonTargetInfo::getHexagonCPUSuffix(StringRef Name) {
|
|
const CPUSuffix *Item = llvm::find_if(
|
|
Suffixes, [Name](const CPUSuffix &S) { return S.Name == Name; });
|
|
if (Item == std::end(Suffixes))
|
|
return nullptr;
|
|
return Item->Suffix.data();
|
|
}
|
|
|
|
void HexagonTargetInfo::fillValidCPUList(
|
|
SmallVectorImpl<StringRef> &Values) const {
|
|
for (const CPUSuffix &Suffix : Suffixes)
|
|
Values.push_back(Suffix.Name);
|
|
}
|
|
|
|
llvm::SmallVector<Builtin::InfosShard>
|
|
HexagonTargetInfo::getTargetBuiltins() const {
|
|
return {{&BuiltinStrings, BuiltinInfos},
|
|
{&BuiltinStrings, PrefixedBuiltinInfos, "__builtin_HEXAGON_"}};
|
|
}
|