Skip to content

Commit

Permalink
[BZ #51] Prevent indirect tail calls from using callee-saved registers
Browse files Browse the repository at this point in the history
Change-Id: Ic52d74c58f9488e5793f85e9c4a4fe08e1ca2bb7
  • Loading branch information
Dragan Mladjenovic committed Sep 13, 2022
1 parent 58ae15b commit 78bb37b
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 2 deletions.
12 changes: 12 additions & 0 deletions llvm/lib/Target/Mips/MipsRegisterInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,18 @@ def GPR3 :
RegisterClass<"Mips", [i32], 32,
(add A0_NM, A1_NM, A2_NM, A3_NM, S0_NM, S1_NM, S2_NM, S3_NM)>;

def GPR32NM_TAIL :
RegisterClass<"Mips", [i32], 32,
(add
// Not preserved across procedure calls
T4_NM, T5_NM,
// Return Values and Arguments
A0_NM, A1_NM, A2_NM, A3_NM, A4_NM, A5_NM, A6_NM, A7_NM,
// Not preserved across procedure calls
T0_NM, T1_NM, T2_NM, T3_NM,
// Not preserved across procedure calls
T8_NM, T9_NM)>;

class GPR32Class<list<ValueType> regTypes> :
RegisterClass<"Mips", regTypes, 32, (add
// Reserved
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/Mips/NanoMipsInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,8 @@ class TailCallBase : PseudoInstNM<(outs), (ins calltarget:$target), []>,
}
def TAILCALL_NM : TailCallBase;

class TailCallRegBase : PseudoInstNM<(outs), (ins GPR32NMOpnd:$rs),
[(MipsTailCall GPR32NMOpnd:$rs)]>,
class TailCallRegBase : PseudoInstNM<(outs), (ins RegisterOperand<GPR32NM_TAIL>:$rs),
[(MipsTailCall RegisterOperand<GPR32NM_TAIL>:$rs)]>,
PseudoInstExpansion<(JRC_NM GPR32NMOpnd:$rs)> {
let isCall = 1;
let isTerminator = 1;
Expand Down
56 changes: 56 additions & 0 deletions llvm/test/CodeGen/Mips/nanomips/tail.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
; RUN: llc -mtriple=nanomips -verify-machineinstrs < %s | FileCheck %s
; CHECK-NOT: jrc ${{s[0-7]}}

define dso_local void @foo(i32 signext %i) local_unnamed_addr {
entry:
%0 = tail call { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } asm "nop", "={$16},={$17},={$18},={$19},={$20},={$21},={$22},={$23},~{$1}"()
switch i32 %i, label %sw.default [
i32 0, label %sw.bb
i32 1, label %sw.bb8
i32 2, label %sw.bb9
i32 3, label %sw.bb10
i32 4, label %sw.bb11
i32 5, label %sw.bb12
i32 6, label %sw.bb13
]

sw.bb:
%asmresult = extractvalue { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } %0, 0
tail call void %asmresult()
ret void

sw.bb8:
%asmresult1 = extractvalue { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } %0, 1
tail call void %asmresult1()
ret void

sw.bb9:
%asmresult2 = extractvalue { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } %0, 2
tail call void %asmresult2()
ret void

sw.bb10:
%asmresult3 = extractvalue { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } %0, 3
tail call void %asmresult3()
ret void

sw.bb11:
%asmresult4 = extractvalue { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } %0, 4
tail call void %asmresult4()
ret void

sw.bb12:
%asmresult5 = extractvalue { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } %0, 5
tail call void %asmresult5()
ret void

sw.bb13:
%asmresult6 = extractvalue { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } %0, 6
tail call void %asmresult6()
ret void

sw.default:
%asmresult7 = extractvalue { void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()*, void ()* } %0, 7
tail call void %asmresult7()
ret void
}

0 comments on commit 78bb37b

Please sign in to comment.