Skip to content

Commit 4c2c177

Browse files
authored
[LoongArch] Add options for annotate tablejump
This aligns with GCC. LoongArch kernel developers requested that this option generate some corresponding relations in a section, including the addresses of the jump instruction(jr) and the `MachineJumpTableEntry`. Reviewed By: heiher Pull Request: #102411
1 parent b2b0e6c commit 4c2c177

File tree

8 files changed

+268
-1
lines changed

8 files changed

+268
-1
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5384,9 +5384,14 @@ def mlasx : Flag<["-"], "mlasx">, Group<m_loongarch_Features_Group>,
53845384
HelpText<"Enable Loongson Advanced SIMD Extension (LASX).">;
53855385
def mno_lasx : Flag<["-"], "mno-lasx">, Group<m_loongarch_Features_Group>,
53865386
HelpText<"Disable Loongson Advanced SIMD Extension (LASX).">;
5387+
let Flags = [TargetSpecific] in {
53875388
def msimd_EQ : Joined<["-"], "msimd=">, Group<m_loongarch_Features_Group>,
5388-
Flags<[TargetSpecific]>,
53895389
HelpText<"Select the SIMD extension(s) to be enabled in LoongArch either 'none', 'lsx', 'lasx'.">;
5390+
def mannotate_tablejump : Flag<["-"], "mannotate-tablejump">, Group<m_loongarch_Features_Group>,
5391+
HelpText<"Enable annotate table jump instruction to correlate it with the jump table.">;
5392+
def mno_annotate_tablejump : Flag<["-"], "mno-annotate-tablejump">, Group<m_loongarch_Features_Group>,
5393+
HelpText<"Disable annotate table jump instruction to correlate it with the jump table.">;
5394+
} // let Flags = [TargetSpecific]
53905395
def mnop_mcount : Flag<["-"], "mnop-mcount">, HelpText<"Generate mcount/__fentry__ calls as nops. To activate they need to be patched in.">,
53915396
Visibility<[ClangOption, CC1Option]>, Group<m_Group>,
53925397
MarshallingInfoFlag<CodeGenOpts<"MNopMCount">>;

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,14 @@ void Clang::AddLoongArchTargetArgs(const ArgList &Args,
18701870
CmdArgs.push_back("-tune-cpu");
18711871
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
18721872
}
1873+
1874+
if (Arg *A = Args.getLastArg(options::OPT_mannotate_tablejump,
1875+
options::OPT_mno_annotate_tablejump)) {
1876+
if (A->getOption().matches(options::OPT_mannotate_tablejump)) {
1877+
CmdArgs.push_back("-mllvm");
1878+
CmdArgs.push_back("-loongarch-annotate-tablejump");
1879+
}
1880+
}
18731881
}
18741882

18751883
void Clang::AddMIPSTargetArgs(const ArgList &Args,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// Test -m[no-]annotate-tablejump options.
2+
3+
// RUN: %clang --target=loongarch64 -mannotate-tablejump %s -### 2>&1 | \
4+
// RUN: FileCheck %s --check-prefix=CC1-ANOTATE
5+
// RUN: %clang --target=loongarch64 -mno-annotate-tablejump %s -### 2>&1 | \
6+
// RUN: FileCheck %s --check-prefix=CC1-NO-ANOTATE
7+
// RUN: %clang --target=loongarch64 -mannotate-tablejump -mno-annotate-tablejump %s -### 2>&1 | \
8+
// RUN: FileCheck %s --check-prefix=CC1-NO-ANOTATE
9+
// RUN: %clang --target=loongarch64 -mno-annotate-tablejump -mannotate-tablejump %s -### 2>&1 | \
10+
// RUN: FileCheck %s --check-prefix=CC1-ANOTATE
11+
12+
// CC1-ANOTATE: "-loongarch-annotate-tablejump"
13+
// CC1-NO-ANOTATE-NOT: "-loongarch-annotate-tablejump"

llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,30 @@
1313

1414
#include "LoongArchAsmPrinter.h"
1515
#include "LoongArch.h"
16+
#include "LoongArchInstrInfo.h"
17+
#include "LoongArchMachineFunctionInfo.h"
1618
#include "LoongArchTargetMachine.h"
1719
#include "MCTargetDesc/LoongArchInstPrinter.h"
20+
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
1821
#include "TargetInfo/LoongArchTargetInfo.h"
1922
#include "llvm/CodeGen/AsmPrinter.h"
23+
#include "llvm/CodeGen/MachineJumpTableInfo.h"
24+
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
2025
#include "llvm/MC/MCContext.h"
2126
#include "llvm/MC/MCInstBuilder.h"
27+
#include "llvm/MC/MCSectionELF.h"
2228
#include "llvm/MC/TargetRegistry.h"
2329

2430
using namespace llvm;
2531

2632
#define DEBUG_TYPE "loongarch-asm-printer"
2733

34+
cl::opt<bool> LArchAnnotateTableJump(
35+
"loongarch-annotate-tablejump", cl::Hidden,
36+
cl::desc(
37+
"Annotate table jump instruction to correlate it with the jump table."),
38+
cl::init(false));
39+
2840
// Simple pseudo-instructions have their lowering (with expansion to real
2941
// instructions) auto-generated.
3042
#include "LoongArchGenMCPseudoLowering.inc"
@@ -238,6 +250,39 @@ void LoongArchAsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
238250
recordSled(BeginOfSled, MI, Kind, 2);
239251
}
240252

253+
void LoongArchAsmPrinter::emitJumpTableInfo() {
254+
AsmPrinter::emitJumpTableInfo();
255+
256+
if (!LArchAnnotateTableJump)
257+
return;
258+
259+
assert(TM.getTargetTriple().isOSBinFormatELF());
260+
261+
unsigned Size = getDataLayout().getPointerSize();
262+
auto *LAFI = MF->getInfo<LoongArchMachineFunctionInfo>();
263+
unsigned EntrySize = LAFI->getJumpInfoSize();
264+
265+
if (0 == EntrySize)
266+
return;
267+
268+
// Emit an additional section to store the correlation info as pairs of
269+
// addresses, each pair contains the address of a jump instruction (jr) and
270+
// the address of the jump table.
271+
OutStreamer->switchSection(MMI->getContext().getELFSection(
272+
".discard.tablejump_annotate", ELF::SHT_PROGBITS, 0));
273+
274+
for (unsigned Idx = 0; Idx < EntrySize; ++Idx) {
275+
OutStreamer->emitValue(
276+
MCSymbolRefExpr::create(LAFI->getJumpInfoJrMI(Idx)->getPreInstrSymbol(),
277+
OutContext),
278+
Size);
279+
OutStreamer->emitValue(
280+
MCSymbolRefExpr::create(
281+
GetJTISymbol(LAFI->getJumpInfoJTIMO(Idx)->getIndex()), OutContext),
282+
Size);
283+
}
284+
}
285+
241286
bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
242287
AsmPrinter::runOnMachineFunction(MF);
243288
// Emit the XRay table for this function.

llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class LLVM_LIBRARY_VISIBILITY LoongArchAsmPrinter : public AsmPrinter {
5555
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
5656
return lowerLoongArchMachineOperandToMCOperand(MO, MCOp, *this);
5757
}
58+
void emitJumpTableInfo() override;
5859
};
5960

6061
} // end namespace llvm

llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "LoongArch.h"
1515
#include "LoongArchInstrInfo.h"
16+
#include "LoongArchMachineFunctionInfo.h"
1617
#include "LoongArchTargetMachine.h"
1718
#include "MCTargetDesc/LoongArchBaseInfo.h"
1819
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
@@ -27,6 +28,8 @@
2728

2829
using namespace llvm;
2930

31+
extern cl::opt<bool> LArchAnnotateTableJump;
32+
3033
#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
3134
"LoongArch Pre-RA pseudo instruction expansion pass"
3235
#define LOONGARCH_EXPAND_PSEUDO_NAME \
@@ -103,6 +106,8 @@ class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
103106
MachineBasicBlock::iterator MBBI,
104107
MachineBasicBlock::iterator &NextMBBI,
105108
bool IsTailCall);
109+
void annotateTableJump(MachineBasicBlock &MBB,
110+
MachineBasicBlock::iterator MBBI);
106111
};
107112

108113
char LoongArchPreRAExpandPseudo::ID = 0;
@@ -167,6 +172,12 @@ bool LoongArchPreRAExpandPseudo::expandMI(
167172
case LoongArch::PseudoTAIL_MEDIUM:
168173
case LoongArch::PseudoTAIL_LARGE:
169174
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
175+
case LoongArch::PseudoBRIND:
176+
// If the PseudoBRIND is used to table jump, then emit a label to annotate
177+
// the `jr` instruction, and save the instructions.
178+
if (LArchAnnotateTableJump)
179+
annotateTableJump(MBB, MBBI);
180+
break;
170181
}
171182
return false;
172183
}
@@ -601,6 +612,44 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
601612
return true;
602613
}
603614

615+
void LoongArchPreRAExpandPseudo::annotateTableJump(
616+
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
617+
MachineFunction *MF = MBB.getParent();
618+
MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
619+
620+
bool IsFound = false;
621+
622+
std::function<void(MachineInstr *, int)> FindJTIMI = [&](MachineInstr *MInst,
623+
int FindDepth) {
624+
if (FindDepth < 0)
625+
return;
626+
for (auto &MO : MInst->all_uses()) {
627+
if (IsFound)
628+
return;
629+
Register Reg = MO.getReg();
630+
if (!Reg.isVirtual())
631+
continue;
632+
MachineInstr *DefMI = MRI.getVRegDef(Reg);
633+
if (!DefMI)
634+
continue;
635+
for (unsigned Idx = 0; Idx < DefMI->getNumOperands(); ++Idx) {
636+
MachineOperand &MO = DefMI->getOperand(Idx);
637+
if (MO.isJTI()) {
638+
MBBI->setPreInstrSymbol(
639+
*MF, MF->getContext().createNamedTempSymbol("jrtb_"));
640+
MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(&*MBBI, &MO);
641+
IsFound = true;
642+
return;
643+
}
644+
}
645+
FindJTIMI(DefMI, --FindDepth);
646+
}
647+
};
648+
649+
// FindDepth = 3, probably sufficient.
650+
FindJTIMI(&*MBBI, /*FindDepth=*/3);
651+
}
652+
604653
class LoongArchExpandPseudo : public MachineFunctionPass {
605654
public:
606655
const LoongArchInstrInfo *TII;

llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
3939
/// Registers that have been sign extended from i32.
4040
SmallVector<Register, 8> SExt32Registers;
4141

42+
/// Pairs of `jr` instructions and corresponding JTI operands, used for the
43+
/// `annotate-tablejump` option.
44+
SmallVector<std::pair<MachineInstr *, MachineOperand *>, 4> JumpInfos;
45+
4246
public:
4347
LoongArchMachineFunctionInfo(const Function &F,
4448
const TargetSubtargetInfo *STI) {}
@@ -71,6 +75,15 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
7175
bool isSExt32Register(Register Reg) const {
7276
return is_contained(SExt32Registers, Reg);
7377
}
78+
79+
void setJumpInfo(MachineInstr *JrMI, MachineOperand *JTIMO) {
80+
JumpInfos.push_back(std::make_pair(JrMI, JTIMO));
81+
}
82+
unsigned getJumpInfoSize() { return JumpInfos.size(); }
83+
MachineInstr *getJumpInfoJrMI(unsigned Idx) { return JumpInfos[Idx].first; }
84+
MachineOperand *getJumpInfoJTIMO(unsigned Idx) {
85+
return JumpInfos[Idx].second;
86+
}
7487
};
7588

7689
} // end namespace llvm
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc --mtriple=loongarch32 -mattr=+d \
3+
; RUN: --min-jump-table-entries=4 < %s \
4+
; RUN: --loongarch-annotate-tablejump \
5+
; RUN: | FileCheck %s --check-prefix=LA32-JT
6+
; RUN: llc --mtriple=loongarch64 -mattr=+d \
7+
; RUN: --min-jump-table-entries=4 < %s \
8+
; RUN: --loongarch-annotate-tablejump \
9+
; RUN: | FileCheck %s --check-prefix=LA64-JT
10+
11+
define void @switch_4_arms(i32 %in, ptr %out) nounwind {
12+
; LA32-JT-LABEL: switch_4_arms:
13+
; LA32-JT: # %bb.0: # %entry
14+
; LA32-JT-NEXT: addi.w $a3, $a0, -1
15+
; LA32-JT-NEXT: ori $a2, $zero, 3
16+
; LA32-JT-NEXT: bltu $a2, $a3, .LBB0_7
17+
; LA32-JT-NEXT: # %bb.1: # %entry
18+
; LA32-JT-NEXT: pcalau12i $a4, %pc_hi20(.LJTI0_0)
19+
; LA32-JT-NEXT: addi.w $a4, $a4, %pc_lo12(.LJTI0_0)
20+
; LA32-JT-NEXT: alsl.w $a3, $a3, $a4, 2
21+
; LA32-JT-NEXT: ld.w $a3, $a3, 0
22+
; LA32-JT-NEXT: .Ljrtb_0:
23+
; LA32-JT-NEXT: jr $a3
24+
; LA32-JT-NEXT: .LBB0_2: # %bb1
25+
; LA32-JT-NEXT: ori $a3, $zero, 4
26+
; LA32-JT-NEXT: b .LBB0_6
27+
; LA32-JT-NEXT: .LBB0_3: # %bb2
28+
; LA32-JT-NEXT: ori $a3, $zero, 3
29+
; LA32-JT-NEXT: b .LBB0_6
30+
; LA32-JT-NEXT: .LBB0_4: # %bb3
31+
; LA32-JT-NEXT: ori $a3, $zero, 2
32+
; LA32-JT-NEXT: b .LBB0_6
33+
; LA32-JT-NEXT: .LBB0_5: # %bb4
34+
; LA32-JT-NEXT: ori $a3, $zero, 1
35+
; LA32-JT-NEXT: .LBB0_6: # %exit
36+
; LA32-JT-NEXT: st.w $a3, $a1, 0
37+
; LA32-JT-NEXT: .LBB0_7: # %exit
38+
; LA32-JT-NEXT: addi.w $a3, $a0, -5
39+
; LA32-JT-NEXT: bltu $a2, $a3, .LBB0_9
40+
; LA32-JT-NEXT: # %bb.8: # %exit
41+
; LA32-JT-NEXT: pcalau12i $a4, %pc_hi20(.LJTI0_1)
42+
; LA32-JT-NEXT: addi.w $a4, $a4, %pc_lo12(.LJTI0_1)
43+
; LA32-JT-NEXT: alsl.w $a3, $a3, $a4, 2
44+
; LA32-JT-NEXT: ld.w $a3, $a3, 0
45+
; LA32-JT-NEXT: .Ljrtb_1:
46+
; LA32-JT-NEXT: jr $a3
47+
; LA32-JT-NEXT: .LBB0_9: # %exit2
48+
; LA32-JT-NEXT: ret
49+
;
50+
; LA64-JT-LABEL: switch_4_arms:
51+
; LA64-JT: # %bb.0: # %entry
52+
; LA64-JT-NEXT: addi.w $a0, $a0, 0
53+
; LA64-JT-NEXT: addi.d $a3, $a0, -1
54+
; LA64-JT-NEXT: ori $a2, $zero, 3
55+
; LA64-JT-NEXT: bltu $a2, $a3, .LBB0_7
56+
; LA64-JT-NEXT: # %bb.1: # %entry
57+
; LA64-JT-NEXT: slli.d $a3, $a3, 3
58+
; LA64-JT-NEXT: pcalau12i $a4, %pc_hi20(.LJTI0_0)
59+
; LA64-JT-NEXT: addi.d $a4, $a4, %pc_lo12(.LJTI0_0)
60+
; LA64-JT-NEXT: ldx.d $a3, $a3, $a4
61+
; LA64-JT-NEXT: .Ljrtb_0:
62+
; LA64-JT-NEXT: jr $a3
63+
; LA64-JT-NEXT: .LBB0_2: # %bb1
64+
; LA64-JT-NEXT: ori $a3, $zero, 4
65+
; LA64-JT-NEXT: b .LBB0_6
66+
; LA64-JT-NEXT: .LBB0_3: # %bb2
67+
; LA64-JT-NEXT: ori $a3, $zero, 3
68+
; LA64-JT-NEXT: b .LBB0_6
69+
; LA64-JT-NEXT: .LBB0_4: # %bb3
70+
; LA64-JT-NEXT: ori $a3, $zero, 2
71+
; LA64-JT-NEXT: b .LBB0_6
72+
; LA64-JT-NEXT: .LBB0_5: # %bb4
73+
; LA64-JT-NEXT: ori $a3, $zero, 1
74+
; LA64-JT-NEXT: .LBB0_6: # %exit
75+
; LA64-JT-NEXT: st.w $a3, $a1, 0
76+
; LA64-JT-NEXT: .LBB0_7: # %exit
77+
; LA64-JT-NEXT: addi.d $a3, $a0, -5
78+
; LA64-JT-NEXT: bltu $a2, $a3, .LBB0_9
79+
; LA64-JT-NEXT: # %bb.8: # %exit
80+
; LA64-JT-NEXT: slli.d $a3, $a3, 3
81+
; LA64-JT-NEXT: pcalau12i $a4, %pc_hi20(.LJTI0_1)
82+
; LA64-JT-NEXT: addi.d $a4, $a4, %pc_lo12(.LJTI0_1)
83+
; LA64-JT-NEXT: ldx.d $a3, $a3, $a4
84+
; LA64-JT-NEXT: .Ljrtb_1:
85+
; LA64-JT-NEXT: jr $a3
86+
; LA64-JT-NEXT: .LBB0_9: # %exit2
87+
; LA64-JT-NEXT: ret
88+
entry:
89+
switch i32 %in, label %exit [
90+
i32 1, label %bb1
91+
i32 2, label %bb2
92+
i32 3, label %bb3
93+
i32 4, label %bb4
94+
]
95+
bb1:
96+
store i32 4, ptr %out
97+
br label %exit
98+
bb2:
99+
store i32 3, ptr %out
100+
br label %exit
101+
bb3:
102+
store i32 2, ptr %out
103+
br label %exit
104+
bb4:
105+
store i32 1, ptr %out
106+
br label %exit
107+
exit:
108+
switch i32 %in, label %exit2 [
109+
i32 5, label %bb1
110+
i32 6, label %bb2
111+
i32 7, label %bb3
112+
i32 8, label %bb4
113+
]
114+
exit2:
115+
ret void
116+
}
117+
118+
; UTC_ARGS: --disable
119+
120+
; LA32-JT-LABEL: .LJTI0_0:
121+
; LA32-JT: .section .discard.tablejump_annotate,"",@progbits
122+
; LA32-JT-NEXT: .word .Ljrtb_0
123+
; LA32-JT-NEXT: .word .LJTI0_0
124+
; LA32-JT-NEXT: .word .Ljrtb_1
125+
; LA32-JT-NEXT: .word .LJTI0_1
126+
127+
; UTC_ARGS: --disable
128+
; LA64-JT-LABEL: .LJTI0_0:
129+
; LA64-JT: .section .discard.tablejump_annotate,"",@progbits
130+
; LA64-JT-NEXT: .dword .Ljrtb_0
131+
; LA64-JT-NEXT: .dword .LJTI0_0
132+
; LA64-JT-NEXT: .dword .Ljrtb_1
133+
; LA64-JT-NEXT: .dword .LJTI0_1

0 commit comments

Comments
 (0)