Now that more operations are allowed for noce_convert_multiple_sets, we need to check noce_can_force_operand on the sequence before calling try_emit_cmove_seq. Otherwise an inappropriate argument may be given to copy_to_mode_reg and result in an ICE.
Fix-up for the recent ifcvt commit 72c9b5f438f22cca493b4e2a8a2a31ff61bf1477 PR tree-optimization/116353 gcc/ChangeLog: * ifcvt.cc (bb_ok_for_noce_convert_multiple_sets): Check noce_can_force_operand. gcc/testsuite/ChangeLog: * gcc.target/i386/pr116353.c: New test. Tested-by: Christoph Müllner <christoph.muell...@vrull.eu> Signed-off-by: Manolis Tsamis <manolis.tsa...@vrull.eu> --- gcc/ifcvt.cc | 6 ++- gcc/testsuite/gcc.target/i386/pr116353.c | 55 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr116353.c diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc index 3e25f30b67e..da59c907891 100644 --- a/gcc/ifcvt.cc +++ b/gcc/ifcvt.cc @@ -3938,8 +3938,10 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb, unsigned *cost) rtx src = SET_SRC (set); /* Do not handle anything involving memory loads/stores since it might - violate data-race-freedom guarantees. */ - if (!REG_P (dest) || contains_mem_rtx_p (src)) + violate data-race-freedom guarantees. Make sure we can force SRC + to a register as that may be needed in try_emit_cmove_seq. */ + if (!REG_P (dest) || contains_mem_rtx_p (src) + || !noce_can_force_operand (src)) return false; /* Destination and source must be appropriate. */ diff --git a/gcc/testsuite/gcc.target/i386/pr116353.c b/gcc/testsuite/gcc.target/i386/pr116353.c new file mode 100644 index 00000000000..8e254653d5d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr116353.c @@ -0,0 +1,55 @@ +/* PR tree-optimization/116353 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +enum desmode { C }; +struct { + unsigned char des_ivec[]; +} _des_crypt_desp; +int des_SPtrans_6_0, des_SPtrans_4_0, des_encrypt_encrypt, des_encrypt_i; +long des_encrypt_s_0, _des_crypt_tin1, _des_crypt_tout0, _des_crypt_tout1, + _des_crypt_tin0; +enum desmode _des_crypt_desp_0; +unsigned long _des_crypt_tbuf[2]; +char _des_crypt_out; +void des_encrypt(unsigned long *buf) { + long l, r, t; + l = buf[0]; + r = buf[1]; + t = r; + r ^= l ^= t < 6; + if (des_encrypt_encrypt) + for (;; des_encrypt_i += 4) + des_encrypt_s_0 ^= des_SPtrans_4_0 | des_SPtrans_6_0; + buf[1] = r; +} +void _des_crypt() { + long xor0, xor1; + unsigned char *in; + int cbc_mode = _des_crypt_desp_0; + in = _des_crypt_desp.des_ivec; + xor0 = xor1 = 0; + for (;;) { + _des_crypt_tin0 = *in++; + _des_crypt_tin0 |= *in++ << 8; + _des_crypt_tin0 |= *in++ << 16; + _des_crypt_tin0 |= (long)*in << 24; + _des_crypt_tin1 = *in++; + _des_crypt_tin1 |= *in++ << 8; + _des_crypt_tin1 |= *in++ << 16; + _des_crypt_tin1 |= (long)*in << 24; + _des_crypt_tbuf[0] = _des_crypt_tin0; + _des_crypt_tbuf[1] = _des_crypt_tin1; + des_encrypt(_des_crypt_tbuf); + if (cbc_mode) { + _des_crypt_tout0 = xor0; + _des_crypt_tout1 = _des_crypt_tbuf[1] ^ xor1; + xor0 = _des_crypt_tin0; + xor1 = _des_crypt_tin1; + } else { + _des_crypt_tout0 = _des_crypt_tbuf[0]; + _des_crypt_tout1 = _des_crypt_tbuf[1]; + } + _des_crypt_out = _des_crypt_tout0 * _des_crypt_tout1; + } +} -- 2.34.1