-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LoongArch] Add options for annotate tablejump #102411
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LoongArch] Add options for annotate tablejump #102411
Conversation
Created using spr 1.3.5-bogner
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-backend-loongarch Author: wanglei (wangleiat) Changesdraft pr. Full diff: https://github.com/llvm/llvm-project/pull/102411.diff 6 Files Affected:
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 51ec29f1dc321..18ad7f5868e48 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5319,6 +5319,10 @@ def mno_lasx : Flag<["-"], "mno-lasx">, Group<m_loongarch_Features_Group>,
def msimd_EQ : Joined<["-"], "msimd=">, Group<m_loongarch_Features_Group>,
Flags<[TargetSpecific]>,
HelpText<"Select the SIMD extension(s) to be enabled in LoongArch either 'none', 'lsx', 'lasx'.">;
+def mannotate_tablejump : Flag<["-"], "mannotate-tablejump">, Group<m_loongarch_Features_Group>,
+ HelpText<"Enable annotate table jump instruction to correlate it with the jump table.">;
+def mno_annotate_tablejump : Flag<["-"], "mno-annotate-tablejump">, Group<m_loongarch_Features_Group>,
+ HelpText<"Disable annotate table jump instruction to correlate it with the jump table.">;
def mnop_mcount : Flag<["-"], "mnop-mcount">, HelpText<"Generate mcount/__fentry__ calls as nops. To activate they need to be patched in.">,
Visibility<[ClangOption, CC1Option]>, Group<m_Group>,
MarshallingInfoFlag<CodeGenOpts<"MNopMCount">>;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 2054c8fe928e2..342c083b01101 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1876,6 +1876,14 @@ void Clang::AddLoongArchTargetArgs(const ArgList &Args,
CmdArgs.push_back("-tune-cpu");
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
}
+
+ if (Arg *A = Args.getLastArg(options::OPT_mannotate_tablejump,
+ options::OPT_mno_annotate_tablejump)) {
+ if (A->getOption().matches(options::OPT_mannotate_tablejump)) {
+ CmdArgs.push_back("-mllvm");
+ CmdArgs.push_back("-loongarch-annotate-tablejump");
+ }
+ }
}
void Clang::AddMIPSTargetArgs(const ArgList &Args,
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
index f478870217ec6..b4c5be194bff5 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
@@ -15,16 +15,26 @@
#include "LoongArch.h"
#include "LoongArchTargetMachine.h"
#include "MCTargetDesc/LoongArchInstPrinter.h"
+#include "MCTargetDesc/LoongArchMCTargetDesc.h"
#include "TargetInfo/LoongArchTargetInfo.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/TargetRegistry.h"
using namespace llvm;
#define DEBUG_TYPE "loongarch-asm-printer"
+cl::opt<bool> LArchAnnotateTableJump(
+ "loongarch-annotate-tablejump", cl::Hidden,
+ cl::desc(
+ "Annotate table jump instruction to correlate it with the jump table."),
+ cl::init(false));
+
// Simple pseudo-instructions have their lowering (with expansion to real
// instructions) auto-generated.
#include "LoongArchGenMCPseudoLowering.inc"
@@ -189,6 +199,45 @@ void LoongArchAsmPrinter::emitSled(const MachineInstr &MI, SledKind Kind) {
recordSled(BeginOfSled, MI, Kind, 2);
}
+void LoongArchAsmPrinter::emitJumpTableInfo() {
+ AsmPrinter::emitJumpTableInfo();
+
+ if (!LArchAnnotateTableJump)
+ return;
+
+ assert(TM.getTargetTriple().isOSBinFormatELF());
+
+ const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
+ if (!MJTI)
+ return;
+
+ const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+ if (JT.empty())
+ return;
+
+ OutStreamer->switchSection(MMI->getContext().getELFSection(
+ ".discard.tablejump_annotate", ELF::SHT_PROGBITS, 0));
+
+ unsigned Size = getDataLayout().getPointerSize();
+
+ for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
+ const std::vector<MachineBasicBlock *> &JTBBs = JT[JTI].MBBs;
+ if (JTBBs.empty())
+ continue;
+ for (auto *Pred : JTBBs[0]->predecessors()) {
+ for (auto &MI : Pred->instrs()) {
+ if (MI.getOpcode() != LoongArch::PseudoBRIND || !MI.getPreInstrSymbol())
+ continue;
+ OutStreamer->emitValue(
+ MCSymbolRefExpr::create(MI.getPreInstrSymbol(), OutContext), Size);
+ MCSymbol *JTISymbol = GetJTISymbol(JTI);
+ OutStreamer->emitValue(MCSymbolRefExpr::create(JTISymbol, OutContext),
+ Size);
+ }
+ }
+ }
+}
+
bool LoongArchAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
AsmPrinter::runOnMachineFunction(MF);
// Emit the XRay table for this function.
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
index 9da90886627ec..b5239ab37e147 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
@@ -53,6 +53,7 @@ class LLVM_LIBRARY_VISIBILITY LoongArchAsmPrinter : public AsmPrinter {
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
return lowerLoongArchMachineOperandToMCOperand(MO, MCOp, *this);
}
+ void emitJumpTableInfo() override;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index 33b93e42bb5c4..c72f9157525f4 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -27,6 +27,8 @@
using namespace llvm;
+extern cl::opt<bool> LArchAnnotateTableJump;
+
#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \
"LoongArch Pre-RA pseudo instruction expansion pass"
#define LOONGARCH_EXPAND_PSEUDO_NAME \
@@ -167,6 +169,21 @@ bool LoongArchPreRAExpandPseudo::expandMI(
case LoongArch::PseudoTAIL_MEDIUM:
case LoongArch::PseudoTAIL_LARGE:
return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);
+ case LoongArch::PseudoBRIND:
+ // If the PseudoBRIND is used to table jump, then emit a label to annotate
+ // the `jr` instruction.
+ if (!LArchAnnotateTableJump)
+ return false;
+ for (auto &MI : MBB.instrs()) {
+ for (auto MO : MI.operands()) {
+ if (!MO.isJTI())
+ continue;
+ MachineFunction *MF = MBB.getParent();
+ MBBI->setPreInstrSymbol(
+ *MF, MF->getContext().createNamedTempSymbol("jrtb_"));
+ return false;
+ }
+ }
}
return false;
}
diff --git a/llvm/test/CodeGen/LoongArch/annotate-tablejump.ll b/llvm/test/CodeGen/LoongArch/annotate-tablejump.ll
new file mode 100644
index 0000000000000..ddea8c80b0ea4
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/annotate-tablejump.ll
@@ -0,0 +1,102 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 -mattr=+d \
+; RUN: --min-jump-table-entries=4 < %s \
+; RUN: --loongarch-annotate-tablejump \
+; RUN: | FileCheck %s --check-prefix=LA32-JT
+; RUN: llc --mtriple=loongarch64 -mattr=+d \
+; RUN: --min-jump-table-entries=4 < %s \
+; RUN: --loongarch-annotate-tablejump \
+; RUN: | FileCheck %s --check-prefix=LA64-JT
+
+define void @switch_4_arms(i32 %in, ptr %out) nounwind {
+; LA32-JT-LABEL: switch_4_arms:
+; LA32-JT: # %bb.0: # %entry
+; LA32-JT-NEXT: addi.w $a0, $a0, -1
+; LA32-JT-NEXT: ori $a2, $zero, 3
+; LA32-JT-NEXT: bltu $a2, $a0, .LBB0_7
+; LA32-JT-NEXT: # %bb.1: # %entry
+; LA32-JT-NEXT: pcalau12i $a2, %pc_hi20(.LJTI0_0)
+; LA32-JT-NEXT: addi.w $a2, $a2, %pc_lo12(.LJTI0_0)
+; LA32-JT-NEXT: alsl.w $a0, $a0, $a2, 2
+; LA32-JT-NEXT: ld.w $a0, $a0, 0
+; LA32-JT-NEXT: .Ljrtb_0:
+; LA32-JT-NEXT: jr $a0
+; LA32-JT-NEXT: .LBB0_2: # %bb1
+; LA32-JT-NEXT: ori $a0, $zero, 4
+; LA32-JT-NEXT: b .LBB0_6
+; LA32-JT-NEXT: .LBB0_3: # %bb3
+; LA32-JT-NEXT: ori $a0, $zero, 2
+; LA32-JT-NEXT: b .LBB0_6
+; LA32-JT-NEXT: .LBB0_4: # %bb4
+; LA32-JT-NEXT: ori $a0, $zero, 1
+; LA32-JT-NEXT: b .LBB0_6
+; LA32-JT-NEXT: .LBB0_5: # %bb2
+; LA32-JT-NEXT: ori $a0, $zero, 3
+; LA32-JT-NEXT: .LBB0_6: # %exit
+; LA32-JT-NEXT: st.w $a0, $a1, 0
+; LA32-JT-NEXT: .LBB0_7: # %exit
+; LA32-JT-NEXT: ret
+;
+; LA64-JT-LABEL: switch_4_arms:
+; LA64-JT: # %bb.0: # %entry
+; LA64-JT-NEXT: addi.w $a0, $a0, 0
+; LA64-JT-NEXT: addi.d $a0, $a0, -1
+; LA64-JT-NEXT: ori $a2, $zero, 3
+; LA64-JT-NEXT: bltu $a2, $a0, .LBB0_7
+; LA64-JT-NEXT: # %bb.1: # %entry
+; LA64-JT-NEXT: slli.d $a0, $a0, 3
+; LA64-JT-NEXT: pcalau12i $a2, %pc_hi20(.LJTI0_0)
+; LA64-JT-NEXT: addi.d $a2, $a2, %pc_lo12(.LJTI0_0)
+; LA64-JT-NEXT: ldx.d $a0, $a0, $a2
+; LA64-JT-NEXT: .Ljrtb_0:
+; LA64-JT-NEXT: jr $a0
+; LA64-JT-NEXT: .LBB0_2: # %bb1
+; LA64-JT-NEXT: ori $a0, $zero, 4
+; LA64-JT-NEXT: b .LBB0_6
+; LA64-JT-NEXT: .LBB0_3: # %bb3
+; LA64-JT-NEXT: ori $a0, $zero, 2
+; LA64-JT-NEXT: b .LBB0_6
+; LA64-JT-NEXT: .LBB0_4: # %bb4
+; LA64-JT-NEXT: ori $a0, $zero, 1
+; LA64-JT-NEXT: b .LBB0_6
+; LA64-JT-NEXT: .LBB0_5: # %bb2
+; LA64-JT-NEXT: ori $a0, $zero, 3
+; LA64-JT-NEXT: .LBB0_6: # %exit
+; LA64-JT-NEXT: st.w $a0, $a1, 0
+; LA64-JT-NEXT: .LBB0_7: # %exit
+; LA64-JT-NEXT: ret
+entry:
+ switch i32 %in, label %exit [
+ i32 1, label %bb1
+ i32 2, label %bb2
+ i32 3, label %bb3
+ i32 4, label %bb4
+ ]
+bb1:
+ store i32 4, ptr %out
+ br label %exit
+bb2:
+ store i32 3, ptr %out
+ br label %exit
+bb3:
+ store i32 2, ptr %out
+ br label %exit
+bb4:
+ store i32 1, ptr %out
+ br label %exit
+exit:
+ ret void
+}
+
+; UTC_ARGS: --disable
+
+; LA32-JT-LABEL: .LJTI0_0:
+; LA32-JT: .section .discard.tablejump_annotate,"",@progbits
+; LA32-JT-NEXT: .word .Ljrtb_0
+; LA32-JT-NEXT: .word .LJTI0_0
+
+; UTC_ARGS: --disable
+; LA64-JT-LABEL: .LJTI0_0:
+; LA64-JT: .section .discard.tablejump_annotate,"",@progbits
+; LA64-JT-NEXT: .dword .Ljrtb_0
+; LA64-JT-NEXT: .dword .LJTI0_0
|
Created using spr 1.3.5-bogner
define void @switch_4_arms(i32 %in, ptr %out) nounwind {
entry:
switch i32 %in, label %exit [
i32 1, label %bb1
i32 2, label %bb2
i32 3, label %bb3
i32 4, label %bb4
]
bb1:
store i32 4, ptr %out
br label %exit
bb2:
store i32 3, ptr %out
br label %exit
bb3:
store i32 2, ptr %out
br label %exit
bb4:
store i32 1, ptr %out
br label %exit
exit:
switch i32 %in, label %exit2 [
i32 5, label %bb1
i32 6, label %bb2
i32 7, label %bb3
i32 8, label %bb4
]
exit2:
ret void
} or extern void asdf0(void);
extern void asdf1(void);
extern void asdf2(void);
extern void asdf3(void);
extern void asdf4(void);
void foo(int x, int y) {
switch (x) {
case 0: goto l0;
case 1: goto l1;
case 2: goto l2;
case 3: goto l3;
case 4: goto l4;
}
switch (y) {
case 5: goto l0;
case 6: goto l1;
case 7: goto l2;
case 8: goto l3;
case 9: goto l4;
}
return;
l0:
asdf0();
return;
l1:
asdf1();
return;
l2:
asdf2();
return;
l3:
asdf3();
return;
l4:
asdf4();
return;
} .Ljrtb_0:
jr $a3
...
.Ljrtb_1:
jr $a3
...
.section .discard.tablejump_annotate,"",@progbits
.dword .Ljrtb_0
.dword .LJTI0_0
.dword .Ljrtb_1
.dword .LJTI0_0
.dword .Ljrtb_0
.dword .LJTI0_1
.dword .Ljrtb_1
.dword .LJTI0_1 Is this expected? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to add gcc's links to commit message to let people know the background.
@@ -5340,6 +5340,10 @@ def mno_lasx : Flag<["-"], "mno-lasx">, Group<m_loongarch_Features_Group>, | |||
def msimd_EQ : Joined<["-"], "msimd=">, Group<m_loongarch_Features_Group>, | |||
Flags<[TargetSpecific]>, | |||
HelpText<"Select the SIMD extension(s) to be enabled in LoongArch either 'none', 'lsx', 'lasx'.">; | |||
def mannotate_tablejump : Flag<["-"], "mannotate-tablejump">, Group<m_loongarch_Features_Group>, | |||
HelpText<"Enable annotate table jump instruction to correlate it with the jump table.">; | |||
def mno_annotate_tablejump : Flag<["-"], "mno-annotate-tablejump">, Group<m_loongarch_Features_Group>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The negative option is useless?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
aligns gcc.
if (A->getOption().matches(options::OPT_mannotate_tablejump)) { | ||
CmdArgs.push_back("-mllvm"); | ||
CmdArgs.push_back("-loongarch-annotate-tablejump"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
else: -loongarch-annotate-tablejump=false
Thank you very much. I didn't take into account the situation where a basic block belongs to multiple |
Created using spr 1.3.5-bogner
Created using spr 1.3.5-bogner
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, Thanks.
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
.