aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManolis Tsamis <manolis.tsamis@vrull.eu>2024-08-13 10:17:49 +0200
committerPhilipp Tomsich <philipp.tomsich@vrull.eu>2024-08-13 21:52:18 +0200
commitcc00a737e840986f4916918759ba214a95ae6888 (patch)
treee7ef5b06eae5c5994e417e0ecfeed068910c0395
parent9988d7e004796ab531df7bcda45788a7aa9276d7 (diff)
downloadgcc-cc00a737e840986f4916918759ba214a95ae6888.zip
gcc-cc00a737e840986f4916918759ba214a95ae6888.tar.gz
gcc-cc00a737e840986f4916918759ba214a95ae6888.tar.bz2
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.
-rw-r--r--gcc/ifcvt.cc6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr116353.c55
2 files changed, 59 insertions, 2 deletions
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 3e25f30..da59c90 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 0000000..8e25465
--- /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;
+ }
+}