[llvm] [LoongArch] Add machine function pass to merge base + offset (PR #101139)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 7 23:07:43 PDT 2024


https://github.com/heiher updated https://github.com/llvm/llvm-project/pull/101139

>From da73216f364b591d6f82d7b24878a4e67aa0f600 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Sat, 27 Jul 2024 11:41:52 +0800
Subject: [PATCH 1/2] [LoongArch] Add machine function pass to merge base +
 offset

This commit references RISC-V to add a machine function pass to merge the base
address and offset.
---
 llvm/lib/Target/LoongArch/CMakeLists.txt      |   1 +
 llvm/lib/Target/LoongArch/LoongArch.h         |   2 +
 .../Target/LoongArch/LoongArchAsmPrinter.cpp  |   6 +
 .../LoongArch/LoongArchMergeBaseOffset.cpp    | 633 ++++++++++++++++++
 .../LoongArch/LoongArchTargetMachine.cpp      |   3 +
 llvm/test/CodeGen/LoongArch/block-address.ll  |  10 +-
 .../CodeGen/LoongArch/calling-conv-lp64d.ll   |  21 +-
 llvm/test/CodeGen/LoongArch/double-imm.ll     |   6 +-
 llvm/test/CodeGen/LoongArch/float-imm.ll      |   6 +-
 llvm/test/CodeGen/LoongArch/ghc-cc.ll         |  51 +-
 llvm/test/CodeGen/LoongArch/global-address.ll |  18 +-
 .../LoongArch/global-variable-code-model.ll   |   6 +-
 .../LoongArch/inline-asm-constraint-f.ll      |   6 +-
 .../LoongArch/inline-asm-constraint-m.ll      |  10 +-
 .../LoongArch/ir-instruction/atomicrmw-fp.ll  |  45 +-
 .../ir-instruction/double-convert.ll          |  12 +-
 .../LoongArch/ir-instruction/float-convert.ll |  18 +-
 .../LoongArch/ir-instruction/load-store.ll    |  28 +-
 .../LoongArch/machinelicm-address-pseudos.ll  |  23 +-
 .../CodeGen/LoongArch/merge-base-offset.ll    | 435 +++++-------
 llvm/test/CodeGen/LoongArch/opt-pipeline.ll   |   1 +
 .../LoongArch/psabi-restricted-scheduling.ll  |  12 +-
 llvm/test/CodeGen/LoongArch/vector-fp-imm.ll  | 126 ++--
 ...arch_generated_funcs.ll.generated.expected |   3 +-
 ...ch_generated_funcs.ll.nogenerated.expected |   3 +-
 .../llvm/lib/Target/LoongArch/BUILD.gn        |   1 +
 26 files changed, 951 insertions(+), 535 deletions(-)
 create mode 100644 llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp

diff --git a/llvm/lib/Target/LoongArch/CMakeLists.txt b/llvm/lib/Target/LoongArch/CMakeLists.txt
index cadc335a621f2e..0f674b1b0fa9e2 100644
--- a/llvm/lib/Target/LoongArch/CMakeLists.txt
+++ b/llvm/lib/Target/LoongArch/CMakeLists.txt
@@ -24,6 +24,7 @@ add_llvm_target(LoongArchCodeGen
   LoongArchISelDAGToDAG.cpp
   LoongArchISelLowering.cpp
   LoongArchMCInstLower.cpp
+  LoongArchMergeBaseOffset.cpp
   LoongArchOptWInstrs.cpp
   LoongArchRegisterInfo.cpp
   LoongArchSubtarget.cpp
diff --git a/llvm/lib/Target/LoongArch/LoongArch.h b/llvm/lib/Target/LoongArch/LoongArch.h
index adfb844ee31b64..db605237388809 100644
--- a/llvm/lib/Target/LoongArch/LoongArch.h
+++ b/llvm/lib/Target/LoongArch/LoongArch.h
@@ -36,12 +36,14 @@ bool lowerLoongArchMachineOperandToMCOperand(const MachineOperand &MO,
 FunctionPass *createLoongArchDeadRegisterDefinitionsPass();
 FunctionPass *createLoongArchExpandAtomicPseudoPass();
 FunctionPass *createLoongArchISelDag(LoongArchTargetMachine &TM);
+FunctionPass *createLoongArchMergeBaseOffsetOptPass();
 FunctionPass *createLoongArchOptWInstrsPass();
 FunctionPass *createLoongArchPreRAExpandPseudoPass();
 FunctionPass *createLoongArchExpandPseudoPass();
 void initializeLoongArchDAGToDAGISelLegacyPass(PassRegistry &);
 void initializeLoongArchDeadRegisterDefinitionsPass(PassRegistry &);
 void initializeLoongArchExpandAtomicPseudoPass(PassRegistry &);
+void initializeLoongArchMergeBaseOffsetOptPass(PassRegistry &);
 void initializeLoongArchOptWInstrsPass(PassRegistry &);
 void initializeLoongArchPreRAExpandPseudoPass(PassRegistry &);
 void initializeLoongArchExpandPseudoPass(PassRegistry &);
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
index f478870217ec60..8bb9497a847fa7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
@@ -130,10 +130,16 @@ bool LoongArchAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
   OS << "$" << LoongArchInstPrinter::getRegisterName(BaseMO.getReg());
   // Print the offset operand.
   const MachineOperand &OffsetMO = MI->getOperand(OpNo + 1);
+  MCOperand MCO;
+  if (!lowerOperand(OffsetMO, MCO))
+    return true;
   if (OffsetMO.isReg())
     OS << ", $" << LoongArchInstPrinter::getRegisterName(OffsetMO.getReg());
   else if (OffsetMO.isImm())
     OS << ", " << OffsetMO.getImm();
+  else if (OffsetMO.isGlobal() || OffsetMO.isBlockAddress() ||
+           OffsetMO.isMCSymbol())
+    OS << ", " << *MCO.getExpr();
   else
     return true;
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp b/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp
new file mode 100644
index 00000000000000..4fbe31616a7efc
--- /dev/null
+++ b/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp
@@ -0,0 +1,633 @@
+//===---- LoongArchMergeBaseOffset.cpp - Optimise address calculations ----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Merge the offset of address calculation into the offset field
+// of instructions in a global address lowering sequence.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LoongArch.h"
+#include "LoongArchTargetMachine.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetOptions.h"
+#include <optional>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "loongarch-merge-base-offset"
+#define LoongArch_MERGE_BASE_OFFSET_NAME "LoongArch Merge Base Offset"
+
+namespace {
+
+class LoongArchMergeBaseOffsetOpt : public MachineFunctionPass {
+  const LoongArchSubtarget *ST = nullptr;
+  MachineRegisterInfo *MRI;
+
+public:
+  static char ID;
+  bool runOnMachineFunction(MachineFunction &Fn) override;
+  bool detectFoldable(MachineInstr &Hi20, MachineInstr *&Lo12,
+                      MachineInstr *&Lo20, MachineInstr *&Hi12,
+                      MachineInstr *&Last);
+
+  bool detectAndFoldOffset(MachineInstr &Hi20, MachineInstr &Lo12,
+                           MachineInstr *&Lo20, MachineInstr *&Hi12,
+                           MachineInstr *&Last);
+  void foldOffset(MachineInstr &Hi20, MachineInstr &Lo12, MachineInstr *&Lo20,
+                  MachineInstr *&Hi12, MachineInstr *&Last, MachineInstr &Tail,
+                  int64_t Offset);
+  bool foldLargeOffset(MachineInstr &Hi20, MachineInstr &Lo12,
+                       MachineInstr *&Lo20, MachineInstr *&Hi12,
+                       MachineInstr *&Last, MachineInstr &TailAdd,
+                       Register GAReg);
+
+  bool foldIntoMemoryOps(MachineInstr &Hi20, MachineInstr &Lo12,
+                         MachineInstr *&Lo20, MachineInstr *&Hi12,
+                         MachineInstr *&Last);
+
+  LoongArchMergeBaseOffsetOpt() : MachineFunctionPass(ID) {}
+
+  MachineFunctionProperties getRequiredProperties() const override {
+    return MachineFunctionProperties().set(
+        MachineFunctionProperties::Property::IsSSA);
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesCFG();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+
+  StringRef getPassName() const override {
+    return LoongArch_MERGE_BASE_OFFSET_NAME;
+  }
+};
+} // end anonymous namespace
+
+char LoongArchMergeBaseOffsetOpt::ID = 0;
+INITIALIZE_PASS(LoongArchMergeBaseOffsetOpt, DEBUG_TYPE,
+                LoongArch_MERGE_BASE_OFFSET_NAME, false, false)
+
+// Detect either of the patterns:
+//
+// 1. (small/medium):
+//   pcalau12i vreg1, %pc_hi20(s)
+//   addi.d    vreg2, vreg1, %pc_lo12(s)
+//
+// 2. (large):
+//   pcalau12i vreg1, %pc_hi20(s)
+//   addi.d    vreg2, $zero, %pc_lo12(s)
+//   lu32i.d   vreg3, vreg2, %pc64_lo20(s)
+//   lu52i.d   vreg4, vreg3, %pc64_hi12(s)
+//   add.d     vreg5, vreg4, vreg1
+
+// The pattern is only accepted if:
+//    1) For small and medium pattern, the first instruction has only one use,
+//       which is the ADDI.
+//    2) For large pattern, the first four instructions each have only one use,
+//       and the user of the fourth instruction is ADD.
+//    3) The address operands have the appropriate type, reflecting the
+//       lowering of a global address or constant pool using the pattern.
+//    4) The offset value in the Global Address or Constant Pool is 0.
+bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
+                                                 MachineInstr *&Lo12,
+                                                 MachineInstr *&Lo20,
+                                                 MachineInstr *&Hi12,
+                                                 MachineInstr *&Last) {
+  if (Hi20.getOpcode() != LoongArch::PCALAU12I)
+    return false;
+
+  const MachineOperand &Hi20Op1 = Hi20.getOperand(1);
+  if (Hi20Op1.getTargetFlags() != LoongArchII::MO_PCREL_HI)
+    return false;
+
+  if (!(Hi20Op1.isGlobal() || Hi20Op1.isCPI() || Hi20Op1.isBlockAddress()) ||
+      Hi20Op1.getOffset() != 0)
+    return false;
+
+  Register HiDestReg = Hi20.getOperand(0).getReg();
+  if (!MRI->hasOneUse(HiDestReg))
+    return false;
+
+  MachineInstr *UseInst = &*MRI->use_instr_begin(HiDestReg);
+  if (UseInst->getOpcode() != LoongArch::ADD_D) {
+    Lo12 = UseInst;
+    if ((ST->is64Bit() && Lo12->getOpcode() != LoongArch::ADDI_D) ||
+        (!ST->is64Bit() && Lo12->getOpcode() != LoongArch::ADDI_W))
+      return false;
+  } else {
+    assert(ST->is64Bit());
+    Last = UseInst;
+
+    Hi12 = MRI->getVRegDef(Last->getOperand(1).getReg());
+    const MachineOperand &Hi12Op2 = Hi12->getOperand(2);
+    if (Hi12Op2.getTargetFlags() != LoongArchII::MO_PCREL64_HI)
+      return false;
+    if (!(Hi12Op2.isGlobal() || Hi12Op2.isCPI() || Hi12Op2.isBlockAddress()) ||
+        Hi12Op2.getOffset() != 0)
+      return false;
+    if (!MRI->hasOneUse(Hi12->getOperand(0).getReg()))
+      return false;
+
+    Lo20 = MRI->getVRegDef(Hi12->getOperand(1).getReg());
+    const MachineOperand &Lo20Op2 = Lo20->getOperand(2);
+    if (Lo20Op2.getTargetFlags() != LoongArchII::MO_PCREL64_LO)
+      return false;
+    if (!(Lo20Op2.isGlobal() || Lo20Op2.isCPI() || Lo20Op2.isBlockAddress()) ||
+        Lo20Op2.getOffset() != 0)
+      return false;
+    if (!MRI->hasOneUse(Lo20->getOperand(0).getReg()))
+      return false;
+
+    Lo12 = MRI->getVRegDef(Lo20->getOperand(1).getReg());
+    if (!MRI->hasOneUse(Lo12->getOperand(0).getReg()))
+      return false;
+  }
+
+  const MachineOperand &Lo12Op2 = Lo12->getOperand(2);
+  assert(Hi20.getOpcode() == LoongArch::PCALAU12I);
+  if (Lo12Op2.getTargetFlags() != LoongArchII::MO_PCREL_LO ||
+      !(Lo12Op2.isGlobal() || Lo12Op2.isCPI() || Lo12Op2.isBlockAddress() ||
+        Lo12Op2.isMCSymbol()) ||
+      Lo12Op2.getOffset() != 0)
+    return false;
+
+  if (Hi20Op1.isGlobal()) {
+    LLVM_DEBUG(dbgs() << "  Found lowered global address: "
+                      << *Hi20Op1.getGlobal() << "\n");
+  } else if (Hi20Op1.isBlockAddress()) {
+    LLVM_DEBUG(dbgs() << "  Found lowered basic address: "
+                      << *Hi20Op1.getBlockAddress() << "\n");
+  } else if (Hi20Op1.isCPI()) {
+    LLVM_DEBUG(dbgs() << "  Found lowered constant pool: " << Hi20Op1.getIndex()
+                      << "\n");
+  }
+
+  return true;
+}
+
+// Update the offset in Hi20, Lo12, Lo20 and Hi12 instructions.
+// Delete the tail instruction and update all the uses to use the
+// output from Last.
+void LoongArchMergeBaseOffsetOpt::foldOffset(
+    MachineInstr &Hi20, MachineInstr &Lo12, MachineInstr *&Lo20,
+    MachineInstr *&Hi12, MachineInstr *&Last, MachineInstr &Tail,
+    int64_t Offset) {
+  assert(isInt<32>(Offset) && "Unexpected offset");
+  // Put the offset back in Hi and the Lo
+  Hi20.getOperand(1).setOffset(Offset);
+  Lo12.getOperand(2).setOffset(Offset);
+  if (Lo20 && Hi12) {
+    Lo20->getOperand(2).setOffset(Offset);
+    Hi12->getOperand(2).setOffset(Offset);
+  }
+  // Delete the tail instruction.
+  MachineInstr *Def = Last ? Last : &Lo12;
+  MRI->constrainRegClass(Def->getOperand(0).getReg(),
+                         MRI->getRegClass(Tail.getOperand(0).getReg()));
+  MRI->replaceRegWith(Tail.getOperand(0).getReg(), Def->getOperand(0).getReg());
+  Tail.eraseFromParent();
+  LLVM_DEBUG(dbgs() << "  Merged offset " << Offset << " into base.\n"
+                    << "     " << Hi20 << "     " << Lo12;);
+  if (Lo20 && Hi12) {
+    LLVM_DEBUG(dbgs() << "     " << *Lo20 << "     " << *Hi12;);
+  }
+}
+
+// Detect patterns for large offsets that are passed into an ADD instruction.
+// If the pattern is found, updates the offset in Hi20, Lo12, Lo20 and Hi12
+// instructions and deletes TailAdd and the instructions that produced the
+// offset.
+//
+//                     Base address lowering is of the form:
+//                       Hi20:  pcalau12i vreg1, %pc_hi20(s)
+//                       Lo12:  addi.d vreg2, vreg1, %pc_lo12(s)
+//                       /                                  \
+//                      /                                    \
+//                     /                                      \
+//                    /  The large offset can be of two forms: \
+//  1) Offset that has non zero bits in lower      2) Offset that has non zero
+//     12 bits and upper 20 bits                      bits in upper 20 bits only
+//   OffsetHi: lu12i.w vreg3, 4
+//   OffsetLo: ori voff, vreg3, 188                 OffsetHi: lu12i.w voff, 128
+//                    \                                        /
+//                     \                                      /
+//                      \                                    /
+//                       \                                  /
+//                        TailAdd: add.d  vreg4, vreg2, voff
+bool LoongArchMergeBaseOffsetOpt::foldLargeOffset(
+    MachineInstr &Hi20, MachineInstr &Lo12, MachineInstr *&Lo20,
+    MachineInstr *&Hi12, MachineInstr *&Last, MachineInstr &TailAdd,
+    Register GAReg) {
+  assert((TailAdd.getOpcode() == LoongArch::ADD_W ||
+          TailAdd.getOpcode() == LoongArch::ADD_D) &&
+         "Expected ADD instruction!");
+  Register Rs = TailAdd.getOperand(1).getReg();
+  Register Rt = TailAdd.getOperand(2).getReg();
+  Register Reg = Rs == GAReg ? Rt : Rs;
+
+  // Can't fold if the register has more than one use.
+  if (!Reg.isVirtual() || !MRI->hasOneUse(Reg))
+    return false;
+  // This can point to an ORI or a LU12I.W:
+  MachineInstr &OffsetTail = *MRI->getVRegDef(Reg);
+  if (OffsetTail.getOpcode() == LoongArch::ORI) {
+    // The offset value has non zero bits in both %hi and %lo parts.
+    // Detect an ORI that feeds from a LU12I.W instruction.
+    MachineOperand &OriImmOp = OffsetTail.getOperand(2);
+    if (OriImmOp.getTargetFlags() != LoongArchII::MO_None)
+      return false;
+    Register OriReg = OffsetTail.getOperand(1).getReg();
+    int64_t OffLo = OriImmOp.getImm();
+
+    // Handle rs1 of ORI is R0.
+    if (OriReg == LoongArch::R0) {
+      LLVM_DEBUG(dbgs() << "  Offset Instrs: " << OffsetTail);
+      foldOffset(Hi20, Lo12, Lo20, Hi12, Last, TailAdd, OffLo);
+      OffsetTail.eraseFromParent();
+      return true;
+    }
+
+    MachineInstr &OffsetLu12i = *MRI->getVRegDef(OriReg);
+    MachineOperand &Lu12iImmOp = OffsetLu12i.getOperand(1);
+    if (OffsetLu12i.getOpcode() != LoongArch::LU12I_W ||
+        Lu12iImmOp.getTargetFlags() != LoongArchII::MO_None ||
+        !MRI->hasOneUse(OffsetLu12i.getOperand(0).getReg()))
+      return false;
+    int64_t Offset = SignExtend64<32>(Lu12iImmOp.getImm() << 12);
+    Offset += OffLo;
+    // LU12I.W+ORI sign extends the result.
+    Offset = SignExtend64<32>(Offset);
+    LLVM_DEBUG(dbgs() << "  Offset Instrs: " << OffsetTail
+                      << "                 " << OffsetLu12i);
+    foldOffset(Hi20, Lo12, Lo20, Hi12, Last, TailAdd, Offset);
+    OffsetTail.eraseFromParent();
+    OffsetLu12i.eraseFromParent();
+    return true;
+  } else if (OffsetTail.getOpcode() == LoongArch::LU12I_W) {
+    // The offset value has all zero bits in the lower 12 bits. Only LU12I.W
+    // exists.
+    LLVM_DEBUG(dbgs() << "  Offset Instr: " << OffsetTail);
+    int64_t Offset = SignExtend64<32>(OffsetTail.getOperand(1).getImm() << 12);
+    foldOffset(Hi20, Lo12, Lo20, Hi12, Last, TailAdd, Offset);
+    OffsetTail.eraseFromParent();
+    return true;
+  }
+  return false;
+}
+
+bool LoongArchMergeBaseOffsetOpt::detectAndFoldOffset(MachineInstr &Hi20,
+                                                      MachineInstr &Lo12,
+                                                      MachineInstr *&Lo20,
+                                                      MachineInstr *&Hi12,
+                                                      MachineInstr *&Last) {
+  Register DestReg =
+      Last ? Last->getOperand(0).getReg() : Lo12.getOperand(0).getReg();
+
+  // Look for arithmetic instructions we can get an offset from.
+  // We might be able to remove the arithmetic instructions by folding the
+  // offset into the PCALAU12I+(ADDI/ADDI+LU32I+LU52I).
+  if (!MRI->hasOneUse(DestReg))
+    return false;
+
+  // DestReg has only one use.
+  MachineInstr &Tail = *MRI->use_instr_begin(DestReg);
+  switch (Tail.getOpcode()) {
+  default:
+    LLVM_DEBUG(dbgs() << "Don't know how to get offset from this instr:"
+                      << Tail);
+    break;
+  case LoongArch::ADDI_W:
+    if (ST->is64Bit())
+      return false;
+    [[fallthrough]];
+  case LoongArch::ADDI_D:
+  case LoongArch::ADDU16I_D: {
+    // Offset is simply an immediate operand.
+    int64_t Offset = Tail.getOperand(2).getImm();
+    if (Tail.getOpcode() == LoongArch::ADDU16I_D)
+      Offset = SignExtend64<32>(Offset << 16);
+
+    // We might have two ADDIs in a row.
+    Register TailDestReg = Tail.getOperand(0).getReg();
+    if (MRI->hasOneUse(TailDestReg)) {
+      MachineInstr &TailTail = *MRI->use_instr_begin(TailDestReg);
+      if (ST->is64Bit() && TailTail.getOpcode() == LoongArch::ADDI_W)
+        return false;
+      if (TailTail.getOpcode() == LoongArch::ADDI_W ||
+          TailTail.getOpcode() == LoongArch::ADDI_D) {
+        Offset += TailTail.getOperand(2).getImm();
+        LLVM_DEBUG(dbgs() << "  Offset Instrs: " << Tail << TailTail);
+        foldOffset(Hi20, Lo12, Lo20, Hi12, Last, TailTail, Offset);
+        Tail.eraseFromParent();
+        return true;
+      }
+    }
+
+    LLVM_DEBUG(dbgs() << "  Offset Instr: " << Tail);
+    foldOffset(Hi20, Lo12, Lo20, Hi12, Last, Tail, Offset);
+    return true;
+  }
+  case LoongArch::ADD_W:
+    if (ST->is64Bit())
+      return false;
+    [[fallthrough]];
+  case LoongArch::ADD_D:
+    // The offset is too large to fit in the immediate field of ADDI.
+    // This can be in two forms:
+    // 1) LU12I.W hi_offset followed by:
+    //    ORI lo_offset
+    //    This happens in case the offset has non zero bits in
+    //    both hi 20 and lo 12 bits.
+    // 2) LU12I.W (offset20)
+    //    This happens in case the lower 12 bits of the offset are zeros.
+    return foldLargeOffset(Hi20, Lo12, Lo20, Hi12, Last, Tail, DestReg);
+    break;
+  }
+
+  return false;
+}
+
+// Memory access opcode mapping for transforms.
+static unsigned getNewOpc(unsigned Op, bool isLarge) {
+  switch (Op) {
+  case LoongArch::LD_B:
+    return isLarge ? LoongArch::LDX_B : LoongArch::LD_B;
+  case LoongArch::LD_H:
+    return isLarge ? LoongArch::LDX_H : LoongArch::LD_H;
+  case LoongArch::LD_W:
+  case LoongArch::LDPTR_W:
+    return isLarge ? LoongArch::LDX_W : LoongArch::LD_W;
+  case LoongArch::LD_D:
+  case LoongArch::LDPTR_D:
+    return isLarge ? LoongArch::LDX_D : LoongArch::LD_D;
+  case LoongArch::LD_BU:
+    return isLarge ? LoongArch::LDX_BU : LoongArch::LD_BU;
+  case LoongArch::LD_HU:
+    return isLarge ? LoongArch::LDX_HU : LoongArch::LD_HU;
+  case LoongArch::LD_WU:
+    return isLarge ? LoongArch::LDX_WU : LoongArch::LD_WU;
+  case LoongArch::FLD_S:
+    return isLarge ? LoongArch::FLDX_S : LoongArch::FLD_S;
+  case LoongArch::FLD_D:
+    return isLarge ? LoongArch::FLDX_D : LoongArch::FLD_D;
+  case LoongArch::ST_B:
+    return isLarge ? LoongArch::STX_B : LoongArch::ST_B;
+  case LoongArch::ST_H:
+    return isLarge ? LoongArch::STX_H : LoongArch::ST_H;
+  case LoongArch::ST_W:
+  case LoongArch::STPTR_W:
+    return isLarge ? LoongArch::STX_W : LoongArch::ST_W;
+  case LoongArch::ST_D:
+  case LoongArch::STPTR_D:
+    return isLarge ? LoongArch::STX_D : LoongArch::ST_D;
+  case LoongArch::FST_S:
+    return isLarge ? LoongArch::FSTX_S : LoongArch::FST_S;
+  case LoongArch::FST_D:
+    return isLarge ? LoongArch::FSTX_D : LoongArch::FST_D;
+  default:
+    llvm_unreachable("Unexpected opcode for replacement");
+  }
+}
+
+bool LoongArchMergeBaseOffsetOpt::foldIntoMemoryOps(MachineInstr &Hi20,
+                                                    MachineInstr &Lo12,
+                                                    MachineInstr *&Lo20,
+                                                    MachineInstr *&Hi12,
+                                                    MachineInstr *&Last) {
+  Register DestReg =
+      Last ? Last->getOperand(0).getReg() : Lo12.getOperand(0).getReg();
+
+  // If all the uses are memory ops with the same offset, we can transform:
+  //
+  // 1. (small/medium):
+  //   pcalau12i vreg1, %pc_hi20(s)
+  //   addi.d    vreg2, vreg1, %pc_lo12(s)
+  //   ld.w      vreg3, 8(vreg2)
+  //
+  //   =>
+  //
+  //   pcalau12i vreg1, %pc_hi20(s+8)
+  //   ld.w      vreg3, vreg1, %pc_lo12(s+8)(vreg1)
+  //
+  // 2. (large):
+  //   pcalau12i vreg1, %pc_hi20(s)
+  //   addi.d    vreg2, $zero, %pc_lo12(s)
+  //   lu32i.d   vreg3, vreg2, %pc64_lo20(s)
+  //   lu52i.d   vreg4, vreg3, %pc64_hi12(s)
+  //   add.d     vreg5, vreg4, vreg1
+  //   ld.w      vreg6, 8(vreg5)
+  //
+  //   =>
+  //
+  //   pcalau12i vreg1, %pc_hi20(s+8)
+  //   addi.d    vreg2, $zero, %pc_lo12(s+8)
+  //   lu32i.d   vreg3, vreg2, %pc64_lo20(s+8)
+  //   lu52i.d   vreg4, vreg3, %pc64_hi12(s+8)
+  //   ldx.w     vreg6, vreg4, vreg1
+
+  std::optional<int64_t> CommonOffset;
+  DenseMap<const MachineInstr *, SmallVector<unsigned>>
+      InlineAsmMemoryOpIndexesMap;
+  for (const MachineInstr &UseMI : MRI->use_instructions(DestReg)) {
+    switch (UseMI.getOpcode()) {
+    default:
+      LLVM_DEBUG(dbgs() << "Not a load or store instruction: " << UseMI);
+      return false;
+    case LoongArch::LD_B:
+    case LoongArch::LD_H:
+    case LoongArch::LD_W:
+    case LoongArch::LD_D:
+    case LoongArch::LD_BU:
+    case LoongArch::LD_HU:
+    case LoongArch::LD_WU:
+    case LoongArch::LDPTR_W:
+    case LoongArch::LDPTR_D:
+    case LoongArch::FLD_S:
+    case LoongArch::FLD_D:
+    case LoongArch::ST_B:
+    case LoongArch::ST_H:
+    case LoongArch::ST_W:
+    case LoongArch::ST_D:
+    case LoongArch::STPTR_W:
+    case LoongArch::STPTR_D:
+    case LoongArch::FST_S:
+    case LoongArch::FST_D: {
+      if (UseMI.getOperand(1).isFI())
+        return false;
+      // Register defined by Lo should not be the value register.
+      if (DestReg == UseMI.getOperand(0).getReg())
+        return false;
+      assert(DestReg == UseMI.getOperand(1).getReg() &&
+             "Expected base address use");
+      // All load/store instructions must use the same offset.
+      int64_t Offset = UseMI.getOperand(2).getImm();
+      if (CommonOffset && Offset != CommonOffset)
+        return false;
+      CommonOffset = Offset;
+      break;
+    }
+    case LoongArch::INLINEASM:
+    case LoongArch::INLINEASM_BR: {
+      // We can't do this for large pattern.
+      if (Last)
+        return false;
+      SmallVector<unsigned> InlineAsmMemoryOpIndexes;
+      unsigned NumOps = 0;
+      for (unsigned I = InlineAsm::MIOp_FirstOperand;
+           I < UseMI.getNumOperands(); I += 1 + NumOps) {
+        const MachineOperand &FlagsMO = UseMI.getOperand(I);
+        // Should be an imm.
+        if (!FlagsMO.isImm())
+          continue;
+
+        const InlineAsm::Flag Flags(FlagsMO.getImm());
+        NumOps = Flags.getNumOperandRegisters();
+
+        // Memory constraints have two operands.
+        if (NumOps != 2 || !Flags.isMemKind()) {
+          // If the register is used by something other than a memory contraint,
+          // we should not fold.
+          for (unsigned J = 0; J < NumOps; ++J) {
+            const MachineOperand &MO = UseMI.getOperand(I + 1 + J);
+            if (MO.isReg() && MO.getReg() == DestReg)
+              return false;
+          }
+          continue;
+        }
+
+        // We can only do this for constraint m.
+        if (Flags.getMemoryConstraintID() != InlineAsm::ConstraintCode::m)
+          return false;
+
+        const MachineOperand &AddrMO = UseMI.getOperand(I + 1);
+        if (!AddrMO.isReg() || AddrMO.getReg() != DestReg)
+          continue;
+
+        const MachineOperand &OffsetMO = UseMI.getOperand(I + 2);
+        if (!OffsetMO.isImm())
+          continue;
+
+        // All inline asm memory operands must use the same offset.
+        int64_t Offset = OffsetMO.getImm();
+        if (CommonOffset && Offset != CommonOffset)
+          return false;
+        CommonOffset = Offset;
+        InlineAsmMemoryOpIndexes.push_back(I + 1);
+      }
+      InlineAsmMemoryOpIndexesMap.insert(
+          std::make_pair(&UseMI, InlineAsmMemoryOpIndexes));
+      break;
+    }
+    }
+  }
+
+  // We found a common offset.
+  // Update the offsets in global address lowering.
+  // We may have already folded some arithmetic so we need to add to any
+  // existing offset.
+  int64_t NewOffset = Hi20.getOperand(1).getOffset() + *CommonOffset;
+  // LA32 ignores the upper 32 bits.
+  if (!ST->is64Bit())
+    NewOffset = SignExtend64<32>(NewOffset);
+  // We can only fold simm32 offsets.
+  if (!isInt<32>(NewOffset))
+    return false;
+
+  Hi20.getOperand(1).setOffset(NewOffset);
+  MachineOperand &ImmOp = Lo12.getOperand(2);
+  ImmOp.setOffset(NewOffset);
+  if (Lo20 && Hi12) {
+    Lo20->getOperand(2).setOffset(NewOffset);
+    Hi12->getOperand(2).setOffset(NewOffset);
+  }
+
+  // Update the immediate in the load/store instructions to add the offset.
+  const LoongArchInstrInfo &TII = *ST->getInstrInfo();
+  for (MachineInstr &UseMI :
+       llvm::make_early_inc_range(MRI->use_instructions(DestReg))) {
+    if (UseMI.getOpcode() == LoongArch::INLINEASM ||
+        UseMI.getOpcode() == LoongArch::INLINEASM_BR) {
+      auto &InlineAsmMemoryOpIndexes = InlineAsmMemoryOpIndexesMap[&UseMI];
+      for (unsigned I : InlineAsmMemoryOpIndexes) {
+        MachineOperand &MO = UseMI.getOperand(I + 1);
+        switch (ImmOp.getType()) {
+        case MachineOperand::MO_GlobalAddress:
+          MO.ChangeToGA(ImmOp.getGlobal(), ImmOp.getOffset(),
+                        ImmOp.getTargetFlags());
+          break;
+        case MachineOperand::MO_MCSymbol:
+          MO.ChangeToMCSymbol(ImmOp.getMCSymbol(), ImmOp.getTargetFlags());
+          MO.setOffset(ImmOp.getOffset());
+          break;
+        case MachineOperand::MO_BlockAddress:
+          MO.ChangeToBA(ImmOp.getBlockAddress(), ImmOp.getOffset(),
+                        ImmOp.getTargetFlags());
+          break;
+        default:
+          report_fatal_error("unsupported machine operand type");
+          break;
+        }
+      }
+    } else {
+      UseMI.setDesc(TII.get(getNewOpc(UseMI.getOpcode(), Last)));
+      if (Last) {
+        UseMI.removeOperand(2);
+        UseMI.removeOperand(1);
+        UseMI.addOperand(Last->getOperand(1));
+        UseMI.addOperand(Last->getOperand(2));
+        UseMI.getOperand(1).setIsKill(false);
+        UseMI.getOperand(2).setIsKill(false);
+      } else {
+        UseMI.removeOperand(2);
+        UseMI.addOperand(ImmOp);
+      }
+    }
+  }
+
+  if (Last) {
+    Last->eraseFromParent();
+    return true;
+  }
+
+  MRI->replaceRegWith(Lo12.getOperand(0).getReg(), Hi20.getOperand(0).getReg());
+  Lo12.eraseFromParent();
+  return true;
+}
+
+bool LoongArchMergeBaseOffsetOpt::runOnMachineFunction(MachineFunction &Fn) {
+  if (skipFunction(Fn.getFunction()))
+    return false;
+
+  ST = &Fn.getSubtarget<LoongArchSubtarget>();
+
+  bool MadeChange = false;
+  MRI = &Fn.getRegInfo();
+  for (MachineBasicBlock &MBB : Fn) {
+    LLVM_DEBUG(dbgs() << "MBB: " << MBB.getName() << "\n");
+    for (MachineInstr &Hi20 : MBB) {
+      MachineInstr *Lo12 = nullptr;
+      MachineInstr *Lo20 = nullptr;
+      MachineInstr *Hi12 = nullptr;
+      MachineInstr *Last = nullptr;
+      if (!detectFoldable(Hi20, Lo12, Lo20, Hi12, Last))
+        continue;
+      MadeChange |= detectAndFoldOffset(Hi20, *Lo12, Lo20, Hi12, Last);
+      MadeChange |= foldIntoMemoryOps(Hi20, *Lo12, Lo20, Hi12, Last);
+    }
+  }
+
+  return MadeChange;
+}
+
+/// Returns an instance of the Merge Base Offset Optimization pass.
+FunctionPass *llvm::createLoongArchMergeBaseOffsetOptPass() {
+  return new LoongArchMergeBaseOffsetOpt();
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
index e83fc08696aea5..4401aadfe78485 100644
--- a/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchTargetMachine.cpp
@@ -35,6 +35,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeLoongArchTarget() {
   RegisterTargetMachine<LoongArchTargetMachine> Y(getTheLoongArch64Target());
   auto *PR = PassRegistry::getPassRegistry();
   initializeLoongArchDeadRegisterDefinitionsPass(*PR);
+  initializeLoongArchMergeBaseOffsetOptPass(*PR);
   initializeLoongArchOptWInstrsPass(*PR);
   initializeLoongArchPreRAExpandPseudoPass(*PR);
   initializeLoongArchDAGToDAGISelLegacyPass(*PR);
@@ -216,6 +217,8 @@ void LoongArchPassConfig::addMachineSSAOptimization() {
 
 void LoongArchPassConfig::addPreRegAlloc() {
   addPass(createLoongArchPreRAExpandPseudoPass());
+  if (TM->getOptLevel() != CodeGenOptLevel::None)
+    addPass(createLoongArchMergeBaseOffsetOptPass());
 }
 
 bool LoongArchPassConfig::addRegAssignAndRewriteFast() {
diff --git a/llvm/test/CodeGen/LoongArch/block-address.ll b/llvm/test/CodeGen/LoongArch/block-address.ll
index eaba81f3563d7f..114cbb73a51259 100644
--- a/llvm/test/CodeGen/LoongArch/block-address.ll
+++ b/llvm/test/CodeGen/LoongArch/block-address.ll
@@ -8,11 +8,10 @@ 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:    st.w $a1, $a0, %pc_lo12(addr)
+; LA32-NEXT:    ld.w $a0, $a0, %pc_lo12(addr)
 ; LA32-NEXT:    jr $a0
 ; LA32-NEXT:  .Ltmp0: # Block address taken
 ; LA32-NEXT:  .LBB0_1: # %block
@@ -21,11 +20,10 @@ define void @test_blockaddress() nounwind {
 ; 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:    st.d $a1, $a0, %pc_lo12(addr)
+; LA64-NEXT:    ld.d $a0, $a0, %pc_lo12(addr)
 ; LA64-NEXT:    jr $a0
 ; LA64-NEXT:  .Ltmp0: # Block address taken
 ; LA64-NEXT:  .LBB0_1: # %block
diff --git a/llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll b/llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll
index cc6ba057019c65..34fbec03c535b0 100644
--- a/llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll
+++ b/llvm/test/CodeGen/LoongArch/calling-conv-lp64d.ll
@@ -64,26 +64,19 @@ define i64 @caller_double_in_gpr_exhausted_fprs() nounwind {
 ; CHECK-NEXT:    addi.d $sp, $sp, -16
 ; CHECK-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI3_0)
-; CHECK-NEXT:    fld.d $fa1, $a0, 0
+; CHECK-NEXT:    fld.d $fa1, $a0, %pc_lo12(.LCPI3_0)
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_1)
-; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI3_1)
-; CHECK-NEXT:    fld.d $fa2, $a0, 0
+; CHECK-NEXT:    fld.d $fa2, $a0, %pc_lo12(.LCPI3_1)
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_2)
-; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI3_2)
-; CHECK-NEXT:    fld.d $fa3, $a0, 0
+; CHECK-NEXT:    fld.d $fa3, $a0, %pc_lo12(.LCPI3_2)
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_3)
-; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI3_3)
-; CHECK-NEXT:    fld.d $fa4, $a0, 0
+; CHECK-NEXT:    fld.d $fa4, $a0, %pc_lo12(.LCPI3_3)
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_4)
-; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI3_4)
-; CHECK-NEXT:    fld.d $fa5, $a0, 0
+; CHECK-NEXT:    fld.d $fa5, $a0, %pc_lo12(.LCPI3_4)
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_5)
-; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI3_5)
-; CHECK-NEXT:    fld.d $fa6, $a0, 0
+; CHECK-NEXT:    fld.d $fa6, $a0, %pc_lo12(.LCPI3_5)
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_6)
-; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI3_6)
-; CHECK-NEXT:    fld.d $fa7, $a0, 0
+; CHECK-NEXT:    fld.d $fa7, $a0, %pc_lo12(.LCPI3_6)
 ; CHECK-NEXT:    addi.d $a0, $zero, 1
 ; CHECK-NEXT:    movgr2fr.d $fa0, $a0
 ; CHECK-NEXT:    ffint.d.l $fa0, $fa0
diff --git a/llvm/test/CodeGen/LoongArch/double-imm.ll b/llvm/test/CodeGen/LoongArch/double-imm.ll
index 3e89db3ec5c8cc..8d50b27907d72b 100644
--- a/llvm/test/CodeGen/LoongArch/double-imm.ll
+++ b/llvm/test/CodeGen/LoongArch/double-imm.ll
@@ -36,15 +36,13 @@ define double @f64_constant_pi() nounwind {
 ; LA32-LABEL: f64_constant_pi:
 ; LA32:       # %bb.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:    fld.d $fa0, $a0, %pc_lo12(.LCPI2_0)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: f64_constant_pi:
 ; LA64:       # %bb.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:    fld.d $fa0, $a0, %pc_lo12(.LCPI2_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 e2cbf4bf9b3e87..006a9e64b190de 100644
--- a/llvm/test/CodeGen/LoongArch/float-imm.ll
+++ b/llvm/test/CodeGen/LoongArch/float-imm.ll
@@ -34,15 +34,13 @@ define float @f32_constant_pi() nounwind {
 ; LA32-LABEL: f32_constant_pi:
 ; LA32:       # %bb.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:    fld.s $fa0, $a0, %pc_lo12(.LCPI2_0)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: f32_constant_pi:
 ; LA64:       # %bb.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:    fld.s $fa0, $a0, %pc_lo12(.LCPI2_0)
 ; LA64-NEXT:    ret
   ret float 3.14159274101257324218750
 }
diff --git a/llvm/test/CodeGen/LoongArch/ghc-cc.ll b/llvm/test/CodeGen/LoongArch/ghc-cc.ll
index 735315d323a362..f99759b4b5ed56 100644
--- a/llvm/test/CodeGen/LoongArch/ghc-cc.ll
+++ b/llvm/test/CodeGen/LoongArch/ghc-cc.ll
@@ -27,56 +27,39 @@ define ghccc void @foo() nounwind {
 ; LA64-LABEL: foo:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(d4)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(d4)
-; LA64-NEXT:    fld.d $fs7, $a0, 0
+; LA64-NEXT:    fld.d $fs7, $a0, %pc_lo12(d4)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(d3)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(d3)
-; LA64-NEXT:    fld.d $fs6, $a0, 0
+; LA64-NEXT:    fld.d $fs6, $a0, %pc_lo12(d3)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(d2)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(d2)
-; LA64-NEXT:    fld.d $fs5, $a0, 0
+; LA64-NEXT:    fld.d $fs5, $a0, %pc_lo12(d2)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(d1)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(d1)
-; LA64-NEXT:    fld.d $fs4, $a0, 0
+; LA64-NEXT:    fld.d $fs4, $a0, %pc_lo12(d1)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(f4)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(f4)
-; LA64-NEXT:    fld.s $fs3, $a0, 0
+; LA64-NEXT:    fld.s $fs3, $a0, %pc_lo12(f4)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(f3)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(f3)
-; LA64-NEXT:    fld.s $fs2, $a0, 0
+; LA64-NEXT:    fld.s $fs2, $a0, %pc_lo12(f3)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(f2)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(f2)
-; LA64-NEXT:    fld.s $fs1, $a0, 0
+; LA64-NEXT:    fld.s $fs1, $a0, %pc_lo12(f2)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(f1)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(f1)
-; LA64-NEXT:    fld.s $fs0, $a0, 0
+; LA64-NEXT:    fld.s $fs0, $a0, %pc_lo12(f1)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(splim)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(splim)
-; LA64-NEXT:    ld.d $s8, $a0, 0
+; LA64-NEXT:    ld.d $s8, $a0, %pc_lo12(splim)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(r5)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(r5)
-; LA64-NEXT:    ld.d $s7, $a0, 0
+; LA64-NEXT:    ld.d $s7, $a0, %pc_lo12(r5)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(r4)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(r4)
-; LA64-NEXT:    ld.d $s6, $a0, 0
+; LA64-NEXT:    ld.d $s6, $a0, %pc_lo12(r4)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(r3)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(r3)
-; LA64-NEXT:    ld.d $s5, $a0, 0
+; LA64-NEXT:    ld.d $s5, $a0, %pc_lo12(r3)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(r2)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(r2)
-; LA64-NEXT:    ld.d $s4, $a0, 0
+; LA64-NEXT:    ld.d $s4, $a0, %pc_lo12(r2)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(r1)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(r1)
-; LA64-NEXT:    ld.d $s3, $a0, 0
+; LA64-NEXT:    ld.d $s3, $a0, %pc_lo12(r1)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(hp)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(hp)
-; LA64-NEXT:    ld.d $s2, $a0, 0
+; LA64-NEXT:    ld.d $s2, $a0, %pc_lo12(hp)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(sp)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(sp)
-; LA64-NEXT:    ld.d $s1, $a0, 0
+; LA64-NEXT:    ld.d $s1, $a0, %pc_lo12(sp)
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(base)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(base)
-; LA64-NEXT:    ld.d $s0, $a0, 0
+; LA64-NEXT:    ld.d $s0, $a0, %pc_lo12(base)
 ; LA64-NEXT:    b %plt(bar)
 
 entry:
diff --git a/llvm/test/CodeGen/LoongArch/global-address.ll b/llvm/test/CodeGen/LoongArch/global-address.ll
index 2423dd81a4d3a8..89ea48c3b1cbf6 100644
--- a/llvm/test/CodeGen/LoongArch/global-address.ll
+++ b/llvm/test/CodeGen/LoongArch/global-address.ll
@@ -16,8 +16,7 @@ define void @foo() nounwind {
 ; LA32NOPIC-NEXT:    ld.w $a0, $a0, %got_pc_lo12(G)
 ; LA32NOPIC-NEXT:    ld.w $zero, $a0, 0
 ; LA32NOPIC-NEXT:    pcalau12i $a0, %pc_hi20(g)
-; LA32NOPIC-NEXT:    addi.w $a0, $a0, %pc_lo12(g)
-; LA32NOPIC-NEXT:    ld.w $zero, $a0, 0
+; LA32NOPIC-NEXT:    ld.w $zero, $a0, %pc_lo12(g)
 ; LA32NOPIC-NEXT:    ret
 ;
 ; LA32PIC-LABEL: foo:
@@ -26,8 +25,7 @@ define void @foo() nounwind {
 ; LA32PIC-NEXT:    ld.w $a0, $a0, %got_pc_lo12(G)
 ; LA32PIC-NEXT:    ld.w $zero, $a0, 0
 ; LA32PIC-NEXT:    pcalau12i $a0, %pc_hi20(.Lg$local)
-; LA32PIC-NEXT:    addi.w $a0, $a0, %pc_lo12(.Lg$local)
-; LA32PIC-NEXT:    ld.w $zero, $a0, 0
+; LA32PIC-NEXT:    ld.w $zero, $a0, %pc_lo12(.Lg$local)
 ; LA32PIC-NEXT:    ret
 ;
 ; LA64NOPIC-LABEL: foo:
@@ -36,8 +34,7 @@ define void @foo() nounwind {
 ; LA64NOPIC-NEXT:    ld.d $a0, $a0, %got_pc_lo12(G)
 ; LA64NOPIC-NEXT:    ld.w $zero, $a0, 0
 ; LA64NOPIC-NEXT:    pcalau12i $a0, %pc_hi20(g)
-; LA64NOPIC-NEXT:    addi.d $a0, $a0, %pc_lo12(g)
-; LA64NOPIC-NEXT:    ld.w $zero, $a0, 0
+; LA64NOPIC-NEXT:    ld.w $zero, $a0, %pc_lo12(g)
 ; LA64NOPIC-NEXT:    ret
 ;
 ; LA64PIC-LABEL: foo:
@@ -46,8 +43,7 @@ define void @foo() nounwind {
 ; LA64PIC-NEXT:    ld.d $a0, $a0, %got_pc_lo12(G)
 ; LA64PIC-NEXT:    ld.w $zero, $a0, 0
 ; LA64PIC-NEXT:    pcalau12i $a0, %pc_hi20(.Lg$local)
-; LA64PIC-NEXT:    addi.d $a0, $a0, %pc_lo12(.Lg$local)
-; LA64PIC-NEXT:    ld.w $zero, $a0, 0
+; LA64PIC-NEXT:    ld.w $zero, $a0, %pc_lo12(.Lg$local)
 ; LA64PIC-NEXT:    ret
 ;
 ; LA64LARGENOPIC-LABEL: foo:
@@ -62,8 +58,7 @@ define void @foo() nounwind {
 ; LA64LARGENOPIC-NEXT:    addi.d $a1, $zero, %pc_lo12(g)
 ; LA64LARGENOPIC-NEXT:    lu32i.d $a1, %pc64_lo20(g)
 ; LA64LARGENOPIC-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g)
-; LA64LARGENOPIC-NEXT:    add.d $a0, $a1, $a0
-; LA64LARGENOPIC-NEXT:    ld.w $zero, $a0, 0
+; LA64LARGENOPIC-NEXT:    ldx.w $zero, $a1, $a0
 ; LA64LARGENOPIC-NEXT:    ret
 ;
 ; LA64LARGEPIC-LABEL: foo:
@@ -78,8 +73,7 @@ define void @foo() nounwind {
 ; LA64LARGEPIC-NEXT:    addi.d $a1, $zero, %pc_lo12(.Lg$local)
 ; LA64LARGEPIC-NEXT:    lu32i.d $a1, %pc64_lo20(.Lg$local)
 ; LA64LARGEPIC-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(.Lg$local)
-; LA64LARGEPIC-NEXT:    add.d $a0, $a1, $a0
-; LA64LARGEPIC-NEXT:    ld.w $zero, $a0, 0
+; LA64LARGEPIC-NEXT:    ldx.w $zero, $a1, $a0
 ; LA64LARGEPIC-NEXT:    ret
   %V = load volatile i32, ptr @G
   %v = load volatile i32, ptr @g
diff --git a/llvm/test/CodeGen/LoongArch/global-variable-code-model.ll b/llvm/test/CodeGen/LoongArch/global-variable-code-model.ll
index 2b7a862ecde11e..04f6a635778eba 100644
--- a/llvm/test/CodeGen/LoongArch/global-variable-code-model.ll
+++ b/llvm/test/CodeGen/LoongArch/global-variable-code-model.ll
@@ -7,8 +7,7 @@ define dso_local signext i32 @local_small() #0 {
 ; CHECK-LABEL: local_small:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(a)
-; CHECK-NEXT:    addi.d $a0, $a0, %pc_lo12(a)
-; CHECK-NEXT:    ld.w $a0, $a0, 0
+; CHECK-NEXT:    ld.w $a0, $a0, %pc_lo12(a)
 ; CHECK-NEXT:    ret
   %1 = load i32, ptr @a, align 4
   ret i32 %1
@@ -23,8 +22,7 @@ define dso_local signext i32 @local_large() #0 {
 ; CHECK-NEXT:    addi.d $a1, $zero, %pc_lo12(b)
 ; CHECK-NEXT:    lu32i.d $a1, %pc64_lo20(b)
 ; CHECK-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(b)
-; CHECK-NEXT:    add.d $a0, $a1, $a0
-; CHECK-NEXT:    ld.w $a0, $a0, 0
+; CHECK-NEXT:    ldx.w $a0, $a1, $a0
 ; CHECK-NEXT:    ret
   %1 = load i32, ptr @b, align 4
   ret i32 %1
diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll
index fa675e4bbb3243..be9ea29b54c332 100644
--- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll
+++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-f.ll
@@ -10,8 +10,7 @@ define double @constraint_f_double(double %a) nounwind {
 ; LA32-LABEL: constraint_f_double:
 ; LA32:       # %bb.0:
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(gd)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(gd)
-; LA32-NEXT:    fld.d $fa1, $a0, 0
+; LA32-NEXT:    fld.d $fa1, $a0, %pc_lo12(gd)
 ; LA32-NEXT:    #APP
 ; LA32-NEXT:    fadd.d $fa0, $fa0, $fa1
 ; LA32-NEXT:    #NO_APP
@@ -20,8 +19,7 @@ define double @constraint_f_double(double %a) nounwind {
 ; LA64-LABEL: constraint_f_double:
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(gd)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(gd)
-; LA64-NEXT:    fld.d $fa1, $a0, 0
+; LA64-NEXT:    fld.d $fa1, $a0, %pc_lo12(gd)
 ; LA64-NEXT:    #APP
 ; LA64-NEXT:    fadd.d $fa0, $fa0, $fa1
 ; LA64-NEXT:    #NO_APP
diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
index becb3cae46b8c0..565ccdbe6880fb 100644
--- a/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
+++ b/llvm/test/CodeGen/LoongArch/inline-asm-constraint-m.ll
@@ -147,19 +147,17 @@ define i32 @m_offset_2048(ptr %p) nounwind {
 define i32 @m_addr_pcrel() nounwind {
 ; LA32-LABEL: m_addr_pcrel:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i32)
-; LA32-NEXT:    addi.w $a1, $a0, %pc_lo12(g_i32)
+; LA32-NEXT:    pcalau12i $a1, %pc_hi20(g_i32)
 ; LA32-NEXT:    #APP
-; LA32-NEXT:    ld.w $a0, $a1, 0
+; LA32-NEXT:    ld.w $a0, $a1, %pc_lo12(g_i32)
 ; LA32-NEXT:    #NO_APP
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: m_addr_pcrel:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i32)
-; LA64-NEXT:    addi.d $a1, $a0, %pc_lo12(g_i32)
+; LA64-NEXT:    pcalau12i $a1, %pc_hi20(g_i32)
 ; LA64-NEXT:    #APP
-; LA64-NEXT:    ld.w $a0, $a1, 0
+; LA64-NEXT:    ld.w $a0, $a1, %pc_lo12(g_i32)
 ; LA64-NEXT:    #NO_APP
 ; LA64-NEXT:    ret
   %1 = tail call i32 asm sideeffect "ld.w $0, $1", "=&r,*m"(ptr nonnull elementtype(i32) @g_i32)
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-fp.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-fp.ll
index 193fa6c08600ae..7e320d9245f1c2 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-fp.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/atomicrmw-fp.ll
@@ -79,8 +79,7 @@ define float @float_fsub_acquire(ptr %p) nounwind {
 ; LA64F:       # %bb.0:
 ; LA64F-NEXT:    fld.s $fa0, $a0, 0
 ; LA64F-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI1_0)
-; LA64F-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI1_0)
-; LA64F-NEXT:    fld.s $fa1, $a1, 0
+; LA64F-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI1_0)
 ; LA64F-NEXT:    .p2align 4, , 16
 ; LA64F-NEXT:  .LBB1_1: # %atomicrmw.start
 ; LA64F-NEXT:    # =>This Loop Header: Depth=1
@@ -113,8 +112,7 @@ define float @float_fsub_acquire(ptr %p) nounwind {
 ; LA64D:       # %bb.0:
 ; LA64D-NEXT:    fld.s $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI1_0)
-; LA64D-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI1_0)
-; LA64D-NEXT:    fld.s $fa1, $a1, 0
+; LA64D-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI1_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB1_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Loop Header: Depth=1
@@ -413,8 +411,7 @@ define double @double_fsub_acquire(ptr %p) nounwind {
 ; LA64D-NEXT:    move $fp, $a0
 ; LA64D-NEXT:    fld.d $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI5_0)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI5_0)
-; LA64D-NEXT:    fld.d $fs0, $a0, 0
+; LA64D-NEXT:    fld.d $fs0, $a0, %pc_lo12(.LCPI5_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB5_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Inner Loop Header: Depth=1
@@ -665,8 +662,7 @@ define float @float_fsub_release(ptr %p) nounwind {
 ; LA64F:       # %bb.0:
 ; LA64F-NEXT:    fld.s $fa0, $a0, 0
 ; LA64F-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI9_0)
-; LA64F-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI9_0)
-; LA64F-NEXT:    fld.s $fa1, $a1, 0
+; LA64F-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI9_0)
 ; LA64F-NEXT:    .p2align 4, , 16
 ; LA64F-NEXT:  .LBB9_1: # %atomicrmw.start
 ; LA64F-NEXT:    # =>This Loop Header: Depth=1
@@ -699,8 +695,7 @@ define float @float_fsub_release(ptr %p) nounwind {
 ; LA64D:       # %bb.0:
 ; LA64D-NEXT:    fld.s $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI9_0)
-; LA64D-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI9_0)
-; LA64D-NEXT:    fld.s $fa1, $a1, 0
+; LA64D-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI9_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB9_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Loop Header: Depth=1
@@ -999,8 +994,7 @@ define double @double_fsub_release(ptr %p) nounwind {
 ; LA64D-NEXT:    move $fp, $a0
 ; LA64D-NEXT:    fld.d $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI13_0)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI13_0)
-; LA64D-NEXT:    fld.d $fs0, $a0, 0
+; LA64D-NEXT:    fld.d $fs0, $a0, %pc_lo12(.LCPI13_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB13_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Inner Loop Header: Depth=1
@@ -1251,8 +1245,7 @@ define float @float_fsub_acq_rel(ptr %p) nounwind {
 ; LA64F:       # %bb.0:
 ; LA64F-NEXT:    fld.s $fa0, $a0, 0
 ; LA64F-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI17_0)
-; LA64F-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI17_0)
-; LA64F-NEXT:    fld.s $fa1, $a1, 0
+; LA64F-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI17_0)
 ; LA64F-NEXT:    .p2align 4, , 16
 ; LA64F-NEXT:  .LBB17_1: # %atomicrmw.start
 ; LA64F-NEXT:    # =>This Loop Header: Depth=1
@@ -1285,8 +1278,7 @@ define float @float_fsub_acq_rel(ptr %p) nounwind {
 ; LA64D:       # %bb.0:
 ; LA64D-NEXT:    fld.s $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI17_0)
-; LA64D-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI17_0)
-; LA64D-NEXT:    fld.s $fa1, $a1, 0
+; LA64D-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI17_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB17_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Loop Header: Depth=1
@@ -1585,8 +1577,7 @@ define double @double_fsub_acq_rel(ptr %p) nounwind {
 ; LA64D-NEXT:    move $fp, $a0
 ; LA64D-NEXT:    fld.d $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI21_0)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI21_0)
-; LA64D-NEXT:    fld.d $fs0, $a0, 0
+; LA64D-NEXT:    fld.d $fs0, $a0, %pc_lo12(.LCPI21_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB21_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Inner Loop Header: Depth=1
@@ -1837,8 +1828,7 @@ define float @float_fsub_seq_cst(ptr %p) nounwind {
 ; LA64F:       # %bb.0:
 ; LA64F-NEXT:    fld.s $fa0, $a0, 0
 ; LA64F-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI25_0)
-; LA64F-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI25_0)
-; LA64F-NEXT:    fld.s $fa1, $a1, 0
+; LA64F-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI25_0)
 ; LA64F-NEXT:    .p2align 4, , 16
 ; LA64F-NEXT:  .LBB25_1: # %atomicrmw.start
 ; LA64F-NEXT:    # =>This Loop Header: Depth=1
@@ -1871,8 +1861,7 @@ define float @float_fsub_seq_cst(ptr %p) nounwind {
 ; LA64D:       # %bb.0:
 ; LA64D-NEXT:    fld.s $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI25_0)
-; LA64D-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI25_0)
-; LA64D-NEXT:    fld.s $fa1, $a1, 0
+; LA64D-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI25_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB25_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Loop Header: Depth=1
@@ -2171,8 +2160,7 @@ define double @double_fsub_seq_cst(ptr %p) nounwind {
 ; LA64D-NEXT:    move $fp, $a0
 ; LA64D-NEXT:    fld.d $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI29_0)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI29_0)
-; LA64D-NEXT:    fld.d $fs0, $a0, 0
+; LA64D-NEXT:    fld.d $fs0, $a0, %pc_lo12(.LCPI29_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB29_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Inner Loop Header: Depth=1
@@ -2423,8 +2411,7 @@ define float @float_fsub_monotonic(ptr %p) nounwind {
 ; LA64F:       # %bb.0:
 ; LA64F-NEXT:    fld.s $fa0, $a0, 0
 ; LA64F-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI33_0)
-; LA64F-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI33_0)
-; LA64F-NEXT:    fld.s $fa1, $a1, 0
+; LA64F-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI33_0)
 ; LA64F-NEXT:    .p2align 4, , 16
 ; LA64F-NEXT:  .LBB33_1: # %atomicrmw.start
 ; LA64F-NEXT:    # =>This Loop Header: Depth=1
@@ -2457,8 +2444,7 @@ define float @float_fsub_monotonic(ptr %p) nounwind {
 ; LA64D:       # %bb.0:
 ; LA64D-NEXT:    fld.s $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI33_0)
-; LA64D-NEXT:    addi.d $a1, $a1, %pc_lo12(.LCPI33_0)
-; LA64D-NEXT:    fld.s $fa1, $a1, 0
+; LA64D-NEXT:    fld.s $fa1, $a1, %pc_lo12(.LCPI33_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB33_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Loop Header: Depth=1
@@ -2757,8 +2743,7 @@ define double @double_fsub_monotonic(ptr %p) nounwind {
 ; LA64D-NEXT:    move $fp, $a0
 ; LA64D-NEXT:    fld.d $fa0, $a0, 0
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI37_0)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI37_0)
-; LA64D-NEXT:    fld.d $fs0, $a0, 0
+; LA64D-NEXT:    fld.d $fs0, $a0, %pc_lo12(.LCPI37_0)
 ; LA64D-NEXT:    .p2align 4, , 16
 ; LA64D-NEXT:  .LBB37_1: # %atomicrmw.start
 ; LA64D-NEXT:    # =>This Inner Loop Header: Depth=1
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
index ef117f97488715..8d08942c314aa4 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll
@@ -117,8 +117,7 @@ define i32 @convert_double_to_u32(double %a) nounwind {
 ; LA32-LABEL: convert_double_to_u32:
 ; LA32:       # %bb.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:    fld.d $fa1, $a0, %pc_lo12(.LCPI7_0)
 ; LA32-NEXT:    fcmp.clt.d $fcc0, $fa0, $fa1
 ; LA32-NEXT:    fsub.d $fa1, $fa0, $fa1
 ; LA32-NEXT:    ftintrz.w.d $fa1, $fa1
@@ -174,8 +173,7 @@ define i64 @convert_double_to_u64(double %a) nounwind {
 ; LA64-LABEL: convert_double_to_u64:
 ; LA64:       # %bb.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:    fld.d $fa1, $a0, %pc_lo12(.LCPI9_0)
 ; LA64-NEXT:    fcmp.clt.d $fcc0, $fa0, $fa1
 ; LA64-NEXT:    fsub.d $fa1, $fa0, $fa1
 ; LA64-NEXT:    ftintrz.l.d $fa1, $fa1
@@ -234,8 +232,7 @@ define double @convert_u32_to_double(i32 %a) nounwind {
 ; LA32-NEXT:    st.w $a0, $sp, 8
 ; LA32-NEXT:    fld.d $fa0, $sp, 8
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI12_0)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI12_0)
-; LA32-NEXT:    fld.d $fa1, $a0, 0
+; LA32-NEXT:    fld.d $fa1, $a0, %pc_lo12(.LCPI12_0)
 ; LA32-NEXT:    fsub.d $fa0, $fa0, $fa1
 ; LA32-NEXT:    addi.w $sp, $sp, 16
 ; LA32-NEXT:    ret
@@ -264,8 +261,7 @@ define double @convert_u64_to_double(i64 %a) nounwind {
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    srli.d $a1, $a0, 32
 ; LA64-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI13_0)
-; LA64-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI13_0)
-; LA64-NEXT:    fld.d $fa0, $a2, 0
+; LA64-NEXT:    fld.d $fa0, $a2, %pc_lo12(.LCPI13_0)
 ; LA64-NEXT:    lu52i.d $a2, $zero, 1107
 ; LA64-NEXT:    or $a1, $a1, $a2
 ; LA64-NEXT:    movgr2fr.d $fa1, $a1
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
index b01b84ba385ec8..b7de5a592c3598 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll
@@ -182,8 +182,7 @@ define i32 @convert_float_to_u32(float %a) nounwind {
 ; LA32F-LABEL: convert_float_to_u32:
 ; LA32F:       # %bb.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:    fld.s $fa1, $a0, %pc_lo12(.LCPI6_0)
 ; LA32F-NEXT:    fcmp.clt.s $fcc0, $fa0, $fa1
 ; LA32F-NEXT:    fsub.s $fa1, $fa0, $fa1
 ; LA32F-NEXT:    ftintrz.w.s $fa1, $fa1
@@ -201,8 +200,7 @@ define i32 @convert_float_to_u32(float %a) nounwind {
 ; LA32D-LABEL: convert_float_to_u32:
 ; LA32D:       # %bb.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:    fld.s $fa1, $a0, %pc_lo12(.LCPI6_0)
 ; LA32D-NEXT:    fcmp.clt.s $fcc0, $fa0, $fa1
 ; LA32D-NEXT:    fsub.s $fa1, $fa0, $fa1
 ; LA32D-NEXT:    ftintrz.w.s $fa1, $fa1
@@ -220,8 +218,7 @@ define i32 @convert_float_to_u32(float %a) nounwind {
 ; LA64F-LABEL: convert_float_to_u32:
 ; LA64F:       # %bb.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:    fld.s $fa1, $a0, %pc_lo12(.LCPI6_0)
 ; LA64F-NEXT:    fcmp.clt.s $fcc0, $fa0, $fa1
 ; LA64F-NEXT:    fsub.s $fa1, $fa0, $fa1
 ; LA64F-NEXT:    ftintrz.w.s $fa1, $fa1
@@ -267,8 +264,7 @@ define i64 @convert_float_to_u64(float %a) nounwind {
 ; LA64F-LABEL: convert_float_to_u64:
 ; LA64F:       # %bb.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:    fld.s $fa1, $a0, %pc_lo12(.LCPI7_0)
 ; LA64F-NEXT:    fcmp.clt.s $fcc0, $fa0, $fa1
 ; LA64F-NEXT:    fsub.s $fa1, $fa0, $fa1
 ; LA64F-NEXT:    ftintrz.w.s $fa1, $fa1
@@ -286,8 +282,7 @@ define i64 @convert_float_to_u64(float %a) nounwind {
 ; LA64D-LABEL: convert_float_to_u64:
 ; LA64D:       # %bb.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:    fld.s $fa1, $a0, %pc_lo12(.LCPI7_0)
 ; LA64D-NEXT:    fcmp.clt.s $fcc0, $fa0, $fa1
 ; LA64D-NEXT:    fsub.s $fa1, $fa0, $fa1
 ; LA64D-NEXT:    ftintrz.l.s $fa1, $fa1
@@ -506,8 +501,7 @@ define float @convert_u32_to_float(i32 %a) nounwind {
 ; LA32D-NEXT:    st.w $a0, $sp, 8
 ; LA32D-NEXT:    fld.d $fa0, $sp, 8
 ; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI14_0)
-; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI14_0)
-; LA32D-NEXT:    fld.d $fa1, $a0, 0
+; LA32D-NEXT:    fld.d $fa1, $a0, %pc_lo12(.LCPI14_0)
 ; LA32D-NEXT:    fsub.d $fa0, $fa0, $fa1
 ; LA32D-NEXT:    fcvt.s.d $fa0, $fa0
 ; LA32D-NEXT:    addi.w $sp, $sp, 16
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll
index 26f44adc613586..772ae8d81a88bf 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/load-store.ll
@@ -11,38 +11,34 @@
 define i32 @load_store_global() nounwind {
 ; LA32NOPIC-LABEL: load_store_global:
 ; LA32NOPIC:       # %bb.0:
-; LA32NOPIC-NEXT:    pcalau12i $a0, %pc_hi20(G)
-; LA32NOPIC-NEXT:    addi.w $a1, $a0, %pc_lo12(G)
-; LA32NOPIC-NEXT:    ld.w $a0, $a1, 0
+; LA32NOPIC-NEXT:    pcalau12i $a1, %pc_hi20(G)
+; LA32NOPIC-NEXT:    ld.w $a0, $a1, %pc_lo12(G)
 ; LA32NOPIC-NEXT:    addi.w $a0, $a0, 1
-; LA32NOPIC-NEXT:    st.w $a0, $a1, 0
+; LA32NOPIC-NEXT:    st.w $a0, $a1, %pc_lo12(G)
 ; LA32NOPIC-NEXT:    ret
 ;
 ; LA32PIC-LABEL: load_store_global:
 ; LA32PIC:       # %bb.0:
-; LA32PIC-NEXT:    pcalau12i $a0, %pc_hi20(.LG$local)
-; LA32PIC-NEXT:    addi.w $a1, $a0, %pc_lo12(.LG$local)
-; LA32PIC-NEXT:    ld.w $a0, $a1, 0
+; LA32PIC-NEXT:    pcalau12i $a1, %pc_hi20(.LG$local)
+; LA32PIC-NEXT:    ld.w $a0, $a1, %pc_lo12(.LG$local)
 ; LA32PIC-NEXT:    addi.w $a0, $a0, 1
-; LA32PIC-NEXT:    st.w $a0, $a1, 0
+; LA32PIC-NEXT:    st.w $a0, $a1, %pc_lo12(.LG$local)
 ; LA32PIC-NEXT:    ret
 ;
 ; LA64NOPIC-LABEL: load_store_global:
 ; LA64NOPIC:       # %bb.0:
-; LA64NOPIC-NEXT:    pcalau12i $a0, %pc_hi20(G)
-; LA64NOPIC-NEXT:    addi.d $a1, $a0, %pc_lo12(G)
-; LA64NOPIC-NEXT:    ld.w $a0, $a1, 0
+; LA64NOPIC-NEXT:    pcalau12i $a1, %pc_hi20(G)
+; LA64NOPIC-NEXT:    ld.w $a0, $a1, %pc_lo12(G)
 ; LA64NOPIC-NEXT:    addi.w $a0, $a0, 1
-; LA64NOPIC-NEXT:    st.w $a0, $a1, 0
+; LA64NOPIC-NEXT:    st.w $a0, $a1, %pc_lo12(G)
 ; LA64NOPIC-NEXT:    ret
 ;
 ; LA64PIC-LABEL: load_store_global:
 ; LA64PIC:       # %bb.0:
-; LA64PIC-NEXT:    pcalau12i $a0, %pc_hi20(.LG$local)
-; LA64PIC-NEXT:    addi.d $a1, $a0, %pc_lo12(.LG$local)
-; LA64PIC-NEXT:    ld.w $a0, $a1, 0
+; LA64PIC-NEXT:    pcalau12i $a1, %pc_hi20(.LG$local)
+; LA64PIC-NEXT:    ld.w $a0, $a1, %pc_lo12(.LG$local)
 ; LA64PIC-NEXT:    addi.w $a0, $a0, 1
-; LA64PIC-NEXT:    st.w $a0, $a1, 0
+; LA64PIC-NEXT:    st.w $a0, $a1, %pc_lo12(.LG$local)
 ; LA64PIC-NEXT:    ret
   %v = load i32, ptr @G
   %sum = add i32 %v, 1
diff --git a/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll b/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll
index 5248468b6027d5..ba72ef5bd7ba4b 100644
--- a/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll
+++ b/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll
@@ -15,11 +15,10 @@ define void @test_la_pcrel(i32 signext %n) {
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    move $a1, $zero
 ; LA32-NEXT:    pcalau12i $a2, %pc_hi20(l)
-; LA32-NEXT:    addi.w $a2, $a2, %pc_lo12(l)
 ; LA32-NEXT:    .p2align 4, , 16
 ; LA32-NEXT:  .LBB0_1: # %loop
 ; LA32-NEXT:    # =>This Inner Loop Header: Depth=1
-; LA32-NEXT:    ld.w $zero, $a2, 0
+; LA32-NEXT:    ld.w $zero, $a2, %pc_lo12(l)
 ; LA32-NEXT:    addi.w $a1, $a1, 1
 ; LA32-NEXT:    blt $a1, $a0, .LBB0_1
 ; LA32-NEXT:  # %bb.2: # %ret
@@ -29,11 +28,10 @@ define void @test_la_pcrel(i32 signext %n) {
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    move $a1, $zero
 ; LA64-NEXT:    pcalau12i $a2, %pc_hi20(l)
-; LA64-NEXT:    addi.d $a2, $a2, %pc_lo12(l)
 ; LA64-NEXT:    .p2align 4, , 16
 ; LA64-NEXT:  .LBB0_1: # %loop
 ; LA64-NEXT:    # =>This Inner Loop Header: Depth=1
-; LA64-NEXT:    ld.w $zero, $a2, 0
+; LA64-NEXT:    ld.w $zero, $a2, %pc_lo12(l)
 ; LA64-NEXT:    addi.w $a1, $a1, 1
 ; LA64-NEXT:    blt $a1, $a0, .LBB0_1
 ; LA64-NEXT:  # %bb.2: # %ret
@@ -41,18 +39,17 @@ define void @test_la_pcrel(i32 signext %n) {
 ;
 ; LA64LARGE-LABEL: test_la_pcrel:
 ; LA64LARGE:       # %bb.0: # %entry
-; LA64LARGE-NEXT:    pcalau12i $a2, %pc_hi20(l)
-; LA64LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(l)
-; LA64LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(l)
-; LA64LARGE-NEXT:    lu52i.d $a3, $a1, %pc64_hi12(l)
-; LA64LARGE-NEXT:    move $a1, $zero
-; LA64LARGE-NEXT:    add.d $a2, $a3, $a2
+; LA64LARGE-NEXT:    pcalau12i $a1, %pc_hi20(l)
+; LA64LARGE-NEXT:    addi.d $a2, $zero, %pc_lo12(l)
+; LA64LARGE-NEXT:    lu32i.d $a2, %pc64_lo20(l)
+; LA64LARGE-NEXT:    lu52i.d $a2, $a2, %pc64_hi12(l)
+; LA64LARGE-NEXT:    move $a3, $zero
 ; LA64LARGE-NEXT:    .p2align 4, , 16
 ; LA64LARGE-NEXT:  .LBB0_1: # %loop
 ; LA64LARGE-NEXT:    # =>This Inner Loop Header: Depth=1
-; LA64LARGE-NEXT:    ld.w $zero, $a2, 0
-; LA64LARGE-NEXT:    addi.w $a1, $a1, 1
-; LA64LARGE-NEXT:    blt $a1, $a0, .LBB0_1
+; LA64LARGE-NEXT:    ldx.w $zero, $a2, $a1
+; LA64LARGE-NEXT:    addi.w $a3, $a3, 1
+; LA64LARGE-NEXT:    blt $a3, $a0, .LBB0_1
 ; LA64LARGE-NEXT:  # %bb.2: # %ret
 ; LA64LARGE-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/LoongArch/merge-base-offset.ll b/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
index 48d18dbedcaf26..32a4c4bdd1508a 100644
--- a/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
+++ b/llvm/test/CodeGen/LoongArch/merge-base-offset.ll
@@ -12,15 +12,13 @@ define dso_local signext i8 @load_s8() nounwind {
 ; LA32-LABEL: load_s8:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i8)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i8)
-; LA32-NEXT:    ld.b $a0, $a0, 0
+; LA32-NEXT:    ld.b $a0, $a0, %pc_lo12(g_i8)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_s8:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i8)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i8)
-; LA64-NEXT:    ld.b $a0, $a0, 0
+; LA64-NEXT:    ld.b $a0, $a0, %pc_lo12(g_i8)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_s8:
@@ -29,8 +27,7 @@ define dso_local signext i8 @load_s8() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i8)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i8)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i8)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.b $a0, $a0, 0
+; LA64-LARGE-NEXT:    ldx.b $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load i8, ptr @g_i8
@@ -41,15 +38,13 @@ define dso_local zeroext i8 @load_u8() nounwind {
 ; LA32-LABEL: load_u8:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i8)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i8)
-; LA32-NEXT:    ld.bu $a0, $a0, 0
+; LA32-NEXT:    ld.bu $a0, $a0, %pc_lo12(g_i8)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_u8:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i8)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i8)
-; LA64-NEXT:    ld.bu $a0, $a0, 0
+; LA64-NEXT:    ld.bu $a0, $a0, %pc_lo12(g_i8)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_u8:
@@ -58,8 +53,7 @@ define dso_local zeroext i8 @load_u8() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i8)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i8)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i8)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.bu $a0, $a0, 0
+; LA64-LARGE-NEXT:    ldx.bu $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load i8, ptr @g_i8
@@ -70,17 +64,15 @@ define dso_local void @store_i8() nounwind {
 ; LA32-LABEL: store_i8:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i8)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i8)
 ; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    st.b $a1, $a0, 0
+; LA32-NEXT:    st.b $a1, $a0, %pc_lo12(g_i8)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: store_i8:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i8)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i8)
 ; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    st.b $a1, $a0, 0
+; LA64-NEXT:    st.b $a1, $a0, %pc_lo12(g_i8)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_i8:
@@ -89,9 +81,8 @@ define dso_local void @store_i8() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i8)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i8)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i8)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ori $a1, $zero, 1
-; LA64-LARGE-NEXT:    st.b $a1, $a0, 0
+; LA64-LARGE-NEXT:    ori $a2, $zero, 1
+; LA64-LARGE-NEXT:    stx.b $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   store i8 1, ptr @g_i8
@@ -104,15 +95,13 @@ define dso_local signext i16 @load_s16() nounwind {
 ; LA32-LABEL: load_s16:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i16)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i16)
-; LA32-NEXT:    ld.h $a0, $a0, 0
+; LA32-NEXT:    ld.h $a0, $a0, %pc_lo12(g_i16)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_s16:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i16)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i16)
-; LA64-NEXT:    ld.h $a0, $a0, 0
+; LA64-NEXT:    ld.h $a0, $a0, %pc_lo12(g_i16)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_s16:
@@ -121,8 +110,7 @@ define dso_local signext i16 @load_s16() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i16)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i16)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i16)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.h $a0, $a0, 0
+; LA64-LARGE-NEXT:    ldx.h $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load i16, ptr @g_i16
@@ -133,15 +121,13 @@ define dso_local zeroext i16 @load_u16() nounwind {
 ; LA32-LABEL: load_u16:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i16)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i16)
-; LA32-NEXT:    ld.hu $a0, $a0, 0
+; LA32-NEXT:    ld.hu $a0, $a0, %pc_lo12(g_i16)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_u16:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i16)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i16)
-; LA64-NEXT:    ld.hu $a0, $a0, 0
+; LA64-NEXT:    ld.hu $a0, $a0, %pc_lo12(g_i16)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_u16:
@@ -150,8 +136,7 @@ define dso_local zeroext i16 @load_u16() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i16)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i16)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i16)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.hu $a0, $a0, 0
+; LA64-LARGE-NEXT:    ldx.hu $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load i16, ptr @g_i16
@@ -162,17 +147,15 @@ define dso_local void @store_i16() nounwind {
 ; LA32-LABEL: store_i16:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i16)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i16)
 ; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    st.h $a1, $a0, 0
+; LA32-NEXT:    st.h $a1, $a0, %pc_lo12(g_i16)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: store_i16:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i16)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i16)
 ; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    st.h $a1, $a0, 0
+; LA64-NEXT:    st.h $a1, $a0, %pc_lo12(g_i16)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_i16:
@@ -181,9 +164,8 @@ define dso_local void @store_i16() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i16)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i16)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i16)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ori $a1, $zero, 1
-; LA64-LARGE-NEXT:    st.h $a1, $a0, 0
+; LA64-LARGE-NEXT:    ori $a2, $zero, 1
+; LA64-LARGE-NEXT:    stx.h $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   store i16 1, ptr @g_i16
@@ -196,15 +178,13 @@ define dso_local signext i32 @load_s32() nounwind {
 ; LA32-LABEL: load_s32:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i32)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i32)
-; LA32-NEXT:    ld.w $a0, $a0, 0
+; LA32-NEXT:    ld.w $a0, $a0, %pc_lo12(g_i32)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_s32:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i32)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i32)
-; LA64-NEXT:    ld.w $a0, $a0, 0
+; LA64-NEXT:    ld.w $a0, $a0, %pc_lo12(g_i32)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_s32:
@@ -213,8 +193,7 @@ define dso_local signext i32 @load_s32() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i32)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i32)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.w $a0, $a0, 0
+; LA64-LARGE-NEXT:    ldx.w $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load i32, ptr @g_i32
@@ -225,15 +204,13 @@ define dso_local zeroext i32 @load_u32() nounwind {
 ; LA32-LABEL: load_u32:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i32)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i32)
-; LA32-NEXT:    ld.w $a0, $a0, 0
+; LA32-NEXT:    ld.w $a0, $a0, %pc_lo12(g_i32)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_u32:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i32)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i32)
-; LA64-NEXT:    ld.wu $a0, $a0, 0
+; LA64-NEXT:    ld.wu $a0, $a0, %pc_lo12(g_i32)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_u32:
@@ -242,8 +219,7 @@ define dso_local zeroext i32 @load_u32() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i32)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i32)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.wu $a0, $a0, 0
+; LA64-LARGE-NEXT:    ldx.wu $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load i32, ptr @g_i32
@@ -254,17 +230,15 @@ define dso_local void @store_i32() nounwind {
 ; LA32-LABEL: store_i32:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_i32)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_i32)
 ; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    st.w $a1, $a0, 0
+; LA32-NEXT:    st.w $a1, $a0, %pc_lo12(g_i32)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: store_i32:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i32)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i32)
 ; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    st.w $a1, $a0, 0
+; LA64-NEXT:    st.w $a1, $a0, %pc_lo12(g_i32)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_i32:
@@ -273,9 +247,8 @@ define dso_local void @store_i32() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i32)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i32)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ori $a1, $zero, 1
-; LA64-LARGE-NEXT:    st.w $a1, $a0, 0
+; LA64-LARGE-NEXT:    ori $a2, $zero, 1
+; LA64-LARGE-NEXT:    stx.w $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   store i32 1, ptr @g_i32
@@ -296,8 +269,7 @@ define dso_local i64 @load_64() nounwind {
 ; LA64-LABEL: load_64:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i64)
-; LA64-NEXT:    ld.d $a0, $a0, 0
+; LA64-NEXT:    ld.d $a0, $a0, %pc_lo12(g_i64)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_64:
@@ -306,8 +278,7 @@ define dso_local i64 @load_64() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i64)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i64)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i64)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.d $a0, $a0, 0
+; LA64-LARGE-NEXT:    ldx.d $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load i64, ptr @g_i64
@@ -327,9 +298,8 @@ define dso_local void @store_i64() nounwind {
 ; LA64-LABEL: store_i64:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_i64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_i64)
 ; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    st.d $a1, $a0, 0
+; LA64-NEXT:    st.d $a1, $a0, %pc_lo12(g_i64)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_i64:
@@ -338,9 +308,8 @@ define dso_local void @store_i64() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_i64)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_i64)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_i64)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ori $a1, $zero, 1
-; LA64-LARGE-NEXT:    st.d $a1, $a0, 0
+; LA64-LARGE-NEXT:    ori $a2, $zero, 1
+; LA64-LARGE-NEXT:    stx.d $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   store i64 1, ptr @g_i64
@@ -353,15 +322,13 @@ define dso_local float @load_f32() nounwind {
 ; LA32-LABEL: load_f32:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_f32)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_f32)
-; LA32-NEXT:    fld.s $fa0, $a0, 0
+; LA32-NEXT:    fld.s $fa0, $a0, %pc_lo12(g_f32)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_f32:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_f32)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_f32)
-; LA64-NEXT:    fld.s $fa0, $a0, 0
+; LA64-NEXT:    fld.s $fa0, $a0, %pc_lo12(g_f32)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_f32:
@@ -370,8 +337,7 @@ define dso_local float @load_f32() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_f32)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_f32)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_f32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    fld.s $fa0, $a0, 0
+; LA64-LARGE-NEXT:    fldx.s $fa0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load float, ptr @g_f32
@@ -382,17 +348,15 @@ define dso_local void @store_f32() nounwind {
 ; LA32-LABEL: store_f32:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_f32)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_f32)
 ; LA32-NEXT:    lu12i.w $a1, 260096
-; LA32-NEXT:    st.w $a1, $a0, 0
+; LA32-NEXT:    st.w $a1, $a0, %pc_lo12(g_f32)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: store_f32:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_f32)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_f32)
 ; LA64-NEXT:    lu12i.w $a1, 260096
-; LA64-NEXT:    st.w $a1, $a0, 0
+; LA64-NEXT:    st.w $a1, $a0, %pc_lo12(g_f32)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_f32:
@@ -401,9 +365,8 @@ define dso_local void @store_f32() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_f32)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_f32)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_f32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    lu12i.w $a1, 260096
-; LA64-LARGE-NEXT:    st.w $a1, $a0, 0
+; LA64-LARGE-NEXT:    lu12i.w $a2, 260096
+; LA64-LARGE-NEXT:    stx.w $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   store float 1.0, ptr @g_f32
@@ -416,15 +379,13 @@ define dso_local double @load_f64() nounwind {
 ; LA32-LABEL: load_f64:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_f64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_f64)
-; LA32-NEXT:    fld.d $fa0, $a0, 0
+; LA32-NEXT:    fld.d $fa0, $a0, %pc_lo12(g_f64)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_f64:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_f64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_f64)
-; LA64-NEXT:    fld.d $fa0, $a0, 0
+; LA64-NEXT:    fld.d $fa0, $a0, %pc_lo12(g_f64)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_f64:
@@ -433,8 +394,7 @@ define dso_local double @load_f64() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_f64)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_f64)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_f64)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    fld.d $fa0, $a0, 0
+; LA64-LARGE-NEXT:    fldx.d $fa0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load double, ptr @g_f64
@@ -445,20 +405,18 @@ define dso_local void @store_f64() nounwind {
 ; LA32-LABEL: store_f64:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_f64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_f64)
 ; LA32-NEXT:    addi.w $a1, $zero, 1
 ; LA32-NEXT:    movgr2fr.w $fa0, $a1
 ; LA32-NEXT:    ffint.s.w $fa0, $fa0
 ; LA32-NEXT:    fcvt.d.s $fa0, $fa0
-; LA32-NEXT:    fst.d $fa0, $a0, 0
+; LA32-NEXT:    fst.d $fa0, $a0, %pc_lo12(g_f64)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: store_f64:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_f64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_f64)
 ; LA64-NEXT:    lu52i.d $a1, $zero, 1023
-; LA64-NEXT:    st.d $a1, $a0, 0
+; LA64-NEXT:    st.d $a1, $a0, %pc_lo12(g_f64)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_f64:
@@ -467,9 +425,8 @@ define dso_local void @store_f64() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_f64)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_f64)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_f64)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    lu52i.d $a1, $zero, 1023
-; LA64-LARGE-NEXT:    st.d $a1, $a0, 0
+; LA64-LARGE-NEXT:    lu52i.d $a2, $zero, 1023
+; LA64-LARGE-NEXT:    stx.d $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   store double 1.0, ptr @g_f64
@@ -494,11 +451,10 @@ define dso_local void @store_multi() nounwind {
 ; LA64-LABEL: store_multi:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_m64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_m64)
 ; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    st.d $a1, $a0, 0
+; LA64-NEXT:    st.d $a1, $a0, %pc_lo12(g_m64)
 ; LA64-NEXT:    ori $a1, $zero, 2
-; LA64-NEXT:    st.d $a1, $a0, 0
+; LA64-NEXT:    st.d $a1, $a0, %pc_lo12(g_m64)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_multi:
@@ -507,11 +463,10 @@ define dso_local void @store_multi() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_m64)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_m64)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_m64)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ori $a1, $zero, 1
-; LA64-LARGE-NEXT:    st.d $a1, $a0, 0
-; LA64-LARGE-NEXT:    ori $a1, $zero, 2
-; LA64-LARGE-NEXT:    st.d $a1, $a0, 0
+; LA64-LARGE-NEXT:    ori $a2, $zero, 1
+; LA64-LARGE-NEXT:    stx.d $a2, $a1, $a0
+; LA64-LARGE-NEXT:    ori $a2, $zero, 2
+; LA64-LARGE-NEXT:    stx.d $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   store volatile i64 1, ptr @g_m64
@@ -525,17 +480,15 @@ define dso_local void @store_sf32() nounwind {
 ; LA32-LABEL: store_sf32:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_sf32)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_sf32)
-; LA32-NEXT:    fld.s $fa0, $a0, 0
-; LA32-NEXT:    fst.s $fa0, $a0, 0
+; LA32-NEXT:    fld.s $fa0, $a0, %pc_lo12(g_sf32)
+; LA32-NEXT:    fst.s $fa0, $a0, %pc_lo12(g_sf32)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: store_sf32:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_sf32)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_sf32)
-; LA64-NEXT:    fld.s $fa0, $a0, 0
-; LA64-NEXT:    fst.s $fa0, $a0, 0
+; LA64-NEXT:    fld.s $fa0, $a0, %pc_lo12(g_sf32)
+; LA64-NEXT:    fst.s $fa0, $a0, %pc_lo12(g_sf32)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_sf32:
@@ -544,9 +497,8 @@ define dso_local void @store_sf32() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_sf32)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_sf32)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_sf32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    fld.s $fa0, $a0, 0
-; LA64-LARGE-NEXT:    fst.s $fa0, $a0, 0
+; LA64-LARGE-NEXT:    fldx.s $fa0, $a1, $a0
+; LA64-LARGE-NEXT:    fstx.s $fa0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load float, ptr @g_sf32
@@ -560,17 +512,15 @@ define dso_local void @store_sf64() nounwind {
 ; LA32-LABEL: store_sf64:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_sf64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_sf64)
-; LA32-NEXT:    fld.d $fa0, $a0, 0
-; LA32-NEXT:    fst.d $fa0, $a0, 0
+; LA32-NEXT:    fld.d $fa0, $a0, %pc_lo12(g_sf64)
+; LA32-NEXT:    fst.d $fa0, $a0, %pc_lo12(g_sf64)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: store_sf64:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_sf64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_sf64)
-; LA64-NEXT:    fld.d $fa0, $a0, 0
-; LA64-NEXT:    fst.d $fa0, $a0, 0
+; LA64-NEXT:    fld.d $fa0, $a0, %pc_lo12(g_sf64)
+; LA64-NEXT:    fst.d $fa0, $a0, %pc_lo12(g_sf64)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_sf64:
@@ -579,9 +529,8 @@ define dso_local void @store_sf64() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_sf64)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_sf64)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_sf64)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    fld.d $fa0, $a0, 0
-; LA64-LARGE-NEXT:    fst.d $fa0, $a0, 0
+; LA64-LARGE-NEXT:    fldx.d $fa0, $a1, $a0
+; LA64-LARGE-NEXT:    fstx.d $fa0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load double, ptr @g_sf64
@@ -608,10 +557,9 @@ define dso_local void @rmw() nounwind {
 ; LA64-LABEL: rmw:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_rmw)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_rmw)
-; LA64-NEXT:    ld.d $a1, $a0, 0
+; LA64-NEXT:    ld.d $a1, $a0, %pc_lo12(g_rmw)
 ; LA64-NEXT:    addi.d $a1, $a1, 1
-; LA64-NEXT:    st.d $a1, $a0, 0
+; LA64-NEXT:    st.d $a1, $a0, %pc_lo12(g_rmw)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: rmw:
@@ -620,10 +568,9 @@ define dso_local void @rmw() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_rmw)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_rmw)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_rmw)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.d $a1, $a0, 0
-; LA64-LARGE-NEXT:    addi.d $a1, $a1, 1
-; LA64-LARGE-NEXT:    st.d $a1, $a0, 0
+; LA64-LARGE-NEXT:    ldx.d $a2, $a1, $a0
+; LA64-LARGE-NEXT:    addi.d $a2, $a2, 1
+; LA64-LARGE-NEXT:    stx.d $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   %0 = load i64, ptr @g_rmw
@@ -637,31 +584,26 @@ entry:
 define dso_local void @store_a32() nounwind {
 ; LA32-LABEL: store_a32:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a32)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a32)
-; LA32-NEXT:    lu12i.w $a1, 1
-; LA32-NEXT:    add.w $a0, $a0, $a1
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a32+4096)
 ; LA32-NEXT:    ori $a1, $zero, 1
-; LA32-NEXT:    st.w $a1, $a0, 0
+; LA32-NEXT:    st.w $a1, $a0, %pc_lo12(g_a32+4096)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: store_a32:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a32)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a32)
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a32+4096)
 ; LA64-NEXT:    ori $a1, $zero, 1
-; LA64-NEXT:    stptr.w $a1, $a0, 4096
+; LA64-NEXT:    st.w $a1, $a0, %pc_lo12(g_a32+4096)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: store_a32:
 ; LA64-LARGE:       # %bb.0: # %entry
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a32)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a32)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a32)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ori $a1, $zero, 1
-; LA64-LARGE-NEXT:    stptr.w $a1, $a0, 4096
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a32+4096)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a32+4096)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a32+4096)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a32+4096)
+; LA64-LARGE-NEXT:    ori $a2, $zero, 1
+; LA64-LARGE-NEXT:    stx.w $a2, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   store i32 1, ptr getelementptr inbounds ([1 x i32], ptr @g_a32, i32 1024), align 4
@@ -714,48 +656,44 @@ entry:
 define dso_local void @control_flow_with_mem_access() nounwind {
 ; LA32-LABEL: control_flow_with_mem_access:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a32)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a32)
-; LA32-NEXT:    ld.w $a1, $a0, 4
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a32+4)
+; LA32-NEXT:    ld.w $a1, $a0, %pc_lo12(g_a32+4)
 ; LA32-NEXT:    ori $a2, $zero, 1
 ; LA32-NEXT:    blt $a1, $a2, .LBB21_2
 ; LA32-NEXT:  # %bb.1: # %if.then
 ; LA32-NEXT:    ori $a1, $zero, 10
-; LA32-NEXT:    st.w $a1, $a0, 4
+; LA32-NEXT:    st.w $a1, $a0, %pc_lo12(g_a32+4)
 ; LA32-NEXT:  .LBB21_2: # %if.end
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: control_flow_with_mem_access:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a32)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a32)
-; LA64-NEXT:    ld.w $a1, $a0, 4
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a32+4)
+; LA64-NEXT:    ld.w $a1, $a0, %pc_lo12(g_a32+4)
 ; LA64-NEXT:    ori $a2, $zero, 1
 ; LA64-NEXT:    blt $a1, $a2, .LBB21_2
 ; LA64-NEXT:  # %bb.1: # %if.then
 ; LA64-NEXT:    ori $a1, $zero, 10
-; LA64-NEXT:    st.w $a1, $a0, 4
+; LA64-NEXT:    st.w $a1, $a0, %pc_lo12(g_a32+4)
 ; LA64-NEXT:  .LBB21_2: # %if.end
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: control_flow_with_mem_access:
 ; LA64-LARGE:       # %bb.0: # %entry
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a32)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a32)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a32)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.w $a0, $a0, 4
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a32+4)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a32+4)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a32+4)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a32+4)
+; LA64-LARGE-NEXT:    ldx.w $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ori $a1, $zero, 1
 ; LA64-LARGE-NEXT:    blt $a0, $a1, .LBB21_2
 ; LA64-LARGE-NEXT:  # %bb.1: # %if.then
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a32)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a32)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a32)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a32)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ori $a1, $zero, 10
-; LA64-LARGE-NEXT:    st.w $a1, $a0, 4
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a32+4)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a32+4)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a32+4)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a32+4)
+; LA64-LARGE-NEXT:    ori $a2, $zero, 10
+; LA64-LARGE-NEXT:    stx.w $a2, $a1, $a0
 ; LA64-LARGE-NEXT:  .LBB21_2: # %if.end
 ; LA64-LARGE-NEXT:    ret
 entry:
@@ -777,8 +715,7 @@ define dso_local ptr @load_ba_1() nounwind {
 ; LA32-NEXT:  .Ltmp0: # Block address taken
 ; LA32-NEXT:  # %bb.1: # %label
 ; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.Ltmp0)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(.Ltmp0)
-; LA32-NEXT:    ld.w $a0, $a0, 0
+; LA32-NEXT:    ld.w $a0, $a0, %pc_lo12(.Ltmp0)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_ba_1:
@@ -786,8 +723,7 @@ define dso_local ptr @load_ba_1() nounwind {
 ; LA64-NEXT:  .Ltmp0: # Block address taken
 ; LA64-NEXT:  # %bb.1: # %label
 ; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.Ltmp0)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(.Ltmp0)
-; LA64-NEXT:    ld.d $a0, $a0, 0
+; LA64-NEXT:    ld.d $a0, $a0, %pc_lo12(.Ltmp0)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_ba_1:
@@ -798,8 +734,7 @@ define dso_local ptr @load_ba_1() nounwind {
 ; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(.Ltmp0)
 ; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(.Ltmp0)
 ; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(.Ltmp0)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.d $a0, $a0, 0
+; LA64-LARGE-NEXT:    ldx.d $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   br label %label
@@ -813,30 +748,27 @@ define dso_local ptr @load_ba_2() nounwind {
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:  .Ltmp1: # Block address taken
 ; LA32-NEXT:  # %bb.1: # %label
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.Ltmp1)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(.Ltmp1)
-; LA32-NEXT:    ld.w $a0, $a0, 8
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.Ltmp1+8)
+; LA32-NEXT:    ld.w $a0, $a0, %pc_lo12(.Ltmp1+8)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_ba_2:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:  .Ltmp1: # Block address taken
 ; LA64-NEXT:  # %bb.1: # %label
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.Ltmp1)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(.Ltmp1)
-; LA64-NEXT:    ld.d $a0, $a0, 8
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.Ltmp1+8)
+; LA64-NEXT:    ld.d $a0, $a0, %pc_lo12(.Ltmp1+8)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_ba_2:
 ; LA64-LARGE:       # %bb.0: # %entry
 ; LA64-LARGE-NEXT:  .Ltmp1: # Block address taken
 ; LA64-LARGE-NEXT:  # %bb.1: # %label
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(.Ltmp1)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(.Ltmp1)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(.Ltmp1)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(.Ltmp1)
-; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    ld.d $a0, $a0, 8
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(.Ltmp1+8)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(.Ltmp1+8)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(.Ltmp1+8)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(.Ltmp1+8)
+; LA64-LARGE-NEXT:    ldx.d $a0, $a1, $a0
 ; LA64-LARGE-NEXT:    ret
 entry:
   br label %label
@@ -850,26 +782,23 @@ label:
 define dso_local ptr @load_addr_offset_1() nounwind {
 ; LA32-LABEL: load_addr_offset_1:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, 8
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64+8)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_addr_offset_1:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64)
-; LA64-NEXT:    addi.d $a0, $a0, 8
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64+8)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_addr_offset_1:
 ; LA64-LARGE:       # %bb.0: # %entry
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64)
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64+8)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64+8)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64+8)
 ; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    addi.d $a0, $a0, 8
 ; LA64-LARGE-NEXT:    ret
 entry:
   ret ptr getelementptr inbounds ([1 x i64], ptr @g_a64, i64 1)
@@ -878,29 +807,23 @@ entry:
 define dso_local ptr @load_addr_offset_257() nounwind {
 ; LA32-LABEL: load_addr_offset_257:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, 2047
-; LA32-NEXT:    addi.w $a0, $a0, 9
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2056)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64+2056)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_addr_offset_257:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64)
-; LA64-NEXT:    addi.d $a0, $a0, 2047
-; LA64-NEXT:    addi.d $a0, $a0, 9
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2056)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64+2056)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_addr_offset_257:
 ; LA64-LARGE:       # %bb.0: # %entry
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64)
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2056)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64+2056)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64+2056)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64+2056)
 ; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    addi.d $a0, $a0, 2047
-; LA64-LARGE-NEXT:    addi.d $a0, $a0, 9
 ; LA64-LARGE-NEXT:    ret
 entry:
   ret ptr getelementptr inbounds ([1 x i64], ptr @g_a64, i64 257)
@@ -909,27 +832,23 @@ entry:
 define dso_local ptr @load_addr_offset_1048576() nounwind {
 ; LA32-LABEL: load_addr_offset_1048576:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64)
-; LA32-NEXT:    lu12i.w $a1, 2048
-; LA32-NEXT:    add.w $a0, $a0, $a1
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8388608)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64+8388608)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_addr_offset_1048576:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64)
-; LA64-NEXT:    addu16i.d $a0, $a0, 128
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8388608)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64+8388608)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_addr_offset_1048576:
 ; LA64-LARGE:       # %bb.0: # %entry
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64)
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8388608)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64+8388608)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64+8388608)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64+8388608)
 ; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    addu16i.d $a0, $a0, 128
 ; LA64-LARGE-NEXT:    ret
 entry:
   ret ptr getelementptr inbounds ([1 x i64], ptr @g_a64, i64 1048576)
@@ -938,30 +857,23 @@ entry:
 define dso_local ptr @load_addr_offset_1048577() nounwind {
 ; LA32-LABEL: load_addr_offset_1048577:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64)
-; LA32-NEXT:    lu12i.w $a1, 2048
-; LA32-NEXT:    ori $a1, $a1, 8
-; LA32-NEXT:    add.w $a0, $a0, $a1
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8388616)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64+8388616)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_addr_offset_1048577:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64)
-; LA64-NEXT:    addu16i.d $a0, $a0, 128
-; LA64-NEXT:    addi.d $a0, $a0, 8
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8388616)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64+8388616)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_addr_offset_1048577:
 ; LA64-LARGE:       # %bb.0: # %entry
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64)
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+8388616)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64+8388616)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64+8388616)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64+8388616)
 ; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    addu16i.d $a0, $a0, 128
-; LA64-LARGE-NEXT:    addi.d $a0, $a0, 8
 ; LA64-LARGE-NEXT:    ret
 entry:
   ret ptr getelementptr inbounds ([1 x i64], ptr @g_a64, i64 1048577)
@@ -970,29 +882,23 @@ entry:
 define dso_local ptr @load_addr_offset_268432896() nounwind {
 ; LA32-LABEL: load_addr_offset_268432896:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64)
-; LA32-NEXT:    lu12i.w $a1, 524283
-; LA32-NEXT:    add.w $a0, $a0, $a1
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2147463168)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64+2147463168)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_addr_offset_268432896:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64)
-; LA64-NEXT:    lu12i.w $a1, 524283
-; LA64-NEXT:    add.d $a0, $a0, $a1
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2147463168)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64+2147463168)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_addr_offset_268432896:
 ; LA64-LARGE:       # %bb.0: # %entry
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64)
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2147463168)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64+2147463168)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64+2147463168)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64+2147463168)
 ; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    lu12i.w $a1, 524283
-; LA64-LARGE-NEXT:    add.d $a0, $a0, $a1
 ; LA64-LARGE-NEXT:    ret
 entry:
   ret ptr getelementptr inbounds ([1 x i64], ptr @g_a64, i64 268432896)
@@ -1001,32 +907,23 @@ entry:
 define dso_local ptr @load_addr_offset_268432897() nounwind {
 ; LA32-LABEL: load_addr_offset_268432897:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64)
-; LA32-NEXT:    lu12i.w $a1, 524283
-; LA32-NEXT:    ori $a1, $a1, 8
-; LA32-NEXT:    add.w $a0, $a0, $a1
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2147463176)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64+2147463176)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_addr_offset_268432897:
 ; LA64:       # %bb.0: # %entry
-; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64)
-; LA64-NEXT:    lu12i.w $a1, 524283
-; LA64-NEXT:    ori $a1, $a1, 8
-; LA64-NEXT:    add.d $a0, $a0, $a1
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2147463176)
+; LA64-NEXT:    addi.d $a0, $a0, %pc_lo12(g_a64+2147463176)
 ; LA64-NEXT:    ret
 ;
 ; LA64-LARGE-LABEL: load_addr_offset_268432897:
 ; LA64-LARGE:       # %bb.0: # %entry
-; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64)
-; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64)
-; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64)
+; LA64-LARGE-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+2147463176)
+; LA64-LARGE-NEXT:    addi.d $a1, $zero, %pc_lo12(g_a64+2147463176)
+; LA64-LARGE-NEXT:    lu32i.d $a1, %pc64_lo20(g_a64+2147463176)
+; LA64-LARGE-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(g_a64+2147463176)
 ; LA64-LARGE-NEXT:    add.d $a0, $a1, $a0
-; LA64-LARGE-NEXT:    lu12i.w $a1, 524283
-; LA64-LARGE-NEXT:    ori $a1, $a1, 8
-; LA64-LARGE-NEXT:    add.d $a0, $a0, $a1
 ; LA64-LARGE-NEXT:    ret
 entry:
   ret ptr getelementptr inbounds ([1 x i64], ptr @g_a64, i64 268432897)
@@ -1035,11 +932,8 @@ entry:
 define dso_local ptr @load_addr_offset_9380351707272() nounwind {
 ; LA32-LABEL: load_addr_offset_9380351707272:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64)
-; LA32-NEXT:    lu12i.w $a1, 279556
-; LA32-NEXT:    ori $a1, $a1, 1088
-; LA32-NEXT:    add.w $a0, $a0, $a1
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+1145062464)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64+1145062464)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_addr_offset_9380351707272:
@@ -1071,11 +965,8 @@ entry:
 define dso_local ptr @load_addr_offset_614750729487779976() nounwind {
 ; LA32-LABEL: load_addr_offset_614750729487779976:
 ; LA32:       # %bb.0: # %entry
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64)
-; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64)
-; LA32-NEXT:    lu12i.w $a1, 279556
-; LA32-NEXT:    ori $a1, $a1, 1088
-; LA32-NEXT:    add.w $a0, $a0, $a1
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(g_a64+1145062464)
+; LA32-NEXT:    addi.w $a0, $a0, %pc_lo12(g_a64+1145062464)
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: load_addr_offset_614750729487779976:
diff --git a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
index 4e5a5433596dbc..4767adec44eff4 100644
--- a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
+++ b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
@@ -107,6 +107,7 @@
 ; LAXX-NEXT:       Remove dead machine instructions
 ; LA64-NEXT:       LoongArch Optimize W Instructions
 ; LAXX-NEXT:       LoongArch Pre-RA pseudo instruction expansion pass
+; LAXX-NEXT:       LoongArch Merge Base Offset
 ; LAXX-NEXT:       Detect Dead Lanes
 ; LAXX-NEXT:       Init Undef Pass
 ; LAXX-NEXT:       Process Implicit Definitions
diff --git a/llvm/test/CodeGen/LoongArch/psabi-restricted-scheduling.ll b/llvm/test/CodeGen/LoongArch/psabi-restricted-scheduling.ll
index b03a523fb79a9b..a7873f466bee3f 100644
--- a/llvm/test/CodeGen/LoongArch/psabi-restricted-scheduling.ll
+++ b/llvm/test/CodeGen/LoongArch/psabi-restricted-scheduling.ll
@@ -25,8 +25,7 @@ define void @foo() nounwind {
 ; MEDIUM_NO_SCH-NEXT:    ld.d $a0, $a0, %got_pc_lo12(G)
 ; MEDIUM_NO_SCH-NEXT:    ld.d $zero, $a0, 0
 ; MEDIUM_NO_SCH-NEXT:    pcalau12i $a0, %pc_hi20(.Lg$local)
-; MEDIUM_NO_SCH-NEXT:    addi.d $a0, $a0, %pc_lo12(.Lg$local)
-; MEDIUM_NO_SCH-NEXT:    ld.d $zero, $a0, 0
+; MEDIUM_NO_SCH-NEXT:    ld.d $zero, $a0, %pc_lo12(.Lg$local)
 ; MEDIUM_NO_SCH-NEXT:    ori $a0, $zero, 1
 ; MEDIUM_NO_SCH-NEXT:    pcaddu18i $ra, %call36(bar)
 ; MEDIUM_NO_SCH-NEXT:    jirl $ra, $ra, 0
@@ -55,8 +54,7 @@ define void @foo() nounwind {
 ; MEDIUM_SCH-NEXT:    ld.d $a0, $a0, %got_pc_lo12(G)
 ; MEDIUM_SCH-NEXT:    ld.d $zero, $a0, 0
 ; MEDIUM_SCH-NEXT:    pcalau12i $a0, %pc_hi20(.Lg$local)
-; MEDIUM_SCH-NEXT:    addi.d $a0, $a0, %pc_lo12(.Lg$local)
-; MEDIUM_SCH-NEXT:    ld.d $zero, $a0, 0
+; MEDIUM_SCH-NEXT:    ld.d $zero, $a0, %pc_lo12(.Lg$local)
 ; MEDIUM_SCH-NEXT:    ori $a0, $zero, 1
 ; MEDIUM_SCH-NEXT:    pcaddu18i $ra, %call36(bar)
 ; MEDIUM_SCH-NEXT:    jirl $ra, $ra, 0
@@ -91,8 +89,7 @@ define void @foo() nounwind {
 ; LARGE_NO_SCH-NEXT:    addi.d $a1, $zero, %pc_lo12(.Lg$local)
 ; LARGE_NO_SCH-NEXT:    lu32i.d $a1, %pc64_lo20(.Lg$local)
 ; LARGE_NO_SCH-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(.Lg$local)
-; LARGE_NO_SCH-NEXT:    add.d $a0, $a1, $a0
-; LARGE_NO_SCH-NEXT:    ld.d $zero, $a0, 0
+; LARGE_NO_SCH-NEXT:    ldx.d $zero, $a1, $a0
 ; LARGE_NO_SCH-NEXT:    ori $a0, $zero, 1
 ; LARGE_NO_SCH-NEXT:    pcalau12i $a1, %got_pc_hi20(bar)
 ; LARGE_NO_SCH-NEXT:    addi.d $ra, $zero, %got_pc_lo12(bar)
@@ -148,8 +145,7 @@ define void @foo() nounwind {
 ; LARGE_SCH-NEXT:    addi.d $a1, $zero, %pc_lo12(.Lg$local)
 ; LARGE_SCH-NEXT:    lu32i.d $a1, %pc64_lo20(.Lg$local)
 ; LARGE_SCH-NEXT:    lu52i.d $a1, $a1, %pc64_hi12(.Lg$local)
-; LARGE_SCH-NEXT:    add.d $a0, $a1, $a0
-; LARGE_SCH-NEXT:    ld.d $zero, $a0, 0
+; LARGE_SCH-NEXT:    ldx.d $zero, $a1, $a0
 ; LARGE_SCH-NEXT:    ori $a0, $zero, 1
 ; LARGE_SCH-NEXT:    pcalau12i $a1, %got_pc_hi20(bar)
 ; LARGE_SCH-NEXT:    addi.d $ra, $zero, %got_pc_lo12(bar)
diff --git a/llvm/test/CodeGen/LoongArch/vector-fp-imm.ll b/llvm/test/CodeGen/LoongArch/vector-fp-imm.ll
index 0a401ebe5f6b2a..8dd1ec465c13ad 100644
--- a/llvm/test/CodeGen/LoongArch/vector-fp-imm.ll
+++ b/llvm/test/CodeGen/LoongArch/vector-fp-imm.ll
@@ -94,8 +94,7 @@ define void @test_f2(ptr %P, ptr %S) nounwind {
 ; LA32F-NEXT:    fld.s $fa1, $a0, 0
 ; LA32F-NEXT:    addi.w $a0, $zero, 1
 ; LA32F-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI1_0)
-; LA32F-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI1_0)
-; LA32F-NEXT:    fld.s $fa2, $a2, 0
+; LA32F-NEXT:    fld.s $fa2, $a2, %pc_lo12(.LCPI1_0)
 ; LA32F-NEXT:    movgr2fr.w $fa3, $a0
 ; LA32F-NEXT:    ffint.s.w $fa3, $fa3
 ; LA32F-NEXT:    fadd.s $fa1, $fa1, $fa3
@@ -110,8 +109,7 @@ define void @test_f2(ptr %P, ptr %S) nounwind {
 ; LA32D-NEXT:    fld.s $fa1, $a0, 0
 ; LA32D-NEXT:    addi.w $a0, $zero, 1
 ; LA32D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI1_0)
-; LA32D-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI1_0)
-; LA32D-NEXT:    fld.s $fa2, $a2, 0
+; LA32D-NEXT:    fld.s $fa2, $a2, %pc_lo12(.LCPI1_0)
 ; LA32D-NEXT:    movgr2fr.w $fa3, $a0
 ; LA32D-NEXT:    ffint.s.w $fa3, $fa3
 ; LA32D-NEXT:    fadd.s $fa1, $fa1, $fa3
@@ -126,8 +124,7 @@ define void @test_f2(ptr %P, ptr %S) nounwind {
 ; LA64F-NEXT:    fld.s $fa1, $a0, 0
 ; LA64F-NEXT:    addi.w $a0, $zero, 1
 ; LA64F-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI1_0)
-; LA64F-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI1_0)
-; LA64F-NEXT:    fld.s $fa2, $a2, 0
+; LA64F-NEXT:    fld.s $fa2, $a2, %pc_lo12(.LCPI1_0)
 ; LA64F-NEXT:    movgr2fr.w $fa3, $a0
 ; LA64F-NEXT:    ffint.s.w $fa3, $fa3
 ; LA64F-NEXT:    fadd.s $fa1, $fa1, $fa3
@@ -142,8 +139,7 @@ define void @test_f2(ptr %P, ptr %S) nounwind {
 ; LA64D-NEXT:    fld.s $fa1, $a0, 0
 ; LA64D-NEXT:    addi.w $a0, $zero, 1
 ; LA64D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI1_0)
-; LA64D-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI1_0)
-; LA64D-NEXT:    fld.s $fa2, $a2, 0
+; LA64D-NEXT:    fld.s $fa2, $a2, %pc_lo12(.LCPI1_0)
 ; LA64D-NEXT:    movgr2fr.w $fa3, $a0
 ; LA64D-NEXT:    ffint.s.w $fa3, $fa3
 ; LA64D-NEXT:    fadd.s $fa1, $fa1, $fa3
@@ -168,14 +164,11 @@ define void @test_f4(ptr %P, ptr %S) nounwind {
 ; LA32F-NEXT:    movgr2fr.w $fa4, $a0
 ; LA32F-NEXT:    ffint.s.w $fa4, $fa4
 ; LA32F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA32F-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI2_0)
-; LA32F-NEXT:    fld.s $fa5, $a0, 0
+; LA32F-NEXT:    fld.s $fa5, $a0, %pc_lo12(.LCPI2_0)
 ; LA32F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_1)
-; LA32F-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI2_1)
-; LA32F-NEXT:    fld.s $fa6, $a0, 0
+; LA32F-NEXT:    fld.s $fa6, $a0, %pc_lo12(.LCPI2_1)
 ; LA32F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_2)
-; LA32F-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI2_2)
-; LA32F-NEXT:    fld.s $fa7, $a0, 0
+; LA32F-NEXT:    fld.s $fa7, $a0, %pc_lo12(.LCPI2_2)
 ; LA32F-NEXT:    fadd.s $fa3, $fa3, $fa4
 ; LA32F-NEXT:    fadd.s $fa2, $fa2, $fa5
 ; LA32F-NEXT:    fadd.s $fa1, $fa1, $fa6
@@ -196,14 +189,11 @@ define void @test_f4(ptr %P, ptr %S) nounwind {
 ; LA32D-NEXT:    movgr2fr.w $fa4, $a0
 ; LA32D-NEXT:    ffint.s.w $fa4, $fa4
 ; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI2_0)
-; LA32D-NEXT:    fld.s $fa5, $a0, 0
+; LA32D-NEXT:    fld.s $fa5, $a0, %pc_lo12(.LCPI2_0)
 ; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_1)
-; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI2_1)
-; LA32D-NEXT:    fld.s $fa6, $a0, 0
+; LA32D-NEXT:    fld.s $fa6, $a0, %pc_lo12(.LCPI2_1)
 ; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_2)
-; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI2_2)
-; LA32D-NEXT:    fld.s $fa7, $a0, 0
+; LA32D-NEXT:    fld.s $fa7, $a0, %pc_lo12(.LCPI2_2)
 ; LA32D-NEXT:    fadd.s $fa3, $fa3, $fa4
 ; LA32D-NEXT:    fadd.s $fa2, $fa2, $fa5
 ; LA32D-NEXT:    fadd.s $fa1, $fa1, $fa6
@@ -224,14 +214,11 @@ define void @test_f4(ptr %P, ptr %S) nounwind {
 ; LA64F-NEXT:    movgr2fr.w $fa4, $a0
 ; LA64F-NEXT:    ffint.s.w $fa4, $fa4
 ; LA64F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA64F-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI2_0)
-; LA64F-NEXT:    fld.s $fa5, $a0, 0
+; LA64F-NEXT:    fld.s $fa5, $a0, %pc_lo12(.LCPI2_0)
 ; LA64F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_1)
-; LA64F-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI2_1)
-; LA64F-NEXT:    fld.s $fa6, $a0, 0
+; LA64F-NEXT:    fld.s $fa6, $a0, %pc_lo12(.LCPI2_1)
 ; LA64F-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_2)
-; LA64F-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI2_2)
-; LA64F-NEXT:    fld.s $fa7, $a0, 0
+; LA64F-NEXT:    fld.s $fa7, $a0, %pc_lo12(.LCPI2_2)
 ; LA64F-NEXT:    fadd.s $fa3, $fa3, $fa4
 ; LA64F-NEXT:    fadd.s $fa2, $fa2, $fa5
 ; LA64F-NEXT:    fadd.s $fa1, $fa1, $fa6
@@ -252,14 +239,11 @@ define void @test_f4(ptr %P, ptr %S) nounwind {
 ; LA64D-NEXT:    movgr2fr.w $fa4, $a0
 ; LA64D-NEXT:    ffint.s.w $fa4, $fa4
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_0)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI2_0)
-; LA64D-NEXT:    fld.s $fa5, $a0, 0
+; LA64D-NEXT:    fld.s $fa5, $a0, %pc_lo12(.LCPI2_0)
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_1)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI2_1)
-; LA64D-NEXT:    fld.s $fa6, $a0, 0
+; LA64D-NEXT:    fld.s $fa6, $a0, %pc_lo12(.LCPI2_1)
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI2_2)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI2_2)
-; LA64D-NEXT:    fld.s $fa7, $a0, 0
+; LA64D-NEXT:    fld.s $fa7, $a0, %pc_lo12(.LCPI2_2)
 ; LA64D-NEXT:    fadd.s $fa3, $fa3, $fa4
 ; LA64D-NEXT:    fadd.s $fa2, $fa2, $fa5
 ; LA64D-NEXT:    fadd.s $fa1, $fa1, $fa6
@@ -281,14 +265,11 @@ define void @test_f8(ptr %P, ptr %S) nounwind {
 ; LA32F-NEXT:    addi.w $a2, $zero, 1
 ; LA32F-NEXT:    movgr2fr.w $fa0, $a2
 ; LA32F-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_0)
-; LA32F-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI3_0)
-; LA32F-NEXT:    fld.s $fa1, $a2, 0
+; LA32F-NEXT:    fld.s $fa1, $a2, %pc_lo12(.LCPI3_0)
 ; LA32F-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_1)
-; LA32F-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI3_1)
-; LA32F-NEXT:    fld.s $fa2, $a2, 0
+; LA32F-NEXT:    fld.s $fa2, $a2, %pc_lo12(.LCPI3_1)
 ; LA32F-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_2)
-; LA32F-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI3_2)
-; LA32F-NEXT:    fld.s $fa3, $a2, 0
+; LA32F-NEXT:    fld.s $fa3, $a2, %pc_lo12(.LCPI3_2)
 ; LA32F-NEXT:    fld.s $fa4, $a0, 28
 ; LA32F-NEXT:    fld.s $fa5, $a0, 24
 ; LA32F-NEXT:    fld.s $fa6, $a0, 12
@@ -321,14 +302,11 @@ define void @test_f8(ptr %P, ptr %S) nounwind {
 ; LA32D-NEXT:    addi.w $a2, $zero, 1
 ; LA32D-NEXT:    movgr2fr.w $fa0, $a2
 ; LA32D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_0)
-; LA32D-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI3_0)
-; LA32D-NEXT:    fld.s $fa1, $a2, 0
+; LA32D-NEXT:    fld.s $fa1, $a2, %pc_lo12(.LCPI3_0)
 ; LA32D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_1)
-; LA32D-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI3_1)
-; LA32D-NEXT:    fld.s $fa2, $a2, 0
+; LA32D-NEXT:    fld.s $fa2, $a2, %pc_lo12(.LCPI3_1)
 ; LA32D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_2)
-; LA32D-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI3_2)
-; LA32D-NEXT:    fld.s $fa3, $a2, 0
+; LA32D-NEXT:    fld.s $fa3, $a2, %pc_lo12(.LCPI3_2)
 ; LA32D-NEXT:    fld.s $fa4, $a0, 28
 ; LA32D-NEXT:    fld.s $fa5, $a0, 24
 ; LA32D-NEXT:    fld.s $fa6, $a0, 12
@@ -361,14 +339,11 @@ define void @test_f8(ptr %P, ptr %S) nounwind {
 ; LA64F-NEXT:    addi.w $a2, $zero, 1
 ; LA64F-NEXT:    movgr2fr.w $fa0, $a2
 ; LA64F-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_0)
-; LA64F-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI3_0)
-; LA64F-NEXT:    fld.s $fa1, $a2, 0
+; LA64F-NEXT:    fld.s $fa1, $a2, %pc_lo12(.LCPI3_0)
 ; LA64F-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_1)
-; LA64F-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI3_1)
-; LA64F-NEXT:    fld.s $fa2, $a2, 0
+; LA64F-NEXT:    fld.s $fa2, $a2, %pc_lo12(.LCPI3_1)
 ; LA64F-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_2)
-; LA64F-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI3_2)
-; LA64F-NEXT:    fld.s $fa3, $a2, 0
+; LA64F-NEXT:    fld.s $fa3, $a2, %pc_lo12(.LCPI3_2)
 ; LA64F-NEXT:    fld.s $fa4, $a0, 28
 ; LA64F-NEXT:    fld.s $fa5, $a0, 24
 ; LA64F-NEXT:    fld.s $fa6, $a0, 12
@@ -401,14 +376,11 @@ define void @test_f8(ptr %P, ptr %S) nounwind {
 ; LA64D-NEXT:    addi.w $a2, $zero, 1
 ; LA64D-NEXT:    movgr2fr.w $fa0, $a2
 ; LA64D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_0)
-; LA64D-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI3_0)
-; LA64D-NEXT:    fld.s $fa1, $a2, 0
+; LA64D-NEXT:    fld.s $fa1, $a2, %pc_lo12(.LCPI3_0)
 ; LA64D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_1)
-; LA64D-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI3_1)
-; LA64D-NEXT:    fld.s $fa2, $a2, 0
+; LA64D-NEXT:    fld.s $fa2, $a2, %pc_lo12(.LCPI3_1)
 ; LA64D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI3_2)
-; LA64D-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI3_2)
-; LA64D-NEXT:    fld.s $fa3, $a2, 0
+; LA64D-NEXT:    fld.s $fa3, $a2, %pc_lo12(.LCPI3_2)
 ; LA64D-NEXT:    fld.s $fa4, $a0, 28
 ; LA64D-NEXT:    fld.s $fa5, $a0, 24
 ; LA64D-NEXT:    fld.s $fa6, $a0, 12
@@ -488,8 +460,7 @@ define void @test_d2(ptr %P, ptr %S) nounwind {
 ; LA32D-NEXT:    addi.w $a0, $zero, 1
 ; LA32D-NEXT:    movgr2fr.w $fa2, $a0
 ; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI4_0)
-; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI4_0)
-; LA32D-NEXT:    fld.d $fa3, $a0, 0
+; LA32D-NEXT:    fld.d $fa3, $a0, %pc_lo12(.LCPI4_0)
 ; LA32D-NEXT:    ffint.s.w $fa2, $fa2
 ; LA32D-NEXT:    fcvt.d.s $fa2, $fa2
 ; LA32D-NEXT:    fadd.d $fa1, $fa1, $fa2
@@ -529,8 +500,7 @@ define void @test_d2(ptr %P, ptr %S) nounwind {
 ; LA64D-NEXT:    fld.d $fa1, $a0, 0
 ; LA64D-NEXT:    addi.d $a0, $zero, 1
 ; LA64D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI4_0)
-; LA64D-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI4_0)
-; LA64D-NEXT:    fld.d $fa2, $a2, 0
+; LA64D-NEXT:    fld.d $fa2, $a2, %pc_lo12(.LCPI4_0)
 ; LA64D-NEXT:    movgr2fr.d $fa3, $a0
 ; LA64D-NEXT:    ffint.d.l $fa3, $fa3
 ; LA64D-NEXT:    fadd.d $fa1, $fa1, $fa3
@@ -625,14 +595,11 @@ define void @test_d4(ptr %P, ptr %S) nounwind {
 ; LA32D-NEXT:    ffint.s.w $fa4, $fa4
 ; LA32D-NEXT:    fcvt.d.s $fa4, $fa4
 ; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI5_0)
-; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI5_0)
-; LA32D-NEXT:    fld.d $fa5, $a0, 0
+; LA32D-NEXT:    fld.d $fa5, $a0, %pc_lo12(.LCPI5_0)
 ; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI5_1)
-; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI5_1)
-; LA32D-NEXT:    fld.d $fa6, $a0, 0
+; LA32D-NEXT:    fld.d $fa6, $a0, %pc_lo12(.LCPI5_1)
 ; LA32D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI5_2)
-; LA32D-NEXT:    addi.w $a0, $a0, %pc_lo12(.LCPI5_2)
-; LA32D-NEXT:    fld.d $fa7, $a0, 0
+; LA32D-NEXT:    fld.d $fa7, $a0, %pc_lo12(.LCPI5_2)
 ; LA32D-NEXT:    fadd.d $fa3, $fa3, $fa4
 ; LA32D-NEXT:    fadd.d $fa2, $fa2, $fa5
 ; LA32D-NEXT:    fadd.d $fa1, $fa1, $fa6
@@ -696,14 +663,11 @@ define void @test_d4(ptr %P, ptr %S) nounwind {
 ; LA64D-NEXT:    movgr2fr.d $fa4, $a0
 ; LA64D-NEXT:    ffint.d.l $fa4, $fa4
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI5_0)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI5_0)
-; LA64D-NEXT:    fld.d $fa5, $a0, 0
+; LA64D-NEXT:    fld.d $fa5, $a0, %pc_lo12(.LCPI5_0)
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI5_1)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI5_1)
-; LA64D-NEXT:    fld.d $fa6, $a0, 0
+; LA64D-NEXT:    fld.d $fa6, $a0, %pc_lo12(.LCPI5_1)
 ; LA64D-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI5_2)
-; LA64D-NEXT:    addi.d $a0, $a0, %pc_lo12(.LCPI5_2)
-; LA64D-NEXT:    fld.d $fa7, $a0, 0
+; LA64D-NEXT:    fld.d $fa7, $a0, %pc_lo12(.LCPI5_2)
 ; LA64D-NEXT:    fadd.d $fa3, $fa3, $fa4
 ; LA64D-NEXT:    fadd.d $fa2, $fa2, $fa5
 ; LA64D-NEXT:    fadd.d $fa1, $fa1, $fa6
@@ -852,14 +816,11 @@ define void @test_d8(ptr %P, ptr %S) nounwind {
 ; LA32D-NEXT:    addi.w $a2, $zero, 1
 ; LA32D-NEXT:    movgr2fr.w $fa0, $a2
 ; LA32D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI6_0)
-; LA32D-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI6_0)
-; LA32D-NEXT:    fld.d $fa1, $a2, 0
+; LA32D-NEXT:    fld.d $fa1, $a2, %pc_lo12(.LCPI6_0)
 ; LA32D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI6_1)
-; LA32D-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI6_1)
-; LA32D-NEXT:    fld.d $fa2, $a2, 0
+; LA32D-NEXT:    fld.d $fa2, $a2, %pc_lo12(.LCPI6_1)
 ; LA32D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI6_2)
-; LA32D-NEXT:    addi.w $a2, $a2, %pc_lo12(.LCPI6_2)
-; LA32D-NEXT:    fld.d $fa3, $a2, 0
+; LA32D-NEXT:    fld.d $fa3, $a2, %pc_lo12(.LCPI6_2)
 ; LA32D-NEXT:    fld.d $fa4, $a0, 56
 ; LA32D-NEXT:    fld.d $fa5, $a0, 48
 ; LA32D-NEXT:    fld.d $fa6, $a0, 24
@@ -976,14 +937,11 @@ define void @test_d8(ptr %P, ptr %S) nounwind {
 ; LA64D-NEXT:    addi.d $a2, $zero, 1
 ; LA64D-NEXT:    movgr2fr.d $fa0, $a2
 ; LA64D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI6_0)
-; LA64D-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI6_0)
-; LA64D-NEXT:    fld.d $fa1, $a2, 0
+; LA64D-NEXT:    fld.d $fa1, $a2, %pc_lo12(.LCPI6_0)
 ; LA64D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI6_1)
-; LA64D-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI6_1)
-; LA64D-NEXT:    fld.d $fa2, $a2, 0
+; LA64D-NEXT:    fld.d $fa2, $a2, %pc_lo12(.LCPI6_1)
 ; LA64D-NEXT:    pcalau12i $a2, %pc_hi20(.LCPI6_2)
-; LA64D-NEXT:    addi.d $a2, $a2, %pc_lo12(.LCPI6_2)
-; LA64D-NEXT:    fld.d $fa3, $a2, 0
+; LA64D-NEXT:    fld.d $fa3, $a2, %pc_lo12(.LCPI6_2)
 ; LA64D-NEXT:    fld.d $fa4, $a0, 56
 ; LA64D-NEXT:    fld.d $fa5, $a0, 48
 ; LA64D-NEXT:    fld.d $fa6, $a0, 24
diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected
index 56b6c90a2f6f33..7a7115b393b1db 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.generated.expected
@@ -122,7 +122,6 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
 ; CHECK-NEXT:    .cfi_def_cfa 22, 0
 ; CHECK-NEXT:    st.w $zero, $fp, -12
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(x)
-; CHECK-NEXT:    addi.w $a0, $a0, %pc_lo12(x)
 ; CHECK-NEXT:    ori $a1, $zero, 1
 ; CHECK-NEXT:    st.w $a1, $fp, -16
 ; CHECK-NEXT:    ori $a2, $zero, 2
@@ -131,7 +130,7 @@ attributes #0 = { noredzone nounwind ssp uwtable "frame-pointer"="all" }
 ; CHECK-NEXT:    st.w $a3, $fp, -24
 ; CHECK-NEXT:    ori $a4, $zero, 4
 ; CHECK-NEXT:    st.w $a4, $fp, -28
-; CHECK-NEXT:    st.w $a1, $a0, 0
+; CHECK-NEXT:    st.w $a1, $a0, %pc_lo12(x)
 ; CHECK-NEXT:    #APP
 ; CHECK-NEXT:    #NO_APP
 ; CHECK-NEXT:    st.w $a1, $fp, -16
diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected
index 2e063202fcf79e..d99eb3749826f0 100644
--- a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected
+++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/loongarch_generated_funcs.ll.nogenerated.expected
@@ -99,7 +99,6 @@ define dso_local i32 @main() #0 {
 ; CHECK-NEXT:    .cfi_def_cfa 22, 0
 ; CHECK-NEXT:    st.w $zero, $fp, -12
 ; CHECK-NEXT:    pcalau12i $a0, %pc_hi20(x)
-; CHECK-NEXT:    addi.w $a0, $a0, %pc_lo12(x)
 ; CHECK-NEXT:    ori $a1, $zero, 1
 ; CHECK-NEXT:    st.w $a1, $fp, -16
 ; CHECK-NEXT:    ori $a2, $zero, 2
@@ -108,7 +107,7 @@ define dso_local i32 @main() #0 {
 ; CHECK-NEXT:    st.w $a3, $fp, -24
 ; CHECK-NEXT:    ori $a4, $zero, 4
 ; CHECK-NEXT:    st.w $a4, $fp, -28
-; CHECK-NEXT:    st.w $a1, $a0, 0
+; CHECK-NEXT:    st.w $a1, $a0, %pc_lo12(x)
 ; CHECK-NEXT:    #APP
 ; CHECK-NEXT:    #NO_APP
 ; CHECK-NEXT:    st.w $a1, $fp, -16
diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn
index 248e47a9584cdf..09a5311c122fc5 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Target/LoongArch/BUILD.gn
@@ -42,6 +42,7 @@ static_library("LLVMLoongArchCodeGen") {
     "LoongArchISelLowering.cpp",
     "LoongArchInstrInfo.cpp",
     "LoongArchMCInstLower.cpp",
+    "LoongArchMergeBaseOffset.cpp",
     "LoongArchOptWInstrs.cpp",
     "LoongArchRegisterInfo.cpp",
     "LoongArchSubtarget.cpp",

>From 44bc783e25d4d45389c60c1c070dc96a7b4f4667 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Thu, 8 Aug 2024 12:00:47 +0800
Subject: [PATCH 2/2] Address wanglei's comments

---
 .../LoongArch/LoongArchMergeBaseOffset.cpp    | 21 +++++++++++--------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp b/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp
index 4fbe31616a7efc..ae50b7a6f923e3 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMergeBaseOffset.cpp
@@ -108,8 +108,11 @@ bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
   if (Hi20Op1.getTargetFlags() != LoongArchII::MO_PCREL_HI)
     return false;
 
-  if (!(Hi20Op1.isGlobal() || Hi20Op1.isCPI() || Hi20Op1.isBlockAddress()) ||
-      Hi20Op1.getOffset() != 0)
+  auto isGlobalOrCPIOrBlockAddress = [](const MachineOperand &Op) {
+    return Op.isGlobal() || Op.isCPI() || Op.isBlockAddress();
+  };
+
+  if (!isGlobalOrCPIOrBlockAddress(Hi20Op1) || Hi20Op1.getOffset() != 0)
     return false;
 
   Register HiDestReg = Hi20.getOperand(0).getReg();
@@ -126,12 +129,14 @@ bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
     assert(ST->is64Bit());
     Last = UseInst;
 
-    Hi12 = MRI->getVRegDef(Last->getOperand(1).getReg());
+    Register LastOp1Reg = Last->getOperand(1).getReg();
+    if (!LastOp1Reg.isVirtual())
+      return false;
+    Hi12 = MRI->getVRegDef(LastOp1Reg);
     const MachineOperand &Hi12Op2 = Hi12->getOperand(2);
     if (Hi12Op2.getTargetFlags() != LoongArchII::MO_PCREL64_HI)
       return false;
-    if (!(Hi12Op2.isGlobal() || Hi12Op2.isCPI() || Hi12Op2.isBlockAddress()) ||
-        Hi12Op2.getOffset() != 0)
+    if (!isGlobalOrCPIOrBlockAddress(Hi12Op2) || Hi12Op2.getOffset() != 0)
       return false;
     if (!MRI->hasOneUse(Hi12->getOperand(0).getReg()))
       return false;
@@ -140,8 +145,7 @@ bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
     const MachineOperand &Lo20Op2 = Lo20->getOperand(2);
     if (Lo20Op2.getTargetFlags() != LoongArchII::MO_PCREL64_LO)
       return false;
-    if (!(Lo20Op2.isGlobal() || Lo20Op2.isCPI() || Lo20Op2.isBlockAddress()) ||
-        Lo20Op2.getOffset() != 0)
+    if (!isGlobalOrCPIOrBlockAddress(Lo20Op2) || Lo20Op2.getOffset() != 0)
       return false;
     if (!MRI->hasOneUse(Lo20->getOperand(0).getReg()))
       return false;
@@ -154,8 +158,7 @@ bool LoongArchMergeBaseOffsetOpt::detectFoldable(MachineInstr &Hi20,
   const MachineOperand &Lo12Op2 = Lo12->getOperand(2);
   assert(Hi20.getOpcode() == LoongArch::PCALAU12I);
   if (Lo12Op2.getTargetFlags() != LoongArchII::MO_PCREL_LO ||
-      !(Lo12Op2.isGlobal() || Lo12Op2.isCPI() || Lo12Op2.isBlockAddress() ||
-        Lo12Op2.isMCSymbol()) ||
+      !(isGlobalOrCPIOrBlockAddress(Lo12Op2) || Lo12Op2.isMCSymbol()) ||
       Lo12Op2.getOffset() != 0)
     return false;
 



More information about the llvm-commits mailing list