Skip to content

Commit bfad875

Browse files
authored
[LoongArch] Ensure PseudoLA* can be hoisted (#94723)
Since we mark the pseudos as mayLoad but do not provide any MMOs, isSafeToMove conservatively returns false, stopping MachineLICM from hoisting the instructions. PseudoLA_TLS_{LD,GD} does not actually expand to a load, so stop marking that as mayLoad to allow it to be hoisted, and for the others make sure to add MMOs during lowering to indicate they're GOT loads and thus can be freely moved.
1 parent 65f9601 commit bfad875

File tree

5 files changed

+180
-130
lines changed

5 files changed

+180
-130
lines changed

llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
785785
SDLoc DL(N);
786786
EVT Ty = getPointerTy(DAG.getDataLayout());
787787
SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
788+
SDValue Load;
788789

789790
switch (M) {
790791
default:
@@ -796,33 +797,49 @@ SDValue LoongArchTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
796797
// This is not actually used, but is necessary for successfully matching
797798
// the PseudoLA_*_LARGE nodes.
798799
SDValue Tmp = DAG.getConstant(0, DL, Ty);
799-
if (IsLocal)
800+
if (IsLocal) {
800801
// This generates the pattern (PseudoLA_PCREL_LARGE tmp sym), that
801802
// eventually becomes the desired 5-insn code sequence.
802-
return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_PCREL_LARGE, DL, Ty,
803+
Load = SDValue(DAG.getMachineNode(LoongArch::PseudoLA_PCREL_LARGE, DL, Ty,
803804
Tmp, Addr),
804805
0);
805-
806-
// This generates the pattern (PseudoLA_GOT_LARGE tmp sym), that eventually
807-
// becomes the desired 5-insn code sequence.
808-
return SDValue(
809-
DAG.getMachineNode(LoongArch::PseudoLA_GOT_LARGE, DL, Ty, Tmp, Addr),
810-
0);
806+
} else {
807+
// This generates the pattern (PseudoLA_GOT_LARGE tmp sym), that
808+
// eventually becomes the desired 5-insn code sequence.
809+
Load = SDValue(
810+
DAG.getMachineNode(LoongArch::PseudoLA_GOT_LARGE, DL, Ty, Tmp, Addr),
811+
0);
812+
}
813+
break;
811814
}
812815

813816
case CodeModel::Small:
814817
case CodeModel::Medium:
815-
if (IsLocal)
818+
if (IsLocal) {
816819
// This generates the pattern (PseudoLA_PCREL sym), which expands to
817820
// (addi.w/d (pcalau12i %pc_hi20(sym)) %pc_lo12(sym)).
818-
return SDValue(
821+
Load = SDValue(
819822
DAG.getMachineNode(LoongArch::PseudoLA_PCREL, DL, Ty, Addr), 0);
823+
} else {
824+
// This generates the pattern (PseudoLA_GOT sym), which expands to (ld.w/d
825+
// (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).
826+
Load =
827+
SDValue(DAG.getMachineNode(LoongArch::PseudoLA_GOT, DL, Ty, Addr), 0);
828+
}
829+
}
820830

821-
// This generates the pattern (PseudoLA_GOT sym), which expands to (ld.w/d
822-
// (pcalau12i %got_pc_hi20(sym)) %got_pc_lo12(sym)).
823-
return SDValue(DAG.getMachineNode(LoongArch::PseudoLA_GOT, DL, Ty, Addr),
824-
0);
831+
if (!IsLocal) {
832+
// Mark the load instruction as invariant to enable hoisting in MachineLICM.
833+
MachineFunction &MF = DAG.getMachineFunction();
834+
MachineMemOperand *MemOp = MF.getMachineMemOperand(
835+
MachinePointerInfo::getGOT(MF),
836+
MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
837+
MachineMemOperand::MOInvariant,
838+
LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));
839+
DAG.setNodeMemRefs(cast<MachineSDNode>(Load.getNode()), {MemOp});
825840
}
841+
842+
return Load;
826843
}
827844

828845
SDValue LoongArchTargetLowering::lowerBlockAddress(SDValue Op,
@@ -860,7 +877,7 @@ SDValue LoongArchTargetLowering::lowerGlobalAddress(SDValue Op,
860877

861878
SDValue LoongArchTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
862879
SelectionDAG &DAG,
863-
unsigned Opc,
880+
unsigned Opc, bool UseGOT,
864881
bool Large) const {
865882
SDLoc DL(N);
866883
EVT Ty = getPointerTy(DAG.getDataLayout());
@@ -873,6 +890,16 @@ SDValue LoongArchTargetLowering::getStaticTLSAddr(GlobalAddressSDNode *N,
873890
SDValue Offset = Large
874891
? SDValue(DAG.getMachineNode(Opc, DL, Ty, Tmp, Addr), 0)
875892
: SDValue(DAG.getMachineNode(Opc, DL, Ty, Addr), 0);
893+
if (UseGOT) {
894+
// Mark the load instruction as invariant to enable hoisting in MachineLICM.
895+
MachineFunction &MF = DAG.getMachineFunction();
896+
MachineMemOperand *MemOp = MF.getMachineMemOperand(
897+
MachinePointerInfo::getGOT(MF),
898+
MachineMemOperand::MOLoad | MachineMemOperand::MODereferenceable |
899+
MachineMemOperand::MOInvariant,
900+
LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));
901+
DAG.setNodeMemRefs(cast<MachineSDNode>(Offset.getNode()), {MemOp});
902+
}
876903

877904
// Add the thread pointer.
878905
return DAG.getNode(ISD::ADD, DL, Ty, Offset,
@@ -976,13 +1003,14 @@ LoongArchTargetLowering::lowerGlobalTLSAddress(SDValue Op,
9761003
return getStaticTLSAddr(N, DAG,
9771004
Large ? LoongArch::PseudoLA_TLS_IE_LARGE
9781005
: LoongArch::PseudoLA_TLS_IE,
979-
Large);
1006+
/*UseGOT=*/true, Large);
9801007
case TLSModel::LocalExec:
9811008
// This model is used when static linking as the TLS offsets are resolved
9821009
// during program linking.
9831010
//
9841011
// This node doesn't need an extra argument for the large code model.
985-
return getStaticTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_LE);
1012+
return getStaticTLSAddr(N, DAG, LoongArch::PseudoLA_TLS_LE,
1013+
/*UseGOT=*/false);
9861014
}
9871015

9881016
return getTLSDescAddr(N, DAG,

llvm/lib/Target/LoongArch/LoongArchISelLowering.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ class LoongArchTargetLowering : public TargetLowering {
267267
SDValue getAddr(NodeTy *N, SelectionDAG &DAG, CodeModel::Model M,
268268
bool IsLocal = true) const;
269269
SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
270-
unsigned Opc, bool Large = false) const;
270+
unsigned Opc, bool UseGOT, bool Large = false) const;
271271
SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,
272272
unsigned Opc, bool Large = false) const;
273273
SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG,

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,24 +1582,33 @@ def PseudoLA_ABS_LARGE : Pseudo<(outs GPR:$dst),
15821582
"la.abs", "$dst, $src">;
15831583
def PseudoLA_PCREL : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
15841584
"la.pcrel", "$dst, $src">;
1585-
let Defs = [R20], Size = 20 in
1585+
def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1586+
"la.tls.ld", "$dst, $src">;
1587+
def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1588+
"la.tls.gd", "$dst, $src">;
1589+
let Defs = [R20], Size = 20 in {
15861590
def PseudoLA_PCREL_LARGE : Pseudo<(outs GPR:$dst),
15871591
(ins GPR:$tmp, bare_symbol:$src), [],
15881592
"la.pcrel", "$dst, $tmp, $src">,
15891593
Requires<[IsLA64]>;
15901594
def PseudoLA_TLS_LE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
15911595
"la.tls.le", "$dst, $src">;
1596+
def PseudoLA_TLS_LD_LARGE : Pseudo<(outs GPR:$dst),
1597+
(ins GPR:$tmp, bare_symbol:$src), [],
1598+
"la.tls.ld", "$dst, $tmp, $src">,
1599+
Requires<[IsLA64]>;
1600+
def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst),
1601+
(ins GPR:$tmp, bare_symbol:$src), [],
1602+
"la.tls.gd", "$dst, $tmp, $src">,
1603+
Requires<[IsLA64]>;
1604+
} // Defs = [R20], Size = 20
15921605
}
15931606
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
15941607
isAsmParserOnly = 1 in {
15951608
def PseudoLA_GOT : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
15961609
"la.got", "$dst, $src">;
15971610
def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
15981611
"la.tls.ie", "$dst, $src">;
1599-
def PseudoLA_TLS_LD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1600-
"la.tls.ld", "$dst, $src">;
1601-
def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1602-
"la.tls.gd", "$dst, $src">;
16031612
let Defs = [R20], Size = 20 in {
16041613
def PseudoLA_GOT_LARGE : Pseudo<(outs GPR:$dst),
16051614
(ins GPR:$tmp, bare_symbol:$src), [],
@@ -1609,14 +1618,6 @@ def PseudoLA_TLS_IE_LARGE : Pseudo<(outs GPR:$dst),
16091618
(ins GPR:$tmp, bare_symbol:$src), [],
16101619
"la.tls.ie", "$dst, $tmp, $src">,
16111620
Requires<[IsLA64]>;
1612-
def PseudoLA_TLS_LD_LARGE : Pseudo<(outs GPR:$dst),
1613-
(ins GPR:$tmp, bare_symbol:$src), [],
1614-
"la.tls.ld", "$dst, $tmp, $src">,
1615-
Requires<[IsLA64]>;
1616-
def PseudoLA_TLS_GD_LARGE : Pseudo<(outs GPR:$dst),
1617-
(ins GPR:$tmp, bare_symbol:$src), [],
1618-
"la.tls.gd", "$dst, $tmp, $src">,
1619-
Requires<[IsLA64]>;
16201621
} // Defs = [R20], Size = 20
16211622
}
16221623

0 commit comments

Comments
 (0)