diff options
Diffstat (limited to 'lib/Target/RISCV/Utils')
| -rw-r--r-- | lib/Target/RISCV/Utils/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | lib/Target/RISCV/Utils/LLVMBuild.txt | 24 | ||||
| -rw-r--r-- | lib/Target/RISCV/Utils/RISCVBaseInfo.cpp | 9 | ||||
| -rw-r--r-- | lib/Target/RISCV/Utils/RISCVBaseInfo.h | 158 | ||||
| -rw-r--r-- | lib/Target/RISCV/Utils/RISCVMatInt.cpp | 79 | ||||
| -rw-r--r-- | lib/Target/RISCV/Utils/RISCVMatInt.h | 36 |
6 files changed, 310 insertions, 0 deletions
diff --git a/lib/Target/RISCV/Utils/CMakeLists.txt b/lib/Target/RISCV/Utils/CMakeLists.txt new file mode 100644 index 0000000000000..727ab4a9fd771 --- /dev/null +++ b/lib/Target/RISCV/Utils/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_library(LLVMRISCVUtils + RISCVBaseInfo.cpp + RISCVMatInt.cpp + ) diff --git a/lib/Target/RISCV/Utils/LLVMBuild.txt b/lib/Target/RISCV/Utils/LLVMBuild.txt new file mode 100644 index 0000000000000..ec75b93036693 --- /dev/null +++ b/lib/Target/RISCV/Utils/LLVMBuild.txt @@ -0,0 +1,24 @@ +;===- ./lib/Target/RISCV/Utils/LLVMBuild.txt ----------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = RISCVUtils +parent = RISCV +required_libraries = Support +add_to_library_groups = RISCV + diff --git a/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp b/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp new file mode 100644 index 0000000000000..964af1f74cecb --- /dev/null +++ b/lib/Target/RISCV/Utils/RISCVBaseInfo.cpp @@ -0,0 +1,9 @@ +#include "RISCVBaseInfo.h" +#include "llvm/ADT/ArrayRef.h" + +namespace llvm { +namespace RISCVSysReg { +#define GET_SysRegsList_IMPL +#include "RISCVGenSystemOperands.inc" +} // namespace RISCVSysReg +} // namespace llvm diff --git a/lib/Target/RISCV/Utils/RISCVBaseInfo.h b/lib/Target/RISCV/Utils/RISCVBaseInfo.h new file mode 100644 index 0000000000000..372e0e80bbaf8 --- /dev/null +++ b/lib/Target/RISCV/Utils/RISCVBaseInfo.h @@ -0,0 +1,158 @@ +//===-- RISCVBaseInfo.h - Top level definitions for RISCV MC ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// 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/SubtargetFeature.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 +}; + +enum { + MO_None, + MO_LO, + MO_HI, + MO_PCREL_HI, +}; +} // namespace RISCVII + +// 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<RoundingMode>(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; + // 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 "RISCVGenSystemOperands.inc" +} // end namespace RISCVSysReg + +} // namespace llvm + +#endif diff --git a/lib/Target/RISCV/Utils/RISCVMatInt.cpp b/lib/Target/RISCV/Utils/RISCVMatInt.cpp new file mode 100644 index 0000000000000..3dc298246bc56 --- /dev/null +++ b/lib/Target/RISCV/Utils/RISCVMatInt.cpp @@ -0,0 +1,79 @@ +//===- RISCVMatInt.cpp - Immediate materialisation -------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RISCVMatInt.h" +#include "MCTargetDesc/RISCVMCTargetDesc.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MachineValueType.h" +#include "llvm/Support/MathExtras.h" +#include <cstdint> + +namespace llvm { + +namespace RISCVMatInt { +void generateInstSeq(int64_t Val, bool Is64Bit, 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 = (Is64Bit && Hi20) ? RISCV::ADDIW : RISCV::ADDI; + Res.push_back(Inst(AddiOpc, Lo12)); + } + return; + } + + assert(Is64Bit && "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 = (Val + 0x800) >> 12; + int ShiftAmount = 12 + findFirstSet((uint64_t)Hi52); + Hi52 = SignExtend64(Hi52 >> (ShiftAmount - 12), 64 - ShiftAmount); + + generateInstSeq(Hi52, Is64Bit, Res); + + Res.push_back(Inst(RISCV::SLLI, ShiftAmount)); + if (Lo12) + Res.push_back(Inst(RISCV::ADDI, Lo12)); +} +} // namespace RISCVMatInt +} // namespace llvm diff --git a/lib/Target/RISCV/Utils/RISCVMatInt.h b/lib/Target/RISCV/Utils/RISCVMatInt.h new file mode 100644 index 0000000000000..49d1d89adc7a1 --- /dev/null +++ b/lib/Target/RISCV/Utils/RISCVMatInt.h @@ -0,0 +1,36 @@ +//===- RISCVMatInt.h - Immediate materialisation ---------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_RISCV_MATINT_H +#define LLVM_LIB_TARGET_RISCV_MATINT_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MachineValueType.h" +#include <cstdint> + +namespace llvm { + +namespace RISCVMatInt { +struct Inst { + unsigned Opc; + int64_t Imm; + + Inst(unsigned Opc, int64_t Imm) : Opc(Opc), Imm(Imm) {} +}; +using InstSeq = SmallVector<Inst, 8>; + +// 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); +} // namespace RISCVMatInt +} // namespace llvm +#endif |
