[LoongArch 4/6] Add basic tablegen infra for LoongArch
authorLu Weining <luweining@loongson.cn>
Thu, 10 Feb 2022 09:14:18 +0000 (09:14 +0000)
committerRenato Golin <rengolin@systemcall.eu>
Thu, 10 Feb 2022 10:23:34 +0000 (10:23 +0000)
This patch introduces basic tablegen infra such as
LoongArch{InstrFormats,InstrInfo,RegisterInfo,CallingConv,}.td.

For now, only add instruction definitions for LoongArch basic integer
operations.
Our initial target is a working MC layer rather than codegen,
so appropriate SelectionDAG patterns will come later.

Differential revision: https://reviews.llvm.org/D115861

40 files changed:
llvm/lib/Target/LoongArch/CMakeLists.txt
llvm/lib/Target/LoongArch/LoongArch.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArch.td [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchCallingConv.td [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchFrameLowering.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchISelLowering.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchInstrFormats.td [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchInstrInfo.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchInstrInfo.td [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchSubtarget.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
llvm/lib/Target/LoongArch/LoongArchTargetMachine.h
llvm/lib/Target/LoongArch/MCTargetDesc/CMakeLists.txt
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp [new file with mode: 0644]
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.cpp
llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h [new file with mode: 0644]
llvm/lib/Target/LoongArch/TargetInfo/LoongArchTargetInfo.cpp
llvm/test/CodeGen/LoongArch/target_support.ll

index 254320f..ecd6af7 100644 (file)
@@ -1,6 +1,27 @@
 add_llvm_component_group(LoongArch)
 
+set(LLVM_TARGET_DEFINITIONS LoongArch.td)
+
+tablegen(LLVM LoongArchGenAsmMatcher.inc -gen-asm-matcher)
+tablegen(LLVM LoongArchGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM LoongArchGenRegisterInfo.inc -gen-register-info)
+tablegen(LLVM LoongArchGenInstrInfo.inc -gen-instr-info)
+tablegen(LLVM LoongArchGenDAGISel.inc -gen-dag-isel)
+tablegen(LLVM LoongArchGenMCPseudoLowering.inc -gen-pseudo-lowering)
+tablegen(LLVM LoongArchGenMCCodeEmitter.inc -gen-emitter)
+tablegen(LLVM LoongArchGenSubtargetInfo.inc -gen-subtarget)
+
+add_public_tablegen_target(LoongArchCommonTableGen)
+
 add_llvm_target(LoongArchCodeGen
+  LoongArchAsmPrinter.cpp
+  LoongArchFrameLowering.cpp
+  LoongArchInstrInfo.cpp
+  LoongArchISelDAGToDAG.cpp
+  LoongArchISelLowering.cpp
+  LoongArchMCInstLower.cpp
+  LoongArchRegisterInfo.cpp
+  LoongArchSubtarget.cpp
   LoongArchTargetMachine.cpp
 
   LINK_COMPONENTS
diff --git a/llvm/lib/Target/LoongArch/LoongArch.h b/llvm/lib/Target/LoongArch/LoongArch.h
new file mode 100644 (file)
index 0000000..d5269f0
--- /dev/null
@@ -0,0 +1,37 @@
+//===-- LoongArch.h - Top-level interface for LoongArch ---------*- 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 the entry points for global functions defined in the LLVM
+// LoongArch back-end.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H
+
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+class LoongArchTargetMachine;
+class AsmPrinter;
+class FunctionPass;
+class MCInst;
+class MCOperand;
+class MachineInstr;
+class MachineOperand;
+
+bool lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
+                                        AsmPrinter &AP);
+bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
+                                             MCOperand &MCOp,
+                                             const AsmPrinter &AP);
+
+FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM);
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H
diff --git a/llvm/lib/Target/LoongArch/LoongArch.td b/llvm/lib/Target/LoongArch/LoongArch.td
new file mode 100644 (file)
index 0000000..3a211bd
--- /dev/null
@@ -0,0 +1,133 @@
+//===-- LoongArch.td - Describe the LoongArch Target -------*- tablegen -*-===//
+//
+// 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 "llvm/Target/Target.td"
+
+//===----------------------------------------------------------------------===//
+// LoongArch subtarget features and instruction predicates.
+//===----------------------------------------------------------------------===//
+
+// LoongArch is divided into two versions, the 32-bit version (LA32) and the
+// 64-bit version (LA64).
+def Feature64Bit
+    : SubtargetFeature<"64bit", "HasLA64", "true",
+                       "LA64 Basic Integer and Privilege Instruction Set">;
+def IsLA64
+    : Predicate<"Subtarget->is64Bit()">,
+      AssemblerPredicate<(all_of Feature64Bit),
+                         "LA64 Basic Integer and Privilege Instruction Set">;
+def IsLA32
+    : Predicate<"!Subtarget->is64Bit()">,
+      AssemblerPredicate<(all_of(not Feature64Bit)),
+                         "LA32 Basic Integer and Privilege Instruction Set">;
+
+defvar LA32 = DefaultMode;
+def LA64 : HwMode<"+64bit">;
+
+// Single Precision floating point
+def FeatureBasicF : SubtargetFeature<"f", "HasBasicF", "true",
+                                     "'F' (Single-Precision Floating-Point)">;
+def HasBasicF : Predicate<"Subtarget->hasBasicF()">,
+                AssemblerPredicate<(all_of FeatureBasicF),
+                                   "'F' (Single-Precision Floating-Point)">;
+
+// Double Precision floating point
+def FeatureBasicD : SubtargetFeature<"d", "HasBasicD", "true",
+                                     "'D' (Double-Precision Floating-Point)",
+                                     [FeatureBasicF]>;
+def HasBasicD : Predicate<"Subtarget->hasBasicD()">,
+                AssemblerPredicate<(all_of FeatureBasicD),
+                                   "'D' (Double-Precision Floating-Point)">;
+
+// Loongson SIMD eXtension (LSX)
+def FeatureExtLSX
+    : SubtargetFeature<"lsx", "HasExtLSX", "true",
+                       "'LSX' (Loongson SIMD Extension)", [FeatureBasicD]>;
+def HasExtLSX : Predicate<"Subtarget->hasExtLSX()">,
+                AssemblerPredicate<(all_of FeatureExtLSX),
+                                   "'LSX' (Loongson SIMD Extension)">;
+
+// Loongson Advanced SIMD eXtension (LASX)
+def FeatureExtLASX
+    : SubtargetFeature<"lasx", "HasExtLASX", "true",
+                       "'LASX' (Loongson Advanced SIMD Extension)",
+                       [FeatureExtLSX]>;
+def HasExtLASX
+    : Predicate<"Subtarget->hasExtLASX()">,
+      AssemblerPredicate<(all_of FeatureExtLASX),
+                         "'LASX' (Loongson Advanced SIMD Extension)">;
+
+// Loongson VirtualiZation (LVZ)
+def FeatureExtLVZ
+    : SubtargetFeature<"lvz", "HasExtLVZ", "true",
+                       "'LVZ' (Loongson Virtualization Extension)">;
+def HasExtLVZ : Predicate<"Subtarget->hasExtLVZ()">,
+                AssemblerPredicate<(all_of FeatureExtLVZ),
+                                   "'LVZ' (Loongson Virtualization Extension)">;
+
+// Loongson Binary Translation (LBT)
+def FeatureExtLBT
+    : SubtargetFeature<"lbt", "HasExtLBT", "true",
+                       "'LBT' (Loongson Binary Translation Extension)">;
+def HasExtLBT
+    : Predicate<"Subtarget->hasExtLBT()">,
+      AssemblerPredicate<(all_of FeatureExtLBT),
+                         "'LBT' (Loongson Binary Translation Extension)">;
+
+//===----------------------------------------------------------------------===//
+// Registers, instruction descriptions ...
+//===----------------------------------------------------------------------===//
+
+include "LoongArchRegisterInfo.td"
+include "LoongArchCallingConv.td"
+include "LoongArchInstrInfo.td"
+
+//===----------------------------------------------------------------------===//
+// LoongArch processors supported.
+//===----------------------------------------------------------------------===//
+
+def : ProcessorModel<"generic-la32", NoSchedModel, []>;
+def : ProcessorModel<"generic-la64", NoSchedModel, [Feature64Bit]>;
+
+def : ProcessorModel<"la464", NoSchedModel, [Feature64Bit,
+                                             FeatureExtLASX,
+                                             FeatureExtLVZ,
+                                             FeatureExtLBT]>;
+
+//===----------------------------------------------------------------------===//
+// Define the LoongArch target.
+//===----------------------------------------------------------------------===//
+
+def LoongArchInstrInfo : InstrInfo {
+  // guess mayLoad, mayStore, and hasSideEffects
+  // This option is a temporary migration help. It will go away.
+  let guessInstructionProperties = 1;
+}
+
+def LoongArchAsmParser : AsmParser {
+  let ShouldEmitMatchRegisterAltName = 1;
+  let AllowDuplicateRegisterNames = 1;
+}
+
+def LoongArchAsmParserVariant : AsmParserVariant {
+  int Variant = 0;
+  // Recognize hard coded registers.
+  string RegisterPrefix = "$";
+}
+
+def LoongArchAsmWriter : AsmWriter {
+  int PassSubtarget = 1;
+}
+
+def LoongArch : Target {
+  let InstructionSet = LoongArchInstrInfo;
+  let AssemblyParsers = [LoongArchAsmParser];
+  let AssemblyParserVariants = [LoongArchAsmParserVariant];
+  let AssemblyWriters = [LoongArchAsmWriter];
+  let AllowRegisterRenaming = 1;
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
new file mode 100644 (file)
index 0000000..dd61bb2
--- /dev/null
@@ -0,0 +1,48 @@
+//===- LoongArchAsmPrinter.cpp - LoongArch LLVM Assembly Printer -*- 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 a printer that converts from our internal representation
+// of machine-dependent LLVM code to GAS-format LoongArch assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchAsmPrinter.h"
+#include "LoongArch.h"
+#include "LoongArchTargetMachine.h"
+#include "TargetInfo/LoongArchTargetInfo.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-asm-printer"
+
+// Simple pseudo-instructions have their lowering (with expansion to real
+// instructions) auto-generated.
+#include "LoongArchGenMCPseudoLowering.inc"
+
+void LoongArchAsmPrinter::emitInstruction(const MachineInstr *MI) {
+  // Do any auto-generated pseudo lowerings.
+  if (emitPseudoExpansionLowering(*OutStreamer, MI))
+    return;
+
+  MCInst TmpInst;
+  if (!lowerLoongArchMachineInstrToMCInst(MI, TmpInst, *this))
+    EmitToStreamer(*OutStreamer, TmpInst);
+}
+
+bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+  AsmPrinter::runOnMachineFunction(MF);
+  return true;
+}
+
+// Force static initialization.
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchAsmPrinter() {
+  RegisterAsmPrinter<LoongArchAsmPrinter> X(getTheLoongArch32Target());
+  RegisterAsmPrinter<LoongArchAsmPrinter> Y(getTheLoongArch64Target());
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
new file mode 100644 (file)
index 0000000..7e5aa49
--- /dev/null
@@ -0,0 +1,46 @@
+//===- LoongArchAsmPrinter.h - LoongArch LLVM Assembly Printer -*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// LoongArch Assembly printer class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H
+
+#include "LoongArchSubtarget.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+class LLVM_LIBRARY_VISIBILITY LoongArchAsmPrinter : public AsmPrinter {
+  const MCSubtargetInfo *STI;
+
+public:
+  explicit LoongArchAsmPrinter(TargetMachine &TM,
+                               std::unique_ptr<MCStreamer> Streamer)
+      : AsmPrinter(TM, std::move(Streamer)), STI(TM.getMCSubtargetInfo()) {}
+
+  StringRef getPassName() const override {
+    return "LoongArch Assembly Printer";
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  void emitInstruction(const MachineInstr *MI) override;
+
+  // tblgen'erated function.
+  bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
+                                   const MachineInstr *MI);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHASMPRINTER_H
diff --git a/llvm/lib/Target/LoongArch/LoongArchCallingConv.td b/llvm/lib/Target/LoongArch/LoongArchCallingConv.td
new file mode 100644 (file)
index 0000000..9844163
--- /dev/null
@@ -0,0 +1,23 @@
+//=- LoongArchCallingConv.td - Calling Conventions LoongArch -*- tablegen -*-=//
+//
+// 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 describes the calling conventions for the LoongArch architecture.
+//
+//===----------------------------------------------------------------------===//
+
+def CSR_ILP32S_LP64S
+    : CalleeSavedRegs<(add R1, (sequence "R%u", 22, 31))>;
+
+def CSR_ILP32F_LP64F
+    : CalleeSavedRegs<(add CSR_ILP32S_LP64S, (sequence "F%u", 24, 31))>;
+
+def CSR_ILP32D_LP64D
+    : CalleeSavedRegs<(add CSR_ILP32S_LP64S, (sequence "F%u_64", 24, 31))>;
+
+// Needed for implementation of LoongArchRegisterInfo::getNoPreservedMask()
+def CSR_NoRegs : CalleeSavedRegs<(add)>;
diff --git a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp
new file mode 100644 (file)
index 0000000..7182d55
--- /dev/null
@@ -0,0 +1,55 @@
+//===-- LoongArchFrameLowering.cpp - LoongArch Frame Information -*- 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 the LoongArch implementation of TargetFrameLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchFrameLowering.h"
+#include "LoongArchSubtarget.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/MC/MCDwarf.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-frame-lowering"
+
+// Return true if the specified function should have a dedicated frame
+// pointer register.  This is true if frame pointer elimination is
+// disabled, if it needs dynamic stack realignment, if the function has
+// variable sized allocas, or if the frame address is taken.
+bool LoongArchFrameLowering::hasFP(const MachineFunction &MF) const {
+  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
+
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
+         RegInfo->hasStackRealignment(MF) || MFI.hasVarSizedObjects() ||
+         MFI.isFrameAddressTaken();
+}
+
+bool LoongArchFrameLowering::hasBP(const MachineFunction &MF) const {
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  const TargetRegisterInfo *TRI = STI.getRegisterInfo();
+
+  return MFI.hasVarSizedObjects() && TRI->hasStackRealignment(MF);
+}
+
+void LoongArchFrameLowering::emitPrologue(MachineFunction &MF,
+                                          MachineBasicBlock &MBB) const {
+  // TODO: Implement this when we have function calls
+}
+
+void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF,
+                                          MachineBasicBlock &MBB) const {
+  // TODO: Implement this when we have function calls
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h
new file mode 100644 (file)
index 0000000..25c53ef
--- /dev/null
@@ -0,0 +1,38 @@
+//=- LoongArchFrameLowering.h - TargetFrameLowering for LoongArch -*- 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 class implements LoongArch-specific bits of TargetFrameLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H
+
+#include "llvm/CodeGen/TargetFrameLowering.h"
+
+namespace llvm {
+class LoongArchSubtarget;
+
+class LoongArchFrameLowering : public TargetFrameLowering {
+  const LoongArchSubtarget &STI;
+
+public:
+  explicit LoongArchFrameLowering(const LoongArchSubtarget &STI)
+      : TargetFrameLowering(StackGrowsDown,
+                            /*StackAlignment=*/Align(16),
+                            /*LocalAreaOffset=*/0),
+        STI(STI) {}
+
+  void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
+  void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
+
+  bool hasFP(const MachineFunction &MF) const override;
+  bool hasBP(const MachineFunction &MF) const;
+};
+} // namespace llvm
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHFRAMELOWERING_H
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
new file mode 100644 (file)
index 0000000..e754dab
--- /dev/null
@@ -0,0 +1,46 @@
+//=- LoongArchISelDAGToDAG.cpp - A dag to dag inst selector for LoongArch -===//
+//
+// 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 defines an instruction selector for the LoongArch target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchISelDAGToDAG.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-isel"
+
+void LoongArchDAGToDAGISel::Select(SDNode *Node) {
+  // If we have a custom node, we have already selected.
+  if (Node->isMachineOpcode()) {
+    LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n");
+    Node->setNodeId(-1);
+    return;
+  }
+
+  // Instruction Selection not handled by the auto-generated tablegen selection
+  // should be handled here.
+  unsigned Opcode = Node->getOpcode();
+  SDLoc DL(Node);
+
+  switch (Opcode) {
+  default:
+    break;
+    // TODO: Add selection nodes needed later.
+  }
+
+  // Select the default instruction.
+  SelectCode(Node);
+}
+// This pass converts a legalized DAG into a LoongArch-specific DAG, ready
+// for instruction scheduling.
+FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM) {
+  return new LoongArchDAGToDAGISel(TM);
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
new file mode 100644 (file)
index 0000000..673172a
--- /dev/null
@@ -0,0 +1,47 @@
+//=- LoongArchISelDAGToDAG.h - A dag to dag inst selector for LoongArch ---===//
+//
+// 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 defines an instruction selector for the LoongArch target.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H
+
+#include "LoongArch.h"
+#include "LoongArchTargetMachine.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+
+// LoongArch-specific code to select LoongArch machine instructions for
+// SelectionDAG operations.
+namespace llvm {
+class LoongArchDAGToDAGISel : public SelectionDAGISel {
+  const LoongArchSubtarget *Subtarget = nullptr;
+
+public:
+  explicit LoongArchDAGToDAGISel(LoongArchTargetMachine &TM)
+      : SelectionDAGISel(TM) {}
+
+  StringRef getPassName() const override {
+    return "LoongArch DAG->DAG Pattern Instruction Selection";
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override {
+    Subtarget = &MF.getSubtarget<LoongArchSubtarget>();
+    return SelectionDAGISel::runOnMachineFunction(MF);
+  }
+
+  void Select(SDNode *Node) override;
+
+// Include the pieces autogenerated from the target description.
+#include "LoongArchGenDAGISel.inc"
+};
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELDAGTODAG_H
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
new file mode 100644 (file)
index 0000000..b9c7b32
--- /dev/null
@@ -0,0 +1,45 @@
+//=- LoongArchISelLowering.cpp - LoongArch DAG Lowering Implementation  ---===//
+//
+// 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 defines the interfaces that LoongArch uses to lower LLVM code into
+// a selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchISelLowering.h"
+#include "LoongArch.h"
+#include "LoongArchMachineFunctionInfo.h"
+#include "LoongArchRegisterInfo.h"
+#include "LoongArchSubtarget.h"
+#include "LoongArchTargetMachine.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-isel-lowering"
+
+LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
+                                                 const LoongArchSubtarget &STI)
+    : TargetLowering(TM), Subtarget(STI) {
+
+  MVT GRLenVT = Subtarget.getGRLenVT();
+  // Set up the register classes.
+  addRegisterClass(GRLenVT, &LoongArch::GPRRegClass);
+
+  // TODO: add necessary setOperationAction calls later.
+
+  // Compute derived properties from the register classes.
+  computeRegisterProperties(STI.getRegisterInfo());
+
+  setStackPointerRegisterToSaveRestore(LoongArch::R3);
+
+  // Function alignments.
+  const Align FunctionAlignment(4);
+  setMinFunctionAlignment(FunctionAlignment);
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
new file mode 100644 (file)
index 0000000..a7ea084
--- /dev/null
@@ -0,0 +1,46 @@
+//=- LoongArchISelLowering.h - LoongArch DAG Lowering Interface -*- 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 defines the interfaces that LoongArch uses to lower LLVM code into
+// a selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
+
+#include "LoongArch.h"
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/TargetLowering.h"
+
+namespace llvm {
+class LoongArchSubtarget;
+struct LoongArchRegisterInfo;
+namespace LoongArchISD {
+enum NodeType : unsigned {
+  FIRST_NUMBER = ISD::BUILTIN_OP_END,
+
+  // TODO: add more LoongArchISDs
+
+};
+} // namespace LoongArchISD
+
+class LoongArchTargetLowering : public TargetLowering {
+  const LoongArchSubtarget &Subtarget;
+
+public:
+  explicit LoongArchTargetLowering(const TargetMachine &TM,
+                                   const LoongArchSubtarget &STI);
+
+  const LoongArchSubtarget &getSubtarget() const { return Subtarget; }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHISELLOWERING_H
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td b/llvm/lib/Target/LoongArch/LoongArchInstrFormats.td
new file mode 100644 (file)
index 0000000..0fe3585
--- /dev/null
@@ -0,0 +1,330 @@
+//===- LoongArchInstrFormats.td - LoongArch Instr. Formats -*- tablegen -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//  Describe LoongArch instructions format
+//
+//  opcode       - operation code.
+//  {r/f}d       - destination operand.
+//  {r/f}{j/k/a} - source operand.
+//  immN         - immediate data.
+//
+//===----------------------------------------------------------------------===//
+
+class LAInst<dag outs, dag ins, string asmstr, list<dag> pattern = []>
+    : Instruction {
+  field bits<32> Inst;
+  // SoftFail is a field the disassembler can use to provide a way for
+  // instructions to not match without killing the whole decode process. It is
+  // mainly used for ARM, but Tablegen expects this field to exist or it fails
+  // to build the decode table.
+  field bits<32> SoftFail = 0;
+
+  let Namespace = "LoongArch";
+  let Size = 4;
+  let OutOperandList = outs;
+  let InOperandList = ins;
+  let AsmString = asmstr;
+  let Pattern = pattern;
+}
+
+// Pseudo instructions
+class Pseudo<dag outs, dag ins, string asmstr> : LAInst<outs, ins, asmstr> {
+  let isPseudo = 1;
+}
+
+// 2R-type
+// <opcode | rj | rd>
+class Fmt2R<bits<22> op, dag outs, dag ins, string asmstr,
+            list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-10} = op;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 3R-type
+// <opcode | rk | rj | rd>
+// <opcode | fk | fj | fd>
+class Fmt3R<bits<17> op, dag outs, dag ins, string asmstr,
+            list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<5> rk;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-15} = op;
+  let Inst{14-10} = rk;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+class Fmt3FR<bits<17> op, dag outs, dag ins, string asmstr,
+             list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<5> fk;
+  bits<5> fj;
+  bits<5> fd;
+
+  let Inst{31-15} = op;
+  let Inst{14-10} = fk;
+  let Inst{9-5} = fj;
+  let Inst{4-0} = fd;
+}
+
+// 4R-type
+// <opcode | ra | rk | rj | rd>
+class Fmt4R<bits<12> op, dag outs, dag ins, string asmstr,
+            list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<5> ra;
+  bits<5> rk;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-20} = op;
+  let Inst{19-15} = ra;
+  let Inst{14-10} = rk;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 3RI2-type
+// <opcode | I2 | rk | rj | rd>
+class Fmt3RI2<bits<15> op, dag outs, dag ins, string asmstr,
+              list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<2> imm2;
+  bits<5> rk;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-17} = op;
+  let Inst{16-15} = imm2;
+  let Inst{14-10} = rk;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 3RI3-type
+// <opcode | I3 | rk | rj | rd>
+class Fmt3RI3<bits<14> op, dag outs, dag ins, string asmstr,
+              list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<3> imm3;
+  bits<5> rk;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-18} = op;
+  let Inst{17-15} = imm3;
+  let Inst{14-10} = rk;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 2RI5-type
+// <opcode | I5 | rj | rd>
+class Fmt2RI5<bits<17> op, dag outs, dag ins, string asmstr,
+              list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<5> imm5;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-15} = op;
+  let Inst{14-10} = imm5;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 2RI6-type
+// <opcode | I6 | rj | rd>
+class Fmt2RI6<bits<16> op, dag outs, dag ins, string asmstr,
+              list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<6> imm6;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-16} = op;
+  let Inst{15-10} = imm6;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 2RI8-type
+// <opcode | I8 | rj | rd>
+class Fmt2RI8<bits<14> op, dag outs, dag ins, string asmstr,
+              list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<8> imm8;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-18} = op;
+  let Inst{17-10} = imm8;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 2RI12-type
+// <opcode | I12 | rj | rd>
+class Fmt2RI12<bits<10> op, dag outs, dag ins, string asmstr,
+               list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<12> imm12;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-22} = op;
+  let Inst{21-10} = imm12;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 2RI14-type
+// <opcode | I14 | rj | rd>
+class Fmt2RI14<bits<8> op, dag outs, dag ins, string asmstr,
+               list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<14> imm14;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-24} = op;
+  let Inst{23-10} = imm14;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 2RI16-type
+// <opcode | I16 | rj | rd>
+class Fmt2RI16<bits<6> op, dag outs, dag ins, string asmstr,
+               list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<16> imm16;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-26} = op;
+  let Inst{25-10} = imm16;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// 1RI20-type
+// <opcode | I20 | rd>
+class Fmt1RI20<bits<7> op, dag outs, dag ins, string asmstr,
+               list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<20> imm20;
+  bits<5> rd;
+
+  let Inst{31-25} = op;
+  let Inst{24-5} = imm20;
+  let Inst{4-0} = rd;
+}
+
+// 1RI21-type
+// <opcode | I21[15:0] | rj | I21[20:16]>
+class Fmt1RI21<bits<6> op, dag outs, dag ins, string asmstr,
+               list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<21> imm21;
+  bits<5> rj;
+
+  let Inst{31-26} = op;
+  let Inst{25-10} = imm21{15-0};
+  let Inst{9-5} = rj;
+  let Inst{4-0} = imm21{20-16};
+}
+
+// I15-type
+// <opcode | I15>
+class FmtI15<bits<17> op, dag outs, dag ins, string asmstr,
+             list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<15> imm15;
+
+  let Inst{31-15} = op;
+  let Inst{14-0} = imm15;
+}
+
+// I26-type
+// <opcode | I26[15:0] | I26[25:16]>
+class FmtI26<bits<6> op, dag outs, dag ins, string asmstr,
+             list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<26> imm26;
+
+  let Inst{31-26} = op;
+  let Inst{25-10} = imm26{15-0};
+  let Inst{9-0} = imm26{25-16};
+}
+
+// FmtBSTR_W
+// <opcode[11:1] | msb | opcode[0] | lsb | rj | rd>
+class FmtBSTR_W<bits<12> op, dag outs, dag ins, string asmstr,
+                list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<5> msb;
+  bits<5> lsb;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-21} = op{11-1};
+  let Inst{20-16} = msb;
+  let Inst{15} = op{0};
+  let Inst{14-10} = lsb;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// FmtBSTR_D
+// <opcode | msb | lsb | rj | rd>
+class FmtBSTR_D<bits<10> op, dag outs, dag ins, string asmstr,
+                list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<6> msb;
+  bits<6> lsb;
+  bits<5> rj;
+  bits<5> rd;
+
+  let Inst{31-22} = op;
+  let Inst{21-16} = msb;
+  let Inst{15-10} = lsb;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = rd;
+}
+
+// FmtASRT
+// <opcode | rk | rj | 0x0>
+class FmtASRT<bits<17> op, dag outs, dag ins, string asmstr,
+              list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<5> rk;
+  bits<5> rj;
+
+  let Inst{31-15} = op;
+  let Inst{14-10} = rk;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = 0x0;
+}
+
+// FmtPRELD
+// < 0b0010101011 | I12 | rj | I5>
+class FmtPRELD<dag outs, dag ins, string asmstr,
+               list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<12> imm12;
+  bits<5> rj;
+  bits<5> imm5;
+
+  let Inst{31-22} = 0b0010101011;
+  let Inst{21-10} = imm12;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = imm5;
+}
+
+// FmtPRELDX
+// < 0b00111000001011000 | rk | rj | I5>
+class FmtPRELDX<dag outs, dag ins, string asmstr,
+                list<dag> pattern = []> : LAInst<outs, ins, asmstr, pattern> {
+  bits<5> rk;
+  bits<5> rj;
+  bits<5> imm5;
+
+  let Inst{31-15} = 0b00111000001011000;
+  let Inst{14-10} = rk;
+  let Inst{9-5} = rj;
+  let Inst{4-0} = imm5;
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
new file mode 100644 (file)
index 0000000..07b11fe
--- /dev/null
@@ -0,0 +1,24 @@
+//=- LoongArchInstrInfo.cpp - LoongArch Instruction Information -*- 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 the LoongArch implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchInstrInfo.h"
+
+using namespace llvm;
+
+#define GET_INSTRINFO_CTOR_DTOR
+#include "LoongArchGenInstrInfo.inc"
+
+LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
+    // FIXME: add CFSetup and CFDestroy Inst when we implement function call.
+    : LoongArchGenInstrInfo(),
+
+      STI(STI) {}
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
new file mode 100644 (file)
index 0000000..9d737fa
--- /dev/null
@@ -0,0 +1,33 @@
+//=- LoongArchInstrInfo.h - LoongArch Instruction Information ---*- 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 the LoongArch implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H
+
+#include "llvm/CodeGen/TargetInstrInfo.h"
+
+#define GET_INSTRINFO_HEADER
+#include "LoongArchGenInstrInfo.inc"
+
+namespace llvm {
+
+class LoongArchSubtarget;
+
+class LoongArchInstrInfo : public LoongArchGenInstrInfo {
+  const LoongArchSubtarget &STI;
+
+public:
+  explicit LoongArchInstrInfo(LoongArchSubtarget &STI);
+};
+
+} // end namespace llvm
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHINSTRINFO_H
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
new file mode 100644 (file)
index 0000000..54f6ed3
--- /dev/null
@@ -0,0 +1,458 @@
+//== LoongArchInstrInfo.td - Target Description for LoongArch -*- tablegen -*-//
+//
+// 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 describes the LoongArch instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// LoongArch specific DAG Nodes.
+//===----------------------------------------------------------------------===//
+
+// TODO: Add LoongArch specific DAG Nodes
+
+//===----------------------------------------------------------------------===//
+// Operand and SDNode transformation definitions.
+//===----------------------------------------------------------------------===//
+class ImmAsmOperand<string prefix, int width, string suffix> : AsmOperandClass {
+  let Name = prefix # "Imm" # width # suffix;
+  let DiagnosticType = !strconcat("Invalid", Name);
+}
+
+class SImmAsmOperand<int width, string suffix = "">
+    : ImmAsmOperand<"S", width, suffix> {
+}
+
+class UImmAsmOperand<int width, string suffix = "">
+    : ImmAsmOperand<"U", width, suffix> {
+}
+
+def uimm2 : Operand<GRLenVT>;
+def uimm2_plus1 : Operand<GRLenVT>;
+def uimm3 : Operand<GRLenVT>;
+def uimm5 : Operand<GRLenVT>;
+def uimm6 : Operand<GRLenVT>;
+def uimm12 : Operand<GRLenVT>;
+def uimm15 : Operand<GRLenVT>;
+def simm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isInt<12>(Imm);}]>;
+def simm14 : Operand<GRLenVT>;
+def simm14_lsl2 : Operand<GRLenVT>;
+def simm16 : Operand<GRLenVT>;
+def simm16_lsl2 : Operand<GRLenVT>;
+def simm20 : Operand<GRLenVT>;
+def simm21_lsl2 : Operand<GRLenVT>;
+def simm26_lsl2 : Operand<GRLenVT>;
+
+//===----------------------------------------------------------------------===//
+// Instruction Formats
+//===----------------------------------------------------------------------===//
+
+include "LoongArchInstrFormats.td"
+
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+class ALU_3R<bits<17> op, string opstr>
+    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk),
+            !strconcat(opstr, "\t$rd, $rj, $rk")>;
+class ALU_2R<bits<22> op, string opstr>
+    : Fmt2R<op, (outs GPR:$rd), (ins GPR:$rj),
+            !strconcat(opstr, "\t$rd, $rj")>;
+
+class ALU_3RI2<bits<15> op, string opstr, Operand ImmOpnd>
+    : Fmt3RI2<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm2),
+              !strconcat(opstr, "\t$rd, $rj, $rk, $imm2")>;
+class ALU_3RI3<bits<14> op, string opstr, Operand ImmOpnd>
+    : Fmt3RI3<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk, ImmOpnd:$imm3),
+              !strconcat(opstr, "\t$rd, $rj, $rk, $imm3")>;
+class ALU_2RI5<bits<17> op, string opstr, Operand ImmOpnd>
+    : Fmt2RI5<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm5),
+              !strconcat(opstr, "\t$rd, $rj, $imm5")>;
+class ALU_2RI6<bits<16> op, string opstr, Operand ImmOpnd>
+    : Fmt2RI6<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm6),
+              !strconcat(opstr, "\t$rd, $rj, $imm6")>;
+class ALU_2RI12<bits<10> op, string opstr, Operand ImmOpnd>
+    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm12),
+               !strconcat(opstr, "\t$rd, $rj, $imm12")>;
+class ALU_2RI16<bits<6> op, string opstr, Operand ImmOpnd>
+    : Fmt2RI16<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$imm16),
+               !strconcat(opstr, "\t$rd, $rj, $imm16")>;
+class ALU_1RI20<bits<7> op, string opstr, Operand ImmOpnd>
+    : Fmt1RI20<op, (outs GPR:$rd), (ins ImmOpnd:$imm20),
+               !strconcat(opstr, "\t$rd, $imm20")>;
+
+class ALU_BSTRW<bits<12> op, string opstr, Operand ImmOpnd>
+    : FmtBSTR_W<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$msb, ImmOpnd:$lsb),
+                !strconcat(opstr, "\t$rd, $rj, $msb, $lsb")>;
+class ALU_BSTRD<bits<10> op, string opstr, Operand ImmOpnd>
+    : FmtBSTR_D<op, (outs GPR:$rd), (ins GPR:$rj, ImmOpnd:$msb, ImmOpnd:$lsb),
+                !strconcat(opstr, "\t$rd, $rj, $msb, $lsb")>;
+
+class MISC_I15<bits<17> op, string opstr>
+    : FmtI15<op, (outs), (ins uimm15:$imm15), !strconcat(opstr, "\t$imm15")>;
+
+class RDTIME_2R<bits<22> op, string opstr>
+    : Fmt2R<op, (outs GPR:$rd, GPR:$rj), (ins),
+                 !strconcat(opstr, "\t$rd, $rj")>;
+
+class BrCC_2RI16<bits<6> op, string opstr>
+    : Fmt2RI16<op, (outs), (ins GPR:$rj, GPR:$rd, simm16_lsl2:$imm16),
+               !strconcat(opstr, "\t$rj, $rd, $imm16")> {
+  let isBranch = 1;
+  let isTerminator = 1;
+}
+class BrCCZ_1RI21<bits<6> op, string opstr>
+    : Fmt1RI21<op, (outs), (ins GPR:$rj, simm21_lsl2:$imm21),
+               !strconcat(opstr, "\t$rj, $imm21")> {
+  let isBranch = 1;
+  let isTerminator = 1;
+}
+class Br_I26<bits<6> op, string opstr>
+    : FmtI26<op, (outs), (ins simm26_lsl2:$imm26),
+             !strconcat(opstr, "\t$imm26")> {
+  let isBranch = 1;
+  let isTerminator = 1;
+}
+
+let mayLoad = 1 in {
+class LOAD_3R<bits<17> op, string opstr>
+    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk),
+            !strconcat(opstr, "\t$rd, $rj, $rk")>;
+class LOAD_2RI12<bits<10> op, string opstr>
+    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12:$imm12),
+               !strconcat(opstr, "\t$rd, $rj, $imm12")>;
+class LOAD_2RI14<bits<8> op, string opstr>
+    : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14),
+               !strconcat(opstr, "\t$rd, $rj, $imm14")>;
+} // mayLoad = 1
+
+let mayStore = 1 in {
+class STORE_3R<bits<17> op, string opstr>
+    : Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk),
+            !strconcat(opstr, "\t$rd, $rj, $rk")>;
+class STORE_2RI12<bits<10> op, string opstr>
+    : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12:$imm12),
+               !strconcat(opstr, "\t$rd, $rj, $imm12")>;
+class STORE_2RI14<bits<8> op, string opstr>
+    : Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14),
+               !strconcat(opstr, "\t$rd, $rj, $imm14")>;
+} // mayStore = 1
+
+let mayLoad = 1, mayStore = 1 in
+class AM_3R<bits<17> op, string opstr>
+    : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk),
+            !strconcat(opstr, "\t$rd, $rj, $rk")>;
+
+let mayLoad = 1 in
+class LLBase<bits<8> op, string opstr>
+    : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14:$imm14),
+               !strconcat(opstr, "\t$rd, $rj, $imm14")>;
+
+let mayStore = 1, Constraints = "$rd = $dst" in
+class SCBase<bits<8> op, string opstr>
+    : Fmt2RI14<op, (outs GPR:$dst), (ins GPR:$rd, GPR:$rj, simm14:$imm14),
+               !strconcat(opstr, "\t$rd, $rj, $imm14")>;
+
+//===----------------------------------------------------------------------===//
+// Instructions
+//===----------------------------------------------------------------------===//
+
+// Arithmetic Operation Instructions
+def ADD_W : ALU_3R<0b00000000000100000, "add.w">;
+def SUB_W : ALU_3R<0b00000000000100010, "sub.w">;
+def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12>;
+def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>;
+def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20>;
+def SLT  : ALU_3R<0b00000000000100100, "slt">;
+def SLTU : ALU_3R<0b00000000000100101, "sltu">;
+def SLTI  : ALU_2RI12<0b0000001000, "slti", simm12>;
+def SLTUI : ALU_2RI12<0b0000001001, "sltui", simm12>;
+def PCADDI    : ALU_1RI20<0b0001100, "pcaddi", simm20>;
+def PCADDU12I : ALU_1RI20<0b0001110, "pcaddu12i", simm20>;
+def PCALAU12I : ALU_1RI20<0b0001101, "pcalau12i", simm20>;
+def AND  : ALU_3R<0b00000000000101001, "and">;
+def OR   : ALU_3R<0b00000000000101010, "or">;
+def NOR  : ALU_3R<0b00000000000101000, "nor">;
+def XOR  : ALU_3R<0b00000000000101011, "xor">;
+def ANDN : ALU_3R<0b00000000000101101, "andn">;
+def ORN  : ALU_3R<0b00000000000101100, "orn">;
+def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>;
+def ORI  : ALU_2RI12<0b0000001110, "ori", uimm12>;
+def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>;
+def MUL_W   : ALU_3R<0b00000000000111000, "mul.w">;
+def MULH_W  : ALU_3R<0b00000000000111001, "mulh.w">;
+def MULH_WU : ALU_3R<0b00000000000111010, "mulh.wu">;
+def DIV_W   : ALU_3R<0b00000000001000000, "div.w">;
+def MOD_W   : ALU_3R<0b00000000001000001, "mod.w">;
+def DIV_WU  : ALU_3R<0b00000000001000010, "div.wu">;
+def MOD_WU  : ALU_3R<0b00000000001000011, "mod.wu">;
+
+// Bit-shift Instructions
+def SLL_W  : ALU_3R<0b00000000000101110, "sll.w">;
+def SRL_W  : ALU_3R<0b00000000000101111, "srl.w">;
+def SRA_W  : ALU_3R<0b00000000000110000, "sra.w">;
+def ROTR_W : ALU_3R<0b00000000000110110, "rotr.w">;
+
+def SLLI_W  : ALU_2RI5<0b00000000010000001, "slli.w", uimm5>;
+def SRLI_W  : ALU_2RI5<0b00000000010001001, "srli.w", uimm5>;
+def SRAI_W  : ALU_2RI5<0b00000000010010001, "srai.w", uimm5>;
+def ROTRI_W : ALU_2RI5<0b00000000010011001, "rotri.w", uimm5>;
+
+// Bit-manipulation Instructions
+def EXT_W_B : ALU_2R<0b0000000000000000010111, "ext.w.b">;
+def EXT_W_H : ALU_2R<0b0000000000000000010110, "ext.w.h">;
+def CLO_W   : ALU_2R<0b0000000000000000000100, "clo.w">;
+def CLZ_W   : ALU_2R<0b0000000000000000000101, "clz.w">;
+def CTO_W   : ALU_2R<0b0000000000000000000110, "cto.w">;
+def CTZ_W   : ALU_2R<0b0000000000000000000111, "ctz.w">;
+def BYTEPICK_W : ALU_3RI2<0b000000000000100, "bytepick.w", uimm2>;
+def REVB_2H   : ALU_2R<0b0000000000000000001100, "revb.2h">;
+def BITREV_4B : ALU_2R<0b0000000000000000010010, "bitrev.4b">;
+def BITREV_W  : ALU_2R<0b0000000000000000010100, "bitrev.w">;
+def BSTRINS_W  : ALU_BSTRW<0b000000000110, "bstrins.w", uimm5>;
+def BSTRPICK_W : ALU_BSTRW<0b000000000111, "bstrpick.w", uimm5>;
+def MASKEQZ : ALU_3R<0b00000000000100110, "maskeqz">;
+def MASKNEZ : ALU_3R<0b00000000000100111, "masknez">;
+
+// Branch Instructions
+def BEQ  : BrCC_2RI16<0b010110, "beq">;
+def BNE  : BrCC_2RI16<0b010111, "bne">;
+def BLT  : BrCC_2RI16<0b011000, "blt">;
+def BGE  : BrCC_2RI16<0b011001, "bge">;
+def BLTU : BrCC_2RI16<0b011010, "bltu">;
+def BGEU : BrCC_2RI16<0b011011, "bgeu">;
+def BEQZ : BrCCZ_1RI21<0b010000, "beqz">;
+def BNEZ : BrCCZ_1RI21<0b010001, "bnez">;
+def B : Br_I26<0b010100, "b">;
+
+let isCall = 1 in
+def BL : FmtI26<0b010101, (outs), (ins simm26_lsl2:$imm26), "bl\t$imm26">;
+def JIRL : Fmt2RI16<0b010011, (outs GPR:$rd),
+                    (ins GPR:$rj, simm16_lsl2:$imm16),
+                    "jirl\t$rd, $rj, $imm16">;
+
+// Common Memory Access Instructions
+def LD_B  : LOAD_2RI12<0b0010100000, "ld.b">;
+def LD_H  : LOAD_2RI12<0b0010100001, "ld.h">;
+def LD_W  : LOAD_2RI12<0b0010100010, "ld.w">;
+def LD_BU : LOAD_2RI12<0b0010101000, "ld.bu">;
+def LD_HU : LOAD_2RI12<0b0010101001, "ld.hu">;
+def ST_B : STORE_2RI12<0b0010100100, "st.b">;
+def ST_H : STORE_2RI12<0b0010100101, "st.h">;
+def ST_W : STORE_2RI12<0b0010100110, "st.w">;
+def PRELD : FmtPRELD<(outs), (ins uimm5:$imm5, GPR:$rj, simm12:$imm12),
+                     "preld\t$imm5, $rj, $imm12">;
+
+// Atomic Memory Access Instructions
+def LL_W : LLBase<0b00100000, "ll.w">;
+def SC_W : SCBase<0b00100001, "sc.w">;
+
+// Barrier Instructions
+def DBAR : MISC_I15<0b00111000011100100, "dbar">;
+def IBAR : MISC_I15<0b00111000011100101, "ibar">;
+
+// Other Miscellaneous Instructions
+def SYSCALL : MISC_I15<0b00000000001010110, "syscall">;
+def BREAK   : MISC_I15<0b00000000001010100, "break">;
+def RDTIMEL_W : RDTIME_2R<0b0000000000000000011000, "rdtimel.w">;
+def RDTIMEH_W : RDTIME_2R<0b0000000000000000011001, "rdtimeh.w">;
+def CPUCFG : ALU_2R<0b0000000000000000011011, "cpucfg">;
+
+/// LA64 instructions
+let Predicates = [IsLA64] in {
+
+// Arithmetic Operation Instructions for 64-bits
+def ADD_D : ALU_3R<0b00000000000100001, "add.d">;
+def SUB_D : ALU_3R<0b00000000000100011, "sub.d">;
+def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12>;
+def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>;
+def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>;
+def ALSL_D  : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>;
+def LU32I_D : ALU_1RI20<0b0001011, "lu32i.d", simm20>;
+def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12>;
+def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>;
+def MUL_D     : ALU_3R<0b00000000000111011, "mul.d">;
+def MULH_D    : ALU_3R<0b00000000000111100, "mulh.d">;
+def MULH_DU   : ALU_3R<0b00000000000111101, "mulh.du">;
+def MULW_D_W  : ALU_3R<0b00000000000111110, "mulw.d.w">;
+def MULW_D_WU : ALU_3R<0b00000000000111111, "mulw.d.wu">;
+def DIV_D     : ALU_3R<0b00000000001000100, "div.d">;
+def MOD_D     : ALU_3R<0b00000000001000101, "mod.d">;
+def DIV_DU    : ALU_3R<0b00000000001000110, "div.du">;
+def MOD_DU    : ALU_3R<0b00000000001000111, "mod.du">;
+
+// Bit-shift Instructions for 64-bits
+def SLL_D  : ALU_3R<0b00000000000110001, "sll.d">;
+def SRL_D  : ALU_3R<0b00000000000110010, "srl.d">;
+def SRA_D  : ALU_3R<0b00000000000110011, "sra.d">;
+def ROTR_D : ALU_3R<0b00000000000110111, "rotr.d">;
+def SLLI_D  : ALU_2RI6<0b0000000001000001, "slli.d", uimm6>;
+def SRLI_D  : ALU_2RI6<0b0000000001000101, "srli.d", uimm6>;
+def SRAI_D  : ALU_2RI6<0b0000000001001001, "srai.d", uimm6>;
+def ROTRI_D : ALU_2RI6<0b0000000001001101, "rotri.d", uimm6>;
+
+// Bit-manipulation Instructions for 64-bits
+def CLO_D : ALU_2R<0b0000000000000000001000, "clo.d">;
+def CLZ_D : ALU_2R<0b0000000000000000001001, "clz.d">;
+def CTO_D : ALU_2R<0b0000000000000000001010, "cto.d">;
+def CTZ_D : ALU_2R<0b0000000000000000001011, "ctz.d">;
+def BYTEPICK_D : ALU_3RI3<0b00000000000011, "bytepick.d", uimm3>;
+def REVB_4H   : ALU_2R<0b0000000000000000001101, "revb.4h">;
+def REVB_2W   : ALU_2R<0b0000000000000000001110, "revb.2w">;
+def REVB_D    : ALU_2R<0b0000000000000000001111, "revb.d">;
+def REVH_2W   : ALU_2R<0b0000000000000000010000, "revh.2w">;
+def REVH_D    : ALU_2R<0b0000000000000000010001, "revh.d">;
+def BITREV_8B : ALU_2R<0b0000000000000000010011, "bitrev.8b">;
+def BITREV_D  : ALU_2R<0b0000000000000000010101, "bitrev.d">;
+def BSTRINS_D  : ALU_BSTRD<0b0000000010, "bstrins.d", uimm6>;
+def BSTRPICK_D : ALU_BSTRD<0b0000000011, "bstrpick.d", uimm6>;
+
+// Common Memory Access Instructions for 64-bits
+def LD_WU : LOAD_2RI12<0b0010101010, "ld.wu">;
+def ST_D : STORE_2RI12<0b0010100111, "st.d">;
+def LDX_B  : LOAD_3R<0b00111000000000000, "ldx.b">;
+def LDX_H  : LOAD_3R<0b00111000000001000, "ldx.h">;
+def LDX_W  : LOAD_3R<0b00111000000010000, "ldx.w">;
+def LDX_D  : LOAD_3R<0b00111000000011000, "ldx.d">;
+def LDX_BU : LOAD_3R<0b00111000001000000, "ldx.bu">;
+def LDX_HU : LOAD_3R<0b00111000001001000, "ldx.hu">;
+def LDX_WU : LOAD_3R<0b00111000001010000, "ldx.wu">;
+def STX_B : STORE_3R<0b00111000000100000, "stx.b">;
+def STX_H : STORE_3R<0b00111000000101000, "stx.h">;
+def STX_W : STORE_3R<0b00111000000110000, "stx.w">;
+def STX_D : STORE_3R<0b00111000000111000, "stx.d">;
+def LDPTR_W : LOAD_2RI14<0b00100100, "ldptr.w">;
+def LDPTR_D : LOAD_2RI14<0b00100110, "ldptr.d">;
+def STPTR_W : STORE_2RI14<0b00100101, "stptr.w">;
+def STPTR_D : STORE_2RI14<0b00100111, "stptr.d">;
+def PRELDX : FmtPRELDX<(outs), (ins uimm5:$imm5, GPR:$rj, GPR:$rk),
+                       "preldx\t$imm5, $rj, $rk">;
+
+// Bound Check Memory Access Instructions
+def LDGT_B : LOAD_3R<0b00111000011110000, "ldgt.b">;
+def LDGT_H : LOAD_3R<0b00111000011110001, "ldgt.h">;
+def LDGT_W : LOAD_3R<0b00111000011110010, "ldgt.w">;
+def LDGT_D : LOAD_3R<0b00111000011110011, "ldgt.d">;
+def LDLE_B : LOAD_3R<0b00111000011110100, "ldle.b">;
+def LDLE_H : LOAD_3R<0b00111000011110101, "ldle.h">;
+def LDLE_W : LOAD_3R<0b00111000011110110, "ldle.w">;
+def LDLE_D : LOAD_3R<0b00111000011110111, "ldle.d">;
+def STGT_B : STORE_3R<0b00111000011111000, "stgt.b">;
+def STGT_H : STORE_3R<0b00111000011111001, "stgt.h">;
+def STGT_W : STORE_3R<0b00111000011111010, "stgt.w">;
+def STGT_D : STORE_3R<0b00111000011111011, "stgt.d">;
+def STLE_B : STORE_3R<0b00111000011111100, "stle.b">;
+def STLE_H : STORE_3R<0b00111000011111101, "stle.h">;
+def STLE_W : STORE_3R<0b00111000011111110, "stle.w">;
+def STLE_D : STORE_3R<0b00111000011111111, "stle.d">;
+
+// Atomic Memory Access Instructions for 64-bits
+def AMSWAP_W    : AM_3R<0b00111000011000000, "amswap.w">;
+def AMSWAP_D    : AM_3R<0b00111000011000001, "amswap.d">;
+def AMADD_W     : AM_3R<0b00111000011000010, "amadd.w">;
+def AMADD_D     : AM_3R<0b00111000011000011, "amadd.d">;
+def AMAND_W     : AM_3R<0b00111000011000100, "amand.w">;
+def AMAND_D     : AM_3R<0b00111000011000101, "amand.d">;
+def AMOR_W      : AM_3R<0b00111000011000110, "amor.w">;
+def AMOR_D      : AM_3R<0b00111000011000111, "amor.d">;
+def AMXOR_W     : AM_3R<0b00111000011001000, "amxor.w">;
+def AMXOR_D     : AM_3R<0b00111000011001001, "amxor.d">;
+def AMMAX_W     : AM_3R<0b00111000011001010, "ammax.w">;
+def AMMAX_D     : AM_3R<0b00111000011001011, "ammax.d">;
+def AMMIN_W     : AM_3R<0b00111000011001100, "ammin.w">;
+def AMMIN_D     : AM_3R<0b00111000011001101, "ammin.d">;
+def AMMAX_WU    : AM_3R<0b00111000011001110, "ammax.wu">;
+def AMMAX_DU    : AM_3R<0b00111000011001111, "ammax.du">;
+def AMMIN_WU    : AM_3R<0b00111000011010000, "ammin.wu">;
+def AMMIN_DU    : AM_3R<0b00111000011010001, "ammin.du">;
+def AMSWAP_DB_W : AM_3R<0b00111000011010010, "amswap_db.w">;
+def AMSWAP_DB_D : AM_3R<0b00111000011010011, "amswap_db.d">;
+def AMADD_DB_W  : AM_3R<0b00111000011010100, "amadd_db.w">;
+def AMADD_DB_D  : AM_3R<0b00111000011010101, "amadd_db.d">;
+def AMAND_DB_W  : AM_3R<0b00111000011010110, "amand_db.w">;
+def AMAND_DB_D  : AM_3R<0b00111000011010111, "amand_db.d">;
+def AMOR_DB_W   : AM_3R<0b00111000011011000, "amor_db.w">;
+def AMOR_DB_D   : AM_3R<0b00111000011011001, "amor_db.d">;
+def AMXOR_DB_W  : AM_3R<0b00111000011011010, "amxor_db.w">;
+def AMXOR_DB_D  : AM_3R<0b00111000011011011, "amxor_db.d">;
+def AMMAX_DB_W  : AM_3R<0b00111000011011100, "ammax_db.w">;
+def AMMAX_DB_D  : AM_3R<0b00111000011011101, "ammax_db.d">;
+def AMMIN_DB_W  : AM_3R<0b00111000011011110, "ammin_db.w">;
+def AMMIN_DB_D  : AM_3R<0b00111000011011111, "ammin_db.d">;
+def AMMAX_DB_WU : AM_3R<0b00111000011100000, "ammax_db.wu">;
+def AMMAX_DB_DU : AM_3R<0b00111000011100001, "ammax_db.du">;
+def AMMIN_DB_WU : AM_3R<0b00111000011100010, "ammin_db.wu">;
+def AMMIN_DB_DU : AM_3R<0b00111000011100011, "ammin_db.du">;
+def LL_D : LLBase<0b00100010, "ll.d">;
+def SC_D : SCBase<0b00100011, "sc.d">;
+
+// CRC Check Instructions
+def CRC_W_B_W  : ALU_3R<0b00000000001001000, "crc.w.b.w">;
+def CRC_W_H_W  : ALU_3R<0b00000000001001001, "crc.w.h.w">;
+def CRC_W_W_W  : ALU_3R<0b00000000001001010, "crc.w.w.w">;
+def CRC_W_D_W  : ALU_3R<0b00000000001001011, "crc.w.d.w">;
+def CRCC_W_B_W : ALU_3R<0b00000000001001100, "crcc.w.b.w">;
+def CRCC_W_H_W : ALU_3R<0b00000000001001101, "crcc.w.h.w">;
+def CRCC_W_W_W : ALU_3R<0b00000000001001110, "crcc.w.w.w">;
+def CRCC_W_D_W : ALU_3R<0b00000000001001111, "crcc.w.d.w">;
+
+// Other Miscellaneous Instructions for 64-bits
+def ASRTLE_D : FmtASRT<0b00000000000000010, (outs), (ins GPR:$rj, GPR:$rk),
+                       "asrtle.d\t$rj, $rk">;
+def ASRTGT_D : FmtASRT<0b00000000000000011, (outs), (ins GPR:$rj, GPR:$rk),
+                       "asrtgt.d\t$rj, $rk">;
+def RDTIME_D : RDTIME_2R<0b0000000000000000011010, "rdtime.d">;
+} // Predicates = [IsLA64]
+
+//===----------------------------------------------------------------------===//
+// Pseudo-instructions and codegen patterns
+//
+// Naming convention: For 'generic' pattern classes, we use the naming
+// convention PatTy1Ty2.
+//===----------------------------------------------------------------------===//
+
+/// Generic pattern classes
+
+class PatGprGpr<SDPatternOperator OpNode, LAInst Inst>
+    : Pat<(OpNode GPR:$rj, GPR:$rk), (Inst GPR:$rj, GPR:$rk)>;
+class PatGprGpr_32<SDPatternOperator OpNode, LAInst Inst>
+    : Pat<(sext_inreg (OpNode GPR:$rj, GPR:$rk), i32), (Inst GPR:$rj, GPR:$rk)>;
+
+class PatGprImm<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
+    : Pat<(OpNode GPR:$rj, ImmOpnd:$imm),
+          (Inst GPR:$rj, ImmOpnd:$imm)>;
+class PatGprImm_32<SDPatternOperator OpNode, LAInst Inst, Operand ImmOpnd>
+    : Pat<(sext_inreg (OpNode GPR:$rj, ImmOpnd:$imm), i32),
+          (Inst GPR:$rj, ImmOpnd:$imm)>;
+
+def : PatGprGpr<and, AND>;
+def : PatGprGpr<or, OR>;
+def : PatGprGpr<xor, XOR>;
+
+/// LA32 patterns
+let Predicates = [IsLA32] in {
+def : PatGprGpr<add, ADD_W>;
+def : PatGprImm<add, ADDI_W, simm12>;
+} // Predicates = [IsLA32]
+
+/// LA64 patterns
+let Predicates = [IsLA64] in {
+def : Pat<(sext_inreg GPR:$rj, i32), (ADDI_W GPR:$rj, 0)>;
+
+def : PatGprGpr<add, ADD_D>;
+def : PatGprGpr_32<add, ADD_W>;
+
+def : PatGprImm<add, ADDI_D, simm12>;
+def : PatGprImm_32<add, ADDI_W, simm12>;
+} // Predicates = [IsLA64]
+
+//===----------------------------------------------------------------------===//
+// Assembler Pseudo Instructions
+//===----------------------------------------------------------------------===//
+def : InstAlias<"nop", (ANDI R0, R0, 0)>;
+def : InstAlias<"move $dst, $src", (OR GPR:$dst, GPR:$src, R0)>;
diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
new file mode 100644 (file)
index 0000000..7416c93
--- /dev/null
@@ -0,0 +1,66 @@
+//=- LoongArchMCInstLower.cpp - Convert LoongArch MachineInstr to an MCInst -=//
+//
+// 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 code to lower LoongArch MachineInstrs to their
+// corresponding MCInst records.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArch.h"
+#include "LoongArchSubtarget.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
+                                                   MCOperand &MCOp,
+                                                   const AsmPrinter &AP) {
+  switch (MO.getType()) {
+  default:
+    report_fatal_error(
+        "lowerLoongArchMachineOperandToMCOperand: unknown operand type");
+  case MachineOperand::MO_Register:
+    // Ignore all implicit register operands.
+    if (MO.isImplicit())
+      return false;
+    MCOp = MCOperand::createReg(MO.getReg());
+    break;
+  case MachineOperand::MO_RegisterMask:
+    // Regmasks are like implicit defs.
+    return false;
+  case MachineOperand::MO_Immediate:
+    MCOp = MCOperand::createImm(MO.getImm());
+    break;
+  // TODO: lower special operands
+  case MachineOperand::MO_MachineBasicBlock:
+  case MachineOperand::MO_GlobalAddress:
+  case MachineOperand::MO_BlockAddress:
+  case MachineOperand::MO_ExternalSymbol:
+  case MachineOperand::MO_ConstantPoolIndex:
+  case MachineOperand::MO_JumpTableIndex:
+    break;
+  }
+  return true;
+}
+
+bool llvm::lowerLoongArchMachineInstrToMCInst(const MachineInstr *MI,
+                                              MCInst &OutMI, AsmPrinter &AP) {
+  OutMI.setOpcode(MI->getOpcode());
+
+  for (const MachineOperand &MO : MI->operands()) {
+    MCOperand MCOp;
+    if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP))
+      OutMI.addOperand(MCOp);
+  }
+  return false;
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
new file mode 100644 (file)
index 0000000..08e7cec
--- /dev/null
@@ -0,0 +1,50 @@
+//=- LoongArchMachineFunctionInfo.h - LoongArch machine function info -----===//
+//
+// 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 declares LoongArch-specific per-machine-function information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H
+
+#include "LoongArchSubtarget.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+
+namespace llvm {
+
+/// LoongArchMachineFunctionInfo - This class is derived from
+/// MachineFunctionInfo and contains private LoongArch-specific information for
+/// each MachineFunction.
+class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
+private:
+  /// FrameIndex for start of varargs area
+  int VarArgsFrameIndex = 0;
+  /// Size of the save area used for varargs
+  int VarArgsSaveSize = 0;
+
+  /// Size of stack frame to save callee saved registers
+  unsigned CalleeSavedStackSize = 0;
+
+public:
+  LoongArchMachineFunctionInfo(const MachineFunction &MF) {}
+
+  int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
+  void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
+
+  unsigned getVarArgsSaveSize() const { return VarArgsSaveSize; }
+  void setVarArgsSaveSize(int Size) { VarArgsSaveSize = Size; }
+
+  unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; }
+  void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHMACHINEFUNCTIONINFO_H
diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
new file mode 100644 (file)
index 0000000..b9bae8e
--- /dev/null
@@ -0,0 +1,115 @@
+//===- LoongArchRegisterInfo.cpp - LoongArch Register Information -*- 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 the LoongArch implementation of the TargetRegisterInfo
+// class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchRegisterInfo.h"
+#include "LoongArch.h"
+#include "LoongArchSubtarget.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+#define GET_REGINFO_TARGET_DESC
+#include "LoongArchGenRegisterInfo.inc"
+
+LoongArchRegisterInfo::LoongArchRegisterInfo(unsigned HwMode)
+    : LoongArchGenRegisterInfo(LoongArch::R1, /*DwarfFlavour*/ 0,
+                               /*EHFlavor*/ 0,
+                               /*PC*/ 0, HwMode) {}
+
+const MCPhysReg *
+LoongArchRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
+  auto &Subtarget = MF->getSubtarget<LoongArchSubtarget>();
+
+  switch (Subtarget.getTargetABI()) {
+  default:
+    llvm_unreachable("Unrecognized ABI");
+  case LoongArchABI::ABI_ILP32S:
+  case LoongArchABI::ABI_LP64S:
+    return CSR_ILP32S_LP64S_SaveList;
+  case LoongArchABI::ABI_ILP32F:
+  case LoongArchABI::ABI_LP64F:
+    return CSR_ILP32F_LP64F_SaveList;
+  case LoongArchABI::ABI_ILP32D:
+  case LoongArchABI::ABI_LP64D:
+    return CSR_ILP32D_LP64D_SaveList;
+  }
+}
+
+const uint32_t *
+LoongArchRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
+                                            CallingConv::ID CC) const {
+  auto &Subtarget = MF.getSubtarget<LoongArchSubtarget>();
+
+  switch (Subtarget.getTargetABI()) {
+  default:
+    llvm_unreachable("Unrecognized ABI");
+  case LoongArchABI::ABI_ILP32S:
+  case LoongArchABI::ABI_LP64S:
+    return CSR_ILP32S_LP64S_RegMask;
+  case LoongArchABI::ABI_ILP32F:
+  case LoongArchABI::ABI_LP64F:
+    return CSR_ILP32F_LP64F_RegMask;
+  case LoongArchABI::ABI_ILP32D:
+  case LoongArchABI::ABI_LP64D:
+    return CSR_ILP32D_LP64D_RegMask;
+  }
+}
+
+const uint32_t *LoongArchRegisterInfo::getNoPreservedMask() const {
+  return CSR_NoRegs_RegMask;
+}
+
+BitVector
+LoongArchRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+  const LoongArchFrameLowering *TFI = getFrameLowering(MF);
+  BitVector Reserved(getNumRegs());
+
+  // Use markSuperRegs to ensure any register aliases are also reserved
+  markSuperRegs(Reserved, LoongArch::R0);  // zero
+  markSuperRegs(Reserved, LoongArch::R2);  // tp
+  markSuperRegs(Reserved, LoongArch::R3);  // sp
+  markSuperRegs(Reserved, LoongArch::R21); // non-allocatable
+  if (TFI->hasFP(MF))
+    markSuperRegs(Reserved, LoongArch::R22); // fp
+  // Reserve the base register if we need to realign the stack and allocate
+  // variable-sized objects at runtime.
+  if (TFI->hasBP(MF))
+    markSuperRegs(Reserved, LoongArchABI::getBPReg()); // bp
+
+  assert(checkAllSuperRegsMarked(Reserved));
+  return Reserved;
+}
+
+bool LoongArchRegisterInfo::isConstantPhysReg(MCRegister PhysReg) const {
+  return PhysReg == LoongArch::R0;
+}
+
+Register
+LoongArchRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
+  const TargetFrameLowering *TFI = getFrameLowering(MF);
+  return TFI->hasFP(MF) ? LoongArch::R22 : LoongArch::R3;
+}
+
+void LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
+                                                int SPAdj,
+                                                unsigned FIOperandNum,
+                                                RegScavenger *RS) const {
+  assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
+  // TODO: Implement this when we have function calls
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.h
new file mode 100644 (file)
index 0000000..02c9156
--- /dev/null
@@ -0,0 +1,50 @@
+//= LoongArchRegisterInfo.h - LoongArch Register Information Impl -*- 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 the LoongArch implementation of the TargetRegisterInfo
+// class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H
+
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+
+#define GET_REGINFO_HEADER
+#include "LoongArchGenRegisterInfo.inc"
+
+namespace llvm {
+
+struct LoongArchRegisterInfo : public LoongArchGenRegisterInfo {
+
+  LoongArchRegisterInfo(unsigned HwMode);
+
+  const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
+  const uint32_t *getCallPreservedMask(const MachineFunction &MF,
+                                       CallingConv::ID) const override;
+  const uint32_t *getNoPreservedMask() const override;
+
+  BitVector getReservedRegs(const MachineFunction &MF) const override;
+  bool isConstantPhysReg(MCRegister PhysReg) const override;
+
+  const TargetRegisterClass *
+  getPointerRegClass(const MachineFunction &MF,
+                     unsigned Kind = 0) const override {
+    return &LoongArch::GPRRegClass;
+  }
+
+  void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
+                           unsigned FIOperandNum,
+                           RegScavenger *RS = nullptr) const override;
+
+  Register getFrameRegister(const MachineFunction &MF) const override;
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHREGISTERINFO_H
diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
new file mode 100644 (file)
index 0000000..41bef68
--- /dev/null
@@ -0,0 +1,143 @@
+//===-- LoongArchRegisterInfo.td - LoongArch Register defs -*- tablegen -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//  Declarations that describe the LoongArch register files
+//===----------------------------------------------------------------------===//
+
+let Namespace = "LoongArch" in {
+class LoongArchReg<bits<16> Enc, string n, list<string> alt = []>
+    : Register<n> {
+  let HWEncoding = Enc;
+  let AltNames = alt;
+}
+
+class LoongArchReg32<bits<16> Enc, string n, list<string> alt = []>
+    : Register<n> {
+  let HWEncoding = Enc;
+  let AltNames = alt;
+}
+
+def sub_32 : SubRegIndex<32>;
+class LoongArchReg64<LoongArchReg32 subreg> : Register<""> {
+  let HWEncoding = subreg.HWEncoding;
+  let SubRegs = [subreg];
+  let SubRegIndices = [sub_32];
+  let AsmName = subreg.AsmName;
+  let AltNames = subreg.AltNames;
+}
+
+let FallbackRegAltNameIndex = NoRegAltName in
+def RegAliasName : RegAltNameIndex;
+} // Namespace = "LoongArch"
+
+// Integer registers
+
+let RegAltNameIndices = [RegAliasName] in {
+  def R0  : LoongArchReg<0,  "r0", ["zero"]>, DwarfRegNum<[0]>;
+  def R1  : LoongArchReg<1,  "r1", ["ra"]>, DwarfRegNum<[1]>;
+  def R2  : LoongArchReg<2,  "r2", ["tp"]>, DwarfRegNum<[2]>;
+  def R3  : LoongArchReg<3,  "r3", ["sp"]>, DwarfRegNum<[3]>;
+  def R4  : LoongArchReg<4,  "r4", ["a0"]>, DwarfRegNum<[4]>;
+  def R5  : LoongArchReg<5,  "r5", ["a1"]>, DwarfRegNum<[5]>;
+  def R6  : LoongArchReg<6,  "r6", ["a2"]>, DwarfRegNum<[6]>;
+  def R7  : LoongArchReg<7,  "r7", ["a3"]>, DwarfRegNum<[7]>;
+  def R8  : LoongArchReg<8,  "r8", ["a4"]>, DwarfRegNum<[8]>;
+  def R9  : LoongArchReg<9,  "r9", ["a5"]>, DwarfRegNum<[9]>;
+  def R10 : LoongArchReg<10, "r10", ["a6"]>, DwarfRegNum<[10]>;
+  def R11 : LoongArchReg<11, "r11", ["a7"]>, DwarfRegNum<[11]>;
+  def R12 : LoongArchReg<12, "r12", ["t0"]>, DwarfRegNum<[12]>;
+  def R13 : LoongArchReg<13, "r13", ["t1"]>, DwarfRegNum<[13]>;
+  def R14 : LoongArchReg<14, "r14", ["t2"]>, DwarfRegNum<[14]>;
+  def R15 : LoongArchReg<15, "r15", ["t3"]>, DwarfRegNum<[15]>;
+  def R16 : LoongArchReg<16, "r16", ["t4"]>, DwarfRegNum<[16]>;
+  def R17 : LoongArchReg<17, "r17", ["t5"]>, DwarfRegNum<[17]>;
+  def R18 : LoongArchReg<18, "r18", ["t6"]>, DwarfRegNum<[18]>;
+  def R19 : LoongArchReg<19, "r19", ["t7"]>, DwarfRegNum<[19]>;
+  def R20 : LoongArchReg<20, "r20", ["t8"]>, DwarfRegNum<[20]>;
+  def R21 : LoongArchReg<21, "r21", [""]>, DwarfRegNum<[21]>;
+  def R22 : LoongArchReg<22, "r22", ["fp", "s9"]>, DwarfRegNum<[22]>;
+  def R23 : LoongArchReg<23, "r23", ["s0"]>, DwarfRegNum<[23]>;
+  def R24 : LoongArchReg<24, "r24", ["s1"]>, DwarfRegNum<[24]>;
+  def R25 : LoongArchReg<25, "r25", ["s2"]>, DwarfRegNum<[25]>;
+  def R26 : LoongArchReg<26, "r26", ["s3"]>, DwarfRegNum<[26]>;
+  def R27 : LoongArchReg<27, "r27", ["s4"]>, DwarfRegNum<[27]>;
+  def R28 : LoongArchReg<28, "r28", ["s5"]>, DwarfRegNum<[28]>;
+  def R29 : LoongArchReg<29, "r29", ["s6"]>, DwarfRegNum<[29]>;
+  def R30 : LoongArchReg<30, "r30", ["s7"]>, DwarfRegNum<[30]>;
+  def R31 : LoongArchReg<31, "r31", ["s8"]>, DwarfRegNum<[31]>;
+} // RegAltNameIndices = [RegAliasName]
+
+def GRLenVT : ValueTypeByHwMode<[LA32, LA64],
+                                [i32,  i64]>;
+def GRLenRI : RegInfoByHwMode<
+      [LA32,              LA64],
+      [RegInfo<32,32,32>, RegInfo<64,64,64>]>;
+
+// The order of registers represents the preferred allocation sequence.
+// Registers are listed in the order caller-save, callee-save, specials.
+def GPR : RegisterClass<"LoongArch", [GRLenVT], 32, (add
+    // Argument registers (a0...a7)
+    (sequence "R%u", 4, 11),
+    // Temporary registers (t0...t8)
+    (sequence "R%u", 12, 20),
+    // Static register (s9/fp, s0...s8)
+    (sequence "R%u", 22, 31),
+    // Specials (r0, ra, tp, sp)
+    (sequence "R%u", 0, 3),
+    // Reserved (Non-allocatable)
+    R21
+  )> {
+  let RegInfos = GRLenRI;
+}
+
+// Floating point registers
+
+let RegAltNameIndices = [RegAliasName] in {
+  def F0  : LoongArchReg32<0, "f0", ["fa0"]>, DwarfRegNum<[32]>;
+  def F1  : LoongArchReg32<1, "f1", ["fa1"]>, DwarfRegNum<[33]>;
+  def F2  : LoongArchReg32<2, "f2", ["fa2"]>, DwarfRegNum<[34]>;
+  def F3  : LoongArchReg32<3, "f3", ["fa3"]>, DwarfRegNum<[35]>;
+  def F4  : LoongArchReg32<4, "f4", ["fa4"]>, DwarfRegNum<[36]>;
+  def F5  : LoongArchReg32<5, "f5", ["fa5"]>, DwarfRegNum<[37]>;
+  def F6  : LoongArchReg32<6, "f6", ["fa6"]>, DwarfRegNum<[38]>;
+  def F7  : LoongArchReg32<7, "f7", ["fa7"]>, DwarfRegNum<[39]>;
+  def F8  : LoongArchReg32<8, "f8", ["ft0"]>, DwarfRegNum<[40]>;
+  def F9  : LoongArchReg32<9, "f9", ["ft1"]>, DwarfRegNum<[41]>;
+  def F10 : LoongArchReg32<10,"f10", ["ft2"]>, DwarfRegNum<[42]>;
+  def F11 : LoongArchReg32<11,"f11", ["ft3"]>, DwarfRegNum<[43]>;
+  def F12 : LoongArchReg32<12,"f12", ["ft4"]>, DwarfRegNum<[44]>;
+  def F13 : LoongArchReg32<13,"f13", ["ft5"]>, DwarfRegNum<[45]>;
+  def F14 : LoongArchReg32<14,"f14", ["ft6"]>, DwarfRegNum<[46]>;
+  def F15 : LoongArchReg32<15,"f15", ["ft7"]>, DwarfRegNum<[47]>;
+  def F16 : LoongArchReg32<16,"f16", ["ft8"]>, DwarfRegNum<[48]>;
+  def F17 : LoongArchReg32<17,"f17", ["ft9"]>, DwarfRegNum<[49]>;
+  def F18 : LoongArchReg32<18,"f18", ["ft10"]>, DwarfRegNum<[50]>;
+  def F19 : LoongArchReg32<19,"f19", ["ft11"]>, DwarfRegNum<[51]>;
+  def F20 : LoongArchReg32<20,"f20", ["ft12"]>, DwarfRegNum<[52]>;
+  def F21 : LoongArchReg32<21,"f21", ["ft13"]>, DwarfRegNum<[53]>;
+  def F22 : LoongArchReg32<22,"f22", ["ft14"]>, DwarfRegNum<[54]>;
+  def F23 : LoongArchReg32<23,"f23", ["ft15"]>, DwarfRegNum<[55]>;
+  def F24 : LoongArchReg32<24,"f24", ["fs0"]>, DwarfRegNum<[56]>;
+  def F25 : LoongArchReg32<25,"f25", ["fs1"]>, DwarfRegNum<[57]>;
+  def F26 : LoongArchReg32<26,"f26", ["fs2"]>, DwarfRegNum<[58]>;
+  def F27 : LoongArchReg32<27,"f27", ["fs3"]>, DwarfRegNum<[59]>;
+  def F28 : LoongArchReg32<28,"f28", ["fs4"]>, DwarfRegNum<[60]>;
+  def F29 : LoongArchReg32<29,"f29", ["fs5"]>, DwarfRegNum<[61]>;
+  def F30 : LoongArchReg32<30,"f30", ["fs6"]>, DwarfRegNum<[62]>;
+  def F31 : LoongArchReg32<31,"f31", ["fs7"]>, DwarfRegNum<[63]>;
+
+  foreach I = 0-31 in {
+    def F#I#_64 : LoongArchReg64<!cast<LoongArchReg32>("F"#I)>,
+      DwarfRegNum<[!add(I, 32)]>;
+  }
+}
+
+// The order of registers represents the preferred allocation sequence.
+def FPR32 : RegisterClass<"LoongArch", [f32], 32, (sequence "F%u", 0, 31)>;
+def FPR64 : RegisterClass<"LoongArch", [f64], 64, (sequence "F%u_64", 0, 31)>;
diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp b/llvm/lib/Target/LoongArch/LoongArchSubtarget.cpp
new file mode 100644 (file)
index 0000000..ff84e7c
--- /dev/null
@@ -0,0 +1,54 @@
+//===-- LoongArchSubtarget.cpp - LoongArch Subtarget Information -*- 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 the LoongArch specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchSubtarget.h"
+#include "LoongArchFrameLowering.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-subtarget"
+
+#define GET_SUBTARGETINFO_TARGET_DESC
+#define GET_SUBTARGETINFO_CTOR
+#include "LoongArchGenSubtargetInfo.inc"
+
+void LoongArchSubtarget::anchor() {}
+
+LoongArchSubtarget &LoongArchSubtarget::initializeSubtargetDependencies(
+    const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS,
+    StringRef ABIName) {
+  bool Is64Bit = TT.isArch64Bit();
+  if (CPU.empty())
+    CPU = Is64Bit ? "generic-la64" : "generic-la32";
+
+  if (TuneCPU.empty())
+    TuneCPU = CPU;
+
+  ParseSubtargetFeatures(CPU, TuneCPU, FS);
+  if (Is64Bit) {
+    GRLenVT = MVT::i64;
+    GRLen = 64;
+  }
+
+  // TODO: ILP32{S,F} LP64{S,F}
+  TargetABI = Is64Bit ? LoongArchABI::ABI_LP64D : LoongArchABI::ABI_ILP32D;
+  return *this;
+}
+
+LoongArchSubtarget::LoongArchSubtarget(const Triple &TT, StringRef CPU,
+                                       StringRef TuneCPU, StringRef FS,
+                                       StringRef ABIName,
+                                       const TargetMachine &TM)
+    : LoongArchGenSubtargetInfo(TT, CPU, TuneCPU, FS),
+      FrameLowering(
+          initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)),
+      InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {}
diff --git a/llvm/lib/Target/LoongArch/LoongArchSubtarget.h b/llvm/lib/Target/LoongArch/LoongArchSubtarget.h
new file mode 100644 (file)
index 0000000..95c2c67
--- /dev/null
@@ -0,0 +1,89 @@
+//===- LoongArchSubtarget.h - Define Subtarget for the LoongArch -*- 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 declares the LoongArch specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H
+#define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H
+
+#include "LoongArchFrameLowering.h"
+#include "LoongArchISelLowering.h"
+#include "LoongArchInstrInfo.h"
+#include "LoongArchRegisterInfo.h"
+#include "MCTargetDesc/LoongArchBaseInfo.h"
+#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define GET_SUBTARGETINFO_HEADER
+#include "LoongArchGenSubtargetInfo.inc"
+
+namespace llvm {
+class StringRef;
+
+class LoongArchSubtarget : public LoongArchGenSubtargetInfo {
+  virtual void anchor();
+  bool HasLA64 = false;
+  bool HasBasicF = false;
+  bool HasBasicD = false;
+  bool HasExtLSX = false;
+  bool HasExtLASX = false;
+  bool HasExtLVZ = false;
+  bool HasExtLBT = false;
+  unsigned GRLen = 32;
+  MVT GRLenVT = MVT::i32;
+  LoongArchABI::ABI TargetABI = LoongArchABI::ABI_Unknown;
+  LoongArchFrameLowering FrameLowering;
+  LoongArchInstrInfo InstrInfo;
+  LoongArchRegisterInfo RegInfo;
+  LoongArchTargetLowering TLInfo;
+
+  /// Initializes using the passed in CPU and feature strings so that we can
+  /// use initializer lists for subtarget initialization.
+  LoongArchSubtarget &initializeSubtargetDependencies(const Triple &TT,
+                                                      StringRef CPU,
+                                                      StringRef TuneCPU,
+                                                      StringRef FS,
+                                                      StringRef ABIName);
+
+public:
+  // Initializes the data members to match that of the specified triple.
+  LoongArchSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
+                     StringRef FS, StringRef ABIName, const TargetMachine &TM);
+
+  // Parses features string setting specified subtarget options. The
+  // definition of this function is auto-generated by tblgen.
+  void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
+
+  const LoongArchFrameLowering *getFrameLowering() const override {
+    return &FrameLowering;
+  }
+  const LoongArchInstrInfo *getInstrInfo() const override { return &InstrInfo; }
+  const LoongArchRegisterInfo *getRegisterInfo() const override {
+    return &RegInfo;
+  }
+  const LoongArchTargetLowering *getTargetLowering() const override {
+    return &TLInfo;
+  }
+  bool is64Bit() const { return HasLA64; }
+  bool hasBasicF() const { return HasBasicF; }
+  bool hasBasicD() const { return HasBasicD; }
+  bool hasExtLSX() const { return HasExtLSX; }
+  bool hasExtLASX() const { return HasExtLASX; }
+  bool hasExtLVZ() const { return HasExtLVZ; }
+  bool hasExtLBT() const { return HasExtLBT; }
+  MVT getGRLenVT() const { return GRLenVT; }
+  unsigned getGRLen() const { return GRLen; }
+  LoongArchABI::ABI getTargetABI() const { return TargetABI; }
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCHSUBTARGET_H
index 66507b4..5726b48 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "LoongArchTargetMachine.h"
+#include "LoongArch.h"
+#include "MCTargetDesc/LoongArchBaseInfo.h"
 #include "TargetInfo/LoongArchTargetInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
 #include "llvm/MC/TargetRegistry.h"
 
 using namespace llvm;
@@ -45,8 +50,70 @@ LoongArchTargetMachine::LoongArchTargetMachine(
     Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
                         getEffectiveRelocModel(TT, RM),
-                        getEffectiveCodeModel(CM, CodeModel::Small), OL) {
+                        getEffectiveCodeModel(CM, CodeModel::Small), OL),
+      TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
   initAsmInfo();
 }
 
 LoongArchTargetMachine::~LoongArchTargetMachine() = default;
+
+const LoongArchSubtarget *
+LoongArchTargetMachine::getSubtargetImpl(const Function &F) const {
+  Attribute CPUAttr = F.getFnAttribute("target-cpu");
+  Attribute TuneAttr = F.getFnAttribute("tune-cpu");
+  Attribute FSAttr = F.getFnAttribute("target-features");
+
+  std::string CPU =
+      CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
+  std::string TuneCPU =
+      TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
+  std::string FS =
+      FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
+
+  std::string Key = CPU + TuneCPU + FS;
+  auto &I = SubtargetMap[Key];
+  if (!I) {
+    // This needs to be done before we create a new subtarget since any
+    // creation will depend on the TM and the code generation flags on the
+    // function that reside in TargetOptions.
+    resetTargetOptions(F);
+    auto ABIName = Options.MCOptions.getABIName();
+    if (const MDString *ModuleTargetABI = dyn_cast_or_null<MDString>(
+            F.getParent()->getModuleFlag("target-abi"))) {
+      auto TargetABI = LoongArchABI::getTargetABI(ABIName);
+      if (TargetABI != LoongArchABI::ABI_Unknown &&
+          ModuleTargetABI->getString() != ABIName) {
+        report_fatal_error("-target-abi option != target-abi module flag");
+      }
+      ABIName = ModuleTargetABI->getString();
+    }
+    I = std::make_unique<LoongArchSubtarget>(TargetTriple, CPU, TuneCPU, FS,
+                                             ABIName, *this);
+  }
+  return I.get();
+}
+
+namespace {
+class LoongArchPassConfig : public TargetPassConfig {
+public:
+  LoongArchPassConfig(LoongArchTargetMachine &TM, PassManagerBase &PM)
+      : TargetPassConfig(TM, PM) {}
+
+  LoongArchTargetMachine &getLoongArchTargetMachine() const {
+    return getTM<LoongArchTargetMachine>();
+  }
+
+  bool addInstSelector() override;
+};
+} // namespace
+
+TargetPassConfig *
+LoongArchTargetMachine::createPassConfig(PassManagerBase &PM) {
+  return new LoongArchPassConfig(*this, PM);
+}
+
+bool LoongArchPassConfig::addInstSelector() {
+  addPass(createLoongArchISelDag(getLoongArchTargetMachine()));
+
+  return false;
+}
index 31c78ee..cbd8720 100644 (file)
 #ifndef LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H
 #define LLVM_LIB_TARGET_LOONGARCH_LOONGARCHTARGETMACHINE_H
 
+#include "LoongArchSubtarget.h"
 #include "llvm/Target/TargetMachine.h"
 
 namespace llvm {
 
 class LoongArchTargetMachine : public LLVMTargetMachine {
+  std::unique_ptr<TargetLoweringObjectFile> TLOF;
+  mutable StringMap<std::unique_ptr<LoongArchSubtarget>> SubtargetMap;
 
 public:
   LoongArchTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
@@ -26,6 +29,16 @@ public:
                          Optional<CodeModel::Model> CM, CodeGenOpt::Level OL,
                          bool JIT);
   ~LoongArchTargetMachine() override;
+
+  const LoongArchSubtarget *getSubtargetImpl(const Function &F) const override;
+  const LoongArchSubtarget *getSubtargetImpl() const = delete;
+
+  // Pass Pipeline Configuration
+  TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
+
+  TargetLoweringObjectFile *getObjFileLowering() const override {
+    return TLOF.get();
+  }
 };
 
 } // end namespace llvm
index 27d5940..a97a68b 100644 (file)
@@ -1,5 +1,11 @@
 add_llvm_component_library(LLVMLoongArchDesc
+  LoongArchAsmBackend.cpp
+  LoongArchBaseInfo.cpp
+  LoongArchELFObjectWriter.cpp
+  LoongArchInstPrinter.cpp
+  LoongArchMCAsmInfo.cpp
   LoongArchMCTargetDesc.cpp
+  LoongArchMCCodeEmitter.cpp
 
   LINK_COMPONENTS
   MC
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
new file mode 100644 (file)
index 0000000..94a0688
--- /dev/null
@@ -0,0 +1,68 @@
+//===-- LoongArchAsmBackend.cpp - LoongArch Assembler Backend -*- 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 the LoongArchAsmBackend class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchAsmBackend.h"
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
+
+#define DEBUG_TYPE "loongarch-asmbackend"
+
+using namespace llvm;
+
+void LoongArchAsmBackend::applyFixup(const MCAssembler &Asm,
+                                     const MCFixup &Fixup,
+                                     const MCValue &Target,
+                                     MutableArrayRef<char> Data, uint64_t Value,
+                                     bool IsResolved,
+                                     const MCSubtargetInfo *STI) const {
+  // TODO: Apply the Value for given Fixup into the provided data fragment.
+  return;
+}
+
+bool LoongArchAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
+                                                const MCFixup &Fixup,
+                                                const MCValue &Target) {
+  // TODO: Determine which relocation require special processing at linking
+  // time.
+  return false;
+}
+
+bool LoongArchAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
+                                       const MCSubtargetInfo *STI) const {
+  // Check for byte count not multiple of instruction word size
+  if (Count % 4 != 0)
+    return false;
+
+  // The nop on LoongArch is andi r0, r0, 0.
+  for (; Count >= 4; Count -= 4)
+    support::endian::write<uint32_t>(OS, 0x03400000, support::little);
+
+  return true;
+}
+
+std::unique_ptr<MCObjectTargetWriter>
+LoongArchAsmBackend::createObjectTargetWriter() const {
+  return createLoongArchELFObjectWriter(OSABI, Is64Bit);
+}
+
+MCAsmBackend *llvm::createLoongArchAsmBackend(const Target &T,
+                                              const MCSubtargetInfo &STI,
+                                              const MCRegisterInfo &MRI,
+                                              const MCTargetOptions &Options) {
+  const Triple &TT = STI.getTargetTriple();
+  uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
+  return new LoongArchAsmBackend(STI, OSABI, TT.isArch64Bit());
+}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.h
new file mode 100644 (file)
index 0000000..a2cb3d4
--- /dev/null
@@ -0,0 +1,64 @@
+//===-- LoongArchAsmBackend.h - LoongArch Assembler Backend ---*- 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 defines the LoongArchAsmBackend class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H
+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H
+
+#include "MCTargetDesc/LoongArchBaseInfo.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCFixupKindInfo.h"
+
+namespace llvm {
+
+class LoongArchAsmBackend : public MCAsmBackend {
+  const MCSubtargetInfo &STI;
+  uint8_t OSABI;
+  bool Is64Bit;
+
+public:
+  LoongArchAsmBackend(const MCSubtargetInfo &STI, uint8_t OSABI, bool Is64Bit)
+      : MCAsmBackend(support::little), STI(STI), OSABI(OSABI),
+        Is64Bit(Is64Bit) {}
+  ~LoongArchAsmBackend() override {}
+
+  void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+                  const MCValue &Target, MutableArrayRef<char> Data,
+                  uint64_t Value, bool IsResolved,
+                  const MCSubtargetInfo *STI) const override;
+
+  bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
+                             const MCValue &Target) override;
+
+  bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+                            const MCRelaxableFragment *DF,
+                            const MCAsmLayout &Layout) const override {
+    return false;
+  }
+
+  unsigned getNumFixupKinds() const override {
+    // FIXME: Implement this when we define fixup kind
+    return 0;
+  }
+
+  void relaxInstruction(MCInst &Inst,
+                        const MCSubtargetInfo &STI) const override {}
+
+  bool writeNopData(raw_ostream &OS, uint64_t Count,
+                    const MCSubtargetInfo *STI) const override;
+
+  std::unique_ptr<MCObjectTargetWriter>
+  createObjectTargetWriter() const override;
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHASMBACKEND_H
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.cpp
new file mode 100644 (file)
index 0000000..f0c9858
--- /dev/null
@@ -0,0 +1,40 @@
+//= LoongArchBaseInfo.cpp - Top level definitions for LoongArch 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 implements helper functions for the LoongArch target useful for the
+// compiler back-end and the MC libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchBaseInfo.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+
+namespace llvm {
+
+namespace LoongArchABI {
+
+ABI getTargetABI(StringRef ABIName) {
+  auto TargetABI = StringSwitch<ABI>(ABIName)
+                       .Case("ilp32s", ABI_ILP32S)
+                       .Case("ilp32f", ABI_ILP32F)
+                       .Case("ilp32d", ABI_ILP32D)
+                       .Case("lp64s", ABI_LP64S)
+                       .Case("lp64f", ABI_LP64F)
+                       .Case("lp64d", ABI_LP64D)
+                       .Default(ABI_Unknown);
+  return TargetABI;
+}
+
+// FIXME: other register?
+MCRegister getBPReg() { return LoongArch::R31; }
+
+} // namespace LoongArchABI
+
+} // namespace llvm
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
new file mode 100644 (file)
index 0000000..e26f22d
--- /dev/null
@@ -0,0 +1,44 @@
+//=- LoongArchBaseInfo.h - Top level definitions for LoongArch 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 and helper function
+// definitions for the LoongArch target useful for the compiler back-end and the
+// MC libraries.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H
+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H
+
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/MC/SubtargetFeature.h"
+
+namespace llvm {
+
+namespace LoongArchABI {
+enum ABI {
+  ABI_ILP32S,
+  ABI_ILP32F,
+  ABI_ILP32D,
+  ABI_LP64S,
+  ABI_LP64F,
+  ABI_LP64D,
+  ABI_Unknown
+};
+
+ABI getTargetABI(StringRef ABIName);
+
+// Returns the register used to hold the stack pointer after realignment.
+MCRegister getBPReg();
+} // namespace LoongArchABI
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHBASEINFO_H
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp
new file mode 100644 (file)
index 0000000..254d619
--- /dev/null
@@ -0,0 +1,65 @@
+//===-- LoongArchELFObjectWriter.cpp - LoongArch ELF Writer ---*- 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 "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCELFObjectWriter.h"
+#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+namespace {
+class LoongArchELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+  LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit);
+
+  ~LoongArchELFObjectWriter() override;
+
+  // Return true if the given relocation must be with a symbol rather than
+  // section plus offset.
+  bool needsRelocateWithSymbol(const MCSymbol &Sym,
+                               unsigned Type) const override {
+    return true;
+  }
+
+protected:
+  unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+                        const MCFixup &Fixup, bool IsPCRel) const override;
+};
+} // namespace
+
+LoongArchELFObjectWriter::LoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit)
+    : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_LOONGARCH,
+                              /*HasRelocationAddend*/ true) {}
+
+LoongArchELFObjectWriter::~LoongArchELFObjectWriter() {}
+
+unsigned LoongArchELFObjectWriter::getRelocType(MCContext &Ctx,
+                                                const MCValue &Target,
+                                                const MCFixup &Fixup,
+                                                bool IsPCRel) const {
+  const MCExpr *Expr = Fixup.getValue();
+  // Determine the type of the relocation
+  unsigned Kind = Fixup.getTargetKind();
+
+  if (Kind >= FirstLiteralRelocationKind)
+    return Kind - FirstLiteralRelocationKind;
+
+  switch (Kind) {
+  // TODO: Implement this when we defined fixup kind.
+  default:
+    return ELF::R_LARCH_NONE;
+  }
+}
+
+std::unique_ptr<MCObjectTargetWriter>
+llvm::createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit) {
+  return std::make_unique<LoongArchELFObjectWriter>(OSABI, Is64Bit);
+}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.cpp
new file mode 100644 (file)
index 0000000..1a5b44e
--- /dev/null
@@ -0,0 +1,63 @@
+//===- LoongArchInstPrinter.cpp - Convert LoongArch MCInst to asm syntax --===//
+//
+// 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 class prints an LoongArch MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchInstPrinter.h"
+#include "LoongArchBaseInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCSymbol.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-asm-printer"
+
+// Include the auto-generated portion of the assembly writer.
+#define PRINT_ALIAS_INSTR
+#include "LoongArchGenAsmWriter.inc"
+
+void LoongArchInstPrinter::printInst(const MCInst *MI, uint64_t Address,
+                                     StringRef Annot,
+                                     const MCSubtargetInfo &STI,
+                                     raw_ostream &O) {
+  if (!printAliasInstr(MI, Address, STI, O))
+    printInstruction(MI, Address, STI, O);
+  printAnnotation(O, Annot);
+}
+
+void LoongArchInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const {
+  O << getRegisterName(RegNo);
+}
+
+void LoongArchInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
+                                        const MCSubtargetInfo &STI,
+                                        raw_ostream &O) {
+  const MCOperand &MO = MI->getOperand(OpNo);
+
+  if (MO.isReg()) {
+    printRegName(O, MO.getReg());
+    return;
+  }
+
+  if (MO.isImm()) {
+    O << MO.getImm();
+    return;
+  }
+
+  assert(MO.isExpr() && "Unknown operand kind in printOperand");
+  MO.getExpr()->print(O, &MAI);
+}
+
+const char *LoongArchInstPrinter::getRegisterName(unsigned RegNo) {
+  // Default print reg alias name
+  return getRegisterName(RegNo, LoongArch::RegAliasName);
+}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchInstPrinter.h
new file mode 100644 (file)
index 0000000..727fc6a
--- /dev/null
@@ -0,0 +1,49 @@
+//===-- LoongArchInstPrinter.h - Convert LoongArch MCInst to asm syntax ---===//
+//
+// 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 class prints a LoongArch MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H
+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H
+
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "llvm/MC/MCInstPrinter.h"
+
+namespace llvm {
+
+class LoongArchInstPrinter : public MCInstPrinter {
+public:
+  LoongArchInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
+                       const MCRegisterInfo &MRI)
+      : MCInstPrinter(MAI, MII, MRI) {}
+
+  void printInst(const MCInst *MI, uint64_t Address, StringRef Annot,
+                 const MCSubtargetInfo &STI, raw_ostream &O) override;
+  void printRegName(raw_ostream &O, unsigned RegNo) const override;
+
+  // Autogenerated by tblgen.
+  std::pair<const char *, uint64_t> getMnemonic(const MCInst *MI) override;
+  void printInstruction(const MCInst *MI, uint64_t Address,
+                        const MCSubtargetInfo &STI, raw_ostream &O);
+  bool printAliasInstr(const MCInst *MI, uint64_t Address,
+                       const MCSubtargetInfo &STI, raw_ostream &O);
+  void printCustomAliasOperand(const MCInst *MI, uint64_t Address,
+                               unsigned OpIdx, unsigned PrintMethodIdx,
+                               const MCSubtargetInfo &STI, raw_ostream &O);
+  static const char *getRegisterName(unsigned RegNo);
+  static const char *getRegisterName(unsigned RegNo, unsigned AltIdx);
+
+private:
+  void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI,
+                    raw_ostream &O);
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHINSTPRINTER_H
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.cpp
new file mode 100644 (file)
index 0000000..01993f9
--- /dev/null
@@ -0,0 +1,33 @@
+//===-- LoongArchMCAsmInfo.cpp - LoongArch Asm properties ------*- 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 the declarations of the LoongArchMCAsmInfo properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArchMCAsmInfo.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/MC/MCStreamer.h"
+
+using namespace llvm;
+
+void LoongArchMCAsmInfo::anchor() {}
+
+LoongArchMCAsmInfo::LoongArchMCAsmInfo(const Triple &TT) {
+  CodePointerSize = CalleeSaveStackSlotSize = TT.isArch64Bit() ? 8 : 4;
+  AlignmentIsInBytes = false;
+  Data8bitsDirective = "\t.byte\t";
+  Data16bitsDirective = "\t.half\t";
+  Data32bitsDirective = "\t.word\t";
+  Data64bitsDirective = "\t.dword\t";
+  ZeroDirective = "\t.space\t";
+  CommentString = "#";
+  SupportsDebugInformation = true;
+  ExceptionsType = ExceptionHandling::DwarfCFI;
+}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCAsmInfo.h
new file mode 100644 (file)
index 0000000..1cf8a2f
--- /dev/null
@@ -0,0 +1,30 @@
+//===-- LoongArchMCAsmInfo.h - LoongArch Asm Info --------------*- 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 the declaration of the LoongArchMCAsmInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H
+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H
+
+#include "llvm/MC/MCAsmInfoELF.h"
+
+namespace llvm {
+class Triple;
+
+class LoongArchMCAsmInfo : public MCAsmInfoELF {
+  void anchor() override;
+
+public:
+  explicit LoongArchMCAsmInfo(const Triple &TargetTriple);
+};
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCASMINFO_H
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
new file mode 100644 (file)
index 0000000..09937e5
--- /dev/null
@@ -0,0 +1,95 @@
+//=- LoongArchMCCodeEmitter.cpp - Convert LoongArch code to machine code --===//
+//
+// 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 the LoongArchMCCodeEmitter class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/LoongArchBaseInfo.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/Support/EndianStream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "mccodeemitter"
+
+namespace {
+class LoongArchMCCodeEmitter : public MCCodeEmitter {
+  LoongArchMCCodeEmitter(const LoongArchMCCodeEmitter &) = delete;
+  void operator=(const LoongArchMCCodeEmitter &) = delete;
+  MCContext &Ctx;
+  MCInstrInfo const &MCII;
+
+public:
+  LoongArchMCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
+      : Ctx(ctx), MCII(MCII) {}
+
+  ~LoongArchMCCodeEmitter() override {}
+
+  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
+                         SmallVectorImpl<MCFixup> &Fixups,
+                         const MCSubtargetInfo &STI) const override;
+
+  /// TableGen'erated function for getting the binary encoding for an
+  /// instruction.
+  uint64_t getBinaryCodeForInstr(const MCInst &MI,
+                                 SmallVectorImpl<MCFixup> &Fixups,
+                                 const MCSubtargetInfo &STI) const;
+
+  /// Return binary encoding of operand. If the machine operand requires
+  /// relocation, record the relocation and return zero.
+  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+                             SmallVectorImpl<MCFixup> &Fixups,
+                             const MCSubtargetInfo &STI) const;
+};
+} // end anonymous namespace
+
+unsigned
+LoongArchMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+                                          SmallVectorImpl<MCFixup> &Fixups,
+                                          const MCSubtargetInfo &STI) const {
+
+  if (MO.isReg())
+    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
+
+  if (MO.isImm())
+    return static_cast<unsigned>(MO.getImm());
+
+  llvm_unreachable("Unhandled expression!");
+  return 0;
+}
+
+void LoongArchMCCodeEmitter::encodeInstruction(
+    const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
+    const MCSubtargetInfo &STI) const {
+  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
+  // Get byte count of instruction.
+  unsigned Size = Desc.getSize();
+
+  switch (Size) {
+  default:
+    llvm_unreachable("Unhandled encodeInstruction length!");
+  case 4: {
+    uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
+    support::endian::write(OS, Bits, support::little);
+    break;
+  }
+  }
+}
+
+MCCodeEmitter *llvm::createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
+                                                  const MCRegisterInfo &MRI,
+                                                  MCContext &Ctx) {
+  return new LoongArchMCCodeEmitter(Ctx, MCII);
+}
+
+#include "LoongArchGenMCCodeEmitter.inc"
index 4d9735e..d7bf3dd 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#include "LoongArchMCTargetDesc.h"
+#include "LoongArchBaseInfo.h"
+#include "LoongArchInstPrinter.h"
+#include "LoongArchMCAsmInfo.h"
+#include "TargetInfo/LoongArchTargetInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDwarf.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/Compiler.h"
 
-// FIXME: This is just a placeholder to make current commit buildable. Body of
-// this function will be filled in later commits.
-extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() {}
+#define GET_INSTRINFO_MC_DESC
+#include "LoongArchGenInstrInfo.inc"
+
+#define GET_REGINFO_MC_DESC
+#include "LoongArchGenRegisterInfo.inc"
+
+#define GET_SUBTARGETINFO_MC_DESC
+#include "LoongArchGenSubtargetInfo.inc"
+
+using namespace llvm;
+
+static MCRegisterInfo *createLoongArchMCRegisterInfo(const Triple &TT) {
+  MCRegisterInfo *X = new MCRegisterInfo();
+  InitLoongArchMCRegisterInfo(X, LoongArch::R1);
+  return X;
+}
+
+static MCInstrInfo *createLoongArchMCInstrInfo() {
+  MCInstrInfo *X = new MCInstrInfo();
+  InitLoongArchMCInstrInfo(X);
+  return X;
+}
+
+static MCSubtargetInfo *
+createLoongArchMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
+  if (CPU.empty())
+    CPU = TT.isArch64Bit() ? "la464" : "generic-la32";
+  return createLoongArchMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FS);
+}
+
+static MCAsmInfo *createLoongArchMCAsmInfo(const MCRegisterInfo &MRI,
+                                           const Triple &TT,
+                                           const MCTargetOptions &Options) {
+  MCAsmInfo *MAI = new LoongArchMCAsmInfo(TT);
+
+  MCRegister SP = MRI.getDwarfRegNum(LoongArch::R2, true);
+  MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(nullptr, SP, 0);
+  MAI->addInitialFrameState(Inst);
+
+  return MAI;
+}
+
+static MCInstPrinter *createLoongArchMCInstPrinter(const Triple &T,
+                                                   unsigned SyntaxVariant,
+                                                   const MCAsmInfo &MAI,
+                                                   const MCInstrInfo &MII,
+                                                   const MCRegisterInfo &MRI) {
+  return new LoongArchInstPrinter(MAI, MII, MRI);
+}
+
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetMC() {
+  for (Target *T : {&getTheLoongArch32Target(), &getTheLoongArch64Target()}) {
+    // Register the MC register info.
+    TargetRegistry::RegisterMCRegInfo(*T, createLoongArchMCRegisterInfo);
+
+    // Register the MC instruction info.
+    TargetRegistry::RegisterMCInstrInfo(*T, createLoongArchMCInstrInfo);
+
+    // Register the MC subtarget info.
+    TargetRegistry::RegisterMCSubtargetInfo(*T, createLoongArchMCSubtargetInfo);
+
+    // Register the MC asm info.
+    TargetRegistry::RegisterMCAsmInfo(*T, createLoongArchMCAsmInfo);
+
+    // Register the MC Code Emitter
+    TargetRegistry::RegisterMCCodeEmitter(*T, createLoongArchMCCodeEmitter);
+
+    // Register the asm backend.
+    TargetRegistry::RegisterMCAsmBackend(*T, createLoongArchAsmBackend);
+
+    // Register the MCInstPrinter.
+    TargetRegistry::RegisterMCInstPrinter(*T, createLoongArchMCInstPrinter);
+  }
+}
diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCTargetDesc.h
new file mode 100644 (file)
index 0000000..42a2bf9
--- /dev/null
@@ -0,0 +1,55 @@
+//===- LoongArchMCTargetDesc.h - LoongArch Target Descriptions --*- 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 LoongArch specific target descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H
+#define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H
+
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Support/DataTypes.h"
+#include <memory>
+
+namespace llvm {
+class MCAsmBackend;
+class MCCodeEmitter;
+class MCContext;
+class MCInstrInfo;
+class MCObjectTargetWriter;
+class MCRegisterInfo;
+class MCSubtargetInfo;
+class Target;
+
+MCCodeEmitter *createLoongArchMCCodeEmitter(const MCInstrInfo &MCII,
+                                            const MCRegisterInfo &MRI,
+                                            MCContext &Ctx);
+
+MCAsmBackend *createLoongArchAsmBackend(const Target &T,
+                                        const MCSubtargetInfo &STI,
+                                        const MCRegisterInfo &MRI,
+                                        const MCTargetOptions &Options);
+
+std::unique_ptr<MCObjectTargetWriter>
+createLoongArchELFObjectWriter(uint8_t OSABI, bool Is64Bit);
+
+} // namespace llvm
+
+// Defines symbolic names for LoongArch registers.
+#define GET_REGINFO_ENUM
+#include "LoongArchGenRegisterInfo.inc"
+
+// Defines symbolic names for LoongArch instructions.
+#define GET_INSTRINFO_ENUM
+#include "LoongArchGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_ENUM
+#include "LoongArchGenSubtargetInfo.inc"
+
+#endif // LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHMCTARGETDESC_H
index 64b1a5b..1065451 100644 (file)
@@ -22,9 +22,9 @@ Target &llvm::getTheLoongArch64Target() {
 
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTargetInfo() {
   RegisterTarget<Triple::loongarch32, /*HasJIT=*/false> X(
-      getTheLoongArch32Target(), "loongarch32", "LoongArch (32-bit)",
+      getTheLoongArch32Target(), "loongarch32", "32-bit LoongArch",
       "LoongArch");
   RegisterTarget<Triple::loongarch64, /*HasJIT=*/false> Y(
-      getTheLoongArch64Target(), "loongarch64", "LoongArch (64-bit)",
+      getTheLoongArch64Target(), "loongarch64", "64-bit LoongArch",
       "LoongArch");
 }
index 528cdfa..b7796e6 100644 (file)
@@ -1,3 +1,3 @@
 ; RUN: llc --version | FileCheck %s
-; CHECK:    loongarch32 - LoongArch (32-bit)
-; CHECK:    loongarch64 - LoongArch (64-bit)
+; CHECK:    loongarch32 - 32-bit LoongArch
+; CHECK:    loongarch64 - 64-bit LoongArch