From 78bb37b9bd84715f61ac2ca7ad138be8a21b8147 Mon Sep 17 00:00:00 2001 From: Dragan Mladjenovic Date: Thu, 8 Sep 2022 00:08:43 +0800 Subject: [PATCH] [BZ #51] Prevent indirect tail calls from using callee-saved registers Change-Id: Ic52d74c58f9488e5793f85e9c4a4fe08e1ca2bb7 --- llvm/lib/Target/Mips/MipsRegisterInfo.td | 12 +++++ llvm/lib/Target/Mips/NanoMipsInstrInfo.td | 4 +- llvm/test/CodeGen/Mips/nanomips/tail.ll | 56 +++++++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/Mips/nanomips/tail.ll diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.td b/llvm/lib/Target/Mips/MipsRegisterInfo.td index 45329b2a52eb1..57125a28af03c 100644 --- a/llvm/lib/Target/Mips/MipsRegisterInfo.td +++ b/llvm/lib/Target/Mips/MipsRegisterInfo.td @@ -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 regTypes> : RegisterClass<"Mips", regTypes, 32, (add // Reserved diff --git a/llvm/lib/Target/Mips/NanoMipsInstrInfo.td b/llvm/lib/Target/Mips/NanoMipsInstrInfo.td index eda4057fca1e9..cfe251905803d 100644 --- a/llvm/lib/Target/Mips/NanoMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/NanoMipsInstrInfo.td @@ -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:$rs), + [(MipsTailCall RegisterOperand:$rs)]>, PseudoInstExpansion<(JRC_NM GPR32NMOpnd:$rs)> { let isCall = 1; let isTerminator = 1; diff --git a/llvm/test/CodeGen/Mips/nanomips/tail.ll b/llvm/test/CodeGen/Mips/nanomips/tail.ll new file mode 100644 index 0000000000000..c4091138fa806 --- /dev/null +++ b/llvm/test/CodeGen/Mips/nanomips/tail.ll @@ -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 +}