The trampoline code generation for Zicfilp (CFI landing pads) uses
three registers and includes a redundant LUI instruction.
Before this patch, the trampoline code was:
lpad 0
auipc t3, 0
l[wd] t0, (target_function_offset - 4)(t3)
l[wd] t3, (static_chain_offset - 4)(t3)
lui t2, 0
jr t0
This uses three registers (t0, t2, t3) and has a redundant "lui t2, 0"
instruction that is never used.
After this patch, the trampoline code is:
lpad 0
auipc t3, 0
l[wd] t2, (target_function_offset - 4)(t3)
l[wd] t3, (static_chain_offset - 4)(t3)
jr t2
nop
The optimization removes the redundant LUI instruction, uses only two
registers (t2, t3), and adds a nop for proper 8-byte alignment to avoid
-Wpadded warnings.
Changes in v2:
- Fix zicfilp-trampoline test for Linux targets.
- Fix line length exceeding 80 characters.
gcc/
* config/riscv/riscv.cc (riscv_trampoline_init): Remove redundant
LUI instruction.
gcc/testsuite/
* gcc.target/riscv/zicfilp-trampoline.c: New test.
---
gcc/config/riscv/riscv.cc | 19 +++++++++----------
.../gcc.target/riscv/zicfilp-trampoline.c | 14 ++++++++++++++
2 files changed, 23 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/zicfilp-trampoline.c
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 623aaa83b0e..e70df9530d9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -12504,28 +12504,27 @@ riscv_trampoline_init (rtx m_tramp, tree fndecl, rtx
chain_value)
}
else
{
- /* lpad 1
+ /* lpad 0
auipc t3, 0
- l[wd] t0, (target_function_offset - 4)(t3)
+ l[wd] t2, (target_function_offset - 4)(t3)
l[wd] t3, (static_chain_offset - 4)(t3)
- lui t2, 1
- jr t0
+ jr t2
+ nop
*/
trampoline_cfi[0] = OPCODE_AUIPC | (0 << SHIFT_RD) | (lp_value <<
IMM_BITS);
trampoline_cfi[1] = OPCODE_AUIPC | (STATIC_CHAIN_REGNUM << SHIFT_RD);
trampoline_cfi[2] = (Pmode == DImode ? OPCODE_LD : OPCODE_LW)
- | (RISCV_PROLOGUE_TEMP_REGNUM << SHIFT_RD)
+ | (RISCV_CALL_ADDRESS_LPAD_REGNUM << SHIFT_RD)
| (STATIC_CHAIN_REGNUM << SHIFT_RS1)
| ((target_function_offset - 4) << SHIFT_IMM);
trampoline_cfi[3] = (Pmode == DImode ? OPCODE_LD : OPCODE_LW)
| (STATIC_CHAIN_REGNUM << SHIFT_RD)
| (STATIC_CHAIN_REGNUM << SHIFT_RS1)
| ((static_chain_offset - 4) << SHIFT_IMM);
- trampoline_cfi[4] = OPCODE_LUI
- | (RISCV_CALL_ADDRESS_LPAD_REGNUM << SHIFT_RD)
- | (lp_value << IMM_BITS);
- trampoline_cfi[5] = OPCODE_JALR | (RISCV_PROLOGUE_TEMP_REGNUM <<
SHIFT_RS1);
-
+ trampoline_cfi[4] = OPCODE_JALR
+ | (RISCV_CALL_ADDRESS_LPAD_REGNUM << SHIFT_RS1);
+ trampoline_cfi[5] = OPCODE_ADDI | (0 << SHIFT_RD)
+ | (0 << SHIFT_RS1) | (0 << SHIFT_IMM);
/* Copy the trampoline code. */
for (i = 0; i < ARRAY_SIZE (trampoline_cfi); i++)
{
diff --git a/gcc/testsuite/gcc.target/riscv/zicfilp-trampoline.c
b/gcc/testsuite/gcc.target/riscv/zicfilp-trampoline.c
new file mode 100644
index 00000000000..575708365e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicfilp-trampoline.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-require-effective-target trampolines } */
+/* { dg-options "-Wpadded -march=rv64gc_zicfilp -mabi=lp64d
-fcf-protection=branch -O2" } */
+/* { dg-final { scan-assembler "lpad\\s+0" } } */
+
+extern int baz(int (*) (int));
+int foo(void)
+{
+ int k = 3;
+ int bar(int x) {
+ return x + k;
+ }
+ return baz(bar);
+}
--
2.54.0