[llvm] [RISCV] Avoid using x7/t2 for indirect branches which need landing pad. (PR #68292)
Yeting Kuo via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 24 00:58:52 PDT 2024
https://github.com/yetingk updated https://github.com/llvm/llvm-project/pull/68292
>From 435de8219a624853b28bf22ee65107b8bfb86fde Mon Sep 17 00:00:00 2001
From: Yeting Kuo <yeting.kuo at sifive.com>
Date: Thu, 5 Oct 2023 16:38:38 +0800
Subject: [PATCH] [RISCV] Avoid using x7/t2 for indirect branches which need
landing pad.
When Zicfilp enabled, this avoids selecting brind/call/tail to
PseudoBRIND/CALLIndirect/TAILIndirect, since it may use X7 as its scratch
register and be identified as a software guarded jump.
There is an another PR #66762 to use software guarded jump for jumptable branch.
---
llvm/lib/Target/RISCV/RISCVFeatures.td | 2 +
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 32 ++++++++++++++-
llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 3 ++
llvm/test/CodeGen/RISCV/zicfilp-brind.ll | 48 ++++++++++++++++++++++
4 files changed, 83 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/zicfilp-brind.ll
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 3d3486b7fa8956..7ba09d65e54d13 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -672,6 +672,8 @@ def FeatureStdExtZicfilp
def HasStdExtZicfilp : Predicate<"Subtarget->hasStdExtZicfilp()">,
AssemblerPredicate<(all_of FeatureStdExtZicfilp),
"'Zicfilp' (Landing pad)">;
+def NoStdExtZicfilp : Predicate<"!Subtarget->hasStdExtZicfilp()">,
+ AssemblerPredicate<(all_of (not FeatureStdExtZicfilp))>;
def FeatureStdExtZicond
: SubtargetFeature<"experimental-zicond", "HasStdExtZicond", "true",
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index abbeff78b6e286..af32965ec17171 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1641,9 +1641,25 @@ let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in
def PseudoBRIND : Pseudo<(outs), (ins GPRJALR:$rs1, simm12:$imm12), []>,
PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
+let Predicates = [HasStdExtZicfilp],
+ isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in {
+def PseudoBRINDNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1, simm12:$imm12), []>,
+ PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>;
+}
+
+// For Zicfilp, need to avoid using X7/T2 for indirect branches which need
+// landing pad.
+let Predicates = [HasStdExtZicfilp] in {
+def : Pat<(brind GPRJALRNonX7:$rs1), (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, 0)>;
+def : Pat<(brind (add GPRJALRNonX7:$rs1, simm12:$imm12)),
+ (PseudoBRINDNonX7 GPRJALRNonX7:$rs1, simm12:$imm12)>;
+}
+
+let Predicates = [NoStdExtZicfilp] in {
def : Pat<(brind GPRJALR:$rs1), (PseudoBRIND GPRJALR:$rs1, 0)>;
def : Pat<(brind (add GPRJALR:$rs1, simm12:$imm12)),
(PseudoBRIND GPRJALR:$rs1, simm12:$imm12)>;
+}
// PseudoCALLReg is a generic pseudo instruction for calls which will eventually
// expand to auipc and jalr while encoding, with any given register used as the
@@ -1673,10 +1689,16 @@ def : Pat<(riscv_call texternalsym:$func), (PseudoCALL texternalsym:$func)>;
def : Pat<(riscv_sret_glue), (SRET (XLenVT X0), (XLenVT X0))>;
def : Pat<(riscv_mret_glue), (MRET (XLenVT X0), (XLenVT X0))>;
-let isCall = 1, Defs = [X1] in
+let isCall = 1, Defs = [X1] in {
+let Predicates = [NoStdExtZicfilp] in
def PseudoCALLIndirect : Pseudo<(outs), (ins GPRJALR:$rs1),
[(riscv_call GPRJALR:$rs1)]>,
PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
+let Predicates = [HasStdExtZicfilp] in
+def PseudoCALLIndirectNonX7 : Pseudo<(outs), (ins GPRJALRNonX7:$rs1),
+ [(riscv_call GPRJALRNonX7:$rs1)]>,
+ PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>;
+}
let isBarrier = 1, isReturn = 1, isTerminator = 1 in
def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_glue)]>,
@@ -1691,10 +1713,16 @@ def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), [],
"tail", "$dst">,
Sched<[WriteIALU, WriteJalr, ReadJalr]>;
-let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in
+let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in {
+let Predicates = [NoStdExtZicfilp] in
def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1),
[(riscv_tail GPRTC:$rs1)]>,
PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
+let Predicates = [HasStdExtZicfilp] in
+def PseudoTAILIndirectNonX7 : Pseudo<(outs), (ins GPRTCNonX7:$rs1),
+ [(riscv_tail GPRTCNonX7:$rs1)]>,
+ PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>;
+}
def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)),
(PseudoTAIL tglobaladdr:$dst)>;
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index ab0d354967b34c..08ab55056b50c4 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -148,6 +148,8 @@ def GPRNoX0X2 : GPRRegisterClass<(sub GPR, X0, X2)>;
// by tablegen.
def GPRJALR : GPRRegisterClass<(sub GPR, (sequence "X%u", 0, 5))>;
+def GPRJALRNonX7 : GPRRegisterClass<(sub GPRJALR, X7)>;
+
def GPRC : GPRRegisterClass<(add (sequence "X%u", 10, 15),
(sequence "X%u", 8, 9))>;
@@ -158,6 +160,7 @@ def GPRC : GPRRegisterClass<(add (sequence "X%u", 10, 15),
def GPRTC : GPRRegisterClass<(add (sequence "X%u", 6, 7),
(sequence "X%u", 10, 17),
(sequence "X%u", 28, 31))>;
+def GPRTCNonX7 : GPRRegisterClass<(sub GPRTC, X7)>;
def SP : GPRRegisterClass<(add X2)>;
diff --git a/llvm/test/CodeGen/RISCV/zicfilp-brind.ll b/llvm/test/CodeGen/RISCV/zicfilp-brind.ll
new file mode 100644
index 00000000000000..bccd28ee7e2b39
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/zicfilp-brind.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=riscv64 -stop-after=finalize-isel < %s | FileCheck %s
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfilp -stop-after=finalize-isel < %s | FileCheck -check-prefixes=ZICFILP %s
+
+ at brind.arr = internal unnamed_addr constant [2 x ptr] [ptr blockaddress(@brind, %5), ptr blockaddress(@brind, %8)], align 8
+ at x = dso_local global i32 0, align 4
+
+define void @brind(i32 noundef signext %0) {
+ ; CHECK-LABEL: name: brind
+ ; CHECK: PseudoBRIND killed [[VAR:%.*]], 0
+ ; ZICFILP-LABEL: name: brind
+ ; ZICFILP: PseudoBRINDNonX7 killed [[VAR:%.*]], 0
+ %2 = sext i32 %0 to i64
+ %3 = getelementptr inbounds [2 x ptr], ptr @brind.arr, i64 0, i64 %2
+ %4 = load ptr, ptr %3, align 8
+ indirectbr ptr %4, [label %5, label %8]
+
+5: ; preds = %1
+ %6 = load i32, ptr @x, align 4
+ %7 = add nsw i32 %6, 2
+ store i32 %7, ptr @x, align 4
+ br label %8
+
+8: ; preds = %5, %1
+ %9 = load i32, ptr @x, align 4
+ %10 = add nsw i32 %9, 1
+ store i32 %10, ptr @x, align 4
+ ret void
+}
+
+define i32 @indirect_call(ptr %0) {
+ ; CHECK-LABEL: name: indirect_call
+ ; CHECK: PseudoCALLIndirect
+ ; ZICFILP-LABEL: name: indirect_call
+ ; ZICFILP: PseudoCALLIndirectNonX7
+ call void %0()
+ ret i32 0
+}
+
+
+define void @indirect_tail(ptr %0) {
+ ; CHECK-LABEL: name: indirect_tail
+ ; CHECK: PseudoTAILIndirect
+ ; ZICFILP-LABEL: name: indirect_tail
+ ; ZICFILP: PseudoTAILIndirectNonX7
+ tail call void %0()
+ ret void
+}
More information about the llvm-commits
mailing list