[clang] 4c2c177 - [LoongArch] Add options for annotate tablejump
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 15 20:58:04 PDT 2024
Author: wanglei
Date: 2024-10-16T11:58:00+08:00
New Revision: 4c2c177567390cd3d8de3fd757e9234f1da832b7
URL: https://github.com/llvm/llvm-project/commit/4c2c177567390cd3d8de3fd757e9234f1da832b7
DIFF: https://github.com/llvm/llvm-project/commit/4c2c177567390cd3d8de3fd757e9234f1da832b7.diff
LOG: [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: https://github.com/llvm/llvm-project/pull/102411
Added:
clang/test/Driver/loongarch-mannotate-tablejump.c
llvm/test/CodeGen/LoongArch/annotate-tablejump.ll
Modified:
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/Clang.cpp
llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 6491e9ac73ce99..2072ae45d55414 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5384,9 +5384,14 @@ def mlasx : Flag<["-"], "mlasx">, Group<m_loongarch_Features_Group>,
HelpText<"Enable Loongson Advanced SIMD Extension (LASX).">;
def mno_lasx : Flag<["-"], "mno-lasx">, Group<m_loongarch_Features_Group>,
HelpText<"Disable Loongson Advanced SIMD Extension (LASX).">;
+let Flags = [TargetSpecific] in {
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.">;
+} // let Flags = [TargetSpecific]
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 9d2f7a8960b45f..c132fa35098ae4 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1870,6 +1870,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/clang/test/Driver/loongarch-mannotate-tablejump.c b/clang/test/Driver/loongarch-mannotate-tablejump.c
new file mode 100644
index 00000000000000..586e62c35f4f76
--- /dev/null
+++ b/clang/test/Driver/loongarch-mannotate-tablejump.c
@@ -0,0 +1,13 @@
+/// Test -m[no-]annotate-tablejump options.
+
+// RUN: %clang --target=loongarch64 -mannotate-tablejump %s -### 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CC1-ANOTATE
+// RUN: %clang --target=loongarch64 -mno-annotate-tablejump %s -### 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CC1-NO-ANOTATE
+// RUN: %clang --target=loongarch64 -mannotate-tablejump -mno-annotate-tablejump %s -### 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CC1-NO-ANOTATE
+// RUN: %clang --target=loongarch64 -mno-annotate-tablejump -mannotate-tablejump %s -### 2>&1 | \
+// RUN: FileCheck %s --check-prefix=CC1-ANOTATE
+
+// CC1-ANOTATE: "-loongarch-annotate-tablejump"
+// CC1-NO-ANOTATE-NOT: "-loongarch-annotate-tablejump"
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
index d643017b90db1e..89f8978e687384 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
@@ -13,18 +13,30 @@
#include "LoongArchAsmPrinter.h"
#include "LoongArch.h"
+#include "LoongArchInstrInfo.h"
+#include "LoongArchMachineFunctionInfo.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"
@@ -238,6 +250,39 @@ 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());
+
+ unsigned Size = getDataLayout().getPointerSize();
+ auto *LAFI = MF->getInfo<LoongArchMachineFunctionInfo>();
+ unsigned EntrySize = LAFI->getJumpInfoSize();
+
+ if (0 == EntrySize)
+ return;
+
+ // Emit an additional section to store the correlation info as pairs of
+ // addresses, each pair contains the address of a jump instruction (jr) and
+ // the address of the jump table.
+ OutStreamer->switchSection(MMI->getContext().getELFSection(
+ ".discard.tablejump_annotate", ELF::SHT_PROGBITS, 0));
+
+ for (unsigned Idx = 0; Idx < EntrySize; ++Idx) {
+ OutStreamer->emitValue(
+ MCSymbolRefExpr::create(LAFI->getJumpInfoJrMI(Idx)->getPreInstrSymbol(),
+ OutContext),
+ Size);
+ OutStreamer->emitValue(
+ MCSymbolRefExpr::create(
+ GetJTISymbol(LAFI->getJumpInfoJTIMO(Idx)->getIndex()), 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 fc12f1079490bd..312631e4f0dc55 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
@@ -55,6 +55,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 33b93e42bb5c47..4a10f2e282d133 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -13,6 +13,7 @@
#include "LoongArch.h"
#include "LoongArchInstrInfo.h"
+#include "LoongArchMachineFunctionInfo.h"
#include "LoongArchTargetMachine.h"
#include "MCTargetDesc/LoongArchBaseInfo.h"
#include "MCTargetDesc/LoongArchMCTargetDesc.h"
@@ -27,6 +28,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 \
@@ -103,6 +106,8 @@ class LoongArchPreRAExpandPseudo : public MachineFunctionPass {
MachineBasicBlock::iterator MBBI,
MachineBasicBlock::iterator &NextMBBI,
bool IsTailCall);
+ void annotateTableJump(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI);
};
char LoongArchPreRAExpandPseudo::ID = 0;
@@ -167,6 +172,12 @@ 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, and save the instructions.
+ if (LArchAnnotateTableJump)
+ annotateTableJump(MBB, MBBI);
+ break;
}
return false;
}
@@ -601,6 +612,44 @@ bool LoongArchPreRAExpandPseudo::expandFunctionCALL(
return true;
}
+void LoongArchPreRAExpandPseudo::annotateTableJump(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
+ MachineFunction *MF = MBB.getParent();
+ MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+
+ bool IsFound = false;
+
+ std::function<void(MachineInstr *, int)> FindJTIMI = [&](MachineInstr *MInst,
+ int FindDepth) {
+ if (FindDepth < 0)
+ return;
+ for (auto &MO : MInst->all_uses()) {
+ if (IsFound)
+ return;
+ Register Reg = MO.getReg();
+ if (!Reg.isVirtual())
+ continue;
+ MachineInstr *DefMI = MRI.getVRegDef(Reg);
+ if (!DefMI)
+ continue;
+ for (unsigned Idx = 0; Idx < DefMI->getNumOperands(); ++Idx) {
+ MachineOperand &MO = DefMI->getOperand(Idx);
+ if (MO.isJTI()) {
+ MBBI->setPreInstrSymbol(
+ *MF, MF->getContext().createNamedTempSymbol("jrtb_"));
+ MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(&*MBBI, &MO);
+ IsFound = true;
+ return;
+ }
+ }
+ FindJTIMI(DefMI, --FindDepth);
+ }
+ };
+
+ // FindDepth = 3, probably sufficient.
+ FindJTIMI(&*MBBI, /*FindDepth=*/3);
+}
+
class LoongArchExpandPseudo : public MachineFunctionPass {
public:
const LoongArchInstrInfo *TII;
diff --git a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
index a7366a5dba0412..daa47c4dc7e322 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
+++ b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
@@ -39,6 +39,10 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
/// Registers that have been sign extended from i32.
SmallVector<Register, 8> SExt32Registers;
+ /// Pairs of `jr` instructions and corresponding JTI operands, used for the
+ /// `annotate-tablejump` option.
+ SmallVector<std::pair<MachineInstr *, MachineOperand *>, 4> JumpInfos;
+
public:
LoongArchMachineFunctionInfo(const Function &F,
const TargetSubtargetInfo *STI) {}
@@ -71,6 +75,15 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
bool isSExt32Register(Register Reg) const {
return is_contained(SExt32Registers, Reg);
}
+
+ void setJumpInfo(MachineInstr *JrMI, MachineOperand *JTIMO) {
+ JumpInfos.push_back(std::make_pair(JrMI, JTIMO));
+ }
+ unsigned getJumpInfoSize() { return JumpInfos.size(); }
+ MachineInstr *getJumpInfoJrMI(unsigned Idx) { return JumpInfos[Idx].first; }
+ MachineOperand *getJumpInfoJTIMO(unsigned Idx) {
+ return JumpInfos[Idx].second;
+ }
};
} // end namespace llvm
diff --git a/llvm/test/CodeGen/LoongArch/annotate-tablejump.ll b/llvm/test/CodeGen/LoongArch/annotate-tablejump.ll
new file mode 100644
index 00000000000000..a8c660609d9904
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/annotate-tablejump.ll
@@ -0,0 +1,133 @@
+; 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 $a3, $a0, -1
+; LA32-JT-NEXT: ori $a2, $zero, 3
+; LA32-JT-NEXT: bltu $a2, $a3, .LBB0_7
+; LA32-JT-NEXT: # %bb.1: # %entry
+; LA32-JT-NEXT: pcalau12i $a4, %pc_hi20(.LJTI0_0)
+; LA32-JT-NEXT: addi.w $a4, $a4, %pc_lo12(.LJTI0_0)
+; LA32-JT-NEXT: alsl.w $a3, $a3, $a4, 2
+; LA32-JT-NEXT: ld.w $a3, $a3, 0
+; LA32-JT-NEXT: .Ljrtb_0:
+; LA32-JT-NEXT: jr $a3
+; LA32-JT-NEXT: .LBB0_2: # %bb1
+; LA32-JT-NEXT: ori $a3, $zero, 4
+; LA32-JT-NEXT: b .LBB0_6
+; LA32-JT-NEXT: .LBB0_3: # %bb2
+; LA32-JT-NEXT: ori $a3, $zero, 3
+; LA32-JT-NEXT: b .LBB0_6
+; LA32-JT-NEXT: .LBB0_4: # %bb3
+; LA32-JT-NEXT: ori $a3, $zero, 2
+; LA32-JT-NEXT: b .LBB0_6
+; LA32-JT-NEXT: .LBB0_5: # %bb4
+; LA32-JT-NEXT: ori $a3, $zero, 1
+; LA32-JT-NEXT: .LBB0_6: # %exit
+; LA32-JT-NEXT: st.w $a3, $a1, 0
+; LA32-JT-NEXT: .LBB0_7: # %exit
+; LA32-JT-NEXT: addi.w $a3, $a0, -5
+; LA32-JT-NEXT: bltu $a2, $a3, .LBB0_9
+; LA32-JT-NEXT: # %bb.8: # %exit
+; LA32-JT-NEXT: pcalau12i $a4, %pc_hi20(.LJTI0_1)
+; LA32-JT-NEXT: addi.w $a4, $a4, %pc_lo12(.LJTI0_1)
+; LA32-JT-NEXT: alsl.w $a3, $a3, $a4, 2
+; LA32-JT-NEXT: ld.w $a3, $a3, 0
+; LA32-JT-NEXT: .Ljrtb_1:
+; LA32-JT-NEXT: jr $a3
+; LA32-JT-NEXT: .LBB0_9: # %exit2
+; 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 $a3, $a0, -1
+; LA64-JT-NEXT: ori $a2, $zero, 3
+; LA64-JT-NEXT: bltu $a2, $a3, .LBB0_7
+; LA64-JT-NEXT: # %bb.1: # %entry
+; LA64-JT-NEXT: slli.d $a3, $a3, 3
+; LA64-JT-NEXT: pcalau12i $a4, %pc_hi20(.LJTI0_0)
+; LA64-JT-NEXT: addi.d $a4, $a4, %pc_lo12(.LJTI0_0)
+; LA64-JT-NEXT: ldx.d $a3, $a3, $a4
+; LA64-JT-NEXT: .Ljrtb_0:
+; LA64-JT-NEXT: jr $a3
+; LA64-JT-NEXT: .LBB0_2: # %bb1
+; LA64-JT-NEXT: ori $a3, $zero, 4
+; LA64-JT-NEXT: b .LBB0_6
+; LA64-JT-NEXT: .LBB0_3: # %bb2
+; LA64-JT-NEXT: ori $a3, $zero, 3
+; LA64-JT-NEXT: b .LBB0_6
+; LA64-JT-NEXT: .LBB0_4: # %bb3
+; LA64-JT-NEXT: ori $a3, $zero, 2
+; LA64-JT-NEXT: b .LBB0_6
+; LA64-JT-NEXT: .LBB0_5: # %bb4
+; LA64-JT-NEXT: ori $a3, $zero, 1
+; LA64-JT-NEXT: .LBB0_6: # %exit
+; LA64-JT-NEXT: st.w $a3, $a1, 0
+; LA64-JT-NEXT: .LBB0_7: # %exit
+; LA64-JT-NEXT: addi.d $a3, $a0, -5
+; LA64-JT-NEXT: bltu $a2, $a3, .LBB0_9
+; LA64-JT-NEXT: # %bb.8: # %exit
+; LA64-JT-NEXT: slli.d $a3, $a3, 3
+; LA64-JT-NEXT: pcalau12i $a4, %pc_hi20(.LJTI0_1)
+; LA64-JT-NEXT: addi.d $a4, $a4, %pc_lo12(.LJTI0_1)
+; LA64-JT-NEXT: ldx.d $a3, $a3, $a4
+; LA64-JT-NEXT: .Ljrtb_1:
+; LA64-JT-NEXT: jr $a3
+; LA64-JT-NEXT: .LBB0_9: # %exit2
+; 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:
+ switch i32 %in, label %exit2 [
+ i32 5, label %bb1
+ i32 6, label %bb2
+ i32 7, label %bb3
+ i32 8, label %bb4
+ ]
+exit2:
+ ret void
+}
+
+; UTC_ARGS: --disable
+
+; LA32-JT-LABEL: .LJTI0_0:
+; LA32-JT: .section .discard.tablejump_annotate,"", at progbits
+; LA32-JT-NEXT: .word .Ljrtb_0
+; LA32-JT-NEXT: .word .LJTI0_0
+; LA32-JT-NEXT: .word .Ljrtb_1
+; LA32-JT-NEXT: .word .LJTI0_1
+
+; UTC_ARGS: --disable
+; LA64-JT-LABEL: .LJTI0_0:
+; LA64-JT: .section .discard.tablejump_annotate,"", at progbits
+; LA64-JT-NEXT: .dword .Ljrtb_0
+; LA64-JT-NEXT: .dword .LJTI0_0
+; LA64-JT-NEXT: .dword .Ljrtb_1
+; LA64-JT-NEXT: .dword .LJTI0_1
More information about the cfe-commits
mailing list