Skip to content

Commit 21ef17c

Browse files
authored
[LoongArch] Avoid indirect branch jumps using the ra register
Micro-architecture unconditionally treats a "jr $ra" as "return from subroutine", hence doing "jr $ra" would interfere with both subroutine return prediction and the more general indirect branch prediction. GCC thread: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110136 Reviewed By: SixWeining Pull Request: #115424
1 parent 2eaf507 commit 21ef17c

File tree

3 files changed

+15
-9
lines changed

3 files changed

+15
-9
lines changed

llvm/lib/Target/LoongArch/LoongArchInstrInfo.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,12 +1469,12 @@ def PseudoBR : Pseudo<(outs), (ins simm26_b:$imm26), [(br bb:$imm26)]>,
14691469
PseudoInstExpansion<(B simm26_b:$imm26)>;
14701470

14711471
let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
1472-
def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
1472+
def PseudoBRIND : Pseudo<(outs), (ins GPRJR:$rj, simm16_lsl2:$imm16)>,
14731473
PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>;
14741474

1475-
def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>;
1476-
def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)),
1477-
(PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>;
1475+
def : Pat<(brind GPRJR:$rj), (PseudoBRIND GPRJR:$rj, 0)>;
1476+
def : Pat<(brind (add GPRJR:$rj, simm16_lsl2:$imm16)),
1477+
(PseudoBRIND GPRJR:$rj, simm16_lsl2:$imm16)>;
14781478

14791479
// Function call with 'Small' code model.
14801480
let isCall = 1, Defs = [R1] in

llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ def GPR : GPRRegisterClass<(add // Argument registers (a0...a7)
121121
def GPRT : GPRRegisterClass<(add // a0...a7, t0...t8
122122
(sequence "R%u", 4, 20))>;
123123

124+
// Don't use R1 for JR since that micro-architecture unconditionally treats a
125+
// "jr $ra" as "return from subroutine", hence doing "jr $ra" would interfere
126+
// with both subroutine return prediction and the more general indirect branch
127+
// prediction.
128+
def GPRJR : GPRRegisterClass<(sub GPR, R1)>;
129+
124130
// Floating point registers
125131

126132
let RegAltNameIndices = [RegAliasName] in {

llvm/test/CodeGen/LoongArch/jr-without-ra.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ define void @jr_without_ra(ptr %rtwdev, ptr %chan, ptr %h2c, i8 %.pre, i1 %cmp.i
4444
; CHECK-NEXT: addi.w $s4, $zero, -41
4545
; CHECK-NEXT: ori $s3, $zero, 1
4646
; CHECK-NEXT: slli.d $s4, $s4, 3
47-
; CHECK-NEXT: ori $s5, $zero, 50
4847
; CHECK-NEXT: ori $s6, $zero, 3
4948
; CHECK-NEXT: lu32i.d $s6, 262144
5049
; CHECK-NEXT: b .LBB0_4
@@ -54,8 +53,8 @@ define void @jr_without_ra(ptr %rtwdev, ptr %chan, ptr %h2c, i8 %.pre, i1 %cmp.i
5453
; CHECK-NEXT: ori $s8, $zero, 1
5554
; CHECK-NEXT: .LBB0_2: # %if.else.i106
5655
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
57-
; CHECK-NEXT: alsl.d $ra, $s0, $s0, 3
58-
; CHECK-NEXT: alsl.d $s0, $ra, $s0, 1
56+
; CHECK-NEXT: alsl.d $s5, $s0, $s0, 3
57+
; CHECK-NEXT: alsl.d $s0, $s5, $s0, 1
5958
; CHECK-NEXT: add.d $s0, $t0, $s0
6059
; CHECK-NEXT: ldx.bu $s8, $s0, $s8
6160
; CHECK-NEXT: .LBB0_3: # %phy_tssi_get_ofdm_de.exit
@@ -92,6 +91,7 @@ define void @jr_without_ra(ptr %rtwdev, ptr %chan, ptr %h2c, i8 %.pre, i1 %cmp.i
9291
; CHECK-NEXT: .LBB0_9: # %if.end.i
9392
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
9493
; CHECK-NEXT: andi $s7, $s7, 255
94+
; CHECK-NEXT: ori $s5, $zero, 50
9595
; CHECK-NEXT: bltu $s5, $s7, .LBB0_15
9696
; CHECK-NEXT: # %bb.10: # %if.end.i
9797
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
@@ -113,8 +113,8 @@ define void @jr_without_ra(ptr %rtwdev, ptr %chan, ptr %h2c, i8 %.pre, i1 %cmp.i
113113
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
114114
; CHECK-NEXT: pcalau12i $ra, %pc_hi20(.LJTI0_1)
115115
; CHECK-NEXT: addi.d $ra, $ra, %pc_lo12(.LJTI0_1)
116-
; CHECK-NEXT: ldx.d $ra, $s4, $ra
117-
; CHECK-NEXT: ret
116+
; CHECK-NEXT: ldx.d $s5, $s4, $ra
117+
; CHECK-NEXT: jr $s5
118118
; CHECK-NEXT: .LBB0_13: # %phy_tssi_get_ofdm_trim_de.exit
119119
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
120120
; CHECK-NEXT: bnez $s3, .LBB0_1

0 commit comments

Comments
 (0)