Skip to content

Commit d488a54

Browse files
authored
[RISCV] Use software guarded branch for indirect jump table branch. (#66762)
When Zicfilp enabled, indirect jump table branch should be a software guarded branch.
1 parent 4014e2e commit d488a54

File tree

5 files changed

+138
-1
lines changed

5 files changed

+138
-1
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21660,6 +21660,20 @@ MCPhysReg RVVArgDispatcher::getNextPhysReg() {
2166021660
return AllocatedPhysRegs[CurIdx++];
2166121661
}
2166221662

21663+
SDValue RISCVTargetLowering::expandIndirectJTBranch(const SDLoc &dl,
21664+
SDValue Value, SDValue Addr,
21665+
int JTI,
21666+
SelectionDAG &DAG) const {
21667+
if (Subtarget.hasStdExtZicfilp()) {
21668+
// When Zicfilp enabled, we need to use software guarded branch for jump
21669+
// table branch.
21670+
SDValue JTInfo = DAG.getJumpTableDebugInfo(JTI, Value, dl);
21671+
return DAG.getNode(RISCVISD::SW_GUARDED_BRIND, dl, MVT::Other, JTInfo,
21672+
Addr);
21673+
}
21674+
return TargetLowering::expandIndirectJTBranch(dl, Value, Addr, JTI, DAG);
21675+
}
21676+
2166321677
namespace llvm::RISCVVIntrinsicsTable {
2166421678

2166521679
#define GET_RISCVVIntrinsicsTable_IMPL

llvm/lib/Target/RISCV/RISCVISelLowering.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,10 @@ enum NodeType : unsigned {
400400
CZERO_EQZ, // vt.maskc for XVentanaCondOps.
401401
CZERO_NEZ, // vt.maskcn for XVentanaCondOps.
402402

403+
/// Software guarded BRIND node. Operand 0 is the chain operand and
404+
/// operand 1 is the target address.
405+
SW_GUARDED_BRIND,
406+
403407
// FP to 32 bit int conversions for RV64. These are used to keep track of the
404408
// result being sign extended to 64 bit. These saturate out of range inputs.
405409
STRICT_FCVT_W_RV64 = ISD::FIRST_TARGET_STRICTFP_OPCODE,
@@ -869,6 +873,9 @@ class RISCVTargetLowering : public TargetLowering {
869873

870874
bool supportKCFIBundles() const override { return true; }
871875

876+
SDValue expandIndirectJTBranch(const SDLoc &dl, SDValue Value, SDValue Addr,
877+
int JTI, SelectionDAG &DAG) const override;
878+
872879
MachineInstr *EmitKCFICheck(MachineBasicBlock &MBB,
873880
MachineBasicBlock::instr_iterator &MBBI,
874881
const TargetInstrInfo *TII) const override;

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ def riscv_brcc : SDNode<"RISCVISD::BR_CC", SDT_RISCVBrCC,
6969
def riscv_tail : SDNode<"RISCVISD::TAIL", SDT_RISCVCall,
7070
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
7171
SDNPVariadic]>;
72+
def riscv_sw_guarded_brind : SDNode<"RISCVISD::SW_GUARDED_BRIND",
73+
SDTBrind, [SDNPHasChain]>;
7274
def riscv_sllw : SDNode<"RISCVISD::SLLW", SDT_RISCVIntBinOpW>;
7375
def riscv_sraw : SDNode<"RISCVISD::SRAW", SDT_RISCVIntBinOpW>;
7476
def riscv_srlw : SDNode<"RISCVISD::SRLW", SDT_RISCVIntBinOpW>;
@@ -1454,16 +1456,23 @@ def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>,
14541456
PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
14551457

14561458
let Predicates = [HasStdExtZicfilp],
1457-
isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
1459+
isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in {
14581460
def PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12:$imm12), []>,
14591461
PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
1462+
def PseudoBRINDX7 : Pseudo<(outs), (ins GPRX7:$rs1, simm12:$imm12), []>,
1463+
PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
1464+
}
14601465

14611466
// For Zicfilp, need to avoid using X7/T2 for indirect branches which need
14621467
// landing pad.
14631468
let Predicates = [HasStdExtZicfilp] in {
14641469
def : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>;
14651470
def : Pat<(brind (add GPRJALRNonX7:$rs1, simm12:$imm12)),
14661471
(PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12:$imm12)>;
1472+
1473+
def : Pat<(riscv_sw_guarded_brind GPRX7:$rs1), (PseudoBRINDX7 GPRX7:$rs1, 0)>;
1474+
def : Pat<(riscv_sw_guarded_brind (add GPRX7:$rs1, simm12:$imm12)),
1475+
(PseudoBRINDX7 GPRX7:$rs1, simm12:$imm12)>;
14671476
}
14681477

14691478
let Predicates = [NoStdExtZicfilp] in {

llvm/lib/Target/RISCV/RISCVRegisterInfo.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ def GPRNoX0 : GPRRegisterClass<(sub GPR, X0)>;
167167

168168
def GPRNoX0X2 : GPRRegisterClass<(sub GPR, X0, X2)>;
169169

170+
def GPRX7 : GPRRegisterClass<(add X7)>;
171+
170172
// Don't use X1 or X5 for JALR since that is a hint to pop the return address
171173
// stack on some microarchitectures. Also remove the reserved registers X0, X2,
172174
// X3, and X4 as it reduces the number of register classes that get synthesized
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple riscv32 -mattr=+experimental-zicfilp < %s | FileCheck %s
3+
; RUN: llc -mtriple riscv64 -mattr=+experimental-zicfilp < %s | FileCheck %s
4+
; RUN: llc -mtriple riscv32 < %s | FileCheck %s --check-prefix=NO-ZICFILP
5+
; RUN: llc -mtriple riscv64 < %s | FileCheck %s --check-prefix=NO-ZICFILP
6+
7+
; Test using t2 to jump table branch.
8+
define void @above_threshold(i32 signext %in, ptr %out) nounwind {
9+
; CHECK-LABEL: above_threshold:
10+
; CHECK: # %bb.0: # %entry
11+
; CHECK-NEXT: addi a0, a0, -1
12+
; CHECK-NEXT: li a2, 5
13+
; CHECK-NEXT: bltu a2, a0, .LBB0_9
14+
; CHECK-NEXT: # %bb.1: # %entry
15+
; CHECK-NEXT: slli a0, a0, 2
16+
; CHECK-NEXT: lui a2, %hi(.LJTI0_0)
17+
; CHECK-NEXT: addi a2, a2, %lo(.LJTI0_0)
18+
; CHECK-NEXT: add a0, a0, a2
19+
; CHECK-NEXT: lw t2, 0(a0)
20+
; CHECK-NEXT: jr t2
21+
; CHECK-NEXT: .LBB0_2: # %bb1
22+
; CHECK-NEXT: li a0, 4
23+
; CHECK-NEXT: j .LBB0_8
24+
; CHECK-NEXT: .LBB0_3: # %bb5
25+
; CHECK-NEXT: li a0, 100
26+
; CHECK-NEXT: j .LBB0_8
27+
; CHECK-NEXT: .LBB0_4: # %bb3
28+
; CHECK-NEXT: li a0, 2
29+
; CHECK-NEXT: j .LBB0_8
30+
; CHECK-NEXT: .LBB0_5: # %bb4
31+
; CHECK-NEXT: li a0, 1
32+
; CHECK-NEXT: j .LBB0_8
33+
; CHECK-NEXT: .LBB0_6: # %bb2
34+
; CHECK-NEXT: li a0, 3
35+
; CHECK-NEXT: j .LBB0_8
36+
; CHECK-NEXT: .LBB0_7: # %bb6
37+
; CHECK-NEXT: li a0, 200
38+
; CHECK-NEXT: .LBB0_8: # %exit
39+
; CHECK-NEXT: sw a0, 0(a1)
40+
; CHECK-NEXT: .LBB0_9: # %exit
41+
; CHECK-NEXT: ret
42+
;
43+
; NO-ZICFILP-LABEL: above_threshold:
44+
; NO-ZICFILP: # %bb.0: # %entry
45+
; NO-ZICFILP-NEXT: addi a0, a0, -1
46+
; NO-ZICFILP-NEXT: li a2, 5
47+
; NO-ZICFILP-NEXT: bltu a2, a0, .LBB0_9
48+
; NO-ZICFILP-NEXT: # %bb.1: # %entry
49+
; NO-ZICFILP-NEXT: slli a0, a0, 2
50+
; NO-ZICFILP-NEXT: lui a2, %hi(.LJTI0_0)
51+
; NO-ZICFILP-NEXT: addi a2, a2, %lo(.LJTI0_0)
52+
; NO-ZICFILP-NEXT: add a0, a0, a2
53+
; NO-ZICFILP-NEXT: lw a0, 0(a0)
54+
; NO-ZICFILP-NEXT: jr a0
55+
; NO-ZICFILP-NEXT: .LBB0_2: # %bb1
56+
; NO-ZICFILP-NEXT: li a0, 4
57+
; NO-ZICFILP-NEXT: j .LBB0_8
58+
; NO-ZICFILP-NEXT: .LBB0_3: # %bb5
59+
; NO-ZICFILP-NEXT: li a0, 100
60+
; NO-ZICFILP-NEXT: j .LBB0_8
61+
; NO-ZICFILP-NEXT: .LBB0_4: # %bb3
62+
; NO-ZICFILP-NEXT: li a0, 2
63+
; NO-ZICFILP-NEXT: j .LBB0_8
64+
; NO-ZICFILP-NEXT: .LBB0_5: # %bb4
65+
; NO-ZICFILP-NEXT: li a0, 1
66+
; NO-ZICFILP-NEXT: j .LBB0_8
67+
; NO-ZICFILP-NEXT: .LBB0_6: # %bb2
68+
; NO-ZICFILP-NEXT: li a0, 3
69+
; NO-ZICFILP-NEXT: j .LBB0_8
70+
; NO-ZICFILP-NEXT: .LBB0_7: # %bb6
71+
; NO-ZICFILP-NEXT: li a0, 200
72+
; NO-ZICFILP-NEXT: .LBB0_8: # %exit
73+
; NO-ZICFILP-NEXT: sw a0, 0(a1)
74+
; NO-ZICFILP-NEXT: .LBB0_9: # %exit
75+
; NO-ZICFILP-NEXT: ret
76+
entry:
77+
switch i32 %in, label %exit [
78+
i32 1, label %bb1
79+
i32 2, label %bb2
80+
i32 3, label %bb3
81+
i32 4, label %bb4
82+
i32 5, label %bb5
83+
i32 6, label %bb6
84+
]
85+
bb1:
86+
store i32 4, ptr %out
87+
br label %exit
88+
bb2:
89+
store i32 3, ptr %out
90+
br label %exit
91+
bb3:
92+
store i32 2, ptr %out
93+
br label %exit
94+
bb4:
95+
store i32 1, ptr %out
96+
br label %exit
97+
bb5:
98+
store i32 100, ptr %out
99+
br label %exit
100+
bb6:
101+
store i32 200, ptr %out
102+
br label %exit
103+
exit:
104+
ret void
105+
}

0 commit comments

Comments
 (0)