Index: llvm/lib/Target/RISCV/AsmParser/CMakeLists.txt =================================================================== --- llvm/lib/Target/RISCV/AsmParser/CMakeLists.txt +++ llvm/lib/Target/RISCV/AsmParser/CMakeLists.txt @@ -6,7 +6,6 @@ MCParser RISCVDesc RISCVInfo - RISCVUtils Support ADD_TO_COMPONENT Index: llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -7,12 +7,12 @@ //===----------------------------------------------------------------------===// #include "MCTargetDesc/RISCVAsmBackend.h" +#include "MCTargetDesc/RISCVBaseInfo.h" #include "MCTargetDesc/RISCVMCExpr.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "MCTargetDesc/RISCVMatInt.h" #include "MCTargetDesc/RISCVTargetStreamer.h" #include "TargetInfo/RISCVTargetInfo.h" -#include "Utils/RISCVBaseInfo.h" -#include "Utils/RISCVMatInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" Index: llvm/lib/Target/RISCV/CMakeLists.txt =================================================================== --- llvm/lib/Target/RISCV/CMakeLists.txt +++ llvm/lib/Target/RISCV/CMakeLists.txt @@ -47,7 +47,6 @@ MC RISCVDesc RISCVInfo - RISCVUtils SelectionDAG Support Target @@ -61,4 +60,3 @@ add_subdirectory(Disassembler) add_subdirectory(MCTargetDesc) add_subdirectory(TargetInfo) -add_subdirectory(Utils) Index: llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp =================================================================== --- llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -10,9 +10,9 @@ // //===----------------------------------------------------------------------===// +#include "MCTargetDesc/RISCVBaseInfo.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "TargetInfo/RISCVTargetInfo.h" -#include "Utils/RISCVBaseInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCFixedLenDisassembler.h" Index: llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt +++ llvm/lib/Target/RISCV/MCTargetDesc/CMakeLists.txt @@ -1,18 +1,19 @@ add_llvm_component_library(LLVMRISCVDesc RISCVAsmBackend.cpp + RISCVBaseInfo.cpp RISCVELFObjectWriter.cpp RISCVInstPrinter.cpp RISCVMCAsmInfo.cpp RISCVMCCodeEmitter.cpp RISCVMCExpr.cpp RISCVMCTargetDesc.cpp + RISCVMatInt.cpp RISCVTargetStreamer.cpp RISCVELFStreamer.cpp LINK_COMPONENTS MC RISCVInfo - RISCVUtils Support ADD_TO_COMPONENT Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h @@ -9,9 +9,9 @@ #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVASMBACKEND_H #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVASMBACKEND_H +#include "MCTargetDesc/RISCVBaseInfo.h" #include "MCTargetDesc/RISCVFixupKinds.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" -#include "Utils/RISCVBaseInfo.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCSubtargetInfo.h" Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h =================================================================== --- /dev/null +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h @@ -0,0 +1,418 @@ +//===-- RISCVBaseInfo.h - Top level definitions for RISCV MC ----*- 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 contains small standalone enum definitions for the RISCV target +// useful for the compiler back-end and the MC libraries. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H +#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H + +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/SubtargetFeature.h" +#include "llvm/Support/MachineValueType.h" + +namespace llvm { + +// RISCVII - This namespace holds all of the target specific flags that +// instruction info tracks. All definitions must match RISCVInstrFormats.td. +namespace RISCVII { +enum { + InstFormatPseudo = 0, + InstFormatR = 1, + InstFormatR4 = 2, + InstFormatI = 3, + InstFormatS = 4, + InstFormatB = 5, + InstFormatU = 6, + InstFormatJ = 7, + InstFormatCR = 8, + InstFormatCI = 9, + InstFormatCSS = 10, + InstFormatCIW = 11, + InstFormatCL = 12, + InstFormatCS = 13, + InstFormatCA = 14, + InstFormatCB = 15, + InstFormatCJ = 16, + InstFormatOther = 17, + + InstFormatMask = 31, + + ConstraintOffset = 5, + ConstraintMask = 0b1111 +}; + +// Match with the definitions in RISCVInstrFormatsV.td +enum RVVConstraintType { + NoConstraint = 0, + VS2Constraint = 0b0001, + VS1Constraint = 0b0010, + VMConstraint = 0b0100, + OneInput = 0b1000, + + // Illegal instructions: + // + // * The destination vector register group for a masked vector instruction + // cannot overlap the source mask register (v0), unless the destination vector + // register is being written with a mask value (e.g., comparisons) or the + // scalar result of a reduction. + // + // * Widening: The destination vector register group cannot overlap a source + // vector register group of a different EEW + // + // * Narrowing: The destination vector register group cannot overlap the + // first source vector register group + // + // * For vadc and vsbc, an illegal instruction exception is raised if the + // destination vector register is v0. + // + // * For vmadc and vmsbc, an illegal instruction exception is raised if the + // destination vector register overlaps a source vector register group. + // + // * viota: An illegal instruction exception is raised if the destination + // vector register group overlaps the source vector mask register. If the + // instruction is masked, an illegal instruction exception is issued if the + // destination vector register group overlaps v0. + // + // * v[f]slide[1]up: The destination vector register group for vslideup cannot + // overlap the source vector register group. + // + // * vrgather: The destination vector register group cannot overlap with the + // source vector register groups. + // + // * vcompress: The destination vector register group cannot overlap the + // source vector register group or the source mask register + WidenV = VS2Constraint | VS1Constraint | VMConstraint, + WidenW = VS1Constraint | VMConstraint, + WidenCvt = VS2Constraint | VMConstraint | OneInput, + Narrow = VS2Constraint | VMConstraint, + NarrowCvt = VS2Constraint | VMConstraint | OneInput, + Vmadc = VS2Constraint | VS1Constraint, + Iota = VS2Constraint | VMConstraint | OneInput, + SlideUp = VS2Constraint | VMConstraint, + Vrgather = VS2Constraint | VS1Constraint | VMConstraint, + Vcompress = VS2Constraint | VS1Constraint, +}; + +// RISC-V Specific Machine Operand Flags +enum { + MO_None = 0, + MO_CALL = 1, + MO_PLT = 2, + MO_LO = 3, + MO_HI = 4, + MO_PCREL_LO = 5, + MO_PCREL_HI = 6, + MO_GOT_HI = 7, + MO_TPREL_LO = 8, + MO_TPREL_HI = 9, + MO_TPREL_ADD = 10, + MO_TLS_GOT_HI = 11, + MO_TLS_GD_HI = 12, + + // Used to differentiate between target-specific "direct" flags and "bitmask" + // flags. A machine operand can only have one "direct" flag, but can have + // multiple "bitmask" flags. + MO_DIRECT_FLAG_MASK = 15 +}; +} // namespace RISCVII + +namespace RISCVOp { +enum OperandType : unsigned { + OPERAND_FIRST_RISCV_IMM = MCOI::OPERAND_FIRST_TARGET, + OPERAND_UIMM4 = OPERAND_FIRST_RISCV_IMM, + OPERAND_UIMM5, + OPERAND_UIMM12, + OPERAND_SIMM12, + OPERAND_UIMM20, + OPERAND_UIMMLOG2XLEN, + OPERAND_LAST_RISCV_IMM = OPERAND_UIMMLOG2XLEN +}; +} // namespace RISCVOp + +// Describes the predecessor/successor bits used in the FENCE instruction. +namespace RISCVFenceField { +enum FenceField { + I = 8, + O = 4, + R = 2, + W = 1 +}; +} + +// Describes the supported floating point rounding mode encodings. +namespace RISCVFPRndMode { +enum RoundingMode { + RNE = 0, + RTZ = 1, + RDN = 2, + RUP = 3, + RMM = 4, + DYN = 7, + Invalid +}; + +inline static StringRef roundingModeToString(RoundingMode RndMode) { + switch (RndMode) { + default: + llvm_unreachable("Unknown floating point rounding mode"); + case RISCVFPRndMode::RNE: + return "rne"; + case RISCVFPRndMode::RTZ: + return "rtz"; + case RISCVFPRndMode::RDN: + return "rdn"; + case RISCVFPRndMode::RUP: + return "rup"; + case RISCVFPRndMode::RMM: + return "rmm"; + case RISCVFPRndMode::DYN: + return "dyn"; + } +} + +inline static RoundingMode stringToRoundingMode(StringRef Str) { + return StringSwitch(Str) + .Case("rne", RISCVFPRndMode::RNE) + .Case("rtz", RISCVFPRndMode::RTZ) + .Case("rdn", RISCVFPRndMode::RDN) + .Case("rup", RISCVFPRndMode::RUP) + .Case("rmm", RISCVFPRndMode::RMM) + .Case("dyn", RISCVFPRndMode::DYN) + .Default(RISCVFPRndMode::Invalid); +} + +inline static bool isValidRoundingMode(unsigned Mode) { + switch (Mode) { + default: + return false; + case RISCVFPRndMode::RNE: + case RISCVFPRndMode::RTZ: + case RISCVFPRndMode::RDN: + case RISCVFPRndMode::RUP: + case RISCVFPRndMode::RMM: + case RISCVFPRndMode::DYN: + return true; + } +} +} // namespace RISCVFPRndMode + +namespace RISCVSysReg { +struct SysReg { + const char *Name; + unsigned Encoding; + const char *AltName; + // FIXME: add these additional fields when needed. + // Privilege Access: Read, Write, Read-Only. + // unsigned ReadWrite; + // Privilege Mode: User, System or Machine. + // unsigned Mode; + // Check field name. + // unsigned Extra; + // Register number without the privilege bits. + // unsigned Number; + FeatureBitset FeaturesRequired; + bool isRV32Only; + + bool haveRequiredFeatures(FeatureBitset ActiveFeatures) const { + // Not in 32-bit mode. + if (isRV32Only && ActiveFeatures[RISCV::Feature64Bit]) + return false; + // No required feature associated with the system register. + if (FeaturesRequired.none()) + return true; + return (FeaturesRequired & ActiveFeatures) == FeaturesRequired; + } +}; + +#define GET_SysRegsList_DECL +#include "RISCVGenSearchableTables.inc" +} // end namespace RISCVSysReg + +namespace RISCVABI { + +enum ABI { + ABI_ILP32, + ABI_ILP32F, + ABI_ILP32D, + ABI_ILP32E, + ABI_LP64, + ABI_LP64F, + ABI_LP64D, + ABI_Unknown +}; + +// Returns the target ABI, or else a StringError if the requested ABIName is +// not supported for the given TT and FeatureBits combination. +ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, + StringRef ABIName); + +ABI getTargetABI(StringRef ABIName); + +// Returns the register used to hold the stack pointer after realignment. +MCRegister getBPReg(); + +// Returns the register holding shadow call stack pointer. +MCRegister getSCSPReg(); + +} // namespace RISCVABI + +namespace RISCVFeatures { + +// Validates if the given combination of features are valid for the target +// triple. Exits with report_fatal_error if not. +void validate(const Triple &TT, const FeatureBitset &FeatureBits); + +} // namespace RISCVFeatures + +namespace RISCVVMVTs { + +constexpr MVT vint8mf8_t = MVT::nxv1i8; +constexpr MVT vint8mf4_t = MVT::nxv2i8; +constexpr MVT vint8mf2_t = MVT::nxv4i8; +constexpr MVT vint8m1_t = MVT::nxv8i8; +constexpr MVT vint8m2_t = MVT::nxv16i8; +constexpr MVT vint8m4_t = MVT::nxv32i8; +constexpr MVT vint8m8_t = MVT::nxv64i8; + +constexpr MVT vint16mf4_t = MVT::nxv1i16; +constexpr MVT vint16mf2_t = MVT::nxv2i16; +constexpr MVT vint16m1_t = MVT::nxv4i16; +constexpr MVT vint16m2_t = MVT::nxv8i16; +constexpr MVT vint16m4_t = MVT::nxv16i16; +constexpr MVT vint16m8_t = MVT::nxv32i16; + +constexpr MVT vint32mf2_t = MVT::nxv1i32; +constexpr MVT vint32m1_t = MVT::nxv2i32; +constexpr MVT vint32m2_t = MVT::nxv4i32; +constexpr MVT vint32m4_t = MVT::nxv8i32; +constexpr MVT vint32m8_t = MVT::nxv16i32; + +constexpr MVT vint64m1_t = MVT::nxv1i64; +constexpr MVT vint64m2_t = MVT::nxv2i64; +constexpr MVT vint64m4_t = MVT::nxv4i64; +constexpr MVT vint64m8_t = MVT::nxv8i64; + +constexpr MVT vfloat16mf4_t = MVT::nxv1f16; +constexpr MVT vfloat16mf2_t = MVT::nxv2f16; +constexpr MVT vfloat16m1_t = MVT::nxv4f16; +constexpr MVT vfloat16m2_t = MVT::nxv8f16; +constexpr MVT vfloat16m4_t = MVT::nxv16f16; +constexpr MVT vfloat16m8_t = MVT::nxv32f16; + +constexpr MVT vfloat32mf2_t = MVT::nxv1f32; +constexpr MVT vfloat32m1_t = MVT::nxv2f32; +constexpr MVT vfloat32m2_t = MVT::nxv4f32; +constexpr MVT vfloat32m4_t = MVT::nxv8f32; +constexpr MVT vfloat32m8_t = MVT::nxv16f32; + +constexpr MVT vfloat64m1_t = MVT::nxv1f64; +constexpr MVT vfloat64m2_t = MVT::nxv2f64; +constexpr MVT vfloat64m4_t = MVT::nxv4f64; +constexpr MVT vfloat64m8_t = MVT::nxv8f64; + +constexpr MVT vbool1_t = MVT::nxv64i1; +constexpr MVT vbool2_t = MVT::nxv32i1; +constexpr MVT vbool4_t = MVT::nxv16i1; +constexpr MVT vbool8_t = MVT::nxv8i1; +constexpr MVT vbool16_t = MVT::nxv4i1; +constexpr MVT vbool32_t = MVT::nxv2i1; +constexpr MVT vbool64_t = MVT::nxv1i1; + +} // namespace RISCVVMVTs + +enum class RISCVVSEW { + SEW_8 = 0, + SEW_16, + SEW_32, + SEW_64, + SEW_128, + SEW_256, + SEW_512, + SEW_1024, +}; + +enum class RISCVVLMUL { + LMUL_1 = 0, + LMUL_2, + LMUL_4, + LMUL_8, + LMUL_F8 = 5, + LMUL_F4, + LMUL_F2 +}; + +namespace RISCVVType { +// Is this a SEW value that can be encoded into the VTYPE format. +inline static bool isValidSEW(unsigned SEW) { + return isPowerOf2_32(SEW) && SEW >= 8 && SEW <= 1024; +} + +// Is this a LMUL value that can be encoded into the VTYPE format. +inline static bool isValidLMUL(unsigned LMUL, bool Fractional) { + return isPowerOf2_32(LMUL) && LMUL <= 8 && (!Fractional || LMUL != 1); +} + +// Encode VTYPE into the binary format used by the the VSETVLI instruction which +// is used by our MC layer representation. +// +// Bits | Name | Description +// -----+------------+------------------------------------------------ +// 7 | vma | Vector mask agnostic +// 6 | vta | Vector tail agnostic +// 5 | vlmul[2] | Fractional lmul? +// 4:2 | vsew[2:0] | Standard element width (SEW) setting +// 1:0 | vlmul[1:0] | Vector register group multiplier (LMUL) setting +// +// TODO: This format will change for the V extensions spec v1.0. +inline static unsigned encodeVTYPE(RISCVVLMUL VLMUL, RISCVVSEW VSEW, + bool TailAgnostic, bool MaskAgnostic) { + unsigned VLMULBits = static_cast(VLMUL); + unsigned VSEWBits = static_cast(VSEW); + unsigned VTypeI = + ((VLMULBits & 0x4) << 3) | (VSEWBits << 2) | (VLMULBits & 0x3); + if (TailAgnostic) + VTypeI |= 0x40; + if (MaskAgnostic) + VTypeI |= 0x80; + + return VTypeI; +} +} // namespace RISCVVType + +namespace RISCVVPseudosTable { + +struct PseudoInfo { + unsigned int Pseudo; + unsigned int BaseInstr; + uint8_t VLIndex; + uint8_t SEWIndex; + uint8_t MergeOpIndex; + uint8_t VLMul; + + int getVLIndex() const { return static_cast(VLIndex); } + + int getSEWIndex() const { return static_cast(SEWIndex); } + + int getMergeOpIndex() const { return static_cast(MergeOpIndex); } +}; + +using namespace RISCV; + +#define GET_RISCVVPseudosTable_DECL +#include "RISCVGenSearchableTables.inc" + +} // end namespace RISCVVPseudosTable + +} // namespace llvm + +#endif Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.cpp @@ -0,0 +1,104 @@ +//===-- RISCVBaseInfo.cpp - Top level definitions for RISCV MC ------------===// +// +// 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 contains small standalone enum definitions for the RISCV target +// useful for the compiler back-end and the MC libraries. +// +//===----------------------------------------------------------------------===// + +#include "RISCVBaseInfo.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace RISCVSysReg { +#define GET_SysRegsList_IMPL +#include "RISCVGenSearchableTables.inc" +} // namespace RISCVSysReg + +namespace RISCVABI { +ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, + StringRef ABIName) { + auto TargetABI = getTargetABI(ABIName); + bool IsRV64 = TT.isArch64Bit(); + bool IsRV32E = FeatureBits[RISCV::FeatureRV32E]; + + if (!ABIName.empty() && TargetABI == ABI_Unknown) { + errs() + << "'" << ABIName + << "' is not a recognized ABI for this target (ignoring target-abi)\n"; + } else if (ABIName.startswith("ilp32") && IsRV64) { + errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring " + "target-abi)\n"; + TargetABI = ABI_Unknown; + } else if (ABIName.startswith("lp64") && !IsRV64) { + errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring " + "target-abi)\n"; + TargetABI = ABI_Unknown; + } else if (IsRV32E && TargetABI != ABI_ILP32E && TargetABI != ABI_Unknown) { + // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser + errs() + << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n"; + TargetABI = ABI_Unknown; + } + + if (TargetABI != ABI_Unknown) + return TargetABI; + + // For now, default to the ilp32/ilp32e/lp64 ABI if no explicit ABI is given + // or an invalid/unrecognised string is given. In the future, it might be + // worth changing this to default to ilp32f/lp64f and ilp32d/lp64d when + // hardware support for floating point is present. + if (IsRV32E) + return ABI_ILP32E; + if (IsRV64) + return ABI_LP64; + return ABI_ILP32; +} + +ABI getTargetABI(StringRef ABIName) { + auto TargetABI = StringSwitch(ABIName) + .Case("ilp32", ABI_ILP32) + .Case("ilp32f", ABI_ILP32F) + .Case("ilp32d", ABI_ILP32D) + .Case("ilp32e", ABI_ILP32E) + .Case("lp64", ABI_LP64) + .Case("lp64f", ABI_LP64F) + .Case("lp64d", ABI_LP64D) + .Default(ABI_Unknown); + return TargetABI; +} + +// To avoid the BP value clobbered by a function call, we need to choose a +// callee saved register to save the value. RV32E only has X8 and X9 as callee +// saved registers and X8 will be used as fp. So we choose X9 as bp. +MCRegister getBPReg() { return RISCV::X9; } + +// Returns the register holding shadow call stack pointer. +MCRegister getSCSPReg() { return RISCV::X18; } + +} // namespace RISCVABI + +namespace RISCVFeatures { + +void validate(const Triple &TT, const FeatureBitset &FeatureBits) { + if (TT.isArch64Bit() && FeatureBits[RISCV::FeatureRV32E]) + report_fatal_error("RV32E can't be enabled for an RV64 target"); +} + +} // namespace RISCVFeatures + +namespace RISCVVPseudosTable { + +#define GET_RISCVVPseudosTable_IMPL +#include "RISCVGenSearchableTables.inc" + +} // namespace RISCVVPseudosTable + +} // namespace llvm Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -11,9 +11,9 @@ //===----------------------------------------------------------------------===// #include "RISCVELFStreamer.h" -#include "MCTargetDesc/RISCVAsmBackend.h" +#include "RISCVAsmBackend.h" +#include "RISCVBaseInfo.h" #include "RISCVMCTargetDesc.h" -#include "Utils/RISCVBaseInfo.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -11,8 +11,8 @@ //===----------------------------------------------------------------------===// #include "RISCVInstPrinter.h" -#include "MCTargetDesc/RISCVMCExpr.h" -#include "Utils/RISCVBaseInfo.h" +#include "RISCVBaseInfo.h" +#include "RISCVMCExpr.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCCodeEmitter.cpp @@ -10,10 +10,10 @@ // //===----------------------------------------------------------------------===// +#include "MCTargetDesc/RISCVBaseInfo.h" #include "MCTargetDesc/RISCVFixupKinds.h" #include "MCTargetDesc/RISCVMCExpr.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" -#include "Utils/RISCVBaseInfo.h" #include "llvm/ADT/Statistic.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCTargetDesc.cpp @@ -11,12 +11,12 @@ //===----------------------------------------------------------------------===// #include "RISCVMCTargetDesc.h" +#include "RISCVBaseInfo.h" #include "RISCVELFStreamer.h" #include "RISCVInstPrinter.h" #include "RISCVMCAsmInfo.h" #include "RISCVTargetStreamer.h" #include "TargetInfo/RISCVTargetInfo.h" -#include "Utils/RISCVBaseInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInstrAnalysis.h" Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h =================================================================== --- /dev/null +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.h @@ -0,0 +1,43 @@ +//===- RISCVMatInt.h - Immediate materialisation ---------------*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_RISCV_MATINT_H +#define LLVM_LIB_TARGET_RISCV_MATINT_H + +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { +class APInt; + +namespace RISCVMatInt { +struct Inst { + unsigned Opc; + int64_t Imm; + + Inst(unsigned Opc, int64_t Imm) : Opc(Opc), Imm(Imm) {} +}; +using InstSeq = SmallVector; + +// Helper to generate an instruction sequence that will materialise the given +// immediate value into a register. A sequence of instructions represented by +// a simple struct produced rather than directly emitting the instructions in +// order to allow this helper to be used from both the MC layer and during +// instruction selection. +void generateInstSeq(int64_t Val, bool IsRV64, InstSeq &Res); + +// Helper to estimate the number of instructions required to materialise the +// given immediate value into a register. This estimate does not account for +// `Val` possibly fitting into an immediate, and so may over-estimate. +// +// This will attempt to produce instructions to materialise `Val` as an +// `Size`-bit immediate. `IsRV64` should match the target architecture. +int getIntMatCost(const APInt &Val, unsigned Size, bool IsRV64); +} // namespace RISCVMatInt +} // namespace llvm +#endif Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -0,0 +1,91 @@ +//===- RISCVMatInt.cpp - Immediate materialisation -------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "RISCVMatInt.h" +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/ADT/APInt.h" +#include "llvm/Support/MathExtras.h" + +namespace llvm { + +namespace RISCVMatInt { +void generateInstSeq(int64_t Val, bool IsRV64, InstSeq &Res) { + if (isInt<32>(Val)) { + // Depending on the active bits in the immediate Value v, the following + // instruction sequences are emitted: + // + // v == 0 : ADDI + // v[0,12) != 0 && v[12,32) == 0 : ADDI + // v[0,12) == 0 && v[12,32) != 0 : LUI + // v[0,32) != 0 : LUI+ADDI(W) + int64_t Hi20 = ((Val + 0x800) >> 12) & 0xFFFFF; + int64_t Lo12 = SignExtend64<12>(Val); + + if (Hi20) + Res.push_back(Inst(RISCV::LUI, Hi20)); + + if (Lo12 || Hi20 == 0) { + unsigned AddiOpc = (IsRV64 && Hi20) ? RISCV::ADDIW : RISCV::ADDI; + Res.push_back(Inst(AddiOpc, Lo12)); + } + return; + } + + assert(IsRV64 && "Can't emit >32-bit imm for non-RV64 target"); + + // In the worst case, for a full 64-bit constant, a sequence of 8 instructions + // (i.e., LUI+ADDIW+SLLI+ADDI+SLLI+ADDI+SLLI+ADDI) has to be emmitted. Note + // that the first two instructions (LUI+ADDIW) can contribute up to 32 bits + // while the following ADDI instructions contribute up to 12 bits each. + // + // On the first glance, implementing this seems to be possible by simply + // emitting the most significant 32 bits (LUI+ADDIW) followed by as many left + // shift (SLLI) and immediate additions (ADDI) as needed. However, due to the + // fact that ADDI performs a sign extended addition, doing it like that would + // only be possible when at most 11 bits of the ADDI instructions are used. + // Using all 12 bits of the ADDI instructions, like done by GAS, actually + // requires that the constant is processed starting with the least significant + // bit. + // + // In the following, constants are processed from LSB to MSB but instruction + // emission is performed from MSB to LSB by recursively calling + // generateInstSeq. In each recursion, first the lowest 12 bits are removed + // from the constant and the optimal shift amount, which can be greater than + // 12 bits if the constant is sparse, is determined. Then, the shifted + // remaining constant is processed recursively and gets emitted as soon as it + // fits into 32 bits. The emission of the shifts and additions is subsequently + // performed when the recursion returns. + + int64_t Lo12 = SignExtend64<12>(Val); + int64_t Hi52 = ((uint64_t)Val + 0x800ull) >> 12; + int ShiftAmount = 12 + findFirstSet((uint64_t)Hi52); + Hi52 = SignExtend64(Hi52 >> (ShiftAmount - 12), 64 - ShiftAmount); + + generateInstSeq(Hi52, IsRV64, Res); + + Res.push_back(Inst(RISCV::SLLI, ShiftAmount)); + if (Lo12) + Res.push_back(Inst(RISCV::ADDI, Lo12)); +} + +int getIntMatCost(const APInt &Val, unsigned Size, bool IsRV64) { + int PlatRegSize = IsRV64 ? 64 : 32; + + // Split the constant into platform register sized chunks, and calculate cost + // of each chunk. + int Cost = 0; + for (unsigned ShiftVal = 0; ShiftVal < Size; ShiftVal += PlatRegSize) { + APInt Chunk = Val.ashr(ShiftVal).sextOrTrunc(PlatRegSize); + InstSeq MatSeq; + generateInstSeq(Chunk.getSExtValue(), IsRV64, MatSeq); + Cost += MatSeq.size(); + } + return std::max(1, Cost); +} +} // namespace RISCVMatInt +} // namespace llvm Index: llvm/lib/Target/RISCV/RISCV.h =================================================================== --- llvm/lib/Target/RISCV/RISCV.h +++ llvm/lib/Target/RISCV/RISCV.h @@ -14,7 +14,7 @@ #ifndef LLVM_LIB_TARGET_RISCV_RISCV_H #define LLVM_LIB_TARGET_RISCV_RISCV_H -#include "Utils/RISCVBaseInfo.h" +#include "MCTargetDesc/RISCVBaseInfo.h" #include "llvm/Target/TargetMachine.h" namespace llvm { Index: llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -12,7 +12,7 @@ #include "RISCVISelDAGToDAG.h" #include "MCTargetDesc/RISCVMCTargetDesc.h" -#include "Utils/RISCVMatInt.h" +#include "MCTargetDesc/RISCVMatInt.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/Debug.h" Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -12,12 +12,12 @@ //===----------------------------------------------------------------------===// #include "RISCVISelLowering.h" +#include "MCTargetDesc/RISCVMatInt.h" #include "RISCV.h" #include "RISCVMachineFunctionInfo.h" #include "RISCVRegisterInfo.h" #include "RISCVSubtarget.h" #include "RISCVTargetMachine.h" -#include "Utils/RISCVMatInt.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/CallingConvLower.h" Index: llvm/lib/Target/RISCV/RISCVInstrInfo.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -11,10 +11,10 @@ //===----------------------------------------------------------------------===// #include "RISCVInstrInfo.h" +#include "MCTargetDesc/RISCVMatInt.h" #include "RISCV.h" #include "RISCVSubtarget.h" #include "RISCVTargetMachine.h" -#include "Utils/RISCVMatInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" Index: llvm/lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- llvm/lib/Target/RISCV/RISCVSubtarget.h +++ llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -13,10 +13,10 @@ #ifndef LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H #define LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H +#include "MCTargetDesc/RISCVBaseInfo.h" #include "RISCVFrameLowering.h" #include "RISCVISelLowering.h" #include "RISCVInstrInfo.h" -#include "Utils/RISCVBaseInfo.h" #include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" Index: llvm/lib/Target/RISCV/RISCVTargetMachine.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -11,11 +11,11 @@ //===----------------------------------------------------------------------===// #include "RISCVTargetMachine.h" +#include "MCTargetDesc/RISCVBaseInfo.h" #include "RISCV.h" #include "RISCVTargetObjectFile.h" #include "RISCVTargetTransformInfo.h" #include "TargetInfo/RISCVTargetInfo.h" -#include "Utils/RISCVBaseInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/GlobalISel/IRTranslator.h" Index: llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// #include "RISCVTargetTransformInfo.h" -#include "Utils/RISCVMatInt.h" +#include "MCTargetDesc/RISCVMatInt.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/BasicTTIImpl.h" #include "llvm/CodeGen/TargetLowering.h" Index: llvm/lib/Target/RISCV/Utils/CMakeLists.txt =================================================================== --- llvm/lib/Target/RISCV/Utils/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_llvm_component_library(LLVMRISCVUtils - RISCVBaseInfo.cpp - RISCVMatInt.cpp - - LINK_COMPONENTS - Support - - ADD_TO_COMPONENT - RISCV - ) Index: llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h =================================================================== --- llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.h +++ /dev/null @@ -1,418 +0,0 @@ -//===-- RISCVBaseInfo.h - Top level definitions for RISCV MC ----*- 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 contains small standalone enum definitions for the RISCV target -// useful for the compiler back-end and the MC libraries. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H -#define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H - -#include "MCTargetDesc/RISCVMCTargetDesc.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/MC/MCInstrDesc.h" -#include "llvm/MC/SubtargetFeature.h" -#include "llvm/Support/MachineValueType.h" - -namespace llvm { - -// RISCVII - This namespace holds all of the target specific flags that -// instruction info tracks. All definitions must match RISCVInstrFormats.td. -namespace RISCVII { -enum { - InstFormatPseudo = 0, - InstFormatR = 1, - InstFormatR4 = 2, - InstFormatI = 3, - InstFormatS = 4, - InstFormatB = 5, - InstFormatU = 6, - InstFormatJ = 7, - InstFormatCR = 8, - InstFormatCI = 9, - InstFormatCSS = 10, - InstFormatCIW = 11, - InstFormatCL = 12, - InstFormatCS = 13, - InstFormatCA = 14, - InstFormatCB = 15, - InstFormatCJ = 16, - InstFormatOther = 17, - - InstFormatMask = 31, - - ConstraintOffset = 5, - ConstraintMask = 0b1111 -}; - -// Match with the definitions in RISCVInstrFormatsV.td -enum RVVConstraintType { - NoConstraint = 0, - VS2Constraint = 0b0001, - VS1Constraint = 0b0010, - VMConstraint = 0b0100, - OneInput = 0b1000, - - // Illegal instructions: - // - // * The destination vector register group for a masked vector instruction - // cannot overlap the source mask register (v0), unless the destination vector - // register is being written with a mask value (e.g., comparisons) or the - // scalar result of a reduction. - // - // * Widening: The destination vector register group cannot overlap a source - // vector register group of a different EEW - // - // * Narrowing: The destination vector register group cannot overlap the - // first source vector register group - // - // * For vadc and vsbc, an illegal instruction exception is raised if the - // destination vector register is v0. - // - // * For vmadc and vmsbc, an illegal instruction exception is raised if the - // destination vector register overlaps a source vector register group. - // - // * viota: An illegal instruction exception is raised if the destination - // vector register group overlaps the source vector mask register. If the - // instruction is masked, an illegal instruction exception is issued if the - // destination vector register group overlaps v0. - // - // * v[f]slide[1]up: The destination vector register group for vslideup cannot - // overlap the source vector register group. - // - // * vrgather: The destination vector register group cannot overlap with the - // source vector register groups. - // - // * vcompress: The destination vector register group cannot overlap the - // source vector register group or the source mask register - WidenV = VS2Constraint | VS1Constraint | VMConstraint, - WidenW = VS1Constraint | VMConstraint, - WidenCvt = VS2Constraint | VMConstraint | OneInput, - Narrow = VS2Constraint | VMConstraint, - NarrowCvt = VS2Constraint | VMConstraint | OneInput, - Vmadc = VS2Constraint | VS1Constraint, - Iota = VS2Constraint | VMConstraint | OneInput, - SlideUp = VS2Constraint | VMConstraint, - Vrgather = VS2Constraint | VS1Constraint | VMConstraint, - Vcompress = VS2Constraint | VS1Constraint, -}; - -// RISC-V Specific Machine Operand Flags -enum { - MO_None = 0, - MO_CALL = 1, - MO_PLT = 2, - MO_LO = 3, - MO_HI = 4, - MO_PCREL_LO = 5, - MO_PCREL_HI = 6, - MO_GOT_HI = 7, - MO_TPREL_LO = 8, - MO_TPREL_HI = 9, - MO_TPREL_ADD = 10, - MO_TLS_GOT_HI = 11, - MO_TLS_GD_HI = 12, - - // Used to differentiate between target-specific "direct" flags and "bitmask" - // flags. A machine operand can only have one "direct" flag, but can have - // multiple "bitmask" flags. - MO_DIRECT_FLAG_MASK = 15 -}; -} // namespace RISCVII - -namespace RISCVOp { -enum OperandType : unsigned { - OPERAND_FIRST_RISCV_IMM = MCOI::OPERAND_FIRST_TARGET, - OPERAND_UIMM4 = OPERAND_FIRST_RISCV_IMM, - OPERAND_UIMM5, - OPERAND_UIMM12, - OPERAND_SIMM12, - OPERAND_UIMM20, - OPERAND_UIMMLOG2XLEN, - OPERAND_LAST_RISCV_IMM = OPERAND_UIMMLOG2XLEN -}; -} // namespace RISCVOp - -// Describes the predecessor/successor bits used in the FENCE instruction. -namespace RISCVFenceField { -enum FenceField { - I = 8, - O = 4, - R = 2, - W = 1 -}; -} - -// Describes the supported floating point rounding mode encodings. -namespace RISCVFPRndMode { -enum RoundingMode { - RNE = 0, - RTZ = 1, - RDN = 2, - RUP = 3, - RMM = 4, - DYN = 7, - Invalid -}; - -inline static StringRef roundingModeToString(RoundingMode RndMode) { - switch (RndMode) { - default: - llvm_unreachable("Unknown floating point rounding mode"); - case RISCVFPRndMode::RNE: - return "rne"; - case RISCVFPRndMode::RTZ: - return "rtz"; - case RISCVFPRndMode::RDN: - return "rdn"; - case RISCVFPRndMode::RUP: - return "rup"; - case RISCVFPRndMode::RMM: - return "rmm"; - case RISCVFPRndMode::DYN: - return "dyn"; - } -} - -inline static RoundingMode stringToRoundingMode(StringRef Str) { - return StringSwitch(Str) - .Case("rne", RISCVFPRndMode::RNE) - .Case("rtz", RISCVFPRndMode::RTZ) - .Case("rdn", RISCVFPRndMode::RDN) - .Case("rup", RISCVFPRndMode::RUP) - .Case("rmm", RISCVFPRndMode::RMM) - .Case("dyn", RISCVFPRndMode::DYN) - .Default(RISCVFPRndMode::Invalid); -} - -inline static bool isValidRoundingMode(unsigned Mode) { - switch (Mode) { - default: - return false; - case RISCVFPRndMode::RNE: - case RISCVFPRndMode::RTZ: - case RISCVFPRndMode::RDN: - case RISCVFPRndMode::RUP: - case RISCVFPRndMode::RMM: - case RISCVFPRndMode::DYN: - return true; - } -} -} // namespace RISCVFPRndMode - -namespace RISCVSysReg { -struct SysReg { - const char *Name; - unsigned Encoding; - const char *AltName; - // FIXME: add these additional fields when needed. - // Privilege Access: Read, Write, Read-Only. - // unsigned ReadWrite; - // Privilege Mode: User, System or Machine. - // unsigned Mode; - // Check field name. - // unsigned Extra; - // Register number without the privilege bits. - // unsigned Number; - FeatureBitset FeaturesRequired; - bool isRV32Only; - - bool haveRequiredFeatures(FeatureBitset ActiveFeatures) const { - // Not in 32-bit mode. - if (isRV32Only && ActiveFeatures[RISCV::Feature64Bit]) - return false; - // No required feature associated with the system register. - if (FeaturesRequired.none()) - return true; - return (FeaturesRequired & ActiveFeatures) == FeaturesRequired; - } -}; - -#define GET_SysRegsList_DECL -#include "RISCVGenSearchableTables.inc" -} // end namespace RISCVSysReg - -namespace RISCVABI { - -enum ABI { - ABI_ILP32, - ABI_ILP32F, - ABI_ILP32D, - ABI_ILP32E, - ABI_LP64, - ABI_LP64F, - ABI_LP64D, - ABI_Unknown -}; - -// Returns the target ABI, or else a StringError if the requested ABIName is -// not supported for the given TT and FeatureBits combination. -ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, - StringRef ABIName); - -ABI getTargetABI(StringRef ABIName); - -// Returns the register used to hold the stack pointer after realignment. -MCRegister getBPReg(); - -// Returns the register holding shadow call stack pointer. -MCRegister getSCSPReg(); - -} // namespace RISCVABI - -namespace RISCVFeatures { - -// Validates if the given combination of features are valid for the target -// triple. Exits with report_fatal_error if not. -void validate(const Triple &TT, const FeatureBitset &FeatureBits); - -} // namespace RISCVFeatures - -namespace RISCVVMVTs { - -constexpr MVT vint8mf8_t = MVT::nxv1i8; -constexpr MVT vint8mf4_t = MVT::nxv2i8; -constexpr MVT vint8mf2_t = MVT::nxv4i8; -constexpr MVT vint8m1_t = MVT::nxv8i8; -constexpr MVT vint8m2_t = MVT::nxv16i8; -constexpr MVT vint8m4_t = MVT::nxv32i8; -constexpr MVT vint8m8_t = MVT::nxv64i8; - -constexpr MVT vint16mf4_t = MVT::nxv1i16; -constexpr MVT vint16mf2_t = MVT::nxv2i16; -constexpr MVT vint16m1_t = MVT::nxv4i16; -constexpr MVT vint16m2_t = MVT::nxv8i16; -constexpr MVT vint16m4_t = MVT::nxv16i16; -constexpr MVT vint16m8_t = MVT::nxv32i16; - -constexpr MVT vint32mf2_t = MVT::nxv1i32; -constexpr MVT vint32m1_t = MVT::nxv2i32; -constexpr MVT vint32m2_t = MVT::nxv4i32; -constexpr MVT vint32m4_t = MVT::nxv8i32; -constexpr MVT vint32m8_t = MVT::nxv16i32; - -constexpr MVT vint64m1_t = MVT::nxv1i64; -constexpr MVT vint64m2_t = MVT::nxv2i64; -constexpr MVT vint64m4_t = MVT::nxv4i64; -constexpr MVT vint64m8_t = MVT::nxv8i64; - -constexpr MVT vfloat16mf4_t = MVT::nxv1f16; -constexpr MVT vfloat16mf2_t = MVT::nxv2f16; -constexpr MVT vfloat16m1_t = MVT::nxv4f16; -constexpr MVT vfloat16m2_t = MVT::nxv8f16; -constexpr MVT vfloat16m4_t = MVT::nxv16f16; -constexpr MVT vfloat16m8_t = MVT::nxv32f16; - -constexpr MVT vfloat32mf2_t = MVT::nxv1f32; -constexpr MVT vfloat32m1_t = MVT::nxv2f32; -constexpr MVT vfloat32m2_t = MVT::nxv4f32; -constexpr MVT vfloat32m4_t = MVT::nxv8f32; -constexpr MVT vfloat32m8_t = MVT::nxv16f32; - -constexpr MVT vfloat64m1_t = MVT::nxv1f64; -constexpr MVT vfloat64m2_t = MVT::nxv2f64; -constexpr MVT vfloat64m4_t = MVT::nxv4f64; -constexpr MVT vfloat64m8_t = MVT::nxv8f64; - -constexpr MVT vbool1_t = MVT::nxv64i1; -constexpr MVT vbool2_t = MVT::nxv32i1; -constexpr MVT vbool4_t = MVT::nxv16i1; -constexpr MVT vbool8_t = MVT::nxv8i1; -constexpr MVT vbool16_t = MVT::nxv4i1; -constexpr MVT vbool32_t = MVT::nxv2i1; -constexpr MVT vbool64_t = MVT::nxv1i1; - -} // namespace RISCVVMVTs - -enum class RISCVVSEW { - SEW_8 = 0, - SEW_16, - SEW_32, - SEW_64, - SEW_128, - SEW_256, - SEW_512, - SEW_1024, -}; - -enum class RISCVVLMUL { - LMUL_1 = 0, - LMUL_2, - LMUL_4, - LMUL_8, - LMUL_F8 = 5, - LMUL_F4, - LMUL_F2 -}; - -namespace RISCVVType { -// Is this a SEW value that can be encoded into the VTYPE format. -inline static bool isValidSEW(unsigned SEW) { - return isPowerOf2_32(SEW) && SEW >= 8 && SEW <= 1024; -} - -// Is this a LMUL value that can be encoded into the VTYPE format. -inline static bool isValidLMUL(unsigned LMUL, bool Fractional) { - return isPowerOf2_32(LMUL) && LMUL <= 8 && (!Fractional || LMUL != 1); -} - -// Encode VTYPE into the binary format used by the the VSETVLI instruction which -// is used by our MC layer representation. -// -// Bits | Name | Description -// -----+------------+------------------------------------------------ -// 7 | vma | Vector mask agnostic -// 6 | vta | Vector tail agnostic -// 5 | vlmul[2] | Fractional lmul? -// 4:2 | vsew[2:0] | Standard element width (SEW) setting -// 1:0 | vlmul[1:0] | Vector register group multiplier (LMUL) setting -// -// TODO: This format will change for the V extensions spec v1.0. -inline static unsigned encodeVTYPE(RISCVVLMUL VLMUL, RISCVVSEW VSEW, - bool TailAgnostic, bool MaskAgnostic) { - unsigned VLMULBits = static_cast(VLMUL); - unsigned VSEWBits = static_cast(VSEW); - unsigned VTypeI = - ((VLMULBits & 0x4) << 3) | (VSEWBits << 2) | (VLMULBits & 0x3); - if (TailAgnostic) - VTypeI |= 0x40; - if (MaskAgnostic) - VTypeI |= 0x80; - - return VTypeI; -} -} // namespace RISCVVType - -namespace RISCVVPseudosTable { - -struct PseudoInfo { - unsigned int Pseudo; - unsigned int BaseInstr; - uint8_t VLIndex; - uint8_t SEWIndex; - uint8_t MergeOpIndex; - uint8_t VLMul; - - int getVLIndex() const { return static_cast(VLIndex); } - - int getSEWIndex() const { return static_cast(SEWIndex); } - - int getMergeOpIndex() const { return static_cast(MergeOpIndex); } -}; - -using namespace RISCV; - -#define GET_RISCVVPseudosTable_DECL -#include "RISCVGenSearchableTables.inc" - -} // end namespace RISCVVPseudosTable - -} // namespace llvm - -#endif Index: llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp =================================================================== --- llvm/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//===-- RISCVBaseInfo.cpp - Top level definitions for RISCV MC ------------===// -// -// 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 contains small standalone enum definitions for the RISCV target -// useful for the compiler back-end and the MC libraries. -// -//===----------------------------------------------------------------------===// - -#include "RISCVBaseInfo.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { -namespace RISCVSysReg { -#define GET_SysRegsList_IMPL -#include "RISCVGenSearchableTables.inc" -} // namespace RISCVSysReg - -namespace RISCVABI { -ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, - StringRef ABIName) { - auto TargetABI = getTargetABI(ABIName); - bool IsRV64 = TT.isArch64Bit(); - bool IsRV32E = FeatureBits[RISCV::FeatureRV32E]; - - if (!ABIName.empty() && TargetABI == ABI_Unknown) { - errs() - << "'" << ABIName - << "' is not a recognized ABI for this target (ignoring target-abi)\n"; - } else if (ABIName.startswith("ilp32") && IsRV64) { - errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring " - "target-abi)\n"; - TargetABI = ABI_Unknown; - } else if (ABIName.startswith("lp64") && !IsRV64) { - errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring " - "target-abi)\n"; - TargetABI = ABI_Unknown; - } else if (IsRV32E && TargetABI != ABI_ILP32E && TargetABI != ABI_Unknown) { - // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser - errs() - << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n"; - TargetABI = ABI_Unknown; - } - - if (TargetABI != ABI_Unknown) - return TargetABI; - - // For now, default to the ilp32/ilp32e/lp64 ABI if no explicit ABI is given - // or an invalid/unrecognised string is given. In the future, it might be - // worth changing this to default to ilp32f/lp64f and ilp32d/lp64d when - // hardware support for floating point is present. - if (IsRV32E) - return ABI_ILP32E; - if (IsRV64) - return ABI_LP64; - return ABI_ILP32; -} - -ABI getTargetABI(StringRef ABIName) { - auto TargetABI = StringSwitch(ABIName) - .Case("ilp32", ABI_ILP32) - .Case("ilp32f", ABI_ILP32F) - .Case("ilp32d", ABI_ILP32D) - .Case("ilp32e", ABI_ILP32E) - .Case("lp64", ABI_LP64) - .Case("lp64f", ABI_LP64F) - .Case("lp64d", ABI_LP64D) - .Default(ABI_Unknown); - return TargetABI; -} - -// To avoid the BP value clobbered by a function call, we need to choose a -// callee saved register to save the value. RV32E only has X8 and X9 as callee -// saved registers and X8 will be used as fp. So we choose X9 as bp. -MCRegister getBPReg() { return RISCV::X9; } - -// Returns the register holding shadow call stack pointer. -MCRegister getSCSPReg() { return RISCV::X18; } - -} // namespace RISCVABI - -namespace RISCVFeatures { - -void validate(const Triple &TT, const FeatureBitset &FeatureBits) { - if (TT.isArch64Bit() && FeatureBits[RISCV::FeatureRV32E]) - report_fatal_error("RV32E can't be enabled for an RV64 target"); -} - -} // namespace RISCVFeatures - -namespace RISCVVPseudosTable { - -#define GET_RISCVVPseudosTable_IMPL -#include "RISCVGenSearchableTables.inc" - -} // namespace RISCVVPseudosTable - -} // namespace llvm Index: llvm/lib/Target/RISCV/Utils/RISCVMatInt.h =================================================================== --- llvm/lib/Target/RISCV/Utils/RISCVMatInt.h +++ /dev/null @@ -1,43 +0,0 @@ -//===- RISCVMatInt.h - Immediate materialisation ---------------*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_RISCV_MATINT_H -#define LLVM_LIB_TARGET_RISCV_MATINT_H - -#include "llvm/ADT/SmallVector.h" -#include - -namespace llvm { -class APInt; - -namespace RISCVMatInt { -struct Inst { - unsigned Opc; - int64_t Imm; - - Inst(unsigned Opc, int64_t Imm) : Opc(Opc), Imm(Imm) {} -}; -using InstSeq = SmallVector; - -// Helper to generate an instruction sequence that will materialise the given -// immediate value into a register. A sequence of instructions represented by -// a simple struct produced rather than directly emitting the instructions in -// order to allow this helper to be used from both the MC layer and during -// instruction selection. -void generateInstSeq(int64_t Val, bool IsRV64, InstSeq &Res); - -// Helper to estimate the number of instructions required to materialise the -// given immediate value into a register. This estimate does not account for -// `Val` possibly fitting into an immediate, and so may over-estimate. -// -// This will attempt to produce instructions to materialise `Val` as an -// `Size`-bit immediate. `IsRV64` should match the target architecture. -int getIntMatCost(const APInt &Val, unsigned Size, bool IsRV64); -} // namespace RISCVMatInt -} // namespace llvm -#endif Index: llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp =================================================================== --- llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp +++ /dev/null @@ -1,91 +0,0 @@ -//===- RISCVMatInt.cpp - Immediate materialisation -------------*- 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 -// -//===----------------------------------------------------------------------===// - -#include "RISCVMatInt.h" -#include "MCTargetDesc/RISCVMCTargetDesc.h" -#include "llvm/ADT/APInt.h" -#include "llvm/Support/MathExtras.h" - -namespace llvm { - -namespace RISCVMatInt { -void generateInstSeq(int64_t Val, bool IsRV64, InstSeq &Res) { - if (isInt<32>(Val)) { - // Depending on the active bits in the immediate Value v, the following - // instruction sequences are emitted: - // - // v == 0 : ADDI - // v[0,12) != 0 && v[12,32) == 0 : ADDI - // v[0,12) == 0 && v[12,32) != 0 : LUI - // v[0,32) != 0 : LUI+ADDI(W) - int64_t Hi20 = ((Val + 0x800) >> 12) & 0xFFFFF; - int64_t Lo12 = SignExtend64<12>(Val); - - if (Hi20) - Res.push_back(Inst(RISCV::LUI, Hi20)); - - if (Lo12 || Hi20 == 0) { - unsigned AddiOpc = (IsRV64 && Hi20) ? RISCV::ADDIW : RISCV::ADDI; - Res.push_back(Inst(AddiOpc, Lo12)); - } - return; - } - - assert(IsRV64 && "Can't emit >32-bit imm for non-RV64 target"); - - // In the worst case, for a full 64-bit constant, a sequence of 8 instructions - // (i.e., LUI+ADDIW+SLLI+ADDI+SLLI+ADDI+SLLI+ADDI) has to be emmitted. Note - // that the first two instructions (LUI+ADDIW) can contribute up to 32 bits - // while the following ADDI instructions contribute up to 12 bits each. - // - // On the first glance, implementing this seems to be possible by simply - // emitting the most significant 32 bits (LUI+ADDIW) followed by as many left - // shift (SLLI) and immediate additions (ADDI) as needed. However, due to the - // fact that ADDI performs a sign extended addition, doing it like that would - // only be possible when at most 11 bits of the ADDI instructions are used. - // Using all 12 bits of the ADDI instructions, like done by GAS, actually - // requires that the constant is processed starting with the least significant - // bit. - // - // In the following, constants are processed from LSB to MSB but instruction - // emission is performed from MSB to LSB by recursively calling - // generateInstSeq. In each recursion, first the lowest 12 bits are removed - // from the constant and the optimal shift amount, which can be greater than - // 12 bits if the constant is sparse, is determined. Then, the shifted - // remaining constant is processed recursively and gets emitted as soon as it - // fits into 32 bits. The emission of the shifts and additions is subsequently - // performed when the recursion returns. - - int64_t Lo12 = SignExtend64<12>(Val); - int64_t Hi52 = ((uint64_t)Val + 0x800ull) >> 12; - int ShiftAmount = 12 + findFirstSet((uint64_t)Hi52); - Hi52 = SignExtend64(Hi52 >> (ShiftAmount - 12), 64 - ShiftAmount); - - generateInstSeq(Hi52, IsRV64, Res); - - Res.push_back(Inst(RISCV::SLLI, ShiftAmount)); - if (Lo12) - Res.push_back(Inst(RISCV::ADDI, Lo12)); -} - -int getIntMatCost(const APInt &Val, unsigned Size, bool IsRV64) { - int PlatRegSize = IsRV64 ? 64 : 32; - - // Split the constant into platform register sized chunks, and calculate cost - // of each chunk. - int Cost = 0; - for (unsigned ShiftVal = 0; ShiftVal < Size; ShiftVal += PlatRegSize) { - APInt Chunk = Val.ashr(ShiftVal).sextOrTrunc(PlatRegSize); - InstSeq MatSeq; - generateInstSeq(Chunk.getSExtValue(), IsRV64, MatSeq); - Cost += MatSeq.size(); - } - return std::max(1, Cost); -} -} // namespace RISCVMatInt -} // namespace llvm