From: Manolis Tsamis Date: Tue, 13 Aug 2024 08:17:49 +0000 (+0200) Subject: ifcvt: Fix force_operand ICE in noce_convert_multiple_sets [PR116353] X-Git-Tag: basepoints/gcc-16~6650 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc00a737e840986f4916918759ba214a95ae6888;p=thirdparty%2Fgcc.git ifcvt: Fix force_operand ICE in noce_convert_multiple_sets [PR116353] 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. 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. --- 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; + } +}