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

Reply via email to