ia64 uses default_zero_call_used_regs(), which uses emit_move_insn()
to zero out registers. ia64 predicate registers use BImode, which is not
supported by emit_move_insn().
Implement ia64_zero_call_used_regs() to zero PRs by manually emitting
a CCImode move. default_zero_call_used_regs() is then called to handle
the remaining registers.
PR target/121535
gcc/ChangeLog:
* config/ia64/ia64.cc (TARGET_ZERO_CALL_USED_REGS): Override
function with target-specific one.
(struct gcc_target): Move to end of file.
(ia64_zero_call_used_regs): Add target-specific function.
gcc/testsuite/ChangeLog:
* gcc.target/ia64/pr121535.c: New test.
Signed-off-by: Tomas Glozar <[email protected]>
---
I verified that the patch correctly zeroes out the registers
in the testsuite example:
f:
.prologue 2, 2
.vframe r2
mov r2 = r12
.body
...
cmp4.ne p6, p7 = 1, r14
...
(p0) cmp.eq.unc p6, p0 = r0, r0
(p0) cmp.eq.unc p7, p0 = r0, r0
br.ret.sptk.many b0
;;
.endp f#
gcc/config/ia64/ia64.cc | 55 +++++++++++++++++++++++-
gcc/testsuite/gcc.target/ia64/pr121535.c | 7 +++
2 files changed, 60 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/ia64/pr121535.c
diff --git a/gcc/config/ia64/ia64.cc b/gcc/config/ia64/ia64.cc
index 8dab9279fe7..886d5a1055a 100644
--- a/gcc/config/ia64/ia64.cc
+++ b/gcc/config/ia64/ia64.cc
@@ -578,6 +578,9 @@ static const scoped_attribute_specs *const
ia64_attribute_table[] =
#undef TARGET_FUNCTION_VALUE_REGNO_P
#define TARGET_FUNCTION_VALUE_REGNO_P ia64_function_value_regno_p
+#undef TARGET_ZERO_CALL_USED_REGS
+#define TARGET_ZERO_CALL_USED_REGS ia64_zero_call_used_regs
+
#undef TARGET_STRUCT_VALUE_RTX
#define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx
#undef TARGET_RETURN_IN_MEMORY
@@ -688,8 +691,6 @@ static const scoped_attribute_specs *const
ia64_attribute_table[] =
#undef TARGET_DOCUMENTATION_NAME
#define TARGET_DOCUMENTATION_NAME "IA-64"
-
-struct gcc_target targetm = TARGET_INITIALIZER;
/* Returns TRUE iff the target attribute indicated by ATTR_ID takes a plain
identifier as an argument, so the front end shouldn't look it up. */
@@ -5330,6 +5331,54 @@ ia64_function_value_regno_p (const unsigned int regno)
|| (regno >= FR_RET_FIRST && regno <= FR_RET_LAST));
}
+/* TARGET_ZERO_CALL_USED_REGS. */
+/* Generate a sequence of instructions that zero registers specified by
+ NEED_ZEROED_HARDREGS. Return the ZEROED_HARDREGS that are actually
+ zeroed. */
+static HARD_REG_SET
+ia64_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+ HARD_REG_SET nonpredicate, failed;
+
+ CLEAR_HARD_REG_SET (nonpredicate);
+ CLEAR_HARD_REG_SET (failed);
+
+ /* Mark all non-predicate registers. */
+ for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
+ if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno)
+ && !PR_REGNO_P (regno))
+ SET_HARD_REG_BIT (nonpredicate, regno);
+
+ /* Let the generic helper emit zeroing for the remaining hard regs.
+ It returns the subset it actually managed to zero. */
+ if (!hard_reg_set_empty_p (nonpredicate))
+ failed = default_zero_call_used_regs (nonpredicate);
+
+ /* Finally, emit zeroing of predicate registers. */
+ for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno)
+ && PR_REGNO_P (regno))
+ {
+ rtx_insn *last_insn = get_last_insn ();
+ /* Prepare PR0 register, which is hardwired to 1 */
+ rtx zero = gen_rtx_REG (CCImode, PR_REG (0));
+ rtx regno_rtx = gen_rtx_REG (CCImode, regno);
+ enum insn_code code = optab_handler (mov_optab, CCImode);
+
+ gcc_assert (code != CODE_FOR_nothing);
+
+ rtx_insn *insn = emit_insn (GEN_FCN (code) (regno_rtx, zero));
+
+ if (!valid_insn_p (insn))
+ {
+ SET_HARD_REG_BIT (failed, regno);
+ delete_insns_since (last_insn);
+ }
+ }
+
+ return failed;
+}
+
/* This is called from dwarf2out.cc via TARGET_ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */
@@ -11960,4 +12009,6 @@ ia64_can_change_mode_class (machine_mode from,
machine_mode to,
return true;
}
+struct gcc_target targetm = TARGET_INITIALIZER;
+
#include "gt-ia64.h"
diff --git a/gcc/testsuite/gcc.target/ia64/pr121535.c
b/gcc/testsuite/gcc.target/ia64/pr121535.c
new file mode 100644
index 00000000000..134120c019a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/ia64/pr121535.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+__attribute__ ((zero_call_used_regs("used"))) int f(int x)
+{
+ if (x == 1)
+ return 0;
+ return 1;
+}
--
2.51.1