Since uiret should be used only for user interrupt handler return, don't
generate uiret in interrupt handler return with -mcmodel=kernel even if
UINTR is enabled.

gcc/

        PR target/99870
        * config/i386/i386.md (interrupt_return): Don't generate uiret
        for -mcmodel=kernel.

gcc/testsuite/

        * gcc.target/i386/pr99870.c: New test.
---
 gcc/config/i386/i386.md                 |  3 ++-
 gcc/testsuite/gcc.target/i386/pr99870.c | 19 +++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr99870.c

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 9ff35d9a607..1055b4187b2 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -13885,7 +13885,8 @@ (define_insn "interrupt_return"
    (unspec [(const_int 0)] UNSPEC_INTERRUPT_RETURN)]
   "reload_completed"
 {
-  return TARGET_64BIT ? (TARGET_UINTR ? "uiret" : "iretq") : "iret";
+  return TARGET_64BIT ? ((TARGET_UINTR && ix86_cmodel != CM_KERNEL)
+                        ? "uiret" : "iretq") : "iret";
 })
 
 ;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET
diff --git a/gcc/testsuite/gcc.target/i386/pr99870.c 
b/gcc/testsuite/gcc.target/i386/pr99870.c
new file mode 100644
index 00000000000..0dafa001ba9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr99870.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=sapphirerapids -mgeneral-regs-only" } */
+/* { dg-additional-options "-mcmodel=kernel" { target { ! ia32 } } } */
+
+void
+__attribute__((interrupt))
+fn (void *frame)
+{
+}
+
+typedef void (*fn_t) (void *) __attribute__((interrupt));
+
+fn_t fns[] =
+{
+  fn,
+};
+
+/* { dg-final { scan-assembler-times "\\tiret" 1 { target ia32 } } } */
+/* { dg-final { scan-assembler-times "\\tiretq" 1 { target { ! ia32 } } } } */
-- 
2.30.2

Reply via email to