]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PATCH 1/2] ia64: Fix zero_call_used_regs for PRs [PR121535]
authorTomas Glozar <tglozar@gmail.com>
Wed, 7 Jan 2026 16:02:15 +0000 (09:02 -0700)
committerJeff Law <jeffrey.law@oss.qualcomm.com>
Wed, 7 Jan 2026 16:02:15 +0000 (09:02 -0700)
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 <tglozar@gmail.com>
gcc/config/ia64/ia64.cc
gcc/testsuite/gcc.target/ia64/pr121535.c [new file with mode: 0644]

index 3dc94dd1d68bb87c4a5fc14c9d501e4fbe43a040..055af3e8617cbbc2ffc3a8d7374538cb046910b6 100644 (file)
@@ -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;
 \f
 /* 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 (file)
index 0000000..134120c
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+__attribute__ ((zero_call_used_regs("used"))) int f(int x)
+{
+  if (x == 1)
+    return 0;
+  return 1;
+}