[llvm-branch-commits] [LoongArch] Avoid indirect branch jumps using the ra register (PR #115424)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Nov 7 22:05:51 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-loongarch
Author: wanglei (wangleiat)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/115424.diff
3 Files Affected:
- (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.td (+4-4)
- (modified) llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td (+6)
- (modified) llvm/test/CodeGen/LoongArch/jr-without-ra.ll (+5-5)
``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index ccdd5165728231..3de20d6e599dbf 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -1469,12 +1469,12 @@ def PseudoBR : Pseudo<(outs), (ins simm26_b:$imm26), [(br bb:$imm26)]>,
PseudoInstExpansion<(B simm26_b:$imm26)>;
let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
-def PseudoBRIND : Pseudo<(outs), (ins GPR:$rj, simm16_lsl2:$imm16)>,
+def PseudoBRIND : Pseudo<(outs), (ins GPRJR:$rj, simm16_lsl2:$imm16)>,
PseudoInstExpansion<(JIRL R0, GPR:$rj, simm16_lsl2:$imm16)>;
-def : Pat<(brind GPR:$rj), (PseudoBRIND GPR:$rj, 0)>;
-def : Pat<(brind (add GPR:$rj, simm16_lsl2:$imm16)),
- (PseudoBRIND GPR:$rj, simm16_lsl2:$imm16)>;
+def : Pat<(brind GPRJR:$rj), (PseudoBRIND GPRJR:$rj, 0)>;
+def : Pat<(brind (add GPRJR:$rj, simm16_lsl2:$imm16)),
+ (PseudoBRIND GPRJR:$rj, simm16_lsl2:$imm16)>;
// Function call with 'Small' code model.
let isCall = 1, Defs = [R1] in
diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
index 2d3a7c364f0bf4..a8419980868ee1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.td
@@ -121,6 +121,12 @@ def GPR : GPRRegisterClass<(add // Argument registers (a0...a7)
def GPRT : GPRRegisterClass<(add // a0...a7, t0...t8
(sequence "R%u", 4, 20))>;
+// Don't use R1 for JR since that 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.
+def GPRJR : GPRRegisterClass<(sub GPR, R1)>;
+
// Floating point registers
let RegAltNameIndices = [RegAliasName] in {
diff --git a/llvm/test/CodeGen/LoongArch/jr-without-ra.ll b/llvm/test/CodeGen/LoongArch/jr-without-ra.ll
index f32513deee82bd..d1c4459aaa6ee0 100644
--- a/llvm/test/CodeGen/LoongArch/jr-without-ra.ll
+++ b/llvm/test/CodeGen/LoongArch/jr-without-ra.ll
@@ -44,7 +44,6 @@ define void @jr_without_ra(ptr %rtwdev, ptr %chan, ptr %h2c, i8 %.pre, i1 %cmp.i
; CHECK-NEXT: addi.w $s4, $zero, -41
; CHECK-NEXT: ori $s3, $zero, 1
; CHECK-NEXT: slli.d $s4, $s4, 3
-; CHECK-NEXT: ori $s5, $zero, 50
; CHECK-NEXT: ori $s6, $zero, 3
; CHECK-NEXT: lu32i.d $s6, 262144
; 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
; CHECK-NEXT: ori $s8, $zero, 1
; CHECK-NEXT: .LBB0_2: # %if.else.i106
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
-; CHECK-NEXT: alsl.d $ra, $s0, $s0, 3
-; CHECK-NEXT: alsl.d $s0, $ra, $s0, 1
+; CHECK-NEXT: alsl.d $s5, $s0, $s0, 3
+; CHECK-NEXT: alsl.d $s0, $s5, $s0, 1
; CHECK-NEXT: add.d $s0, $t0, $s0
; CHECK-NEXT: ldx.bu $s8, $s0, $s8
; 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
; CHECK-NEXT: .LBB0_9: # %if.end.i
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
; CHECK-NEXT: andi $s7, $s7, 255
+; CHECK-NEXT: ori $s5, $zero, 50
; CHECK-NEXT: bltu $s5, $s7, .LBB0_15
; CHECK-NEXT: # %bb.10: # %if.end.i
; 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
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
; CHECK-NEXT: pcalau12i $ra, %pc_hi20(.LJTI0_1)
; CHECK-NEXT: addi.d $ra, $ra, %pc_lo12(.LJTI0_1)
-; CHECK-NEXT: ldx.d $ra, $s4, $ra
-; CHECK-NEXT: ret
+; CHECK-NEXT: ldx.d $s5, $s4, $ra
+; CHECK-NEXT: jr $s5
; CHECK-NEXT: .LBB0_13: # %phy_tssi_get_ofdm_trim_de.exit
; CHECK-NEXT: # in Loop: Header=BB0_4 Depth=1
; CHECK-NEXT: bnez $s3, .LBB0_1
``````````
</details>
https://github.com/llvm/llvm-project/pull/115424
More information about the llvm-branch-commits
mailing list