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.