summaryrefslogtreecommitdiff
path: root/lib/Target/RISCV/Utils
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/RISCV/Utils')
-rw-r--r--lib/Target/RISCV/Utils/CMakeLists.txt4
-rw-r--r--lib/Target/RISCV/Utils/LLVMBuild.txt24
-rw-r--r--lib/Target/RISCV/Utils/RISCVBaseInfo.cpp9
-rw-r--r--lib/Target/RISCV/Utils/RISCVBaseInfo.h158
-rw-r--r--lib/Target/RISCV/Utils/RISCVMatInt.cpp79
-rw-r--r--lib/Target/RISCV/Utils/RISCVMatInt.h36
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