diff --git a/llvm/include/llvm/TargetParser/XtensaTargetParser.def b/llvm/include/llvm/TargetParser/XtensaTargetParser.def new file mode 100644 index 0000000000000..b0afe6f161770 --- /dev/null +++ b/llvm/include/llvm/TargetParser/XtensaTargetParser.def @@ -0,0 +1,79 @@ +//===- XtensaTargetParser.def - Xtensa target parsing defines ---*- C++ -*-===// +// +// 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 provides defines to build up the Xtensa target parser's logic. +// +//===----------------------------------------------------------------------===// + +#ifndef XTENSA_FEATURE +#define XTENSA_FEATURE(ID, STR) +#endif + +XTENSA_FEATURE(XF_DENSITY, "density") +XTENSA_FEATURE(XF_FP, "fp") +XTENSA_FEATURE(XF_WINDOWED, "windowed") +XTENSA_FEATURE(XF_BOOLEAN, "bool") +XTENSA_FEATURE(XF_LOOP, "loop") +XTENSA_FEATURE(XF_SEXT, "sext") +XTENSA_FEATURE(XF_NSA, "nsa") +XTENSA_FEATURE(XF_CLAMPS, "clamps") +XTENSA_FEATURE(XF_MINMAX, "minmax") +XTENSA_FEATURE(XF_MAC16, "mac16") +XTENSA_FEATURE(XF_MUL32, "mul32") +XTENSA_FEATURE(XF_MUL32HIGH, "mul32high") +XTENSA_FEATURE(XF_DIV32, "div32") +XTENSA_FEATURE(XF_MUL16, "mul16") +XTENSA_FEATURE(XF_DFPACCEL, "dfpaccel") +XTENSA_FEATURE(XF_S32C1I, "s32c1i") +XTENSA_FEATURE(XF_THREADPTR, "threadptr") +XTENSA_FEATURE(XF_EXTENDEDL32R, "extendedl32r") +XTENSA_FEATURE(XF_DATACACHE, "dcache") +XTENSA_FEATURE(XF_DEBUG, "debug") +XTENSA_FEATURE(XF_EXCEPTION, "exception") +XTENSA_FEATURE(XF_HIGHPRIINTERRUPTS, "highpriinterrupts") +XTENSA_FEATURE(XF_HIGHPRIINTERRUPTSLEVEL3, "highpriinterruptslevel3") +XTENSA_FEATURE(XF_HIGHPRIINTERRUPTSLEVEL4, "highpriinterruptslevel4") +XTENSA_FEATURE(XF_HIGHPRIINTERRUPTSLEVEL5, "highpriinterruptslevel5") +XTENSA_FEATURE(XF_HIGHPRIINTERRUPTSLEVEL6, "highpriinterruptslevel6") +XTENSA_FEATURE(XF_HIGHPRIINTERRUPTSLEVEL7, "highpriinterruptslevel7") +XTENSA_FEATURE(XF_COPROCESSOR, "coprocessor") +XTENSA_FEATURE(XF_INTERRUPT, "interrupt") +XTENSA_FEATURE(XF_RVECTOR, "rvector") +XTENSA_FEATURE(XF_TIMERS1, "timers1") +XTENSA_FEATURE(XF_TIMERS2, "timers2") +XTENSA_FEATURE(XF_TIMERS3, "timers3") +XTENSA_FEATURE(XF_PRID, "prid") +XTENSA_FEATURE(XF_REGPROTECT, "regprotect") +XTENSA_FEATURE(XF_MISCSR, "miscsr") + +#undef XTENSA_FEATURE + +#ifndef XTENSA_CPU +#define XTENSA_CPU(ENUM, NAME, FEATURES) +#endif + +XTENSA_CPU(INVALID, {"invalid"}, XF_INVALID) +XTENSA_CPU(GENERIC, {"generic"}, XF_NONE) +XTENSA_CPU(ESP8266, {"esp8266"}, + (XF_DENSITY | XF_NSA | XF_MUL16 | XF_MUL32 | XF_EXTENDEDL32R | XF_DEBUG | XF_EXCEPTION | + XF_HIGHPRIINTERRUPTS | XF_HIGHPRIINTERRUPTSLEVEL3 | XF_INTERRUPT | XF_RVECTOR | XF_TIMERS1 | + XF_REGPROTECT | XF_PRID)) +XTENSA_CPU(ESP32, {"esp32"}, + (XF_DENSITY | XF_FP | XF_LOOP | XF_MAC16 | XF_WINDOWED | XF_BOOLEAN | XF_SEXT | XF_NSA | + XF_CLAMPS | XF_MINMAX | XF_MUL32 | XF_MUL32HIGH | XF_MUL16 | XF_DFPACCEL | XF_S32C1I | + XF_THREADPTR | XF_DIV32 | XF_DATACACHE | XF_DEBUG | XF_EXCEPTION | XF_HIGHPRIINTERRUPTS | + XF_HIGHPRIINTERRUPTSLEVEL7 | XF_COPROCESSOR | XF_INTERRUPT | XF_RVECTOR | XF_TIMERS3 | XF_PRID | + XF_REGPROTECT | XF_MISCSR)) + +#undef XTENSA_CPU + +#ifndef XTENSA_CPU_ALIAS +#define XTENSA_CPU_ALIAS(NAME, ALTNMAME) +#endif + +#undef XTENSA_CPU_ALIAS diff --git a/llvm/include/llvm/TargetParser/XtensaTargetParser.h b/llvm/include/llvm/TargetParser/XtensaTargetParser.h new file mode 100644 index 0000000000000..828b4079ef328 --- /dev/null +++ b/llvm/include/llvm/TargetParser/XtensaTargetParser.h @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements a target parser to recognise Xtensa hardware features. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGETPARSER_XTENSATARGETPARSER_H +#define LLVM_TARGETPARSER_XTENSATARGETPARSER_H + +#include "llvm/TargetParser/Triple.h" +#include + +namespace llvm { +class StringRef; + +namespace Xtensa { + +enum CPUKind : unsigned { +#define XTENSA_CPU(ENUM, NAME, FEATURES) CK_##ENUM, +#include "XtensaTargetParser.def" +}; + +enum XtensaFeatureKind : uint64_t { + XF_INVALID = 0, + XF_NONE = 1, + XF_FP = 1 << 1, + XF_WINDOWED = 1 << 2, + XF_BOOLEAN = 1 << 3, + XF_DENSITY = 1 << 4, + XF_LOOP = 1 << 5, + XF_SEXT = 1 << 6, + XF_NSA = 1 << 7, + XF_CLAMPS = 1 << 8, + XF_MINMAX = 1 << 9, + XF_MAC16 = 1 << 10, + XF_MUL32 = 1 << 11, + XF_MUL32HIGH = 1 << 12, + XF_DIV32 = 1 << 13, + XF_MUL16 = 1 << 14, + XF_DFPACCEL = 1 << 15, + XF_S32C1I = 1 << 16, + XF_THREADPTR = 1 << 17, + XF_EXTENDEDL32R = 1 << 18, + XF_DATACACHE = 1 << 19, + XF_DEBUG = 1 << 20, + XF_EXCEPTION = 1 << 21, + XF_HIGHPRIINTERRUPTS = 1 << 22, + XF_HIGHPRIINTERRUPTSLEVEL3 = 1 << 23, + XF_HIGHPRIINTERRUPTSLEVEL4 = 1 << 24, + XF_HIGHPRIINTERRUPTSLEVEL5 = 1 << 25, + XF_HIGHPRIINTERRUPTSLEVEL6 = 1 << 26, + XF_HIGHPRIINTERRUPTSLEVEL7 = 1 << 27, + XF_COPROCESSOR = 1 << 28, + XF_INTERRUPT = 1 << 29, + XF_RVECTOR = 1 << 30, + XF_TIMERS1 = 1ULL << 31, + XF_TIMERS2 = 1ULL << 32, + XF_TIMERS3 = 1ULL << 33, + XF_PRID = 1ULL << 34, + XF_REGPROTECT = 1ULL << 35, + XF_MISCSR = 1ULL << 36 +}; + +CPUKind parseCPUKind(StringRef CPU); +StringRef getBaseName(StringRef CPU); +void getCPUFeatures(StringRef CPU, SmallVectorImpl &Features); +void fillValidCPUList(SmallVectorImpl &Values); + +} // namespace Xtensa +} // namespace llvm + +#endif // LLVM_SUPPORT_XTENSATARGETPARSER_H diff --git a/llvm/include/module.modulemap b/llvm/include/module.modulemap index ac360b25d7529..98c0c658ca589 100644 --- a/llvm/include/module.modulemap +++ b/llvm/include/module.modulemap @@ -415,6 +415,7 @@ module LLVM_Utils { textual header "llvm/TargetParser/X86TargetParser.def" textual header "llvm/TargetParser/LoongArchTargetParser.def" textual header "llvm/TargetParser/PPCTargetParser.def" + textual header "llvm/TargetParser/XtensaTargetParser.def" } // This part of the module is usable from both C and C++ code. diff --git a/llvm/lib/Target/Xtensa/Xtensa.td b/llvm/lib/Target/Xtensa/Xtensa.td index 2c4bacbe8282b..4ef885e19101e 100644 --- a/llvm/lib/Target/Xtensa/Xtensa.td +++ b/llvm/lib/Target/Xtensa/Xtensa.td @@ -23,10 +23,8 @@ include "XtensaFeatures.td" //===----------------------------------------------------------------------===// // Xtensa supported processors. //===----------------------------------------------------------------------===// -class Proc Features> - : Processor; -def : Proc<"generic", []>; +include "XtensaProcessors.td" //===----------------------------------------------------------------------===// // Register File Description diff --git a/llvm/lib/Target/Xtensa/XtensaProcessors.td b/llvm/lib/Target/Xtensa/XtensaProcessors.td new file mode 100644 index 0000000000000..0faf07d99aaf7 --- /dev/null +++ b/llvm/lib/Target/Xtensa/XtensaProcessors.td @@ -0,0 +1,27 @@ +//===- XtensaProcessors.td - Xtensa Processors -------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// 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 +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Xtensa supported processors. +//===----------------------------------------------------------------------===// +class Proc Features> + : Processor; + +def : Proc<"generic", []>; + +def : Proc<"esp32", [FeatureDensity, FeatureSingleFloat, FeatureLoop, FeatureMAC16, FeatureWindowed, FeatureBoolean, FeatureSEXT, + FeatureNSA, FeatureMul16, FeatureMul32, FeatureMul32High, FeatureDFPAccel, FeatureS32C1I, FeatureTHREADPTR, FeatureDiv32, + FeatureDebug, FeatureException, FeatureHighPriInterrupts, FeatureHighPriInterruptsLevel7, FeatureCoprocessor, + FeatureInterrupt, FeatureDataCache, FeatureRelocatableVector, FeatureTimers3, FeaturePRID, FeatureRegionProtection, FeatureMiscSR, + FeatureMINMAX, FeatureCLAMPS]>; + +def : Proc<"esp8266", [FeatureDensity, FeatureNSA, FeatureMul16, FeatureMul32, FeatureExtendedL32R, FeatureDebug, FeatureException, + FeatureHighPriInterrupts, FeatureHighPriInterruptsLevel3, FeatureInterrupt, FeatureRelocatableVector, FeatureTimers1, + FeatureRegionProtection, FeaturePRID]>; diff --git a/llvm/lib/TargetParser/CMakeLists.txt b/llvm/lib/TargetParser/CMakeLists.txt index 8f8b3a578a1d9..62e97bfebe099 100644 --- a/llvm/lib/TargetParser/CMakeLists.txt +++ b/llvm/lib/TargetParser/CMakeLists.txt @@ -27,6 +27,7 @@ add_llvm_component_library(LLVMTargetParser TargetParser.cpp Triple.cpp X86TargetParser.cpp + XtensaTargetParser.cpp ADDITIONAL_HEADER_DIRS Unix diff --git a/llvm/lib/TargetParser/XtensaTargetParser.cpp b/llvm/lib/TargetParser/XtensaTargetParser.cpp new file mode 100644 index 0000000000000..25725f2688cf3 --- /dev/null +++ b/llvm/lib/TargetParser/XtensaTargetParser.cpp @@ -0,0 +1,93 @@ +//==-- XtensaTargetParser - Parser for Xtensa features ------------*- C++ -*-=// +// +// 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 a target parser to recognise Xtensa hardware features +// +//===----------------------------------------------------------------------===// + +#include "llvm/TargetParser/XtensaTargetParser.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" + +namespace llvm { + +namespace Xtensa { +struct CPUInfo { + StringLiteral Name; + CPUKind Kind; + uint64_t Features; +}; + +struct FeatureName { + uint64_t ID; + const char *NameCStr; + size_t NameLength; + + StringRef getName() const { return StringRef(NameCStr, NameLength); } +}; + +const FeatureName XtensaFeatureNames[] = { +#define XTENSA_FEATURE(ID, NAME) {ID, "+" NAME, sizeof(NAME)}, +#include "llvm/TargetParser/XtensaTargetParser.def" +}; + +constexpr CPUInfo XtensaCPUInfo[] = { +#define XTENSA_CPU(ENUM, NAME, FEATURES) {NAME, CK_##ENUM, FEATURES}, +#include "llvm/TargetParser/XtensaTargetParser.def" +}; + +StringRef getBaseName(StringRef CPU) { + return llvm::StringSwitch(CPU) +#define XTENSA_CPU_ALIAS(NAME, ANAME) .Case(ANAME, NAME) +#include "llvm/TargetParser/XtensaTargetParser.def" + .Default(CPU); +} + +StringRef getAliasName(StringRef CPU) { + return llvm::StringSwitch(CPU) +#define XTENSA_CPU_ALIAS(NAME, ANAME) .Case(NAME, ANAME) +#include "llvm/TargetParser/XtensaTargetParser.def" + .Default(CPU); +} + +CPUKind parseCPUKind(StringRef CPU) { + CPU = getBaseName(CPU); + return llvm::StringSwitch(CPU) +#define XTENSA_CPU(ENUM, NAME, FEATURES) .Case(NAME, CK_##ENUM) +#include "llvm/TargetParser/XtensaTargetParser.def" + .Default(CK_INVALID); +} + +// Get all features for the CPU +void getCPUFeatures(StringRef CPU, std::vector &Features) { + CPU = getBaseName(CPU); + auto I = llvm::find_if(XtensaCPUInfo, + [&](const CPUInfo &CI) { return CI.Name == CPU; }); + assert(I != std::end(XtensaCPUInfo) && "CPU not found!"); + uint64_t Bits = I->Features; + + for (const auto &F : XtensaFeatureNames) { + if ((Bits & F.ID) == F.ID) + Features.push_back(F.getName()); + } +} + +// Find all valid CPUs +void fillValidCPUList(std::vector &Values) { + for (const auto &C : XtensaCPUInfo) { + if (C.Kind != CK_INVALID) { + Values.emplace_back(C.Name); + StringRef Name = getAliasName(C.Name); + if (Name != C.Name) + Values.emplace_back(Name); + } + } +} + +} // namespace Xtensa +} // namespace llvm diff --git a/llvm/test/CodeGen/Xtensa/cpus-invalid.ll b/llvm/test/CodeGen/Xtensa/cpus-invalid.ll new file mode 100644 index 0000000000000..360761cbbbb67 --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/cpus-invalid.ll @@ -0,0 +1,8 @@ +; RUN: llc < %s --mtriple=xtensa --mcpu=invalid 2>&1 | FileCheck %s + +; CHECK: {{.*}} is not a recognized processor for this target + +define void @f() { + ret void +} + diff --git a/llvm/test/CodeGen/Xtensa/cpus.ll b/llvm/test/CodeGen/Xtensa/cpus.ll new file mode 100644 index 0000000000000..d04ee16882381 --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/cpus.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; This tests that llc accepts all valid Xtensa CPUs + +; RUN: llc < %s --mtriple=xtensa --mcpu=esp8266 2>&1 | FileCheck -check-prefix=XTENSA-ESP8266 %s +; RUN: llc < %s --mtriple=xtensa --mcpu=esp32 2>&1 | FileCheck -check-prefix=XTENSA-ESP32 %s +; RUN: llc < %s --mtriple=xtensa --mcpu=generic 2>&1 | FileCheck -check-prefix=XTENSA-GENERIC %s + +define i32 @f(i32 %z) { +; XTENSA-ESP8266-LABEL: f: +; XTENSA-ESP8266: .cfi_startproc +; XTENSA-ESP8266-NEXT: # %bb.0: +; XTENSA-ESP8266-NEXT: movi a2, 0 +; XTENSA-ESP8266-NEXT: ret +; +; XTENSA-ESP32-LABEL: f: +; XTENSA-ESP32: .cfi_startproc +; XTENSA-ESP32-NEXT: # %bb.0: +; XTENSA-ESP32-NEXT: entry a1, 32 +; XTENSA-ESP32-NEXT: .cfi_def_cfa_offset 32 +; XTENSA-ESP32-NEXT: movi a2, 0 +; XTENSA-ESP32-NEXT: retw.n +; +; XTENSA-GENERIC-LABEL: f: +; XTENSA-GENERIC: .cfi_startproc +; XTENSA-GENERIC-NEXT: # %bb.0: +; XTENSA-GENERIC-NEXT: movi a2, 0 +; XTENSA-GENERIC-NEXT: ret + ret i32 0 +} diff --git a/llvm/utils/gn/secondary/llvm/lib/TargetParser/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/TargetParser/BUILD.gn index 3dbc803d0d483..183fa57d47a63 100644 --- a/llvm/utils/gn/secondary/llvm/lib/TargetParser/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/TargetParser/BUILD.gn @@ -20,5 +20,6 @@ static_library("TargetParser") { "TargetParser.cpp", "Triple.cpp", "X86TargetParser.cpp", + "XtensaTargetParser.cpp", ] }