[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