https://gcc.gnu.org/g:dee08b5feed336fe31e520115f6dcd18f84d24c8

commit r17-1558-gdee08b5feed336fe31e520115f6dcd18f84d24c8
Author: Monk Chiang <[email protected]>
Date:   Wed Jan 21 11:29:13 2026 +0800

    RISC-V: Ensure Zicfilp lpad 4-byte alignment
    
    Add LABEL_ALIGN to align non-local goto target labels, removing the
    explicit gen_lpad_align () call.  Extend gpr_save to emit the full
    CFI guard (.p2align 2, .option push/norelax/norvc, call, .option pop,
    lpad 0) when Zicfilp is active.  Add lpad_align before the thunk
    entry lpad.
    
    gcc/ChangeLog:
    
            * config/riscv/riscv-zicfilp.cc (rest_of_insert_landing_pad):
            Remove gen_lpad_align before non-local goto labels; LABEL_ALIGN
            now handles their alignment.  Simplify gpr_save handling: the
            pattern now outputs the full CFI sequence itself.
            * config/riscv/riscv.cc (riscv_output_mi_thunk): Add
            gen_lpad_align before entry lpad.
            * config/riscv/riscv.h (LABEL_ALIGN): New macro; ensures 4-byte
            alignment for Zicfilp non-local goto target labels.
            * config/riscv/riscv.md (gpr_save): When is_zicfilp_p, output
            .p2align 2, .option push/norelax/norvc, call, .option pop, lpad 0.
    
    gcc/testsuite/ChangeLog:
    
            * g++.target/riscv/zicfilp-thunk.C: New test.
            * gcc.target/riscv/zicfilp-func-entry.c: New test.
            * gcc.target/riscv/zicfilp-gpr-save.c: New test.
            * gcc.target/riscv/zicfilp-nonlocal-goto.c: New test.

Diff:
---
 gcc/config/riscv/riscv-zicfilp.cc                  |  6 ++--
 gcc/config/riscv/riscv.cc                          |  5 ++-
 gcc/config/riscv/riscv.h                           |  7 +++++
 gcc/config/riscv/riscv.md                          | 19 ++++++++++--
 gcc/testsuite/g++.target/riscv/zicfilp-thunk.C     | 36 ++++++++++++++++++++++
 .../gcc.target/riscv/zicfilp-func-entry.c          | 15 +++++++++
 gcc/testsuite/gcc.target/riscv/zicfilp-gpr-save.c  | 27 ++++++++++++++++
 .../gcc.target/riscv/zicfilp-nonlocal-goto.c       | 31 +++++++++++++++++++
 8 files changed, 140 insertions(+), 6 deletions(-)

diff --git a/gcc/config/riscv/riscv-zicfilp.cc 
b/gcc/config/riscv/riscv-zicfilp.cc
index 04d9bd923392..6facdd702c39 100644
--- a/gcc/config/riscv/riscv-zicfilp.cc
+++ b/gcc/config/riscv/riscv-zicfilp.cc
@@ -107,16 +107,16 @@ rest_of_insert_landing_pad (void)
               && (LABEL_PRESERVE_P (insn)
                   || bb->flags & BB_NON_LOCAL_GOTO_TARGET))
            {
-             emit_insn_before (gen_lpad_align (), insn);
              emit_insn_after (gen_lpad (const0_rtx), insn);
              continue;
            }
 
+         /* gpr_save outputs the full CFI sequence when Zicfilp is active
+            Reset t2 to 0 so the hardware lpad check passes on return from
+            __riscv_save_N.  */
          if (INSN_P (insn) && INSN_CODE (insn) == CODE_FOR_gpr_save)
            {
              emit_move_insn (RISCV_CALL_ADDRESS_LPAD (Pmode), const0_rtx);
-             emit_insn_before (gen_lpad_align (), insn);
-             emit_insn_after (gen_lpad (const0_rtx), insn);
              continue;
            }
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index b1bdbf1a9ccb..3be5606ba015 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -11834,7 +11834,10 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl 
ATTRIBUTE_UNUSED,
   emit_note (NOTE_INSN_PROLOGUE_END);
 
   if (is_zicfilp_p ())
-    emit_insn (gen_lpad (const0_rtx));
+    {
+      emit_insn (gen_lpad_align ());
+      emit_insn (gen_lpad (const0_rtx));
+    }
 
   /* Determine if we can use a sibcall to call FUNCTION directly.  */
   fnaddr = gen_rtx_MEM (FUNCTION_MODE, XEXP (DECL_RTL (function), 0));
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index cb821ae8b3a6..d72c06ec37f1 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1105,6 +1105,13 @@ extern enum riscv_cc get_riscv_cc (const rtx use);
   fprintf (STREAM, "\t.word\t%sL%d-%sL%d\n",                           \
           LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL)
 
+/* For Zicfilp, labels that may be indirect jump targets need 4-byte
+   alignment so that the lpad instruction after them is properly aligned.  */
+#define LABEL_ALIGN(LABEL)                                             \
+  (TARGET_ZICFILP && LABEL_PRESERVE_P (LABEL)                          \
+   ? ((align_labels.levels[0].log > 2) ? align_labels : align_flags (2)) \
+   : align_labels)
+
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 5231610b0540..88defdd43f0e 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -4347,8 +4347,23 @@
      [(unspec_volatile [(match_operand 0 "const_int_operand")]
                       UNSPECV_GPR_SAVE)])]
   ""
-  "call\tt0,__riscv_save_%0"
-  [(set_attr "type" "call")])
+  {
+    if (is_zicfilp_p ())
+      {
+       output_asm_insn (".p2align\t2", operands);
+       output_asm_insn (".option push", operands);
+       output_asm_insn (".option norelax", operands);
+       output_asm_insn (".option norvc", operands);
+       output_asm_insn ("call\tt0,__riscv_save_%0", operands);
+       output_asm_insn (".option pop", operands);
+       return "lpad\t0";
+      }
+    return "call\tt0,__riscv_save_%0";
+  }
+  [(set_attr "type" "call")
+   (set (attr "length") (if_then_else (match_test "is_zicfilp_p ()")
+                                     (const_string "12")
+                                     (const_string "8")))])
 
 (define_insn "gpr_restore"
   [(unspec_volatile [(match_operand 0 "const_int_operand")] 
UNSPECV_GPR_RESTORE)]
diff --git a/gcc/testsuite/g++.target/riscv/zicfilp-thunk.C 
b/gcc/testsuite/g++.target/riscv/zicfilp-thunk.C
new file mode 100644
index 000000000000..68d67dbc4968
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/zicfilp-thunk.C
@@ -0,0 +1,36 @@
+/* Test RISC-V Zicfilp C++ thunk LPAD.  */
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-O2 -march=rv64gc_zicfilp -mabi=lp64d -fcf-protection=none 
-fcf-protection=branch" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-g" "-flto" } } */
+/* { dg-final { check-function-bodies "**" "" {\.align|lpad} } } */
+
+class Base1 {
+public:
+  virtual int method1 (int x) { return x + 1; }
+  int data1;
+};
+
+class Base2 {
+public:
+  virtual int method2 (int x) { return x + 2; }
+  int data2;
+};
+
+class Derived : public Base1, public Base2 {
+public:
+  virtual int method2 (int x) override { return x + 10; }
+};
+
+Derived global_derived;
+
+int call_method2 (Base2 *p)
+{
+  return p->method2 (42);
+}
+
+/*
+** _ZThn16_N7Derived7method2Ei:
+**     \.align 2
+**     lpad    \d+
+**     ...
+*/
diff --git a/gcc/testsuite/gcc.target/riscv/zicfilp-func-entry.c 
b/gcc/testsuite/gcc.target/riscv/zicfilp-func-entry.c
new file mode 100644
index 000000000000..667acd829235
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicfilp-func-entry.c
@@ -0,0 +1,15 @@
+/* Test RISC-V Zicfilp function entry LPAD.  */
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-O2 -march=rv64gc_zicfilp -mabi=lp64d -fcf-protection=none 
-fcf-protection=branch" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-g" "-flto" } } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** public_function:
+**     lpad    \d+
+**     ...
+*/
+int public_function (int a, int b)
+{
+  return a + b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/zicfilp-gpr-save.c 
b/gcc/testsuite/gcc.target/riscv/zicfilp-gpr-save.c
new file mode 100644
index 000000000000..1d9b6446de44
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicfilp-gpr-save.c
@@ -0,0 +1,27 @@
+/* Test RISC-V Zicfilp gpr_save LPAD alignment with .option norelax.  */
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-O2 -msave-restore -fomit-frame-pointer -march=rv64gc_zicfilp 
-mabi=lp64d -fcf-protection=none -fcf-protection=branch" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-g" "-flto" } } */
+/* { dg-final { check-function-bodies "**" "" {\.p2align|\.option|call|lpad} } 
} */
+
+extern void bar (void);
+
+/*
+** foo:
+**     ...
+**     .p2align        2
+**     .option push
+**     .option norelax
+**     .option norvc
+**     call    t0,__riscv_save_[0-9]+
+**     .option pop
+**     lpad    \d+
+**     ...
+*/
+void foo (void)
+{
+  register long s0 asm ("s0");
+  asm volatile ("li s0, 0x87654321" : "=r"(s0));
+  bar ();
+  asm volatile ("" : : "r"(s0));
+}
diff --git a/gcc/testsuite/gcc.target/riscv/zicfilp-nonlocal-goto.c 
b/gcc/testsuite/gcc.target/riscv/zicfilp-nonlocal-goto.c
new file mode 100644
index 000000000000..1edd30f50273
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicfilp-nonlocal-goto.c
@@ -0,0 +1,31 @@
+/* Test RISC-V Zicfilp non-local goto LPAD with proper alignment.  */
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-march=rv64gc_zicfilp -mabi=lp64d -fcf-protection=none 
-fcf-protection=branch" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-O2" "-O3" "-Os" "-Oz" "-Og" "-g" 
"-flto" } } */
+/* { dg-final { check-function-bodies "**" "" {\.align|\.L[0-9]+:} } } */
+
+extern void do_something (void);
+
+/*
+** outer_function:
+**     lpad    \d+
+**     ...
+**     \.align 2
+**     \.L[0-9]+:
+**     lpad    \d+
+**     ...
+*/
+void outer_function (void *label_addr)
+{
+  __label__ target_label;
+
+  if (label_addr)
+    goto *label_addr;
+
+  do_something ();
+
+target_label:
+  do_something ();
+
+  outer_function (&&target_label);
+}

Reply via email to