Hello! It turned out that recent changes made special handling of memory operands in *testqi_ext_3 obsolete. Combine now always pass correct width of memory operands for the extraction, as assured by added assert.
2017-01-05 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.md (*testqi_ext_3): No need to handle memory operands in a special way. Assert that pos+len <= mode precision. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros.
Index: i386.md =================================================================== --- i386.md (revision 244058) +++ i386.md (working copy) @@ -8007,36 +8007,30 @@ rtx val = operands[2]; HOST_WIDE_INT len = INTVAL (operands[3]); HOST_WIDE_INT pos = INTVAL (operands[4]); - machine_mode mode, submode; + machine_mode mode = GET_MODE (val); - mode = GET_MODE (val); - if (MEM_P (val)) + if (SUBREG_P (val)) { - /* ??? Combine likes to put non-volatile mem extractions in QImode - no matter the size of the test. So find a mode that works. */ - if (! MEM_VOLATILE_P (val)) + machine_mode submode = GET_MODE (SUBREG_REG (val)); + + /* Narrow paradoxical subregs to prevent partial register stalls. */ + if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (submode) + && GET_MODE_CLASS (submode) == MODE_INT) { - mode = smallest_mode_for_size (pos + len, MODE_INT); - val = adjust_address (val, mode, 0); + val = SUBREG_REG (val); + mode = submode; } } - else if (SUBREG_P (val) - && (submode = GET_MODE (SUBREG_REG (val)), - GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (submode)) - && pos + len <= GET_MODE_BITSIZE (submode) - && GET_MODE_CLASS (submode) == MODE_INT) + + /* Small HImode tests can be converted to QImode. */ + if (register_operand (val, HImode) && pos + len <= 8) { - /* Narrow a paradoxical subreg to prevent partial register stalls. */ - mode = submode; - val = SUBREG_REG (val); - } - else if (mode == HImode && pos + len <= 8) - { - /* Small HImode tests can be converted to QImode. */ + val = gen_lowpart (QImode, val); mode = QImode; - val = gen_lowpart (QImode, val); } + gcc_assert (pos + len <= GET_MODE_PRECISION (mode)); + wide_int mask = wi::shifted_mask (pos, len, false, GET_MODE_PRECISION (mode));