[llvm] bf47954 - [LoongArch] Add more fixups and relocations

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 4 23:57:34 PDT 2022


Author: wanglei
Date: 2022-09-05T14:55:18+08:00
New Revision: bf47954703206ae4459aaf6f3ed212602524da70

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

LOG: [LoongArch] Add more fixups and relocations

This patch makes the assembler support all modifiers defined in gnu-as.
Also changes some diagnostic information.

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

Added: 
    

Modified: 
    llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
    llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
    llvm/test/MC/LoongArch/Basic/Integer/invalid.s
    llvm/test/MC/LoongArch/Basic/Integer/invalid64.s
    llvm/test/MC/LoongArch/Relocations/relocations.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
index 2559069e3813b..10b4660fa1988 100644
--- a/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
+++ b/llvm/lib/Target/LoongArch/AsmParser/LoongArchAsmParser.cpp
@@ -170,29 +170,90 @@ class LoongArchOperand : public MCParsedAsmOperand {
   bool isUImm5() const { return isUImm<5>(); }
   bool isUImm6() const { return isUImm<6>(); }
   bool isUImm8() const { return isUImm<8>(); }
-  bool isUImm12() const { return isUImm<12>(); }
-  bool isUImm14() const { return isUImm<14>(); }
-  bool isUImm15() const { return isUImm<15>(); }
+  bool isSImm12() const { return isSImm<12>(); }
+
+  bool isSImm12addlike() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
+    return IsConstantImm
+               ? isInt<12>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
+  }
 
-  bool isSImm12() const {
+  bool isSImm12lu52id() const {
     if (!isImm())
       return false;
 
     int64_t Imm;
     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_PCREL_LO;
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_ABS64_HI12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_PCALA64_HI12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT64_HI12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12;
+    return IsConstantImm
+               ? isInt<12>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
+  }
+
+  bool isUImm12() const { return isUImm<12>(); }
 
+  bool isUImm12ori() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_ABS_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_PCALA_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12;
     return IsConstantImm
-               ? (isInt<12>(Imm) &&
-                  (VK == LoongArchMCExpr::VK_LoongArch_None || IsValidKind))
-               : (LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
-                  IsValidKind);
+               ? isUInt<12>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
   }
 
+  bool isUImm14() const { return isUImm<14>(); }
+  bool isUImm15() const { return isUImm<15>(); }
+
   bool isSImm14lsl2() const { return isSImm<14, 2>(); }
   bool isSImm16() const { return isSImm<16>(); }
-  bool isSImm16lsl2() const { return isSImm<16, 2>(); }
+
+  bool isSImm16lsl2() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_B16;
+    return IsConstantImm
+               ? isShiftedInt<16, 2>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
+  }
+
   bool isSImm20() const { return isSImm<20>(); }
 
   bool isSImm20pcalau12i() const {
@@ -202,29 +263,90 @@ class LoongArchOperand : public MCParsedAsmOperand {
     int64_t Imm;
     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_PCREL_HI;
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_PCALA_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20;
+    return IsConstantImm
+               ? isInt<20>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
+  }
+
+  bool isSImm20lu12iw() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_ABS_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20;
+    return IsConstantImm
+               ? isInt<20>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
+  }
+
+  bool isSImm20lu32id() const {
+    if (!isImm())
+      return false;
+
+    int64_t Imm;
+    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_ABS64_LO20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_PCALA64_LO20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT64_LO20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20 ||
+                       VK == LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20;
 
     return IsConstantImm
-               ? (isInt<20>(Imm) &&
-                  (VK == LoongArchMCExpr::VK_LoongArch_None || IsValidKind))
-               : (LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
-                  IsValidKind);
+               ? isInt<20>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
   }
 
-  bool isSImm21lsl2() const { return isSImm<21, 2>(); }
+  bool isSImm21lsl2() const {
+    if (!isImm())
+      return false;
 
-  bool isSImm26Operand() const {
     int64_t Imm;
     LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
     bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
-    bool IsValidKind = (VK == LoongArchMCExpr::VK_LoongArch_CALL ||
-                        VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT);
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_B21;
+    return IsConstantImm
+               ? isShiftedInt<21, 2>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
+  }
+
+  bool isSImm26Operand() const {
+    if (!isImm())
+      return false;
 
+    int64_t Imm;
+    LoongArchMCExpr::VariantKind VK = LoongArchMCExpr::VK_LoongArch_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    bool IsValidKind = VK == LoongArchMCExpr::VK_LoongArch_None ||
+                       VK == LoongArchMCExpr::VK_LoongArch_CALL ||
+                       VK == LoongArchMCExpr::VK_LoongArch_CALL_PLT ||
+                       VK == LoongArchMCExpr::VK_LoongArch_B26;
     return IsConstantImm
-               ? (isShiftedInt<26, 2>(Imm) &&
-                  (VK == LoongArchMCExpr::VK_LoongArch_None || IsValidKind))
-               : (LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
-                  IsValidKind);
+               ? isShiftedInt<26, 2>(Imm) && IsValidKind
+               : LoongArchAsmParser::classifySymbolRef(getImm(), VK) &&
+                     IsValidKind;
   }
 
   /// Gets location of the first token of this operand.
@@ -687,15 +809,30 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidUImm12:
     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                       /*Upper=*/(1 << 12) - 1);
+  case Match_InvalidUImm12ori:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/0,
+        /*Upper=*/(1 << 12) - 1,
+        "operand must be a symbol with modifier (e.g. %abs_lo12) or an "
+        "integer in the range");
   case Match_InvalidUImm15:
     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/0,
                                       /*Upper=*/(1 << 15) - 1);
   case Match_InvalidSImm12:
+    return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 11),
+                                      /*Upper=*/(1 << 11) - 1);
+  case Match_InvalidSImm12addlike:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, /*Lower=*/-(1 << 11),
         /*Upper=*/(1 << 11) - 1,
         "operand must be a symbol with modifier (e.g. %pc_lo12) or an integer "
         "in the range");
+  case Match_InvalidSImm12lu52id:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 11),
+        /*Upper=*/(1 << 11) - 1,
+        "operand must be a symbol with modifier (e.g. %pc64_hi12) or an "
+        "integer in the range");
   case Match_InvalidSImm14lsl2:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, /*Lower=*/-(1 << 15), /*Upper=*/(1 << 15) - 4,
@@ -706,10 +843,23 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidSImm16lsl2:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, /*Lower=*/-(1 << 17), /*Upper=*/(1 << 17) - 4,
-        "immediate must be a multiple of 4 in the range");
+        "operand must be a symbol with modifier (e.g. %b16) or an integer "
+        "in the range");
   case Match_InvalidSImm20:
     return generateImmOutOfRangeError(Operands, ErrorInfo, /*Lower=*/-(1 << 19),
                                       /*Upper=*/(1 << 19) - 1);
+  case Match_InvalidSImm20lu12iw:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
+        /*Upper=*/(1 << 19) - 1,
+        "operand must be a symbol with modifier (e.g. %abs_hi20) or an integer "
+        "in the range");
+  case Match_InvalidSImm20lu32id:
+    return generateImmOutOfRangeError(
+        Operands, ErrorInfo, /*Lower=*/-(1 << 19),
+        /*Upper=*/(1 << 19) - 1,
+        "operand must be a symbol with modifier (e.g. %abs64_lo20) or an "
+        "integer in the range");
   case Match_InvalidSImm20pcalau12i:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, /*Lower=*/-(1 << 19),
@@ -719,7 +869,8 @@ bool LoongArchAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
   case Match_InvalidSImm21lsl2:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, /*Lower=*/-(1 << 22), /*Upper=*/(1 << 22) - 4,
-        "immediate must be a multiple of 4 in the range");
+        "operand must be a symbol with modifier (e.g. %b21) or an integer "
+        "in the range");
   case Match_InvalidSImm26Operand:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, /*Lower=*/-(1 << 27), /*Upper=*/(1 << 27) - 4,

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 4038636942744..d2a620d67a6bb 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -110,10 +110,19 @@ def uimm8 : Operand<GRLenVT> {
   let ParserMatchClass = UImmAsmOperand<8>;
 }
 
-def uimm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isUInt<12>(Imm);}]> {
+class UImm12Operand : Operand<GRLenVT>,
+                      ImmLeaf <GRLenVT, [{return isUInt<12>(Imm);}]> {
+  let DecoderMethod = "decodeUImmOperand<12>";
+}
+
+def uimm12 : UImm12Operand {
   let ParserMatchClass = UImmAsmOperand<12>;
 }
 
+def uimm12_ori : UImm12Operand {
+  let ParserMatchClass = UImmAsmOperand<12, "ori">;
+}
+
 def uimm14 : Operand<GRLenVT> {
   let ParserMatchClass = UImmAsmOperand<14>;
 }
@@ -122,11 +131,23 @@ def uimm15 : Operand<GRLenVT> {
   let ParserMatchClass = UImmAsmOperand<15>;
 }
 
-def simm12 : Operand<GRLenVT>, ImmLeaf<GRLenVT, [{return isInt<12>(Imm);}]> {
-  let ParserMatchClass = SImmAsmOperand<12>;
+class SImm12Operand : Operand<GRLenVT>,
+                      ImmLeaf <GRLenVT, [{return isInt<12>(Imm);}]> {
   let DecoderMethod = "decodeSImmOperand<12>";
 }
 
+def simm12 : SImm12Operand {
+  let ParserMatchClass = SImmAsmOperand<12>;
+}
+
+def simm12_addlike : SImm12Operand {
+  let ParserMatchClass = SImmAsmOperand<12, "addlike">;
+}
+
+def simm12_lu52id : SImm12Operand {
+  let ParserMatchClass = SImmAsmOperand<12, "lu52id">;
+}
+
 def simm14_lsl2 : Operand<GRLenVT>,
     ImmLeaf<GRLenVT, [{return isShiftedInt<14,2>(Imm);}]> {
   let ParserMatchClass = SImmAsmOperand<14, "lsl2">;
@@ -164,6 +185,14 @@ def simm20_pcalau12i : SImm20Operand {
   let ParserMatchClass = SImmAsmOperand<20, "pcalau12i">;
 }
 
+def simm20_lu12iw : SImm20Operand {
+  let ParserMatchClass = SImmAsmOperand<20, "lu12iw">;
+}
+
+def simm20_lu32id : SImm20Operand {
+  let ParserMatchClass = SImmAsmOperand<20, "lu32id">;
+}
+
 def simm21_lsl2 : Operand<OtherVT> {
   let ParserMatchClass = SImmAsmOperand<21, "lsl2">;
   let EncoderMethod = "getImmOpValueAsr2";
@@ -282,7 +311,7 @@ let mayLoad = 1 in {
 class LOAD_3R<bits<17> op, string opstr>
     : Fmt3R<op, (outs GPR:$rd), (ins GPR:$rj, GPR:$rk), opstr, "$rd, $rj, $rk">;
 class LOAD_2RI12<bits<10> op, string opstr>
-    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12:$imm12), opstr,
+    : Fmt2RI12<op, (outs GPR:$rd), (ins GPR:$rj, simm12_addlike:$imm12), opstr,
                "$rd, $rj, $imm12">;
 class LOAD_2RI14<bits<8> op, string opstr>
     : Fmt2RI14<op, (outs GPR:$rd), (ins GPR:$rj, simm14_lsl2:$imm14), opstr,
@@ -294,7 +323,7 @@ class STORE_3R<bits<17> op, string opstr>
     : Fmt3R<op, (outs), (ins GPR:$rd, GPR:$rj, GPR:$rk), opstr,
             "$rd, $rj, $rk">;
 class STORE_2RI12<bits<10> op, string opstr>
-    : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12:$imm12), opstr,
+    : Fmt2RI12<op, (outs), (ins GPR:$rd, GPR:$rj, simm12_addlike:$imm12), opstr,
                "$rd, $rj, $imm12">;
 class STORE_2RI14<bits<8> op, string opstr>
     : Fmt2RI14<op, (outs), (ins GPR:$rd, GPR:$rj, simm14_lsl2:$imm14), opstr,
@@ -328,9 +357,9 @@ class IOCSRWR<bits<22> op, string opstr>
 // Arithmetic Operation Instructions
 def ADD_W : ALU_3R<0b00000000000100000, "add.w">;
 def SUB_W : ALU_3R<0b00000000000100010, "sub.w">;
-def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12>;
+def ADDI_W : ALU_2RI12<0b0000001010, "addi.w", simm12_addlike>;
 def ALSL_W : ALU_3RI2<0b000000000000010, "alsl.w", uimm2_plus1>;
-def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20>;
+def LU12I_W : ALU_1RI20<0b0001010, "lu12i.w", simm20_lu12iw>;
 def SLT  : ALU_3R<0b00000000000100100, "slt">;
 def SLTU : ALU_3R<0b00000000000100101, "sltu">;
 def SLTI  : ALU_2RI12<0b0000001000, "slti", simm12>;
@@ -345,7 +374,7 @@ def XOR  : ALU_3R<0b00000000000101011, "xor">;
 def ANDN : ALU_3R<0b00000000000101101, "andn">;
 def ORN  : ALU_3R<0b00000000000101100, "orn">;
 def ANDI : ALU_2RI12<0b0000001101, "andi", uimm12>;
-def ORI  : ALU_2RI12<0b0000001110, "ori", uimm12>;
+def ORI  : ALU_2RI12<0b0000001110, "ori", uimm12_ori>;
 def XORI : ALU_2RI12<0b0000001111, "xori", uimm12>;
 def MUL_W   : ALU_3R<0b00000000000111000, "mul.w">;
 def MULH_W  : ALU_3R<0b00000000000111001, "mulh.w">;
@@ -441,16 +470,16 @@ let Predicates = [IsLA64] in {
 // Arithmetic Operation Instructions for 64-bits
 def ADD_D : ALU_3R<0b00000000000100001, "add.d">;
 def SUB_D : ALU_3R<0b00000000000100011, "sub.d">;
-def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12>;
+def ADDI_D : ALU_2RI12<0b0000001011, "addi.d", simm12_addlike>;
 def ADDU16I_D : ALU_2RI16<0b000100, "addu16i.d", simm16>;
 def ALSL_WU : ALU_3RI2<0b000000000000011, "alsl.wu", uimm2_plus1>;
 def ALSL_D  : ALU_3RI2<0b000000000010110, "alsl.d", uimm2_plus1>;
 let Constraints = "$rd = $dst" in {
 def LU32I_D : Fmt1RI20<0b0001011, (outs GPR:$dst),
-                       (ins GPR:$rd, simm20:$imm20), "lu32i.d",
+                       (ins GPR:$rd, simm20_lu32id:$imm20), "lu32i.d",
                        "$rd, $imm20">;
 }
-def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12>;
+def LU52I_D : ALU_2RI12<0b0000001100, "lu52i.d", simm12_lu52id>;
 def PCADDU18I : ALU_1RI20<0b0001111, "pcaddu18i", simm20>;
 def MUL_D     : ALU_3R<0b00000000000111011, "mul.d">;
 def MULH_D    : ALU_3R<0b00000000000111100, "mulh.d">;

diff  --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
index 328cbb56aabf5..68b42956b697a 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -42,10 +42,10 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
     Kind = LoongArchMCExpr::VK_LoongArch_CALL_PLT;
     break;
   case LoongArchII::MO_PCREL_HI:
-    Kind = LoongArchMCExpr::VK_LoongArch_PCREL_HI;
+    Kind = LoongArchMCExpr::VK_LoongArch_PCALA_HI20;
     break;
   case LoongArchII::MO_PCREL_LO:
-    Kind = LoongArchMCExpr::VK_LoongArch_PCREL_LO;
+    Kind = LoongArchMCExpr::VK_LoongArch_PCALA_LO12;
     break;
     // TODO: Handle more target-flags.
   }

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
index f9a024f57ae3e..f321a909170cc 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchAsmBackend.cpp
@@ -45,9 +45,17 @@ LoongArchAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
       // LoongArchFixupKinds.h.
       //
       // {name, offset, bits, flags}
-      {"fixup_loongarch_b26", 0, 26, 0},
-      {"fixup_loongarch_pcala_hi20", 5, 20, MCFixupKindInfo::FKF_IsPCRel},
-      {"fixup_loongarch_pcala_lo12", 10, 12, MCFixupKindInfo::FKF_IsPCRel},
+      {"fixup_loongarch_b16", 10, 16, MCFixupKindInfo::FKF_IsPCRel},
+      {"fixup_loongarch_b21", 0, 26, MCFixupKindInfo::FKF_IsPCRel},
+      {"fixup_loongarch_b26", 0, 26, MCFixupKindInfo::FKF_IsPCRel},
+      {"fixup_loongarch_abs_hi20", 5, 20, 0},
+      {"fixup_loongarch_abs_lo12", 10, 12, 0},
+      {"fixup_loongarch_abs64_lo20", 5, 20, 0},
+      {"fixup_loongarch_abs64_hi12", 10, 12, 0},
+      {"fixup_loongarch_tls_le_hi20", 5, 20, 0},
+      {"fixup_loongarch_tls_le_lo12", 10, 12, 0},
+      {"fixup_loongarch_tls_le64_lo20", 5, 20, 0},
+      {"fixup_loongarch_tls_le64_hi12", 10, 12, 0},
       // TODO: Add more fixup kinds.
   };
 

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp
index 3c09b30cebe1e..87be0b0efc016 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchELFObjectWriter.cpp
@@ -67,12 +67,28 @@ unsigned LoongArchELFObjectWriter::getRelocType(MCContext &Ctx,
     return ELF::R_LARCH_32;
   case FK_Data_8:
     return ELF::R_LARCH_64;
-  case LoongArch::fixup_loongarch_pcala_hi20:
-    return ELF::R_LARCH_PCALA_HI20;
-  case LoongArch::fixup_loongarch_pcala_lo12:
-    return ELF::R_LARCH_PCALA_LO12;
+  case LoongArch::fixup_loongarch_b16:
+    return ELF::R_LARCH_B16;
+  case LoongArch::fixup_loongarch_b21:
+    return ELF::R_LARCH_B21;
   case LoongArch::fixup_loongarch_b26:
     return ELF::R_LARCH_B26;
+  case LoongArch::fixup_loongarch_abs_hi20:
+    return ELF::R_LARCH_ABS_HI20;
+  case LoongArch::fixup_loongarch_abs_lo12:
+    return ELF::R_LARCH_ABS_LO12;
+  case LoongArch::fixup_loongarch_abs64_lo20:
+    return ELF::R_LARCH_ABS64_LO20;
+  case LoongArch::fixup_loongarch_abs64_hi12:
+    return ELF::R_LARCH_ABS64_HI12;
+  case LoongArch::fixup_loongarch_tls_le_hi20:
+    return ELF::R_LARCH_TLS_LE_HI20;
+  case LoongArch::fixup_loongarch_tls_le_lo12:
+    return ELF::R_LARCH_TLS_LE_LO12;
+  case LoongArch::fixup_loongarch_tls_le64_lo20:
+    return ELF::R_LARCH_TLS_LE64_LO20;
+  case LoongArch::fixup_loongarch_tls_le64_hi12:
+    return ELF::R_LARCH_TLS_LE64_HI12;
     // TODO: Handle more fixup-kinds.
   }
 }

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
index 46d40d304c918..ba2d6718cdf9a 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchFixupKinds.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHFIXUPKINDS_H
 #define LLVM_LIB_TARGET_LOONGARCH_MCTARGETDESC_LOONGARCHFIXUPKINDS_H
 
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/MC/MCFixup.h"
 
 #undef LoongArch
@@ -21,17 +22,91 @@ namespace LoongArch {
 // LoongArchAsmBackend.cpp.
 //
 enum Fixups {
-  // 26-bit fixup for symbol references in the b/bl instructions.
-  fixup_loongarch_b26 = FirstTargetFixupKind,
-  // 20-bit fixup corresponding to %pc_hi20(foo) for instruction pcalau12i.
-  fixup_loongarch_pcala_hi20,
-  // 12-bit fixup corresponding to %pc_lo12(foo) for instructions addi.w/d.
-  fixup_loongarch_pcala_lo12,
+  // Define fixups can be handled by LoongArchAsmBackend::applyFixup.
+  // 16-bit fixup corresponding to %b16(foo) for instructions like bne.
+  fixup_loongarch_b16 = FirstTargetFixupKind,
+  // 21-bit fixup corresponding to %b21(foo) for instructions like bnez.
+  fixup_loongarch_b21,
+  // 26-bit fixup corresponding to %b26(foo)/%plt(foo) for instructions b/bl.
+  fixup_loongarch_b26,
+  // 20-bit fixup corresponding to %abs_hi20(foo) for instruction lu12i.w.
+  fixup_loongarch_abs_hi20,
+  // 12-bit fixup corresponding to %abs_lo12(foo) for instruction ori.
+  fixup_loongarch_abs_lo12,
+  // 20-bit fixup corresponding to %abs64_lo20(foo) for instruction lu32i.d.
+  fixup_loongarch_abs64_lo20,
+  // 12-bit fixup corresponding to %abs_hi12(foo) for instruction lu52i.d.
+  fixup_loongarch_abs64_hi12,
+  // 20-bit fixup corresponding to %le_hi20(foo) for instruction lu12i.w.
+  fixup_loongarch_tls_le_hi20,
+  // 12-bit fixup corresponding to %le_lo12(foo) for instruction ori.
+  fixup_loongarch_tls_le_lo12,
+  // 20-bit fixup corresponding to %le64_lo20(foo) for instruction lu32i.d.
+  fixup_loongarch_tls_le64_lo20,
+  // 12-bit fixup corresponding to %le64_hi12(foo) for instruction lu52i.d.
+  fixup_loongarch_tls_le64_hi12,
   // TODO: Add more fixup kind.
 
-  // Used as a sentinel, must be the last.
+  // Used as a sentinel, must be the last of the fixup which can be handled by
+  // LoongArchAsmBackend::applyFixup.
   fixup_loongarch_invalid,
-  NumTargetFixupKinds = fixup_loongarch_invalid - FirstTargetFixupKind
+  NumTargetFixupKinds = fixup_loongarch_invalid - FirstTargetFixupKind,
+
+  // Define fixups for force relocation as FirstLiteralRelocationKind+V
+  // represents the relocation type with number V.
+  // 20-bit fixup corresponding to %pc_hi20(foo) for instruction pcalau12i.
+  fixup_loongarch_pcala_hi20 =
+      FirstLiteralRelocationKind + ELF::R_LARCH_PCALA_HI20,
+  // 12-bit fixup corresponding to %pc_lo12(foo) for instructions like addi.w/d.
+  fixup_loongarch_pcala_lo12,
+  // 20-bit fixup corresponding to %pc64_lo20(foo) for instruction lu32i.d.
+  fixup_loongarch_pcala64_lo20,
+  // 12-bit fixup corresponding to %pc64_hi12(foo) for instruction lu52i.d.
+  fixup_loongarch_pcala64_hi12,
+  // 20-bit fixup corresponding to %got_pc_hi20(foo) for instruction pcalau12i.
+  fixup_loongarch_got_pc_hi20,
+  // 12-bit fixup corresponding to %got_pc_lo12(foo) for instructions
+  // ld.w/ld.d/add.d.
+  fixup_loongarch_got_pc_lo12,
+  // 20-bit fixup corresponding to %got64_pc_lo20(foo) for instruction lu32i.d.
+  fixup_loongarch_got64_pc_lo20,
+  // 12-bit fixup corresponding to %got64_pc_hi12(foo) for instruction lu52i.d.
+  fixup_loongarch_got64_pc_hi12,
+  // 20-bit fixup corresponding to %got_hi20(foo) for instruction lu12i.w.
+  fixup_loongarch_got_hi20,
+  // 12-bit fixup corresponding to %got_lo12(foo) for instruction ori.
+  fixup_loongarch_got_lo12,
+  // 20-bit fixup corresponding to %got64_lo20(foo) for instruction lu32i.d.
+  fixup_loongarch_got64_lo20,
+  // 12-bit fixup corresponding to %got64_hi12(foo) for instruction lu52i.d.
+  fixup_loongarch_got64_hi12,
+  // Skip R_LARCH_TLS_LE_*.
+  // 20-bit fixup corresponding to %ie_pc_hi20(foo) for instruction pcalau12i.
+  fixup_loongarch_tls_ie_pc_hi20 =
+      FirstLiteralRelocationKind + ELF::R_LARCH_TLS_IE_PC_HI20,
+  // 12-bit fixup corresponding to %ie_pc_lo12(foo) for instructions
+  // ld.w/ld.d/add.d.
+  fixup_loongarch_tls_ie_pc_lo12,
+  // 20-bit fixup corresponding to %ie64_pc_lo20(foo) for instruction lu32i.d.
+  fixup_loongarch_tls_ie64_pc_lo20,
+  // 12-bit fixup corresponding to %ie64_pc_hi12(foo) for instruction lu52i.d.
+  fixup_loongarch_tls_ie64_pc_hi12,
+  // 20-bit fixup corresponding to %ie_hi20(foo) for instruction lu12i.w.
+  fixup_loongarch_tls_ie_hi20,
+  // 12-bit fixup corresponding to %ie_lo12(foo) for instruction ori.
+  fixup_loongarch_tls_ie_lo12,
+  // 20-bit fixup corresponding to %ie64_lo20(foo) for instruction lu32i.d.
+  fixup_loongarch_tls_ie64_lo20,
+  // 12-bit fixup corresponding to %ie64_hi12(foo) for instruction lu52i.d.
+  fixup_loongarch_tls_ie64_hi12,
+  // 20-bit fixup corresponding to %ld_pc_hi20(foo) for instruction pcalau12i.
+  fixup_loongarch_tls_ld_pc_hi20,
+  // 20-bit fixup corresponding to %ld_hi20(foo) for instruction lu12i.w.
+  fixup_loongarch_tls_ld_hi20,
+  // 20-bit fixup corresponding to %gd_pc_hi20(foo) for instruction pcalau12i.
+  fixup_loongarch_tls_gd_pc_hi20,
+  // 20-bit fixup corresponding to %gd_hi20(foo) for instruction lu12i.w.
+  fixup_loongarch_tls_gd_hi20
 };
 } // end namespace LoongArch
 } // end namespace llvm

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
index 1a08f352b52fb..e44bcd715b696 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCCodeEmitter.cpp
@@ -135,16 +135,134 @@ LoongArchMCCodeEmitter::getExprOpValue(const MCInst &MI, const MCOperand &MO,
     case LoongArchMCExpr::VK_LoongArch_None:
     case LoongArchMCExpr::VK_LoongArch_Invalid:
       llvm_unreachable("Unhandled fixup kind!");
-    case LoongArchMCExpr::VK_LoongArch_PCREL_HI:
-      FixupKind = LoongArch::fixup_loongarch_pcala_hi20;
+    case LoongArchMCExpr::VK_LoongArch_B16:
+      FixupKind = LoongArch::fixup_loongarch_b16;
       break;
-    case LoongArchMCExpr::VK_LoongArch_PCREL_LO:
-      FixupKind = LoongArch::fixup_loongarch_pcala_lo12;
+    case LoongArchMCExpr::VK_LoongArch_B21:
+      FixupKind = LoongArch::fixup_loongarch_b21;
       break;
+    case LoongArchMCExpr::VK_LoongArch_B26:
     case LoongArchMCExpr::VK_LoongArch_CALL:
     case LoongArchMCExpr::VK_LoongArch_CALL_PLT:
       FixupKind = LoongArch::fixup_loongarch_b26;
       break;
+    case LoongArchMCExpr::VK_LoongArch_ABS_HI20:
+      FixupKind = LoongArch::fixup_loongarch_abs_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_ABS_LO12:
+      FixupKind = LoongArch::fixup_loongarch_abs_lo12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_ABS64_LO20:
+      FixupKind = LoongArch::fixup_loongarch_abs64_lo20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_ABS64_HI12:
+      FixupKind = LoongArch::fixup_loongarch_abs64_hi12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_PCALA_HI20:
+      FixupKind = LoongArch::fixup_loongarch_pcala_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_PCALA_LO12:
+      FixupKind = LoongArch::fixup_loongarch_pcala_lo12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_PCALA64_LO20:
+      FixupKind = LoongArch::fixup_loongarch_pcala64_lo20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_PCALA64_HI12:
+      FixupKind = LoongArch::fixup_loongarch_pcala64_hi12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_GOT_PC_HI20:
+      FixupKind = LoongArch::fixup_loongarch_got_pc_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_GOT_PC_LO12:
+      FixupKind = LoongArch::fixup_loongarch_got_pc_lo12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_GOT64_PC_LO20:
+      FixupKind = LoongArch::fixup_loongarch_got64_pc_lo20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_GOT64_PC_HI12:
+      FixupKind = LoongArch::fixup_loongarch_got64_pc_hi12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_GOT_HI20:
+      FixupKind = LoongArch::fixup_loongarch_got_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_GOT_LO12:
+      FixupKind = LoongArch::fixup_loongarch_got_lo12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_GOT64_LO20:
+      FixupKind = LoongArch::fixup_loongarch_got64_lo20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_GOT64_HI12:
+      FixupKind = LoongArch::fixup_loongarch_got64_hi12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20:
+      FixupKind = LoongArch::fixup_loongarch_tls_le_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12:
+      FixupKind = LoongArch::fixup_loongarch_tls_le_lo12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_LE64_LO20:
+      FixupKind = LoongArch::fixup_loongarch_tls_le64_lo20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_LE64_HI12:
+      FixupKind = LoongArch::fixup_loongarch_tls_le64_hi12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_HI20:
+      FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_IE_PC_LO12:
+      FixupKind = LoongArch::fixup_loongarch_tls_ie_pc_lo12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_LO20:
+      FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_lo20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_IE64_PC_HI12:
+      FixupKind = LoongArch::fixup_loongarch_tls_ie64_pc_hi12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_IE_HI20:
+      FixupKind = LoongArch::fixup_loongarch_tls_ie_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_IE_LO12:
+      FixupKind = LoongArch::fixup_loongarch_tls_ie_lo12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_IE64_LO20:
+      FixupKind = LoongArch::fixup_loongarch_tls_ie64_lo20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_IE64_HI12:
+      FixupKind = LoongArch::fixup_loongarch_tls_ie64_hi12;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_LD_PC_HI20:
+      FixupKind = LoongArch::fixup_loongarch_tls_ld_pc_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_LD_HI20:
+      FixupKind = LoongArch::fixup_loongarch_tls_ld_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_GD_PC_HI20:
+      FixupKind = LoongArch::fixup_loongarch_tls_gd_pc_hi20;
+      break;
+    case LoongArchMCExpr::VK_LoongArch_TLS_GD_HI20:
+      FixupKind = LoongArch::fixup_loongarch_tls_gd_hi20;
+      break;
+    }
+  } else if (Kind == MCExpr::SymbolRef &&
+             cast<MCSymbolRefExpr>(Expr)->getKind() ==
+                 MCSymbolRefExpr::VK_None) {
+    switch (MI.getOpcode()) {
+    default:
+      break;
+    case LoongArch::BEQ:
+    case LoongArch::BNE:
+    case LoongArch::BLT:
+    case LoongArch::BGE:
+    case LoongArch::BLTU:
+    case LoongArch::BGEU:
+      FixupKind = LoongArch::fixup_loongarch_b16;
+      break;
+    case LoongArch::BEQZ:
+    case LoongArch::BNEZ:
+    case LoongArch::BCEQZ:
+    case LoongArch::BCNEZ:
+      FixupKind = LoongArch::fixup_loongarch_b21;
+      break;
     }
   }
 

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
index bbf6de6375569..6760d3e7cbb5b 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.cpp
@@ -65,18 +65,117 @@ StringRef LoongArchMCExpr::getVariantKindName(VariantKind Kind) {
     llvm_unreachable("Invalid ELF symbol kind");
   case VK_LoongArch_CALL_PLT:
     return "plt";
-  case VK_LoongArch_PCREL_HI:
+  case VK_LoongArch_B16:
+    return "b16";
+  case VK_LoongArch_B21:
+    return "b21";
+  case VK_LoongArch_B26:
+    return "b21";
+  case VK_LoongArch_ABS_HI20:
+    return "abs_hi20";
+  case VK_LoongArch_ABS_LO12:
+    return "abs_lo12";
+  case VK_LoongArch_ABS64_LO20:
+    return "abs64_lo20";
+  case VK_LoongArch_ABS64_HI12:
+    return "abs64_hi12";
+  case VK_LoongArch_PCALA_HI20:
     return "pc_hi20";
-  case VK_LoongArch_PCREL_LO:
+  case VK_LoongArch_PCALA_LO12:
     return "pc_lo12";
+  case VK_LoongArch_PCALA64_LO20:
+    return "pc64_lo20";
+  case VK_LoongArch_PCALA64_HI12:
+    return "pc64_hi12";
+  case VK_LoongArch_GOT_PC_HI20:
+    return "got_pc_hi20";
+  case VK_LoongArch_GOT_PC_LO12:
+    return "got_pc_lo12";
+  case VK_LoongArch_GOT64_PC_LO20:
+    return "got64_pc_lo20";
+  case VK_LoongArch_GOT64_PC_HI12:
+    return "got64_pc_hi12";
+  case VK_LoongArch_GOT_HI20:
+    return "got_hi20";
+  case VK_LoongArch_GOT_LO12:
+    return "got_lo12";
+  case VK_LoongArch_GOT64_LO20:
+    return "got64_lo20";
+  case VK_LoongArch_GOT64_HI12:
+    return "got64_hi12";
+  case VK_LoongArch_TLS_LE_HI20:
+    return "le_hi20";
+  case VK_LoongArch_TLS_LE_LO12:
+    return "le_lo12";
+  case VK_LoongArch_TLS_LE64_LO20:
+    return "le64_lo20";
+  case VK_LoongArch_TLS_LE64_HI12:
+    return "le64_hi12";
+  case VK_LoongArch_TLS_IE_PC_HI20:
+    return "ie_pc_hi20";
+  case VK_LoongArch_TLS_IE_PC_LO12:
+    return "ie_pc_lo12";
+  case VK_LoongArch_TLS_IE64_PC_LO20:
+    return "ie64_pc_lo20";
+  case VK_LoongArch_TLS_IE64_PC_HI12:
+    return "ie64_pc_hi12";
+  case VK_LoongArch_TLS_IE_HI20:
+    return "ie_hi20";
+  case VK_LoongArch_TLS_IE_LO12:
+    return "ie_lo12";
+  case VK_LoongArch_TLS_IE64_LO20:
+    return "ie64_lo20";
+  case VK_LoongArch_TLS_IE64_HI12:
+    return "ie64_hi12";
+  case VK_LoongArch_TLS_LD_PC_HI20:
+    return "ld_pc_hi20";
+  case VK_LoongArch_TLS_LD_HI20:
+    return "ld_hi20";
+  case VK_LoongArch_TLS_GD_PC_HI20:
+    return "gd_pc_hi20";
+  case VK_LoongArch_TLS_GD_HI20:
+    return "gd_hi20";
   }
 }
 
 LoongArchMCExpr::VariantKind
 LoongArchMCExpr::getVariantKindForName(StringRef name) {
   return StringSwitch<LoongArchMCExpr::VariantKind>(name)
-      .Case("pc_hi20", VK_LoongArch_PCREL_HI)
-      .Case("pc_lo12", VK_LoongArch_PCREL_LO)
       .Case("plt", VK_LoongArch_CALL_PLT)
+      .Case("b16", VK_LoongArch_B16)
+      .Case("b21", VK_LoongArch_B21)
+      .Case("b26", VK_LoongArch_B26)
+      .Case("abs_hi20", VK_LoongArch_ABS_HI20)
+      .Case("abs_lo12", VK_LoongArch_ABS_LO12)
+      .Case("abs64_lo20", VK_LoongArch_ABS64_LO20)
+      .Case("abs64_hi12", VK_LoongArch_ABS64_HI12)
+      .Case("pc_hi20", VK_LoongArch_PCALA_HI20)
+      .Case("pc_lo12", VK_LoongArch_PCALA_LO12)
+      .Case("pc64_lo20", VK_LoongArch_PCALA64_LO20)
+      .Case("pc64_hi12", VK_LoongArch_PCALA64_HI12)
+      .Case("got_pc_hi20", VK_LoongArch_GOT_PC_HI20)
+      .Case("got_pc_lo12", VK_LoongArch_GOT_PC_LO12)
+      .Case("got64_pc_lo20", VK_LoongArch_GOT64_PC_LO20)
+      .Case("got64_pc_hi12", VK_LoongArch_GOT64_PC_HI12)
+      .Case("got_hi20", VK_LoongArch_GOT_HI20)
+      .Case("got_lo12", VK_LoongArch_GOT_LO12)
+      .Case("got64_lo20", VK_LoongArch_GOT64_LO20)
+      .Case("got64_hi12", VK_LoongArch_GOT64_HI12)
+      .Case("le_hi20", VK_LoongArch_TLS_LE_HI20)
+      .Case("le_lo12", VK_LoongArch_TLS_LE_LO12)
+      .Case("le64_lo20", VK_LoongArch_TLS_LE64_LO20)
+      .Case("le64_hi12", VK_LoongArch_TLS_LE64_HI12)
+      .Case("ie_pc_hi20", VK_LoongArch_TLS_IE_PC_HI20)
+      .Case("ie_pc_lo12", VK_LoongArch_TLS_IE_PC_LO12)
+      .Case("ie64_pc_lo20", VK_LoongArch_TLS_IE64_PC_LO20)
+      .Case("ie64_pc_hi12", VK_LoongArch_TLS_IE64_PC_HI12)
+      .Case("ie_hi20", VK_LoongArch_TLS_IE_HI20)
+      .Case("ie_lo12", VK_LoongArch_TLS_IE_LO12)
+      .Case("ie64_lo20", VK_LoongArch_TLS_IE64_LO20)
+      .Case("ie64_hi12", VK_LoongArch_TLS_IE64_HI12)
+      .Case("ld_pc_hi20", VK_LoongArch_TLS_LD_PC_HI20)
+      .Case("ld_hi20", VK_LoongArch_TLS_LD_HI20)
+      .Case("gd_pc_hi20", VK_LoongArch_TLS_GD_PC_HI20)
+      .Case("gd_hi20", VK_LoongArch_TLS_GD_HI20)
       .Default(VK_LoongArch_Invalid);
 }

diff  --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
index e37c625382d22..4706c2e65fea3 100644
--- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
+++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchMCExpr.h
@@ -23,12 +23,44 @@ class StringRef;
 class LoongArchMCExpr : public MCTargetExpr {
 public:
   enum VariantKind {
-    // TODO: Add more target kinds.
     VK_LoongArch_None,
     VK_LoongArch_CALL,
     VK_LoongArch_CALL_PLT,
-    VK_LoongArch_PCREL_HI,
-    VK_LoongArch_PCREL_LO,
+    VK_LoongArch_B16,
+    VK_LoongArch_B21,
+    VK_LoongArch_B26,
+    VK_LoongArch_ABS_HI20,
+    VK_LoongArch_ABS_LO12,
+    VK_LoongArch_ABS64_LO20,
+    VK_LoongArch_ABS64_HI12,
+    VK_LoongArch_PCALA_HI20,
+    VK_LoongArch_PCALA_LO12,
+    VK_LoongArch_PCALA64_LO20,
+    VK_LoongArch_PCALA64_HI12,
+    VK_LoongArch_GOT_PC_HI20,
+    VK_LoongArch_GOT_PC_LO12,
+    VK_LoongArch_GOT64_PC_LO20,
+    VK_LoongArch_GOT64_PC_HI12,
+    VK_LoongArch_GOT_HI20,
+    VK_LoongArch_GOT_LO12,
+    VK_LoongArch_GOT64_LO20,
+    VK_LoongArch_GOT64_HI12,
+    VK_LoongArch_TLS_LE_HI20,
+    VK_LoongArch_TLS_LE_LO12,
+    VK_LoongArch_TLS_LE64_LO20,
+    VK_LoongArch_TLS_LE64_HI12,
+    VK_LoongArch_TLS_IE_PC_HI20,
+    VK_LoongArch_TLS_IE_PC_LO12,
+    VK_LoongArch_TLS_IE64_PC_LO20,
+    VK_LoongArch_TLS_IE64_PC_HI12,
+    VK_LoongArch_TLS_IE_HI20,
+    VK_LoongArch_TLS_IE_LO12,
+    VK_LoongArch_TLS_IE64_LO20,
+    VK_LoongArch_TLS_IE64_HI12,
+    VK_LoongArch_TLS_LD_PC_HI20,
+    VK_LoongArch_TLS_LD_HI20,
+    VK_LoongArch_TLS_GD_PC_HI20,
+    VK_LoongArch_TLS_GD_HI20,
     VK_LoongArch_Invalid // Must be the last item.
   };
 

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
index 861d382688c11..b226d8c9b7d24 100644
--- a/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
+++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid.s
@@ -1,7 +1,9 @@
 ## Test invalid instructions on both loongarch32 and loongarch64 target.
 
-# RUN: not llvm-mc --triple=loongarch32 --mattr=-f %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK64
-# RUN: not llvm-mc --triple=loongarch64 --mattr=-f %s 2>&1 --defsym=LA64=1 | FileCheck %s
+# RUN: not llvm-mc --triple=loongarch32 --mattr=-f %s 2>&1 \
+# RUN:         | FileCheck %s --check-prefixes=CHECK,CHECK64
+# RUN: not llvm-mc --triple=loongarch64 --mattr=-f %s 2>&1 --defsym=LA64=1 \
+# RUN:         | FileCheck %s
 
 ## Out of range immediates
 ## uimm2
@@ -37,20 +39,24 @@ preld 32, $a0, 0
 ## uimm12
 andi $a0, $a0, -1
 # CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [0, 4095]
-ori $a0, $a0, 4096
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be an integer in the range [0, 4095]
 xori $a0, $a0, 4096
 # CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [0, 4095]
 
+## uimm12_ori
+ori $a0, $a0, 4096
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %abs_lo12) or an integer in the range [0, 4095]
+
 ## simm12
-addi.w $a0, $a0, -2049
-# CHECK: :[[#@LINE-1]]:18: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
 slti $a0, $a0, -2049
-# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
+# CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-2048, 2047]
 sltui $a0, $a0, 2048
-# CHECK: :[[#@LINE-1]]:17: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
+# CHECK: :[[#@LINE-1]]:17: error: immediate must be an integer in the range [-2048, 2047]
 preld 0, $a0, 2048
-# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
+# CHECK: :[[#@LINE-1]]:15: error: immediate must be an integer in the range [-2048, 2047]
+
+## simm12_addlike
+addi.w $a0, $a0, -2049
+# CHECK: :[[#@LINE-1]]:18: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
 ld.b $a0, $a0, 2048
 # CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
 ld.h $a0, $a0, 2048
@@ -80,41 +86,43 @@ sc.w $a0, $a0, 32768
 
 ## simm16_lsl2
 beq $a0, $a0, -0x20004
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
 bne $a0, $a0, -0x20004
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
 blt $a0, $a0, -0x1FFFF
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
 bge $a0, $a0, -0x1FFFF
-# CHECK: :[[#@LINE-1]]:15: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:15: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
 bltu $a0, $a0, 0x1FFFF
-# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
 bgeu $a0, $a0, 0x1FFFF
-# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
 jirl $a0, $a0, 0x20000
-# CHECK: :[[#@LINE-1]]:16: error: immediate must be a multiple of 4 in the range [-131072, 131068]
+# CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %b16) or an integer in the range [-131072, 131068]
 
 ## simm20
-lu12i.w $a0, -0x80001
-# CHECK: :[[#@LINE-1]]:14: error: immediate must be an integer in the range [-524288, 524287]
 pcaddi $a0, -0x80001
 # CHECK: :[[#@LINE-1]]:13: error: immediate must be an integer in the range [-524288, 524287]
 pcaddu12i $a0, 0x80000
 # CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]
 
+## simm20_lu12iw
+lu12i.w $a0, -0x80001
+# CHECK: :[[#@LINE-1]]:14: error: operand must be a symbol with modifier (e.g. %abs_hi20) or an integer in the range [-524288, 524287]
+
 ## simm20_pcalau12i
 pcalau12i $a0, 0x80000
 # CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pc_hi20) or an integer in the range [-524288, 524287]
 
 ## simm21_lsl2
 beqz $a0, -0x400001
-# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a symbol with modifier (e.g. %b21) or an integer in the range [-4194304, 4194300]
 bnez $a0, -0x3FFFFF
-# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a symbol with modifier (e.g. %b21) or an integer in the range [-4194304, 4194300]
 beqz $a0, 0x3FFFFF
-# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a symbol with modifier (e.g. %b21) or an integer in the range [-4194304, 4194300]
 bnez $a0, 0x400000
-# CHECK: :[[#@LINE-1]]:11: error: immediate must be a multiple of 4 in the range [-4194304, 4194300]
+# CHECK: :[[#@LINE-1]]:11: error: operand must be a symbol with modifier (e.g. %b21) or an integer in the range [-4194304, 4194300]
 
 ## simm26_lsl2
 b -0x8000001

diff  --git a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s
index e910a3b086ff9..5ee9659cdb7bf 100644
--- a/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s
+++ b/llvm/test/MC/LoongArch/Basic/Integer/invalid64.s
@@ -29,11 +29,9 @@ bstrins.d $a0, $a0, 63, -1
 bstrpick.d $a0, $a0, 64, 0
 # CHECK: :[[#@LINE-1]]:22: error: immediate must be an integer in the range [0, 63]
 
-## simm12
+## simm12_addlike
 addi.d $a0, $a0, -2049
 # CHECK: :[[#@LINE-1]]:18: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
-lu52i.d $a0, $a0, -2049
-# CHECK: :[[#@LINE-1]]:19: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
 ld.wu $a0, $a0, 2048
 # CHECK: :[[#@LINE-1]]:17: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
 ld.d $a0, $a0, 2048
@@ -41,6 +39,10 @@ ld.d $a0, $a0, 2048
 st.d $a0, $a0, 2048
 # CHECK: :[[#@LINE-1]]:16: error: operand must be a symbol with modifier (e.g. %pc_lo12) or an integer in the range [-2048, 2047]
 
+## simm12_lu52id
+lu52i.d $a0, $a0, 2048
+# CHECK-LA64: :[[#@LINE-1]]:19: error: operand must be a symbol with modifier (e.g. %pc64_hi12) or an integer in the range [-2048, 2047]
+
 ## simm14_lsl2
 ldptr.w $a0, $a0, -32772
 # CHECK: :[[#@LINE-1]]:19: error: immediate must be a multiple of 4 in the range [-32768, 32764]
@@ -62,11 +64,13 @@ addu16i.d $a0, $a0, 32768
 # CHECK: :[[#@LINE-1]]:21: error: immediate must be an integer in the range [-32768, 32767]
 
 ## simm20
-lu32i.d $a0, -0x80001
-# CHECK: :[[#@LINE-1]]:14: error: immediate must be an integer in the range [-524288, 524287]
 pcaddu18i $a0, 0x80000
 # CHECK: :[[#@LINE-1]]:16: error: immediate must be an integer in the range [-524288, 524287]
 
+## simm20_lu32id
+lu32i.d $a0, 0x80000
+# CHECK-LA64: :[[#@LINE-1]]:14: error: operand must be a symbol with modifier (e.g. %abs64_lo20) or an integer in the range [-524288, 524287]
+
 ## msbd < lsbd
 # CHECK: :[[#@LINE+1]]:21: error: msb is less than lsb
 bstrins.d $a0, $a0, 1, 2

diff  --git a/llvm/test/MC/LoongArch/Relocations/relocations.s b/llvm/test/MC/LoongArch/Relocations/relocations.s
index a6bc7c80471a1..5044b459dd95d 100644
--- a/llvm/test/MC/LoongArch/Relocations/relocations.s
+++ b/llvm/test/MC/LoongArch/Relocations/relocations.s
@@ -14,42 +14,202 @@
 .quad foo
 # RELOC: R_LARCH_64 foo
 
+bne $t1, $t2, %b16(foo)
+# RELOC: R_LARCH_B16
+# INSTR: bne $t1, $t2, %b16(foo)
+# FIXUP: fixup A - offset: 0, value: %b16(foo), kind: fixup_loongarch_b16
+
+bnez $t1, %b21(foo)
+# RELOC: R_LARCH_B21
+# INSTR: bnez $t1, %b21(foo)
+# FIXUP: fixup A - offset: 0, value: %b21(foo), kind: fixup_loongarch_b21
+
+bl %plt(foo)
+# RELOC: R_LARCH_B26
+# INSTR: bl %plt(foo)
+# FIXUP: fixup A - offset: 0, value: %plt(foo), kind: fixup_loongarch_b26
+
+bl foo
+# RELOC: R_LARCH_B26
+# INSTR: bl foo
+# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_loongarch_b26
+
+lu12i.w $t1, %abs_hi20(foo)
+# RELOC: R_LARCH_ABS_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %abs_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %abs_hi20(foo), kind: fixup_loongarch_abs_hi20
+
+ori $t1, $t1, %abs_lo12(foo)
+# RELOC: R_LARCH_ABS_LO12 foo 0x0
+# INSTR: ori $t1, $t1, %abs_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %abs_lo12(foo), kind: fixup_loongarch_abs_lo12
+
+lu32i.d $t1, %abs64_lo20(foo)
+# RELOC: R_LARCH_ABS64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %abs64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %abs64_lo20(foo), kind: fixup_loongarch_abs64_lo20
+
+lu52i.d $t1, $t1, %abs64_hi12(foo)
+# RELOC: R_LARCH_ABS64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %abs64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %abs64_hi12(foo), kind: fixup_loongarch_abs64_hi12
+
 pcalau12i $t1, %pc_hi20(foo)
 # RELOC: R_LARCH_PCALA_HI20 foo 0x0
 # INSTR: pcalau12i $t1, %pc_hi20(foo)
-# FIXUP: fixup A - offset: 0, value: %pc_hi20(foo), kind: fixup_loongarch_pcala_hi20
+# FIXUP: fixup A - offset: 0, value: %pc_hi20(foo), kind: FK_NONE
 
 pcalau12i $t1, %pc_hi20(foo+4)
 # RELOC: R_LARCH_PCALA_HI20 foo 0x4
 # INSTR: pcalau12i $t1, %pc_hi20(foo+4)
-# FIXUP: fixup A - offset: 0, value: %pc_hi20(foo+4), kind: fixup_loongarch_pcala_hi20
+# FIXUP: fixup A - offset: 0, value: %pc_hi20(foo+4), kind: FK_NONE
 
 addi.d $t1, $t1, %pc_lo12(foo)
 # RELOC: R_LARCH_PCALA_LO12 foo 0x0
 # INSTR: addi.d  $t1, $t1, %pc_lo12(foo)
-# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo), kind: fixup_loongarch_pcala_lo12
+# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo), kind: FK_NONE
 
 addi.d $t1, $t1, %pc_lo12(foo+4)
 # RELOC: R_LARCH_PCALA_LO12 foo 0x4
 # INSTR: addi.d  $t1, $t1, %pc_lo12(foo+4)
-# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo+4), kind: fixup_loongarch_pcala_lo12
+# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo+4), kind: FK_NONE
 
 st.b $t1, $a2, %pc_lo12(foo)
 # RELOC: R_LARCH_PCALA_LO12 foo 0x0
 # INSTR: st.b  $t1, $a2, %pc_lo12(foo)
-# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo), kind: fixup_loongarch_pcala_lo12
+# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo), kind: FK_NONE
 
 st.b $t1, $a2, %pc_lo12(foo+4)
 # RELOC: R_LARCH_PCALA_LO12 foo 0x4
 # INSTR: st.b  $t1, $a2, %pc_lo12(foo+4)
-# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo+4), kind: fixup_loongarch_pcala_lo12
+# FIXUP: fixup A - offset: 0, value: %pc_lo12(foo+4), kind: FK_NONE
 
-bl %plt(foo)
-# RELOC: R_LARCH_B26
-# INSTR: bl  %plt(foo)
-# FIXUP: fixup A - offset: 0, value: %plt(foo), kind: fixup_loongarch_b26
+lu32i.d $t1, %pc64_lo20(foo)
+# RELOC: R_LARCH_PCALA64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %pc64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %pc64_lo20(foo), kind: FK_NONE
 
-bl foo
-# RELOC: R_LARCH_B26
-# INSTR: bl  foo
-# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_loongarch_b26
+lu52i.d $t1, $t1, %pc64_hi12(foo)
+# RELOC: R_LARCH_PCALA64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %pc64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %pc64_hi12(foo), kind: FK_NONE
+
+pcalau12i $t1, %got_pc_hi20(foo)
+# RELOC: R_LARCH_GOT_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %got_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %got_pc_hi20(foo), kind: FK_NONE
+
+ld.d $t1, $a2, %got_pc_lo12(foo)
+# RELOC: R_LARCH_GOT_PC_LO12 foo 0x0
+# INSTR: ld.d  $t1, $a2, %got_pc_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %got_pc_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %got64_pc_lo20(foo)
+# RELOC: R_LARCH_GOT64_PC_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %got64_pc_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %got64_pc_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %got64_pc_hi12(foo)
+# RELOC: R_LARCH_GOT64_PC_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %got64_pc_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %got64_pc_hi12(foo), kind: FK_NONE
+
+lu12i.w $t1, %got_hi20(foo)
+# RELOC: R_LARCH_GOT_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %got_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %got_hi20(foo), kind: FK_NONE
+
+ori $t1, $a2, %got_lo12(foo)
+# RELOC: R_LARCH_GOT_LO12 foo 0x0
+# INSTR: ori  $t1, $a2, %got_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %got_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %got64_lo20(foo)
+# RELOC: R_LARCH_GOT64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %got64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %got64_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %got64_hi12(foo)
+# RELOC: R_LARCH_GOT64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %got64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %got64_hi12(foo), kind: FK_NONE
+
+lu12i.w $t1, %le_hi20(foo)
+# RELOC: R_LARCH_TLS_LE_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %le_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %le_hi20(foo), kind: fixup_loongarch_tls_le_hi20
+
+ori $t1, $a2, %le_lo12(foo)
+# RELOC: R_LARCH_TLS_LE_LO12 foo 0x0
+# INSTR: ori  $t1, $a2, %le_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %le_lo12(foo), kind: fixup_loongarch_tls_le_lo12
+
+lu32i.d $t1, %le64_lo20(foo)
+# RELOC: R_LARCH_TLS_LE64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %le64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %le64_lo20(foo), kind: fixup_loongarch_tls_le64_lo20
+
+lu52i.d $t1, $t1, %le64_hi12(foo)
+# RELOC: R_LARCH_TLS_LE64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %le64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %le64_hi12(foo), kind: fixup_loongarch_tls_le64_hi12
+
+pcalau12i $t1, %ie_pc_hi20(foo)
+# RELOC: R_LARCH_TLS_IE_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %ie_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %ie_pc_hi20(foo), kind: FK_NONE
+
+ld.d $t1, $a2, %ie_pc_lo12(foo)
+# RELOC: R_LARCH_TLS_IE_PC_LO12 foo 0x0
+# INSTR: ld.d  $t1, $a2, %ie_pc_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %ie_pc_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %ie64_pc_lo20(foo)
+# RELOC: R_LARCH_TLS_IE64_PC_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %ie64_pc_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %ie64_pc_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %ie64_pc_hi12(foo)
+# RELOC: R_LARCH_TLS_IE64_PC_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %ie64_pc_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %ie64_pc_hi12(foo), kind: FK_NONE
+
+lu12i.w $t1, %ie_hi20(foo)
+# RELOC: R_LARCH_TLS_IE_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %ie_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %ie_hi20(foo), kind: FK_NONE
+
+ori $t1, $a2, %ie_lo12(foo)
+# RELOC: R_LARCH_TLS_IE_LO12 foo 0x0
+# INSTR: ori  $t1, $a2, %ie_lo12(foo)
+# FIXUP: fixup A - offset: 0, value: %ie_lo12(foo), kind: FK_NONE
+
+lu32i.d $t1, %ie64_lo20(foo)
+# RELOC: R_LARCH_TLS_IE64_LO20 foo 0x0
+# INSTR: lu32i.d $t1, %ie64_lo20(foo)
+# FIXUP: fixup A - offset: 0, value: %ie64_lo20(foo), kind: FK_NONE
+
+lu52i.d $t1, $t1, %ie64_hi12(foo)
+# RELOC: R_LARCH_TLS_IE64_HI12 foo 0x0
+# INSTR: lu52i.d $t1, $t1, %ie64_hi12(foo)
+# FIXUP: fixup A - offset: 0, value: %ie64_hi12(foo), kind: FK_NONE
+
+pcalau12i $t1, %ld_pc_hi20(foo)
+# RELOC: R_LARCH_TLS_LD_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %ld_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %ld_pc_hi20(foo), kind: FK_NONE
+
+lu12i.w $t1, %ld_hi20(foo)
+# RELOC: R_LARCH_TLS_LD_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %ld_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %ld_hi20(foo), kind: FK_NONE
+
+pcalau12i $t1, %gd_pc_hi20(foo)
+# RELOC: R_LARCH_TLS_GD_PC_HI20 foo 0x0
+# INSTR: pcalau12i $t1, %gd_pc_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %gd_pc_hi20(foo), kind: FK_NONE
+
+lu12i.w $t1, %gd_hi20(foo)
+# RELOC: R_LARCH_TLS_GD_HI20 foo 0x0
+# INSTR: lu12i.w $t1, %gd_hi20(foo)
+# FIXUP: fixup A - offset: 0, value: %gd_hi20(foo), kind: FK_NONE


        


More information about the llvm-commits mailing list