[llvm] 75265c7 - [LoongArch] Lower BlockAddress/JumpTable

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 25 20:01:44 PDT 2022


Author: wanglei
Date: 2022-09-26T10:52:54+08:00
New Revision: 75265c7f4975c199cbeb544b07ca511b6fc865e6

URL: https://github.com/llvm/llvm-project/commit/75265c7f4975c199cbeb544b07ca511b6fc865e6
DIFF: https://github.com/llvm/llvm-project/commit/75265c7f4975c199cbeb544b07ca511b6fc865e6.diff

LOG: [LoongArch] Lower BlockAddress/JumpTable

This patch uses a unified interface for lower GlobalAddress ConstantPool
BlockAddress and JumpTable.

This patch allows lowering addresses by using PC-relative addressing
for DSO-local symbols, and accessing the address through the global
offset table for DSO-preemptable symbols.

Remove hardcoded `MininumJumpTableEntries` for test lower JumpTable.

Also updated some test cases using ConstantPool, due to the addition of
relocation information.

Differential Revision: https://reviews.llvm.org/D134431

Added: 
    llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
    llvm/test/CodeGen/LoongArch/block-address.ll
    llvm/test/CodeGen/LoongArch/global-address.ll

Modified: 
    llvm/lib/Target/LoongArch/CMakeLists.txt
    llvm/lib/Target/LoongArch/LoongArch.h
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
    llvm/lib/Target/LoongArch/LoongArchISelLowering.h
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
    llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
    llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll
    llvm/test/CodeGen/LoongArch/double-imm.ll
    llvm/test/CodeGen/LoongArch/float-imm.ll
    llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
    llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
    llvm/test/CodeGen/LoongArch/jump-table.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/CMakeLists.txt b/llvm/lib/Target/LoongArch/CMakeLists.txt
index 8de85c5fde09a..bf7f730376b64 100644
--- a/llvm/lib/Target/LoongArch/CMakeLists.txt
+++ b/llvm/lib/Target/LoongArch/CMakeLists.txt
@@ -17,6 +17,7 @@ add_public_tablegen_target(LoongArchCommonTableGen)
 add_llvm_target(LoongArchCodeGen
   LoongArchAsmPrinter.cpp
   LoongArchExpandAtomicPseudoInsts.cpp
+  LoongArchExpandPseudoInsts.cpp
   LoongArchFrameLowering.cpp
   LoongArchInstrInfo.cpp
   LoongArchISelDAGToDAG.cpp

diff  --git a/llvm/lib/Target/LoongArch/LoongArch.h b/llvm/lib/Target/LoongArch/LoongArch.h
index 5f0da3aefa118..3d0a3b9ebf55b 100644
--- a/llvm/lib/Target/LoongArch/LoongArch.h
+++ b/llvm/lib/Target/LoongArch/LoongArch.h
@@ -36,6 +36,9 @@ bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
 FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM);
 FunctionPass *createLoongArchExpandAtomicPseudoPass();
 void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &);
+
+FunctionPass *createLoongArchPreRAExpandPseudoPass();
+void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &);
 } // end namespace llvm
 
 #endif // LLVM_LIB_TARGET_LOONGARCH_LOONGARCH_H

diff  --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
new file mode 100644
index 0000000000000..a7a5cd33fec0a
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -0,0 +1,162 @@
+//===-- LoongArchExpandPseudoInsts.cpp - Expand pseudo instructions -------===//
+//
+// 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 pass that expands pseudo instructions into target
+// instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArch.h"
+#include "LoongArchInstrInfo.h"
+#include "LoongArchTargetMachine.h"
+#include "MCTargetDesc/LoongArchBaseInfo.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/MC/MCContext.h"
+
+using namespace llvm;
+
+#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME                                     \
+  "LoongArch Pre-RA pseudo instruction expansion pass"
+
+namespace {
+
+class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
+public:
+  const LoongArchInstrInfo *TII;
+  static char ID;
+
+  LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {
+    initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesCFG();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+  StringRef getPassName() const override {
+    return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;
+  }
+
+private:
+  bool expandMBB(MachineBasicBlock &MBB);
+  bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+                MachineBasicBlock::iterator &NextMBBI);
+  bool expandPcalau12iInstPair(MachineBasicBlock &MBB,
+                               MachineBasicBlock::iterator MBBI,
+                               MachineBasicBlock::iterator &NextMBBI,
+                               unsigned FlagsHi, unsigned SecondOpcode,
+                               unsigned FlagsLo);
+  bool expandLoadAddressPcrel(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MBBI,
+                              MachineBasicBlock::iterator &NextMBBI);
+  bool expandLoadAddressGot(MachineBasicBlock &MBB,
+                            MachineBasicBlock::iterator MBBI,
+                            MachineBasicBlock::iterator &NextMBBI);
+};
+
+char LoongArchPreRAExpandPseudo::ID = 0;
+
+bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
+  TII =
+      static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());
+  bool Modified = false;
+  for (auto &MBB : MF)
+    Modified |= expandMBB(MBB);
+  return Modified;
+}
+
+bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
+  bool Modified = false;
+
+  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
+  while (MBBI != E) {
+    MachineBasicBlock::iterator NMBBI = std::next(MBBI);
+    Modified |= expandMI(MBB, MBBI, NMBBI);
+    MBBI = NMBBI;
+  }
+
+  return Modified;
+}
+
+bool LoongArchPreRAExpandPseudo::expandMI(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  switch (MBBI->getOpcode()) {
+  case LoongArch::PseudoLA_PCREL:
+    return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);
+  case LoongArch::PseudoLA_GOT:
+    return expandLoadAddressGot(MBB, MBBI, NextMBBI);
+  }
+  return false;
+}
+
+bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
+    unsigned SecondOpcode, unsigned FlagsLo) {
+  MachineFunction *MF = MBB.getParent();
+  MachineInstr &MI = *MBBI;
+  DebugLoc DL = MI.getDebugLoc();
+
+  Register DestReg = MI.getOperand(0).getReg();
+  Register ScratchReg =
+      MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);
+  MachineOperand &Symbol = MI.getOperand(1);
+
+  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)
+      .addDisp(Symbol, 0, FlagsHi);
+
+  MachineInstr *SecondMI =
+      BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
+          .addReg(ScratchReg)
+          .addDisp(Symbol, 0, FlagsLo);
+
+  if (MI.hasOneMemOperand())
+    SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
+
+  MI.eraseFromParent();
+  return true;
+}
+
+bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  MachineFunction *MF = MBB.getParent();
+  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
+  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,
+                                 SecondOpcode, LoongArchII::MO_PCREL_LO);
+}
+
+bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+    MachineBasicBlock::iterator &NextMBBI) {
+  MachineFunction *MF = MBB.getParent();
+  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();
+  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
+  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,
+                                 SecondOpcode, LoongArchII::MO_GOT_PC_LO);
+}
+
+} // end namespace
+
+INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "LoongArch-prera-expand-pseudo",
+                LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)
+
+namespace llvm {
+
+FunctionPass *createLoongArchPreRAExpandPseudoPass() {
+  return new LoongArchPreRAExpandPseudo();
+}
+
+} // end namespace llvm

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 314765dcdccc8..920a9da58b859 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -58,7 +58,9 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
   setOperationAction(ISD::ROTL, GRLenVT, Expand);
   setOperationAction(ISD::CTPOP, GRLenVT, Expand);
 
-  setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom);
+  setOperationAction({ISD::GlobalAddress, ISD::BlockAddress, ISD::ConstantPool,
+                      ISD::JumpTable},
+                     GRLenVT, Custom);
 
   setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
 
@@ -128,8 +130,6 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::FMAXNUM_IEEE, MVT::f64, Legal);
   }
 
-  // Effectively disable jump table generation.
-  setMinimumJumpTableEntries(INT_MAX);
   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
 
   setOperationAction(ISD::BR_CC, GRLenVT, Expand);
@@ -180,6 +180,10 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
     return lowerGlobalAddress(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN:
     return lowerINTRINSIC_WO_CHAIN(Op, DAG);
+  case ISD::BlockAddress:
+    return lowerBlockAddress(Op, DAG);
+  case ISD::JumpTable:
+    return lowerJumpTable(Op, DAG);
   case ISD::SHL_PARTS:
     return lowerShiftLeftParts(Op, DAG);
   case ISD::SRA_PARTS:
@@ -272,46 +276,66 @@ SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op,
   return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc);
 }
 
+static SDValue getTargetNode(GlobalAddressSDNode *N, SDLoc DL, EVT Ty,
+                             SelectionDAG &DAG, unsigned Flags) {
+  return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
+}
+
+static SDValue getTargetNode(BlockAddressSDNode *N, SDLoc DL, EVT Ty,
+                             SelectionDAG &DAG, unsigned Flags) {
+  return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
+                                   Flags);
+}
+
+static SDValue getTargetNode(ConstantPoolSDNode *N, SDLoc DL, EVT Ty,
+                             SelectionDAG &DAG, unsigned Flags) {
+  return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
+                                   N->getOffset(), Flags);
+}
+
+static SDValue getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty,
+                             SelectionDAG &DAG, unsigned Flags) {
+  return DAG.getTargetJumpTable(N->getIndex(), Ty, Flags);
+}
+
+template <class NodeTy>
+SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
+                                         bool IsLocal) const {
+  SDLoc DL(N);
+  EVT Ty = getPointerTy(DAG.getDataLayout());
+  SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
+  // TODO: Check CodeModel.
+  if (IsLocal)
+    // This generates the pattern (PseudoLA_PCREL sym), which expands to
+    // (addi.w/d (pcalau12i %pc_hi20(sym)) %pc_lo12(sym)).
+    return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_PCREL, DL, Ty, Addr),
+                   0);
+
+  // This generates the pattern (PseudoLA_GOT sym), which expands to (ld.w/d
+  // (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).
+  return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_GOT, DL, Ty, Addr), 0);
+}
+
+SDValue LoongArchTargetLowering::lowerBlockAddress(SDValue Op,
+                                                   SelectionDAG &DAG) const {
+  return getAddr(cast<BlockAddressSDNode>(Op), DAG);
+}
+
+SDValue LoongArchTargetLowering::lowerJumpTable(SDValue Op,
+                                                SelectionDAG &DAG) const {
+  return getAddr(cast<JumpTableSDNode>(Op), DAG);
+}
+
 SDValue LoongArchTargetLowering::lowerConstantPool(SDValue Op,
                                                    SelectionDAG &DAG) const {
-  SDLoc DL(Op);
-  EVT Ty = Op.getValueType();
-  ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
-
-  // FIXME: Only support PC-relative addressing to access the symbol.
-  // Target flags will be added later.
-  if (!isPositionIndependent()) {
-    SDValue ConstantN = DAG.getTargetConstantPool(
-        N->getConstVal(), Ty, N->getAlign(), N->getOffset());
-    SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, ConstantN),
-                   0);
-    SDValue Addr(DAG.getMachineNode(Subtarget.is64Bit() ? LoongArch::ADDI_D
-                                                        : LoongArch::ADDI_W,
-                                    DL, Ty, AddrHi, ConstantN),
-                 0);
-    return Addr;
-  }
-  report_fatal_error("Unable to lower ConstantPool");
+  return getAddr(cast<ConstantPoolSDNode>(Op), DAG);
 }
 
 SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,
                                                     SelectionDAG &DAG) const {
-  SDLoc DL(Op);
-  EVT Ty = getPointerTy(DAG.getDataLayout());
-  const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
-  unsigned ADDIOp = Subtarget.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
-
-  // TODO: Support dso_preemptable and target flags.
-  if (GV->isDSOLocal()) {
-    SDValue GAHi =
-        DAG.getTargetGlobalAddress(GV, DL, Ty, 0, LoongArchII::MO_PCREL_HI);
-    SDValue GALo =
-        DAG.getTargetGlobalAddress(GV, DL, Ty, 0, LoongArchII::MO_PCREL_LO);
-    SDValue AddrHi(DAG.getMachineNode(LoongArch::PCALAU12I, DL, Ty, GAHi), 0);
-
-    return SDValue(DAG.getMachineNode(ADDIOp, DL, Ty, AddrHi, GALo), 0);
-  }
-  report_fatal_error("Unable to lowerGlobalAddress");
+  GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
+  assert(N->getOffset() == 0 && "unexpected offset in global node");
+  return getAddr(N, DAG, N->getGlobal()->isDSOLocal());
 }
 
 SDValue LoongArchTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index fa70ae450fa1d..714c6398d3a91 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -130,7 +130,11 @@ class LoongArchTargetLowering : public TargetLowering {
                          bool IsRet, CallLoweringInfo *CLI,
                          LoongArchCCAssignFn Fn) const;
 
+  template <class NodeTy>
+  SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const;
   SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
 

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 6b802a410a58d..a90fb8960a8c1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -919,6 +919,12 @@ let isBarrier = 1, isReturn = 1, isTerminator = 1 in
 def PseudoRET : Pseudo<(outs), (ins), [(loongarch_ret)]>,
                 PseudoInstExpansion<(JIRL R0, R1, 0)>;
 
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in
+def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins grlenimm:$src), []>;
+
 /// BSTRINS and BSTRPICK
 
 let Predicates = [IsLA32] in {

diff  --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index 68b42956b697a..af17ffc759886 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -47,6 +47,12 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
   case LoongArchII::MO_PCREL_LO:
     Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
     break;
+  case LoongArchII::MO_GOT_PC_HI:
+    Kind = LoongArchMCExpr::VK_LoongArch_GOT_HI20;
+    break;
+  case LoongArchII::MO_GOT_PC_LO:
+    Kind = LoongArchMCExpr::VK_LoongArch_GOT_LO12;
+    break;
     // TODO: Handle more target-flags.
   }
 
@@ -94,9 +100,12 @@ bool llvm::lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
     MCOp = lowerSymbolOperand(
         MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);
     break;
-  // TODO: lower special operands
   case MachineOperand::MO_BlockAddress:
+    MCOp = lowerSymbolOperand(
+        MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP);
+    break;
   case MachineOperand::MO_JumpTableIndex:
+    MCOp = lowerSymbolOperand(MO, AP.GetJTISymbol(MO.getIndex()), AP);
     break;
   }
   return true;

diff  --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
index 7f45c7ae1cd19..ee6f585cec9d1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
@@ -27,6 +27,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
   // Register the target.
   RegisterTargetMachine<LoongArchTargetMachine> X(getTheLoongArch32Target());
   RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
+  auto *PR = PassRegistry::getPassRegistry();
+  initializeLoongArchPreRAExpandPseudoPass(*PR);
 }
 
 static std::string computeDataLayout(const Triple &TT) {
@@ -103,6 +105,7 @@ class LoongArchPassConfig : public TargetPassConfig {
   void addIRPasses() override;
   bool addInstSelector() override;
   void addPreEmitPass2() override;
+  void addPreRegAlloc() override;
 };
 } // end namespace
 
@@ -129,3 +132,7 @@ void LoongArchPassConfig::addPreEmitPass2() {
   // forward progress in the LL/SC block.
   addPass(createLoongArchExpandAtomicPseudoPass());
 }
+
+void LoongArchPassConfig::addPreRegAlloc() {
+  addPass(createLoongArchPreRAExpandPseudoPass());
+}

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
index 72afab3ec3051..77938b997ec01 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h
@@ -31,6 +31,8 @@ enum {
   MO_CALL_PLT,
   MO_PCREL_HI,
   MO_PCREL_LO,
+  MO_GOT_PC_HI,
+  MO_GOT_PC_LO,
   // TODO: Add more flags.
 };
 } // end namespace LoongArchII

diff  --git a/llvm/test/CodeGen/LoongArch/block-address.ll b/llvm/test/CodeGen/LoongArch/block-address.ll
new file mode 100644
index 0000000000000..63d310dd9beab
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/block-address.ll
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64
+
+ at addr = dso_local global ptr null
+
+define void @test_blockaddress() nounwind {
+; LA32-LABEL: test_blockaddress:
+; LA32:       # %bb.0:
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(addr)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(addr)
+; LA32-NEXT:    pcalau12i $a1, %pc_hi20(.Ltmp0)
+; LA32-NEXT:    addi.w $a1, $a1, %pc_lo12(.Ltmp0)
+; LA32-NEXT:    st.w $a1, $a0, 0
+; LA32-NEXT:    ld.w $a0, $a0, 0
+; LA32-NEXT:    jr $a0
+; LA32-NEXT:  .Ltmp0: # Block address taken
+; LA32-NEXT:  .LBB0_1: # %block
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_blockaddress:
+; LA64:       # %bb.0:
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(addr)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(addr)
+; LA64-NEXT:    pcalau12i $a1, %pc_hi20(.Ltmp0)
+; LA64-NEXT:    addi.d $a1, $a1, %pc_lo12(.Ltmp0)
+; LA64-NEXT:    st.d $a1, $a0, 0
+; LA64-NEXT:    ld.d $a0, $a0, 0
+; LA64-NEXT:    jr $a0
+; LA64-NEXT:  .Ltmp0: # Block address taken
+; LA64-NEXT:  .LBB0_1: # %block
+; LA64-NEXT:    ret
+  store volatile ptr blockaddress(@test_blockaddress, %block), ptr @addr
+  %val = load volatile ptr, ptr @addr
+  indirectbr ptr %val, [label %block]
+
+block:
+  ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll b/llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll
index 28f571e5c6289..ae2ce72914399 100644
--- a/llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll
+++ b/llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll
@@ -462,30 +462,30 @@ define i64 @caller_double_in_gpr_exhausted_fprs() nounwind {
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    addi.d $sp, $sp, -16
 ; CHECK-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
-; CHECK-NEXT:    pcalau12i $a0, .LCPI21_0
-; CHECK-NEXT:    addi.d $a0, $a0, .LCPI21_0
-; CHECK-NEXT:    pcalau12i $a1, .LCPI21_1
-; CHECK-NEXT:    addi.d $a1, $a1, .LCPI21_1
-; CHECK-NEXT:    pcalau12i $a2, .LCPI21_2
-; CHECK-NEXT:    addi.d $a2, $a2, .LCPI21_2
-; CHECK-NEXT:    pcalau12i $a3, .LCPI21_3
-; CHECK-NEXT:    addi.d $a3, $a3, .LCPI21_3
-; CHECK-NEXT:    pcalau12i $a4, .LCPI21_4
-; CHECK-NEXT:    addi.d $a4, $a4, .LCPI21_4
-; CHECK-NEXT:    pcalau12i $a5, .LCPI21_5
-; CHECK-NEXT:    addi.d $a5, $a5, .LCPI21_5
-; CHECK-NEXT:    addi.d $a6, $zero, 1
-; CHECK-NEXT:    movgr2fr.d $fa0, $a6
-; CHECK-NEXT:    ffint.d.l $fa0, $fa0
-; CHECK-NEXT:    fld.d $fa1, $a5, 0
-; CHECK-NEXT:    fld.d $fa2, $a4, 0
-; CHECK-NEXT:    fld.d $fa3, $a3, 0
-; CHECK-NEXT:    fld.d $fa4, $a2, 0
-; CHECK-NEXT:    fld.d $fa5, $a1, 0
+; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI21_0)
+; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI21_0)
+; CHECK-NEXT:    fld.d $fa1, $a0, 0
+; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI21_1)
+; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI21_1)
+; CHECK-NEXT:    fld.d $fa2, $a0, 0
+; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI21_2)
+; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI21_2)
+; CHECK-NEXT:    fld.d $fa3, $a0, 0
+; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI21_3)
+; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI21_3)
+; CHECK-NEXT:    fld.d $fa4, $a0, 0
+; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI21_4)
+; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI21_4)
+; CHECK-NEXT:    fld.d $fa5, $a0, 0
+; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI21_5)
+; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI21_5)
 ; CHECK-NEXT:    fld.d $fa6, $a0, 0
-; CHECK-NEXT:    pcalau12i $a0, .LCPI21_6
-; CHECK-NEXT:    addi.d $a0, $a0, .LCPI21_6
+; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI21_6)
+; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI21_6)
 ; CHECK-NEXT:    fld.d $fa7, $a0, 0
+; CHECK-NEXT:    addi.d $a0, $zero, 1
+; CHECK-NEXT:    movgr2fr.d $fa0, $a0
+; CHECK-NEXT:    ffint.d.l $fa0, $fa0
 ; CHECK-NEXT:    ori $a0, $zero, 0
 ; CHECK-NEXT:    lu32i.d $a0, 131072
 ; CHECK-NEXT:    lu52i.d $a0, $a0, 1026

diff  --git a/llvm/test/CodeGen/LoongArch/double-imm.ll b/llvm/test/CodeGen/LoongArch/double-imm.ll
index f21deb0c00389..3e89db3ec5c8c 100644
--- a/llvm/test/CodeGen/LoongArch/double-imm.ll
+++ b/llvm/test/CodeGen/LoongArch/double-imm.ll
@@ -35,15 +35,15 @@ define double @f64_negative_zero() nounwind {
 define double @f64_constant_pi() nounwind {
 ; LA32-LABEL: f64_constant_pi:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    pcalau12i $a0, .LCPI2_0
-; LA32-NEXT:    addi.w $a0, $a0, .LCPI2_0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI2_0)
 ; LA32-NEXT:    fld.d $fa0, $a0, 0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: f64_constant_pi:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    pcalau12i $a0, .LCPI2_0
-; LA64-NEXT:    addi.d $a0, $a0, .LCPI2_0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI2_0)
 ; LA64-NEXT:    fld.d $fa0, $a0, 0
 ; LA64-NEXT:    ret
   ret double 3.1415926535897931159979634685441851615905761718750

diff  --git a/llvm/test/CodeGen/LoongArch/float-imm.ll b/llvm/test/CodeGen/LoongArch/float-imm.ll
index d9c184571caab..e2cbf4bf9b3e8 100644
--- a/llvm/test/CodeGen/LoongArch/float-imm.ll
+++ b/llvm/test/CodeGen/LoongArch/float-imm.ll
@@ -33,15 +33,15 @@ define float @f32_negative_zero() nounwind {
 define float @f32_constant_pi() nounwind {
 ; LA32-LABEL: f32_constant_pi:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    pcalau12i $a0, .LCPI2_0
-; LA32-NEXT:    addi.w $a0, $a0, .LCPI2_0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI2_0)
 ; LA32-NEXT:    fld.s $fa0, $a0, 0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: f32_constant_pi:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    pcalau12i $a0, .LCPI2_0
-; LA64-NEXT:    addi.d $a0, $a0, .LCPI2_0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI2_0)
 ; LA64-NEXT:    fld.s $fa0, $a0, 0
 ; LA64-NEXT:    ret
   ret float 3.14159274101257324218750

diff  --git a/llvm/test/CodeGen/LoongArch/global-address.ll b/llvm/test/CodeGen/LoongArch/global-address.ll
new file mode 100644
index 0000000000000..56ab2ab27de32
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/global-address.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=loongarch32 --relocation-model=static < %s | FileCheck %s --check-prefix=LA32NOPIC
+; RUN: llc --mtriple=loongarch32 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA32PIC
+; RUN: llc --mtriple=loongarch64 --relocation-model=static < %s | FileCheck %s --check-prefix=LA64NOPIC
+; RUN: llc --mtriple=loongarch64 --relocation-model=pic < %s | FileCheck %s --check-prefix=LA64PIC
+
+ at g = dso_local global i32 zeroinitializer, align 4
+ at G = global i32 zeroinitializer, align 4
+
+define void @foo() nounwind {
+; LA32NOPIC-LABEL: foo:
+; LA32NOPIC:       # %bb.0:
+; LA32NOPIC-NEXT:    pcalau12i $a0, %got_hi20(G)
+; LA32NOPIC-NEXT:    ld.w $a0, $a0, %got_lo12(G)
+; LA32NOPIC-NEXT:    ld.w $a0, $a0, 0
+; LA32NOPIC-NEXT:    pcalau12i $a0, %pc_hi20(g)
+; LA32NOPIC-NEXT:    addi.w $a0, $a0, %pc_lo12(g)
+; LA32NOPIC-NEXT:    ld.w $a0, $a0, 0
+; LA32NOPIC-NEXT:    ret
+;
+; LA32PIC-LABEL: foo:
+; LA32PIC:       # %bb.0:
+; LA32PIC-NEXT:    pcalau12i $a0, %got_hi20(G)
+; LA32PIC-NEXT:    ld.w $a0, $a0, %got_lo12(G)
+; LA32PIC-NEXT:    ld.w $a0, $a0, 0
+; LA32PIC-NEXT:    pcalau12i $a0, %pc_hi20(.Lg$local)
+; LA32PIC-NEXT:    addi.w $a0, $a0, %pc_lo12(.Lg$local)
+; LA32PIC-NEXT:    ld.w $a0, $a0, 0
+; LA32PIC-NEXT:    ret
+;
+; LA64NOPIC-LABEL: foo:
+; LA64NOPIC:       # %bb.0:
+; LA64NOPIC-NEXT:    pcalau12i $a0, %got_hi20(G)
+; LA64NOPIC-NEXT:    ld.d $a0, $a0, %got_lo12(G)
+; LA64NOPIC-NEXT:    ld.w $a0, $a0, 0
+; LA64NOPIC-NEXT:    pcalau12i $a0, %pc_hi20(g)
+; LA64NOPIC-NEXT:    addi.d $a0, $a0, %pc_lo12(g)
+; LA64NOPIC-NEXT:    ld.w $a0, $a0, 0
+; LA64NOPIC-NEXT:    ret
+;
+; LA64PIC-LABEL: foo:
+; LA64PIC:       # %bb.0:
+; LA64PIC-NEXT:    pcalau12i $a0, %got_hi20(G)
+; LA64PIC-NEXT:    ld.d $a0, $a0, %got_lo12(G)
+; LA64PIC-NEXT:    ld.w $a0, $a0, 0
+; LA64PIC-NEXT:    pcalau12i $a0, %pc_hi20(.Lg$local)
+; LA64PIC-NEXT:    addi.d $a0, $a0, %pc_lo12(.Lg$local)
+; LA64PIC-NEXT:    ld.w $a0, $a0, 0
+; LA64PIC-NEXT:    ret
+  %V = load volatile i32, ptr @G
+  %v = load volatile i32, ptr @g
+  ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
index eaa3feba36205..070027b698436 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
@@ -116,8 +116,8 @@ define i32 @convert_double_to_i32(double %a) nounwind {
 define i32 @convert_double_to_u32(double %a) nounwind {
 ; LA32-LABEL: convert_double_to_u32:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    pcalau12i $a0, .LCPI7_0
-; LA32-NEXT:    addi.w $a0, $a0, .LCPI7_0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI7_0)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI7_0)
 ; LA32-NEXT:    fld.d $fa1, $a0, 0
 ; LA32-NEXT:    fsub.d $fa2, $fa0, $fa1
 ; LA32-NEXT:    ftintrz.w.d $fa2, $fa2
@@ -173,8 +173,8 @@ define i64 @convert_double_to_u64(double %a) nounwind {
 ;
 ; LA64-LABEL: convert_double_to_u64:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    pcalau12i $a0, .LCPI9_0
-; LA64-NEXT:    addi.d $a0, $a0, .LCPI9_0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI9_0)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI9_0)
 ; LA64-NEXT:    fld.d $fa1, $a0, 0
 ; LA64-NEXT:    fsub.d $fa2, $fa0, $fa1
 ; LA64-NEXT:    ftintrz.l.d $fa2, $fa2
@@ -232,8 +232,8 @@ define double @convert_u32_to_double(i32 %a) nounwind {
 ; LA32-NEXT:    lu12i.w $a1, 275200
 ; LA32-NEXT:    st.w $a1, $sp, 12
 ; LA32-NEXT:    st.w $a0, $sp, 8
-; LA32-NEXT:    pcalau12i $a0, .LCPI12_0
-; LA32-NEXT:    addi.w $a0, $a0, .LCPI12_0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI12_0)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI12_0)
 ; LA32-NEXT:    fld.d $fa0, $a0, 0
 ; LA32-NEXT:    fld.d $fa1, $sp, 8
 ; LA32-NEXT:    fsub.d $fa0, $fa1, $fa0
@@ -242,12 +242,12 @@ define double @convert_u32_to_double(i32 %a) nounwind {
 ;
 ; LA64-LABEL: convert_u32_to_double:
 ; LA64:       # %bb.0:
+; LA64-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI12_0)
+; LA64-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI12_0)
+; LA64-NEXT:    fld.d $fa0, $a1, 0
 ; LA64-NEXT:    lu52i.d $a1, $zero, 1107
-; LA64-NEXT:    movgr2fr.d $fa0, $a1
-; LA64-NEXT:    pcalau12i $a1, .LCPI12_0
-; LA64-NEXT:    addi.d $a1, $a1, .LCPI12_0
-; LA64-NEXT:    fld.d $fa1, $a1, 0
-; LA64-NEXT:    fsub.d $fa0, $fa0, $fa1
+; LA64-NEXT:    movgr2fr.d $fa1, $a1
+; LA64-NEXT:    fsub.d $fa0, $fa1, $fa0
 ; LA64-NEXT:    lu12i.w $a1, 275200
 ; LA64-NEXT:    bstrins.d $a0, $a1, 63, 32
 ; LA64-NEXT:    movgr2fr.d $fa1, $a0
@@ -273,8 +273,8 @@ define double @convert_u64_to_double(i64 %a) nounwind {
 ; LA64-NEXT:    lu52i.d $a2, $zero, 1107
 ; LA64-NEXT:    or $a1, $a1, $a2
 ; LA64-NEXT:    movgr2fr.d $fa0, $a1
-; LA64-NEXT:    pcalau12i $a1, .LCPI13_0
-; LA64-NEXT:    addi.d $a1, $a1, .LCPI13_0
+; LA64-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI13_0)
+; LA64-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI13_0)
 ; LA64-NEXT:    fld.d $fa1, $a1, 0
 ; LA64-NEXT:    fsub.d $fa0, $fa0, $fa1
 ; LA64-NEXT:    lu12i.w $a1, 275200

diff  --git a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
index 3661d709fb042..559206a4db5ac 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
@@ -181,8 +181,8 @@ define zeroext i16 @convert_float_to_u16(float %a) nounwind {
 define i32 @convert_float_to_u32(float %a) nounwind {
 ; LA32F-LABEL: convert_float_to_u32:
 ; LA32F:       # %bb.0:
-; LA32F-NEXT:    pcalau12i $a0, .LCPI6_0
-; LA32F-NEXT:    addi.w $a0, $a0, .LCPI6_0
+; LA32F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI6_0)
+; LA32F-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI6_0)
 ; LA32F-NEXT:    fld.s $fa1, $a0, 0
 ; LA32F-NEXT:    fsub.s $fa2, $fa0, $fa1
 ; LA32F-NEXT:    ftintrz.w.s $fa2, $fa2
@@ -200,8 +200,8 @@ define i32 @convert_float_to_u32(float %a) nounwind {
 ;
 ; LA32D-LABEL: convert_float_to_u32:
 ; LA32D:       # %bb.0:
-; LA32D-NEXT:    pcalau12i $a0, .LCPI6_0
-; LA32D-NEXT:    addi.w $a0, $a0, .LCPI6_0
+; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI6_0)
+; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI6_0)
 ; LA32D-NEXT:    fld.s $fa1, $a0, 0
 ; LA32D-NEXT:    fsub.s $fa2, $fa0, $fa1
 ; LA32D-NEXT:    ftintrz.w.s $fa2, $fa2
@@ -219,8 +219,8 @@ define i32 @convert_float_to_u32(float %a) nounwind {
 ;
 ; LA64F-LABEL: convert_float_to_u32:
 ; LA64F:       # %bb.0:
-; LA64F-NEXT:    pcalau12i $a0, .LCPI6_0
-; LA64F-NEXT:    addi.d $a0, $a0, .LCPI6_0
+; LA64F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI6_0)
+; LA64F-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI6_0)
 ; LA64F-NEXT:    fld.s $fa1, $a0, 0
 ; LA64F-NEXT:    fsub.s $fa2, $fa0, $fa1
 ; LA64F-NEXT:    ftintrz.w.s $fa2, $fa2
@@ -266,8 +266,8 @@ define i64 @convert_float_to_u64(float %a) nounwind {
 ;
 ; LA64F-LABEL: convert_float_to_u64:
 ; LA64F:       # %bb.0:
-; LA64F-NEXT:    pcalau12i $a0, .LCPI7_0
-; LA64F-NEXT:    addi.d $a0, $a0, .LCPI7_0
+; LA64F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI7_0)
+; LA64F-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI7_0)
 ; LA64F-NEXT:    fld.s $fa1, $a0, 0
 ; LA64F-NEXT:    fsub.s $fa2, $fa0, $fa1
 ; LA64F-NEXT:    ftintrz.w.s $fa2, $fa2
@@ -285,8 +285,8 @@ define i64 @convert_float_to_u64(float %a) nounwind {
 ;
 ; LA64D-LABEL: convert_float_to_u64:
 ; LA64D:       # %bb.0:
-; LA64D-NEXT:    pcalau12i $a0, .LCPI7_0
-; LA64D-NEXT:    addi.d $a0, $a0, .LCPI7_0
+; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI7_0)
+; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI7_0)
 ; LA64D-NEXT:    fld.s $fa1, $a0, 0
 ; LA64D-NEXT:    fsub.s $fa2, $fa0, $fa1
 ; LA64D-NEXT:    ftintrz.l.s $fa2, $fa2
@@ -503,8 +503,8 @@ define float @convert_u32_to_float(i32 %a) nounwind {
 ; LA32D-NEXT:    lu12i.w $a1, 275200
 ; LA32D-NEXT:    st.w $a1, $sp, 12
 ; LA32D-NEXT:    st.w $a0, $sp, 8
-; LA32D-NEXT:    pcalau12i $a0, .LCPI14_0
-; LA32D-NEXT:    addi.w $a0, $a0, .LCPI14_0
+; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI14_0)
+; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI14_0)
 ; LA32D-NEXT:    fld.d $fa0, $a0, 0
 ; LA32D-NEXT:    fld.d $fa1, $sp, 8
 ; LA32D-NEXT:    fsub.d $fa0, $fa1, $fa0

diff  --git a/llvm/test/CodeGen/LoongArch/jump-table.ll b/llvm/test/CodeGen/LoongArch/jump-table.ll
index db0fb059df271..fb75ce2eb912f 100644
--- a/llvm/test/CodeGen/LoongArch/jump-table.ll
+++ b/llvm/test/CodeGen/LoongArch/jump-table.ll
@@ -1,8 +1,17 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s \
+; RUN: llc --mtriple=loongarch32 --min-jump-table-entries=5 < %s \
 ; RUN:   | FileCheck %s --check-prefix=LA32
-; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s \
+; RUN: llc --mtriple=loongarch64 --min-jump-table-entries=5 < %s \
 ; RUN:   | FileCheck %s --check-prefix=LA64
+; RUN: llc --mtriple=loongarch32 --min-jump-table-entries=4 < %s \
+; RUN:   | FileCheck %s --check-prefix=LA32-JT
+; RUN: llc --mtriple=loongarch64 --min-jump-table-entries=4 < %s \
+; RUN:   | FileCheck %s --check-prefix=LA64-JT
+
+;; The default mininum number of entries to use a jump table is 4.
+;;
+;; Note: The parameter `--min-jump-table-entries` will have no effect once we
+;; have set the default value using `setMinimumJumpTableEntries`.
 
 define void @switch_4_arms(i32 %in, ptr %out) nounwind {
 ; LA32-LABEL: switch_4_arms:
@@ -69,6 +78,55 @@ define void @switch_4_arms(i32 %in, ptr %out) nounwind {
 ; LA64-NEXT:    st.w $a2, $a1, 0
 ; LA64-NEXT:  .LBB0_10: # %exit
 ; LA64-NEXT:    ret
+;
+; LA32-JT-LABEL: switch_4_arms:
+; LA32-JT:       # %bb.0: # %entry
+; LA32-JT-NEXT:    addi.w $a2, $a0, -1
+; LA32-JT-NEXT:    ori $a0, $zero, 3
+; LA32-JT-NEXT:    bltu $a0, $a2, .LBB0_6
+; LA32-JT-NEXT:  # %bb.1: # %entry
+; LA32-JT-NEXT:    pcalau12i $a3, %pc_hi20(.LJTI0_0)
+; LA32-JT-NEXT:    addi.w $a3, $a3, %pc_lo12(.LJTI0_0)
+; LA32-JT-NEXT:    alsl.w $a2, $a2, $a3, 2
+; LA32-JT-NEXT:    ld.w $a2, $a2, 0
+; LA32-JT-NEXT:    jr $a2
+; LA32-JT-NEXT:  .LBB0_2: # %bb1
+; LA32-JT-NEXT:    ori $a0, $zero, 4
+; LA32-JT-NEXT:    b .LBB0_5
+; LA32-JT-NEXT:  .LBB0_3: # %bb3
+; LA32-JT-NEXT:    ori $a0, $zero, 2
+; LA32-JT-NEXT:    b .LBB0_5
+; LA32-JT-NEXT:  .LBB0_4: # %bb4
+; LA32-JT-NEXT:    ori $a0, $zero, 1
+; LA32-JT-NEXT:  .LBB0_5: # %exit
+; LA32-JT-NEXT:    st.w $a0, $a1, 0
+; LA32-JT-NEXT:  .LBB0_6: # %exit
+; LA32-JT-NEXT:    ret
+;
+; LA64-JT-LABEL: switch_4_arms:
+; LA64-JT:       # %bb.0: # %entry
+; LA64-JT-NEXT:    bstrpick.d $a0, $a0, 31, 0
+; LA64-JT-NEXT:    addi.d $a2, $a0, -1
+; LA64-JT-NEXT:    ori $a0, $zero, 3
+; LA64-JT-NEXT:    bltu $a0, $a2, .LBB0_6
+; LA64-JT-NEXT:  # %bb.1: # %entry
+; LA64-JT-NEXT:    slli.d $a2, $a2, 3
+; LA64-JT-NEXT:    pcalau12i $a3, %pc_hi20(.LJTI0_0)
+; LA64-JT-NEXT:    addi.d $a3, $a3, %pc_lo12(.LJTI0_0)
+; LA64-JT-NEXT:    ldx.d $a2, $a2, $a3
+; LA64-JT-NEXT:    jr $a2
+; LA64-JT-NEXT:  .LBB0_2: # %bb1
+; LA64-JT-NEXT:    ori $a0, $zero, 4
+; LA64-JT-NEXT:    b .LBB0_5
+; LA64-JT-NEXT:  .LBB0_3: # %bb3
+; LA64-JT-NEXT:    ori $a0, $zero, 2
+; LA64-JT-NEXT:    b .LBB0_5
+; LA64-JT-NEXT:  .LBB0_4: # %bb4
+; LA64-JT-NEXT:    ori $a0, $zero, 1
+; LA64-JT-NEXT:  .LBB0_5: # %exit
+; LA64-JT-NEXT:    st.w $a0, $a1, 0
+; LA64-JT-NEXT:  .LBB0_6: # %exit
+; LA64-JT-NEXT:    ret
 entry:
   switch i32 %in, label %exit [
     i32 1, label %bb1


        


More information about the llvm-commits mailing list