https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121535

Tomáš Glozar <tglozar at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |tglozar at gmail dot com

--- Comment #7 from Tomáš Glozar <tglozar at gmail dot com> ---
I put together a minimal reproducer:

$ cat 121535_minimal.c 
__attribute__ ((zero_call_used_regs("used"))) int f(int x)
{
    /* "if" needed so that a predicate register pair is used and zeroed */
    if (x == 1)
        return 0;
    return 1;
}
$ C_INCLUDE_PATH=$PWD PATH=$PATH:$PWD/gcc-trunk/build/gcc
gcc-trunk/build/gcc/xgcc -S -c 121535_minimal.c 
during RTL pass: zero_call_used_regs
121535_minimal.c: In function 'f':
121535_minimal.c:6:1: internal compiler error: in int_mode_for_mode, at
stor-layout.cc:408
    6 | }
      | ^
0x1bc68dd internal_error(char const*, ...)
    ../../gcc/diagnostic-global-context.cc:787
0x654213 fancy_abort(char const*, int, char const*)
    ../../gcc/diagnostics/context.cc:1806
0x4f9e6d int_mode_for_mode(machine_mode)
    ../../gcc/stor-layout.cc:408
0x94793a emit_move_via_integer
    ../../gcc/expr.cc:4241
0x95cfc8 emit_move_ccmode
    ../../gcc/expr.cc:4467
0x95cfc8 emit_move_insn_1(rtx_def*, rtx_def*)
    ../../gcc/expr.cc:4606
0x95d261 emit_move_insn(rtx_def*, rtx_def*)
    ../../gcc/expr.cc:4757
0xde384d default_zero_call_used_regs(HARD_REG_SET)
    ../../gcc/targhooks.cc:1127
0x9c184c gen_call_used_regs_seq
    ../../gcc/function.cc:5975
0x9c184c execute
    ../../gcc/function.cc:6831
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See <https://gcc.gnu.org/bugs/> for instructions.

I also put together a very hacky "fix" that makes the ICE go away:
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 4a699101bb5..96262ea61b6 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -4456,6 +4456,15 @@ emit_move_ccmode (machine_mode mode, rtx x, rtx y)
        }
     }

+  /* If we have movecci, use it */
+  enum insn_code code = optab_handler (mov_optab, CCImode);
+  if (code != CODE_FOR_nothing)
+    {
+      x = emit_move_change_mode (CCImode, mode, x, true);
+      y = emit_move_change_mode (CCImode, mode, y, true);
+      return emit_insn (GEN_FCN (code) (x, y));
+    }
+
   /* Otherwise, find the MODE_INT mode of the same width.  */
   ret = emit_move_via_integer (mode, x, y, false);
   gcc_assert (ret != NULL);

This makes GCC emit the correct assembly to clear the predicate pair:

$ cat 121535_minimal.s
        .file   "121535_minimal.c"
...
f:
...
        cmp4.ne p6, p7 = 1, r14
...
        mov r14 = r0
        ;;
        tbit.nz p6, p0 = r14, 0
        tbit.nz p7, p0 = r14, 0
        br.ret.sptk.many b0
        ;;
...

This works on ia64, but is not correct for other targets, since CCImode is
ia64-specific.

Reply via email to