aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorHongyu Wang <hongyu.wang@intel.com>2024-02-07 14:42:58 +0800
committerHongyu Wang <hongyu.wang@intel.com>2024-07-04 11:11:11 +0800
commit8e72b1bb3896f6e8d4f4679cbcfbc2a8212d04f9 (patch)
treed66c8badcc16052dcb35bbb89dae3580a2d09f7f /gcc
parentbaac8f710e35cfea14060e5eca49dbb49ffc294d (diff)
downloadgcc-8e72b1bb3896f6e8d4f4679cbcfbc2a8212d04f9.zip
gcc-8e72b1bb3896f6e8d4f4679cbcfbc2a8212d04f9.tar.gz
gcc-8e72b1bb3896f6e8d4f4679cbcfbc2a8212d04f9.tar.bz2
[APX PPX] Avoid generating unmatched pushp/popp in pro/epilogue
According to APX spec, the pushp/popp pairs should be matched, otherwise the PPX hint cannot take effect and cause performance loss. In the ix86_expand_epilogue, there are several optimizations that may cause the epilogue using mov to restore the regs. Check if PPX applied and prevent usage of mov/leave in the epilogue. Also do not use PPX for eh_return. gcc/ChangeLog: * config/i386/i386.cc (ix86_expand_prologue): Set apx_ppx_used flag in m.fs with TARGET_APX_PPX && !crtl->calls_eh_return. (ix86_emit_save_regs): Emit ppx is available only when TARGET_APX_PPX && !crtl->calls_eh_return. (ix86_expand_epilogue): Don't restore reg using mov when apx_ppx_used flag is true. * config/i386/i386.h (struct machine_frame_state): Add apx_ppx_used flag. gcc/testsuite/ChangeLog: * gcc.target/i386/apx-ppx-2.c: New test. * gcc.target/i386/apx-ppx-3.c: Likewise.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386.cc13
-rw-r--r--gcc/config/i386/i386.h4
-rw-r--r--gcc/testsuite/gcc.target/i386/apx-ppx-2.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/apx-ppx-3.c7
4 files changed, 34 insertions, 4 deletions
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index bd74111..99def8d 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -7429,6 +7429,7 @@ ix86_emit_save_regs (void)
{
int regno;
rtx_insn *insn;
+ bool use_ppx = TARGET_APX_PPX && !crtl->calls_eh_return;
if (!TARGET_APX_PUSH2POP2
|| !ix86_can_use_push2pop2 ()
@@ -7438,7 +7439,7 @@ ix86_emit_save_regs (void)
if (GENERAL_REGNO_P (regno) && ix86_save_reg (regno, true, true))
{
insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno),
- TARGET_APX_PPX));
+ use_ppx));
RTX_FRAME_RELATED_P (insn) = 1;
}
}
@@ -7469,7 +7470,7 @@ ix86_emit_save_regs (void)
regno_list[0]),
gen_rtx_REG (word_mode,
regno_list[1]),
- TARGET_APX_PPX));
+ use_ppx));
RTX_FRAME_RELATED_P (insn) = 1;
rtx dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (3));
@@ -7502,7 +7503,7 @@ ix86_emit_save_regs (void)
else
{
insn = emit_insn (gen_push (gen_rtx_REG (word_mode, regno),
- TARGET_APX_PPX));
+ use_ppx));
RTX_FRAME_RELATED_P (insn) = 1;
aligned = true;
}
@@ -7511,7 +7512,7 @@ ix86_emit_save_regs (void)
{
insn = emit_insn (gen_push (gen_rtx_REG (word_mode,
regno_list[0]),
- TARGET_APX_PPX));
+ use_ppx));
RTX_FRAME_RELATED_P (insn) = 1;
}
}
@@ -8985,6 +8986,7 @@ ix86_expand_prologue (void)
if (!frame.save_regs_using_mov)
{
ix86_emit_save_regs ();
+ m->fs.apx_ppx_used = TARGET_APX_PPX && !crtl->calls_eh_return;
int_registers_saved = true;
gcc_assert (m->fs.sp_offset == frame.reg_save_offset);
}
@@ -9870,6 +9872,9 @@ ix86_expand_epilogue (int style)
/* SEH requires the use of pops to identify the epilogue. */
else if (TARGET_SEH)
restore_regs_via_mov = false;
+ /* If we already save reg with pushp, don't use move at epilogue. */
+ else if (m->fs.apx_ppx_used)
+ restore_regs_via_mov = false;
/* If we're only restoring one register and sp cannot be used then
using a move instruction to restore the register since it's
less work than reloading sp and popping the register. */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 147b12c..0c5292e 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2693,6 +2693,10 @@ struct GTY(()) machine_frame_state
The flags realigned and sp_realigned are mutually exclusive. */
BOOL_BITFIELD sp_realigned : 1;
+ /* When APX_PPX used in prologue, force epilogue to emit
+ popp instead of move and leave. */
+ BOOL_BITFIELD apx_ppx_used : 1;
+
/* If sp_realigned is set, this is the last valid offset from the CFA
that can be used for access with the frame pointer. */
HOST_WIDE_INT sp_realigned_fp_last;
diff --git a/gcc/testsuite/gcc.target/i386/apx-ppx-2.c b/gcc/testsuite/gcc.target/i386/apx-ppx-2.c
new file mode 100644
index 0000000..42a9534
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-ppx-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O1 -mapx-features=ppx -fno-omit-frame-pointer" } */
+
+/* { dg-final { scan-assembler "pushp" } } */
+/* { dg-final { scan-assembler "popp" } } */
+/* { dg-final { scan-assembler-not "leave" } } */
+
+extern int bar (int a);
+extern int *q;
+
+void foo (int *a)
+{
+ q[2] = bar (q[1]);
+}
diff --git a/gcc/testsuite/gcc.target/i386/apx-ppx-3.c b/gcc/testsuite/gcc.target/i386/apx-ppx-3.c
new file mode 100644
index 0000000..76931fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-ppx-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mapx-features=ppx" } */
+
+/* { dg-final { scan-assembler-not "pushp" } } */
+/* { dg-final { scan-assembler-not "popp" } } */
+
+#include "eh_return-2.c"