[RISCV] Add new lga pseudoinstruction
authorJessica Clarke <jrtc27@jrtc27.com>
Wed, 31 May 2023 17:30:27 +0000 (18:30 +0100)
committerJessica Clarke <jrtc27@jrtc27.com>
Wed, 31 May 2023 17:48:21 +0000 (18:48 +0100)
This mirrors lla and is always GOT-relative, allowing an explicit
request to use the GOT without having to expand the instruction. This
then means la is just defined in terms of lla and lga in the assembler,
based on whether PIC is enabled, and at the codegen level we replace la
entirely with lga since we only ever use la there when we want to load
from the GOT (and assert that to be the case).

See https://github.com/riscv-non-isa/riscv-asm-manual/issues/50

Reviewed By: asb, MaskRay

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

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.h
llvm/lib/Target/RISCV/RISCVInstrInfo.td
llvm/test/MC/RISCV/rvi-pseudos-invalid.s
llvm/test/MC/RISCV/rvi-pseudos.s

index 6006a13..f7af251 100644 (file)
@@ -139,6 +139,9 @@ class RISCVAsmParser : public MCTargetAsmParser {
   // Helper to emit pseudo instruction "lla" used in PC-rel addressing.
   void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
 
+  // Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
+  void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+
   // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
   void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
 
@@ -3088,29 +3091,34 @@ void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
                     RISCV::ADDI, IDLoc, Out);
 }
 
+void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
+                                           MCStreamer &Out) {
+  // The load global address pseudo-instruction "lga" is used in GOT-indirect
+  // addressing of global symbols:
+  //   lga rdest, symbol
+  // expands to
+  //   TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
+  //             Lx rdest, %pcrel_lo(TmpLabel)(rdest)
+  MCOperand DestReg = Inst.getOperand(0);
+  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
+  unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
+  emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
+                    SecondOpcode, IDLoc, Out);
+}
+
 void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
                                      MCStreamer &Out) {
   // The load address pseudo-instruction "la" is used in PC-relative and
   // GOT-indirect addressing of global symbols:
   //   la rdest, symbol
-  // expands to either (for non-PIC)
-  //   TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
-  //             ADDI rdest, rdest, %pcrel_lo(TmpLabel)
+  // is an alias for either (for non-PIC)
+  //   lla rdest, symbol
   // or (for PIC)
-  //   TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
-  //             Lx rdest, %pcrel_lo(TmpLabel)(rdest)
-  MCOperand DestReg = Inst.getOperand(0);
-  const MCExpr *Symbol = Inst.getOperand(1).getExpr();
-  unsigned SecondOpcode;
-  RISCVMCExpr::VariantKind VKHi;
-  if (ParserOptions.IsPicEnabled) {
-    SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
-    VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
-  } else {
-    SecondOpcode = RISCV::ADDI;
-    VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
-  }
-  emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
+  //   lga rdest, symbol
+  if (ParserOptions.IsPicEnabled)
+    emitLoadGlobalAddress(Inst, IDLoc, Out);
+  else
+    emitLoadLocalAddress(Inst, IDLoc, Out);
 }
 
 void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
@@ -3438,6 +3446,9 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
   case RISCV::PseudoLLA:
     emitLoadLocalAddress(Inst, IDLoc, Out);
     return false;
+  case RISCV::PseudoLGA:
+    emitLoadGlobalAddress(Inst, IDLoc, Out);
+    return false;
   case RISCV::PseudoLA:
     emitLoadAddress(Inst, IDLoc, Out);
     return false;
index 00868da..00b2959 100644 (file)
@@ -371,9 +371,9 @@ private:
   bool expandLoadLocalAddress(MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator MBBI,
                               MachineBasicBlock::iterator &NextMBBI);
-  bool expandLoadAddress(MachineBasicBlock &MBB,
-                         MachineBasicBlock::iterator MBBI,
-                         MachineBasicBlock::iterator &NextMBBI);
+  bool expandLoadGlobalAddress(MachineBasicBlock &MBB,
+                               MachineBasicBlock::iterator MBBI,
+                               MachineBasicBlock::iterator &NextMBBI);
   bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator MBBI,
                               MachineBasicBlock::iterator &NextMBBI);
@@ -431,8 +431,8 @@ bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB,
   switch (MBBI->getOpcode()) {
   case RISCV::PseudoLLA:
     return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
-  case RISCV::PseudoLA:
-    return expandLoadAddress(MBB, MBBI, NextMBBI);
+  case RISCV::PseudoLGA:
+    return expandLoadGlobalAddress(MBB, MBBI, NextMBBI);
   case RISCV::PseudoLA_TLS_IE:
     return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
   case RISCV::PseudoLA_TLS_GD:
@@ -480,17 +480,12 @@ bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(
                              RISCV::ADDI);
 }
 
-bool RISCVPreRAExpandPseudo::expandLoadAddress(
+bool RISCVPreRAExpandPseudo::expandLoadGlobalAddress(
     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
     MachineBasicBlock::iterator &NextMBBI) {
   MachineFunction *MF = MBB.getParent();
 
   const auto &STI = MF->getSubtarget<RISCVSubtarget>();
-  // When HWASAN is used and tagging of global variables is enabled
-  // they should be accessed via the GOT, since the tagged address of a global
-  // is incompatible with existing code models. This also applies to non-pic
-  // mode.
-  assert(MF->getTarget().isPositionIndependent() || STI.allowTaggedGlobals());
   unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,
                              SecondOpcode);
index 582e66b..6662d37 100644 (file)
@@ -5278,7 +5278,7 @@ SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
       return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
 
     // Use PC-relative addressing to access the GOT for this symbol, then load
-    // the address from the GOT. This generates the pattern (PseudoLA sym),
+    // the address from the GOT. This generates the pattern (PseudoLGA sym),
     // which expands to (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
     MachineFunction &MF = DAG.getMachineFunction();
     MachineMemOperand *MemOp = MF.getMachineMemOperand(
@@ -5287,7 +5287,7 @@ SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
             MachineMemOperand::MOInvariant,
         LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));
     SDValue Load =
-        DAG.getMemIntrinsicNode(RISCVISD::LA, DL, DAG.getVTList(Ty, MVT::Other),
+        DAG.getMemIntrinsicNode(RISCVISD::LGA, DL, DAG.getVTList(Ty, MVT::Other),
                                 {DAG.getEntryNode(), Addr}, Ty, MemOp);
     return Load;
   }
@@ -15279,8 +15279,8 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
   NODE_NAME_CASE(ADD_LO)
   NODE_NAME_CASE(HI)
   NODE_NAME_CASE(LLA)
+  NODE_NAME_CASE(LGA)
   NODE_NAME_CASE(ADD_TPREL)
-  NODE_NAME_CASE(LA)
   NODE_NAME_CASE(LA_TLS_IE)
   NODE_NAME_CASE(LA_TLS_GD)
   NODE_NAME_CASE(MULHSU)
index af6849c..6c66982 100644 (file)
@@ -371,8 +371,9 @@ enum NodeType : unsigned {
   // have memop! In fact, starting from FIRST_TARGET_MEMORY_OPCODE all
   // opcodes will be thought as target memory ops!
 
-  // Load address.
-  LA = ISD::FIRST_TARGET_MEMORY_OPCODE,
+  // Represents an AUIPC+L[WD] pair. Selected to PseudoLGA.
+  LGA = ISD::FIRST_TARGET_MEMORY_OPCODE,
+  // Load initial exec thread-local address.
   LA_TLS_IE,
 
   TH_LWD,
index 60f943d..22bd42b 100644 (file)
@@ -84,14 +84,14 @@ def riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE",
 def riscv_add_lo : SDNode<"RISCVISD::ADD_LO", SDTIntBinOp>;
 def riscv_hi : SDNode<"RISCVISD::HI", SDTIntUnaryOp>;
 def riscv_lla : SDNode<"RISCVISD::LLA", SDTIntUnaryOp>;
+def riscv_lga : SDNode<"RISCVISD::LGA", SDTLoad,
+                       [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
 def riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL",
                              SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
                                                   SDTCisSameAs<0, 2>,
                                                   SDTCisSameAs<0, 3>,
                                                   SDTCisInt<0>]>>;
 
-def riscv_la : SDNode<"RISCVISD::LA", SDTLoad,
-                      [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
 def riscv_la_tls_ie : SDNode<"RISCVISD::LA_TLS_IE", SDTLoad,
                              [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
 def riscv_la_tls_gd : SDNode<"RISCVISD::LA_TLS_GD", SDTIntUnaryOp>;
@@ -1601,11 +1601,16 @@ def : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>;
 
 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
     isAsmParserOnly = 1 in
+def PseudoLGA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
+                       "lga", "$dst, $src">;
+
+def : Pat<(riscv_lga tglobaladdr:$in), (PseudoLGA tglobaladdr:$in)>;
+
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
+    isAsmParserOnly = 1 in
 def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
                       "la", "$dst, $src">;
 
-def : Pat<(riscv_la tglobaladdr:$in), (PseudoLA tglobaladdr:$in)>;
-
 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
     isAsmParserOnly = 1 in
 def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
index 9d9849b..f692272 100644 (file)
@@ -11,6 +11,16 @@ lla x1, %lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol na
 lla x1, %hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
 lla x1, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
 
+lga x1, 1234 # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lga x1, %pcrel_hi(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lga x1, %pcrel_lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lga x1, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lga x1, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lga x1, %hi(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lga x1, %lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lga x1, %hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lga x1, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+
 la x1, 1234 # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
 la x1, %pcrel_hi(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
 la x1, %pcrel_lo(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
index 7a20cfc..a79381a 100644 (file)
@@ -38,158 +38,194 @@ lla a4, f1
 # CHECK: addi  a5, a5, %pcrel_lo(.Lpcrel_hi5)
 lla a5, a_symbol + (0xFF << 3)
 
-# CHECK: .Lpcrel_hi6:
+# CHECK:      .Lpcrel_hi6:
+# CHECK:      auipc a0, %got_pcrel_hi(a_symbol)
+# CHECK-RV32: lw    a0, %pcrel_lo(.Lpcrel_hi6)(a0)
+# CHECK-RV64: ld    a0, %pcrel_lo(.Lpcrel_hi6)(a0)
+lga a0, a_symbol
+
+# CHECK:      .Lpcrel_hi7:
+# CHECK:      auipc a1, %got_pcrel_hi(another_symbol)
+# CHECK-RV32: lw    a1, %pcrel_lo(.Lpcrel_hi7)(a1)
+# CHECK-RV64: ld    a1, %pcrel_lo(.Lpcrel_hi7)(a1)
+lga a1, another_symbol
+
+# CHECK:      .Lpcrel_hi8:
+# CHECK:      auipc a2, %got_pcrel_hi(zero)
+# CHECK-RV32: lw    a2, %pcrel_lo(.Lpcrel_hi8)(a2)
+# CHECK-RV64: ld    a2, %pcrel_lo(.Lpcrel_hi8)(a2)
+lga a2, zero
+
+# CHECK:      .Lpcrel_hi9:
+# CHECK:      auipc a3, %got_pcrel_hi(ra)
+# CHECK-RV32: lw    a3, %pcrel_lo(.Lpcrel_hi9)(a3)
+# CHECK-RV64: ld    a3, %pcrel_lo(.Lpcrel_hi9)(a3)
+lga a3, ra
+
+# CHECK:      .Lpcrel_hi10:
+# CHECK:      auipc a4, %got_pcrel_hi(f1)
+# CHECK-RV32: lw    a4, %pcrel_lo(.Lpcrel_hi10)(a4)
+# CHECK-RV64: ld    a4, %pcrel_lo(.Lpcrel_hi10)(a4)
+lga a4, f1
+
+# CHECK:      .Lpcrel_hi11:
+# CHECK:      auipc a5, %got_pcrel_hi(a_symbol+2040)
+# CHECK-RV32: lw    a5, %pcrel_lo(.Lpcrel_hi11)(a5)
+# CHECK-RV64: ld    a5, %pcrel_lo(.Lpcrel_hi11)(a5)
+lga a5, a_symbol + (0xFF << 3)
+
+# CHECK: .Lpcrel_hi12:
 # CHECK-NOPIC: auipc a0, %pcrel_hi(a_symbol)
-# CHECK-NOPIC: addi  a0, a0, %pcrel_lo(.Lpcrel_hi6)
+# CHECK-NOPIC: addi  a0, a0, %pcrel_lo(.Lpcrel_hi12)
 # CHECK-PIC:      auipc a0, %got_pcrel_hi(a_symbol)
-# CHECK-PIC-RV32: lw    a0, %pcrel_lo(.Lpcrel_hi6)(a0)
-# CHECK-PIC-RV64: ld    a0, %pcrel_lo(.Lpcrel_hi6)(a0)
+# CHECK-PIC-RV32: lw    a0, %pcrel_lo(.Lpcrel_hi12)(a0)
+# CHECK-PIC-RV64: ld    a0, %pcrel_lo(.Lpcrel_hi12)(a0)
 la a0, a_symbol
 
-# CHECK: .Lpcrel_hi7:
+# CHECK: .Lpcrel_hi13:
 # CHECK-NOPIC: auipc a1, %pcrel_hi(another_symbol)
-# CHECK-NOPIC: addi  a1, a1, %pcrel_lo(.Lpcrel_hi7)
+# CHECK-NOPIC: addi  a1, a1, %pcrel_lo(.Lpcrel_hi13)
 # CHECK-PIC:      auipc a1, %got_pcrel_hi(another_symbol)
-# CHECK-PIC-RV32: lw    a1, %pcrel_lo(.Lpcrel_hi7)(a1)
-# CHECK-PIC-RV64: ld    a1, %pcrel_lo(.Lpcrel_hi7)(a1)
+# CHECK-PIC-RV32: lw    a1, %pcrel_lo(.Lpcrel_hi13)(a1)
+# CHECK-PIC-RV64: ld    a1, %pcrel_lo(.Lpcrel_hi13)(a1)
 la a1, another_symbol
 
 # Check that we can load the address of symbols that are spelled like a register
-# CHECK: .Lpcrel_hi8:
+# CHECK: .Lpcrel_hi14:
 # CHECK-NOPIC: auipc a2, %pcrel_hi(zero)
-# CHECK-NOPIC: addi  a2, a2, %pcrel_lo(.Lpcrel_hi8)
+# CHECK-NOPIC: addi  a2, a2, %pcrel_lo(.Lpcrel_hi14)
 # CHECK-PIC:      auipc a2, %got_pcrel_hi(zero)
-# CHECK-PIC-RV32: lw    a2, %pcrel_lo(.Lpcrel_hi8)(a2)
-# CHECK-PIC-RV64: ld    a2, %pcrel_lo(.Lpcrel_hi8)(a2)
+# CHECK-PIC-RV32: lw    a2, %pcrel_lo(.Lpcrel_hi14)(a2)
+# CHECK-PIC-RV64: ld    a2, %pcrel_lo(.Lpcrel_hi14)(a2)
 la a2, zero
 
-# CHECK: .Lpcrel_hi9:
+# CHECK: .Lpcrel_hi15:
 # CHECK-NOPIC: auipc a3, %pcrel_hi(ra)
-# CHECK-NOPIC: addi  a3, a3, %pcrel_lo(.Lpcrel_hi9)
+# CHECK-NOPIC: addi  a3, a3, %pcrel_lo(.Lpcrel_hi15)
 # CHECK-PIC:      auipc a3, %got_pcrel_hi(ra)
-# CHECK-PIC-RV32: lw    a3, %pcrel_lo(.Lpcrel_hi9)(a3)
-# CHECK-PIC-RV64: ld    a3, %pcrel_lo(.Lpcrel_hi9)(a3)
+# CHECK-PIC-RV32: lw    a3, %pcrel_lo(.Lpcrel_hi15)(a3)
+# CHECK-PIC-RV64: ld    a3, %pcrel_lo(.Lpcrel_hi15)(a3)
 la a3, ra
 
-# CHECK: .Lpcrel_hi10:
+# CHECK: .Lpcrel_hi16:
 # CHECK-NOPIC: auipc a4, %pcrel_hi(f1)
-# CHECK-NOPIC: addi  a4, a4, %pcrel_lo(.Lpcrel_hi10)
+# CHECK-NOPIC: addi  a4, a4, %pcrel_lo(.Lpcrel_hi16)
 # CHECK-PIC:      auipc a4, %got_pcrel_hi(f1)
-# CHECK-PIC-RV32: lw    a4, %pcrel_lo(.Lpcrel_hi10)(a4)
-# CHECK-PIC-RV64: ld    a4, %pcrel_lo(.Lpcrel_hi10)(a4)
+# CHECK-PIC-RV32: lw    a4, %pcrel_lo(.Lpcrel_hi16)(a4)
+# CHECK-PIC-RV64: ld    a4, %pcrel_lo(.Lpcrel_hi16)(a4)
 la a4, f1
 
-# CHECK: .Lpcrel_hi11:
+# CHECK: .Lpcrel_hi17:
 # CHECK: auipc a0, %tls_ie_pcrel_hi(a_symbol)
-# CHECK-RV32: lw    a0, %pcrel_lo(.Lpcrel_hi11)(a0)
-# CHECK-RV64: ld    a0, %pcrel_lo(.Lpcrel_hi11)(a0)
+# CHECK-RV32: lw    a0, %pcrel_lo(.Lpcrel_hi17)(a0)
+# CHECK-RV64: ld    a0, %pcrel_lo(.Lpcrel_hi17)(a0)
 la.tls.ie a0, a_symbol
 
-# CHECK: .Lpcrel_hi12:
+# CHECK: .Lpcrel_hi18:
 # CHECK: auipc a1, %tls_ie_pcrel_hi(another_symbol)
-# CHECK-RV32: lw    a1, %pcrel_lo(.Lpcrel_hi12)(a1)
-# CHECK-RV64: ld    a1, %pcrel_lo(.Lpcrel_hi12)(a1)
+# CHECK-RV32: lw    a1, %pcrel_lo(.Lpcrel_hi18)(a1)
+# CHECK-RV64: ld    a1, %pcrel_lo(.Lpcrel_hi18)(a1)
 la.tls.ie a1, another_symbol
 
 # Check that we can load the address of symbols that are spelled like a register
-# CHECK: .Lpcrel_hi13:
+# CHECK: .Lpcrel_hi19:
 # CHECK: auipc a2, %tls_ie_pcrel_hi(zero)
-# CHECK-RV32: lw    a2, %pcrel_lo(.Lpcrel_hi13)(a2)
-# CHECK-RV64: ld    a2, %pcrel_lo(.Lpcrel_hi13)(a2)
+# CHECK-RV32: lw    a2, %pcrel_lo(.Lpcrel_hi19)(a2)
+# CHECK-RV64: ld    a2, %pcrel_lo(.Lpcrel_hi19)(a2)
 la.tls.ie a2, zero
 
-# CHECK: .Lpcrel_hi14:
+# CHECK: .Lpcrel_hi20:
 # CHECK: auipc a3, %tls_ie_pcrel_hi(ra)
-# CHECK-RV32: lw    a3, %pcrel_lo(.Lpcrel_hi14)(a3)
-# CHECK-RV64: ld    a3, %pcrel_lo(.Lpcrel_hi14)(a3)
+# CHECK-RV32: lw    a3, %pcrel_lo(.Lpcrel_hi20)(a3)
+# CHECK-RV64: ld    a3, %pcrel_lo(.Lpcrel_hi20)(a3)
 la.tls.ie a3, ra
 
-# CHECK: .Lpcrel_hi15:
+# CHECK: .Lpcrel_hi21:
 # CHECK: auipc a4, %tls_ie_pcrel_hi(f1)
-# CHECK-RV32: lw    a4, %pcrel_lo(.Lpcrel_hi15)(a4)
-# CHECK-RV64: ld    a4, %pcrel_lo(.Lpcrel_hi15)(a4)
+# CHECK-RV32: lw    a4, %pcrel_lo(.Lpcrel_hi21)(a4)
+# CHECK-RV64: ld    a4, %pcrel_lo(.Lpcrel_hi21)(a4)
 la.tls.ie a4, f1
 
-# CHECK: .Lpcrel_hi16:
+# CHECK: .Lpcrel_hi22:
 # CHECK: auipc a0, %tls_gd_pcrel_hi(a_symbol)
-# CHECK: addi  a0, a0, %pcrel_lo(.Lpcrel_hi16)
+# CHECK: addi  a0, a0, %pcrel_lo(.Lpcrel_hi22)
 la.tls.gd a0, a_symbol
 
-# CHECK: .Lpcrel_hi17:
+# CHECK: .Lpcrel_hi23:
 # CHECK: auipc a1, %tls_gd_pcrel_hi(another_symbol)
-# CHECK: addi  a1, a1, %pcrel_lo(.Lpcrel_hi17)
+# CHECK: addi  a1, a1, %pcrel_lo(.Lpcrel_hi23)
 la.tls.gd a1, another_symbol
 
 # Check that we can load the address of symbols that are spelled like a register
-# CHECK: .Lpcrel_hi18:
+# CHECK: .Lpcrel_hi24:
 # CHECK: auipc a2, %tls_gd_pcrel_hi(zero)
-# CHECK: addi  a2, a2, %pcrel_lo(.Lpcrel_hi18)
+# CHECK: addi  a2, a2, %pcrel_lo(.Lpcrel_hi24)
 la.tls.gd a2, zero
 
-# CHECK: .Lpcrel_hi19:
+# CHECK: .Lpcrel_hi25:
 # CHECK: auipc a3, %tls_gd_pcrel_hi(ra)
-# CHECK: addi  a3, a3, %pcrel_lo(.Lpcrel_hi19)
+# CHECK: addi  a3, a3, %pcrel_lo(.Lpcrel_hi25)
 la.tls.gd a3, ra
 
-# CHECK: .Lpcrel_hi20:
+# CHECK: .Lpcrel_hi26:
 # CHECK: auipc a4, %tls_gd_pcrel_hi(f1)
-# CHECK: addi  a4, a4, %pcrel_lo(.Lpcrel_hi20)
+# CHECK: addi  a4, a4, %pcrel_lo(.Lpcrel_hi26)
 la.tls.gd a4, f1
 
-# CHECK: .Lpcrel_hi21:
+# CHECK: .Lpcrel_hi27:
 # CHECK: auipc a0, %pcrel_hi(a_symbol)
-# CHECK: lb  a0, %pcrel_lo(.Lpcrel_hi21)(a0)
+# CHECK: lb  a0, %pcrel_lo(.Lpcrel_hi27)(a0)
 lb a0, a_symbol
 
-# CHECK: .Lpcrel_hi22:
+# CHECK: .Lpcrel_hi28:
 # CHECK: auipc a1, %pcrel_hi(a_symbol)
-# CHECK: lh  a1, %pcrel_lo(.Lpcrel_hi22)(a1)
+# CHECK: lh  a1, %pcrel_lo(.Lpcrel_hi28)(a1)
 lh a1, a_symbol
 
-# CHECK: .Lpcrel_hi23:
+# CHECK: .Lpcrel_hi29:
 # CHECK: auipc a2, %pcrel_hi(a_symbol)
-# CHECK: lhu  a2, %pcrel_lo(.Lpcrel_hi23)(a2)
+# CHECK: lhu  a2, %pcrel_lo(.Lpcrel_hi29)(a2)
 lhu a2, a_symbol
 
-# CHECK: .Lpcrel_hi24:
+# CHECK: .Lpcrel_hi30:
 # CHECK: auipc a3, %pcrel_hi(a_symbol)
-# CHECK: lw  a3, %pcrel_lo(.Lpcrel_hi24)(a3)
+# CHECK: lw  a3, %pcrel_lo(.Lpcrel_hi30)(a3)
 lw a3, a_symbol
 
-# CHECK: .Lpcrel_hi25:
+# CHECK: .Lpcrel_hi31:
 # CHECK: auipc a4, %pcrel_hi(a_symbol)
-# CHECK: sb  a3, %pcrel_lo(.Lpcrel_hi25)(a4)
+# CHECK: sb  a3, %pcrel_lo(.Lpcrel_hi31)(a4)
 sb a3, a_symbol, a4
 
-# CHECK: .Lpcrel_hi26:
+# CHECK: .Lpcrel_hi32:
 # CHECK: auipc a4, %pcrel_hi(a_symbol)
-# CHECK: sh  a3, %pcrel_lo(.Lpcrel_hi26)(a4)
+# CHECK: sh  a3, %pcrel_lo(.Lpcrel_hi32)(a4)
 sh a3, a_symbol, a4
 
-# CHECK: .Lpcrel_hi27:
+# CHECK: .Lpcrel_hi33:
 # CHECK: auipc a4, %pcrel_hi(a_symbol)
-# CHECK: sw  a3, %pcrel_lo(.Lpcrel_hi27)(a4)
+# CHECK: sw  a3, %pcrel_lo(.Lpcrel_hi33)(a4)
 sw a3, a_symbol, a4
 
 # Check that we can load the address of symbols that are spelled like a register
-# CHECK: .Lpcrel_hi28:
+# CHECK: .Lpcrel_hi34:
 # CHECK: auipc a2, %pcrel_hi(zero)
-# CHECK: lw  a2, %pcrel_lo(.Lpcrel_hi28)(a2)
+# CHECK: lw  a2, %pcrel_lo(.Lpcrel_hi34)(a2)
 lw a2, zero
 
-# CHECK: .Lpcrel_hi29:
+# CHECK: .Lpcrel_hi35:
 # CHECK: auipc a4, %pcrel_hi(zero)
-# CHECK: sw  a3, %pcrel_lo(.Lpcrel_hi29)(a4)
+# CHECK: sw  a3, %pcrel_lo(.Lpcrel_hi35)(a4)
 sw a3, zero, a4
 
 ## Check that a complex expression can be simplified and matched.
-# CHECK: .Lpcrel_hi30:
+# CHECK: .Lpcrel_hi36:
 # CHECK: auipc a5, %pcrel_hi((255+a_symbol)-4)
-# CHECK: addi  a5, a5, %pcrel_lo(.Lpcrel_hi30)
+# CHECK: addi  a5, a5, %pcrel_lo(.Lpcrel_hi36)
 lla a5, (0xFF + a_symbol) - 4
 
 ## Check that we don't double-parse a top-level minus.
-# CHECK: .Lpcrel_hi31:
+# CHECK: .Lpcrel_hi37:
 # CHECK: auipc a5, %pcrel_hi(a_symbol-4)
-# CHECK: addi  a5, a5, %pcrel_lo(.Lpcrel_hi31)
+# CHECK: addi  a5, a5, %pcrel_lo(.Lpcrel_hi37)
 lla a5, a_symbol - 4