diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp index 30742c79653b5..0218934ea3344 100644 --- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp @@ -352,11 +352,13 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, MachineBasicBlock::iterator &NextMBBI) { // Code Sequence: + // lu12i.w $rd, %le_hi20_r(sym) + // add.w/d $rd, $rd, $tp, %le_add_r(sym) + // addi.w/d $rd, $rd, %le_lo12_r(sym) + // + // Code Sequence while using the large code model: // lu12i.w $rd, %le_hi20(sym) // ori $rd, $rd, %le_lo12(sym) - // - // And additionally if generating code using the large code model: - // // lu32i.d $rd, %le64_lo20(sym) // lu52i.d $rd, $rd, %le64_hi12(sym) MachineFunction *MF = MBB.getParent(); @@ -366,20 +368,35 @@ bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE( bool Large = MF->getTarget().getCodeModel() == CodeModel::Large; Register DestReg = MI.getOperand(0).getReg(); Register Parts01 = - Large ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) - : DestReg; + MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); Register Part1 = MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); MachineOperand &Symbol = MI.getOperand(1); - BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1) - .addDisp(Symbol, 0, LoongArchII::MO_LE_HI); + if (!Large) { + BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1) + .addDisp(Symbol, 0, LoongArchII::MO_LE_HI_R); - BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01) - .addReg(Part1, RegState::Kill) - .addDisp(Symbol, 0, LoongArchII::MO_LE_LO); + const auto &STI = MF->getSubtarget(); + unsigned AddOp = STI.is64Bit() ? LoongArch::PseudoAddTPRel_D + : LoongArch::PseudoAddTPRel_W; + BuildMI(MBB, MBBI, DL, TII->get(AddOp), Parts01) + .addReg(Part1, RegState::Kill) + .addReg(LoongArch::R2) + .addDisp(Symbol, 0, LoongArchII::MO_LE_ADD_R); + + unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; + BuildMI(MBB, MBBI, DL, TII->get(AddiOp), DestReg) + .addReg(Parts01, RegState::Kill) + .addDisp(Symbol, 0, LoongArchII::MO_LE_LO_R); + } else { + BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1) + .addDisp(Symbol, 0, LoongArchII::MO_LE_HI); + + BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01) + .addReg(Part1, RegState::Kill) + .addDisp(Symbol, 0, LoongArchII::MO_LE_LO); - if (Large) { Register Parts012 = MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 43f76373b7919..4f606d2496f92 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -1816,9 +1816,17 @@ SDValue LoongArchTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N, // PseudoLA_*_LARGE nodes. SDValue Tmp = DAG.getConstant(0, DL, Ty); SDValue Addr = DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, 0); - SDValue Offset = Large + + // Only IE needs an extra argument for large code model. + SDValue Offset = Opc == LoongArch::PseudoLA_TLS_IE_LARGE ? SDValue(DAG.getMachineNode(Opc, DL, Ty, Tmp, Addr), 0) : SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0); + + // If it is LE for normal/medium code model, the add tp operation will occur + // during the pseudo-instruction expansion. + if (Opc == LoongArch::PseudoLA_TLS_LE && !Large) + return Offset; + if (UseGOT) { // Mark the load instruction as invariant to enable hoisting in MachineLICM. MachineFunction &MF = DAG.getMachineFunction(); @@ -1939,7 +1947,7 @@ LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op, // // This node doesn't need an extra argument for the large code model. return getStaticTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_LE, - /*UseGOT=*/false); + /*UseGOT=*/false, Large); } return getTLSDescAddr(N, DAG, diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp index 363cacf726c9c..7d0e4f9d58a16 100644 --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp @@ -651,7 +651,10 @@ LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { {MO_DESC_LD, "loongarch-desc-ld"}, {MO_DESC_CALL, "loongarch-desc-call"}, {MO_LD_PC_HI, "loongarch-ld-pc-hi"}, - {MO_GD_PC_HI, "loongarch-gd-pc-hi"}}; + {MO_GD_PC_HI, "loongarch-gd-pc-hi"}, + {MO_LE_HI_R, "loongarch-le-hi-r"}, + {MO_LE_ADD_R, "loongarch-le-add-r"}, + {MO_LE_LO_R, "loongarch-le-lo-r"}}; return ArrayRef(TargetFlags); } diff --git a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp index 2bacc1273343e..d1de0609f24ce 100644 --- a/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp @@ -114,6 +114,15 @@ static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, case LoongArchII::MO_DESC_CALL: Kind = LoongArchMCExpr::VK_LoongArch_TLS_DESC_CALL; break; + case LoongArchII::MO_LE_HI_R: + Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_HI20_R; + break; + case LoongArchII::MO_LE_ADD_R: + Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_ADD_R; + break; + case LoongArchII::MO_LE_LO_R: + Kind = LoongArchMCExpr::VK_LoongArch_TLS_LE_LO12_R; + break; // TODO: Handle more target-flags. } diff --git a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h index bd63c5edeabca..23699043b9926 100644 --- a/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h +++ b/llvm/lib/Target/LoongArch/MCTargetDesc/LoongArchBaseInfo.h @@ -54,6 +54,9 @@ enum { MO_DESC64_PC_LO, MO_DESC_LD, MO_DESC_CALL, + MO_LE_HI_R, + MO_LE_ADD_R, + MO_LE_LO_R, // TODO: Add more flags. }; diff --git a/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll b/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll index fc0c7ad1686ee..e0a93e3051bf8 100644 --- a/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll +++ b/llvm/test/CodeGen/LoongArch/machinelicm-address-pseudos.ll @@ -315,9 +315,9 @@ define void @test_la_tls_le(i32 signext %n) { ; LA32-LABEL: test_la_tls_le: ; LA32: # %bb.0: # %entry ; LA32-NEXT: move $a1, $zero -; LA32-NEXT: lu12i.w $a2, %le_hi20(le) -; LA32-NEXT: ori $a2, $a2, %le_lo12(le) -; LA32-NEXT: add.w $a2, $a2, $tp +; LA32-NEXT: lu12i.w $a2, %le_hi20_r(le) +; LA32-NEXT: add.w $a2, $a2, $tp, %le_add_r(le) +; LA32-NEXT: addi.w $a2, $a2, %le_lo12_r(le) ; LA32-NEXT: .p2align 4, , 16 ; LA32-NEXT: .LBB4_1: # %loop ; LA32-NEXT: # =>This Inner Loop Header: Depth=1 @@ -330,12 +330,13 @@ define void @test_la_tls_le(i32 signext %n) { ; LA64-LABEL: test_la_tls_le: ; LA64: # %bb.0: # %entry ; LA64-NEXT: move $a1, $zero -; LA64-NEXT: lu12i.w $a2, %le_hi20(le) -; LA64-NEXT: ori $a2, $a2, %le_lo12(le) +; LA64-NEXT: lu12i.w $a2, %le_hi20_r(le) +; LA64-NEXT: add.d $a2, $a2, $tp, %le_add_r(le) +; LA64-NEXT: addi.d $a2, $a2, %le_lo12_r(le) ; LA64-NEXT: .p2align 4, , 16 ; LA64-NEXT: .LBB4_1: # %loop ; LA64-NEXT: # =>This Inner Loop Header: Depth=1 -; LA64-NEXT: ldx.w $zero, $a2, $tp +; LA64-NEXT: ld.w $zero, $a2, 0 ; LA64-NEXT: addi.w $a1, $a1, 1 ; LA64-NEXT: blt $a1, $a0, .LBB4_1 ; LA64-NEXT: # %bb.2: # %ret diff --git a/llvm/test/CodeGen/LoongArch/mir-target-flags.ll b/llvm/test/CodeGen/LoongArch/mir-target-flags.ll index f530e3ef237c1..3bc8a8d309586 100644 --- a/llvm/test/CodeGen/LoongArch/mir-target-flags.ll +++ b/llvm/test/CodeGen/LoongArch/mir-target-flags.ll @@ -28,8 +28,9 @@ define void @caller() nounwind { ; CHECK-NEXT: target-flags(loongarch-got-pc-lo) @t_ld ; CHECK: target-flags(loongarch-ie-pc-hi) @t_ie ; CHECK-NEXT: target-flags(loongarch-ie-pc-lo) @t_ie -; CHECK: target-flags(loongarch-le-hi) @t_le -; CHECK-NEXT: target-flags(loongarch-le-lo) @t_le +; CHECK: target-flags(loongarch-le-hi-r) @t_le +; CHECK-NEXT: target-flags(loongarch-le-add-r) @t_le +; CHECK-NEXT: target-flags(loongarch-le-lo-r) @t_le ; CHECK: target-flags(loongarch-call-plt) @callee1 ; CHECK: target-flags(loongarch-call) @callee2 %a = load volatile i32, ptr @g_e diff --git a/llvm/test/CodeGen/LoongArch/tls-models.ll b/llvm/test/CodeGen/LoongArch/tls-models.ll index dbd7bf6a81269..e3a8ace3bc7e3 100644 --- a/llvm/test/CodeGen/LoongArch/tls-models.ll +++ b/llvm/test/CodeGen/LoongArch/tls-models.ll @@ -330,16 +330,16 @@ entry: define ptr @f4() nounwind { ; LA32PIC-LABEL: f4: ; LA32PIC: # %bb.0: # %entry -; LA32PIC-NEXT: lu12i.w $a0, %le_hi20(le) -; LA32PIC-NEXT: ori $a0, $a0, %le_lo12(le) -; LA32PIC-NEXT: add.w $a0, $a0, $tp +; LA32PIC-NEXT: lu12i.w $a0, %le_hi20_r(le) +; LA32PIC-NEXT: add.w $a0, $a0, $tp, %le_add_r(le) +; LA32PIC-NEXT: addi.w $a0, $a0, %le_lo12_r(le) ; LA32PIC-NEXT: ret ; ; LA64PIC-LABEL: f4: ; LA64PIC: # %bb.0: # %entry -; LA64PIC-NEXT: lu12i.w $a0, %le_hi20(le) -; LA64PIC-NEXT: ori $a0, $a0, %le_lo12(le) -; LA64PIC-NEXT: add.d $a0, $a0, $tp +; LA64PIC-NEXT: lu12i.w $a0, %le_hi20_r(le) +; LA64PIC-NEXT: add.d $a0, $a0, $tp, %le_add_r(le) +; LA64PIC-NEXT: addi.d $a0, $a0, %le_lo12_r(le) ; LA64PIC-NEXT: ret ; ; LA64LARGEPIC-LABEL: f4: @@ -353,16 +353,16 @@ define ptr @f4() nounwind { ; ; LA32NOPIC-LABEL: f4: ; LA32NOPIC: # %bb.0: # %entry -; LA32NOPIC-NEXT: lu12i.w $a0, %le_hi20(le) -; LA32NOPIC-NEXT: ori $a0, $a0, %le_lo12(le) -; LA32NOPIC-NEXT: add.w $a0, $a0, $tp +; LA32NOPIC-NEXT: lu12i.w $a0, %le_hi20_r(le) +; LA32NOPIC-NEXT: add.w $a0, $a0, $tp, %le_add_r(le) +; LA32NOPIC-NEXT: addi.w $a0, $a0, %le_lo12_r(le) ; LA32NOPIC-NEXT: ret ; ; LA64NOPIC-LABEL: f4: ; LA64NOPIC: # %bb.0: # %entry -; LA64NOPIC-NEXT: lu12i.w $a0, %le_hi20(le) -; LA64NOPIC-NEXT: ori $a0, $a0, %le_lo12(le) -; LA64NOPIC-NEXT: add.d $a0, $a0, $tp +; LA64NOPIC-NEXT: lu12i.w $a0, %le_hi20_r(le) +; LA64NOPIC-NEXT: add.d $a0, $a0, $tp, %le_add_r(le) +; LA64NOPIC-NEXT: addi.d $a0, $a0, %le_lo12_r(le) ; LA64NOPIC-NEXT: ret ; ; LA64LARGENOPIC-LABEL: f4: @@ -376,16 +376,16 @@ define ptr @f4() nounwind { ; ; LA32DESC-LABEL: f4: ; LA32DESC: # %bb.0: # %entry -; LA32DESC-NEXT: lu12i.w $a0, %le_hi20(le) -; LA32DESC-NEXT: ori $a0, $a0, %le_lo12(le) -; LA32DESC-NEXT: add.w $a0, $a0, $tp +; LA32DESC-NEXT: lu12i.w $a0, %le_hi20_r(le) +; LA32DESC-NEXT: add.w $a0, $a0, $tp, %le_add_r(le) +; LA32DESC-NEXT: addi.w $a0, $a0, %le_lo12_r(le) ; LA32DESC-NEXT: ret ; ; LA64DESC-LABEL: f4: ; LA64DESC: # %bb.0: # %entry -; LA64DESC-NEXT: lu12i.w $a0, %le_hi20(le) -; LA64DESC-NEXT: ori $a0, $a0, %le_lo12(le) -; LA64DESC-NEXT: add.d $a0, $a0, $tp +; LA64DESC-NEXT: lu12i.w $a0, %le_hi20_r(le) +; LA64DESC-NEXT: add.d $a0, $a0, $tp, %le_add_r(le) +; LA64DESC-NEXT: addi.d $a0, $a0, %le_lo12_r(le) ; LA64DESC-NEXT: ret ; ; DESC64-LABEL: f4: