Attached patch allows only SUBREGs as output operands to movstrict expander and further allows only register operand outputs in various corresponding splitters. This enforces the restriction, as documented for STRICT_LOW_PART RTX:
This expression code is used in only one context: as the destination operand of a 'set' expression. In addition, the operand of this expression must be a non-paradoxical 'subreg' expression. Additionally, the patch removes post-reload calls to movstrict expander and consequently constructs RTXes involving STRICT_LOW_PART with hard registers "by hand". 2019-07-30 Uroš Bizjak <ubiz...@gmail.com> * config/i386/i386.md (movstrict<mode>): Use register_operand predicate for operand 0. Add expander condition. Assert that operand 0 is a SUBREG RTX. (*movstrict<mode>_1): Use register_operand predicate for operand 0. Update operand constraints and insn condition. (zero_extend<mode>si2_and): Do not call gen_movstrict<mode>. (zero_extendqihi2_and): Do not call gen_movstrictqi. (*setcc_qi_slp): Use register_operand predicate for operand 0. Update operand 0 constraints. (setcc_qi_slp splitters): Use register_operand predicate for operand 0. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline SVN. Uros.
Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 273873) +++ config/i386/i386.md (working copy) @@ -2786,26 +2786,20 @@ (set_attr "bdver1_decode" "double")]) (define_expand "movstrict<mode>" - [(set (strict_low_part (match_operand:SWI12 0 "nonimmediate_operand")) + [(set (strict_low_part (match_operand:SWI12 0 "register_operand")) (match_operand:SWI12 1 "general_operand"))] - "" + "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" { - if (TARGET_PARTIAL_REG_STALL && optimize_function_for_speed_p (cfun)) + gcc_assert (SUBREG_P (operands[0])); + if (GET_MODE_CLASS (GET_MODE (SUBREG_REG (operands[0]))) != MODE_INT) FAIL; - if (SUBREG_P (operands[0]) - && GET_MODE_CLASS (GET_MODE (SUBREG_REG (operands[0]))) != MODE_INT) - FAIL; - /* Don't generate memory->memory moves, go through a register */ - if (MEM_P (operands[0]) && MEM_P (operands[1])) - operands[1] = force_reg (<MODE>mode, operands[1]); }) (define_insn "*movstrict<mode>_1" [(set (strict_low_part - (match_operand:SWI12 0 "nonimmediate_operand" "+<r>m,<r>")) - (match_operand:SWI12 1 "general_operand" "<r>n,m"))] - "(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + (match_operand:SWI12 0 "register_operand" "+<r>")) + (match_operand:SWI12 1 "general_operand" "<r>mn"))] + "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)" "mov{<imodesuffix>}\t{%1, %0|%0, %1}" [(set_attr "type" "imov") (set_attr "mode" "<MODE>")]) @@ -4011,8 +4005,10 @@ ix86_expand_clear (operands[0]); gcc_assert (!TARGET_PARTIAL_REG_STALL); - emit_insn (gen_movstrict<mode> - (gen_lowpart (<MODE>mode, operands[0]), operands[1])); + emit_insn (gen_rtx_SET + (gen_rtx_STRICT_LOW_PART + (VOIDmode, gen_lowpart (<MODE>mode, operands[0])), + operands[1])); DONE; } @@ -4063,8 +4059,10 @@ ix86_expand_clear (operands[0]); gcc_assert (!TARGET_PARTIAL_REG_STALL); - emit_insn (gen_movstrictqi - (gen_lowpart (QImode, operands[0]), operands[1])); + emit_insn (gen_rtx_SET + (gen_rtx_STRICT_LOW_PART + (VOIDmode, gen_lowpart (QImode, operands[0])), + operands[1])); DONE; } @@ -11835,7 +11833,7 @@ (set_attr "mode" "QI")]) (define_insn "*setcc_qi_slp" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) + [(set (strict_low_part (match_operand:QI 0 "register_operand" "+q")) (match_operator:QI 1 "ix86_comparison_operator" [(reg FLAGS_REG) (const_int 0)]))] "" @@ -11864,7 +11862,7 @@ }) (define_split - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand")) + [(set (strict_low_part (match_operand:QI 0 "register_operand")) (ne:QI (match_operator 1 "ix86_comparison_operator" [(reg FLAGS_REG) (const_int 0)]) (const_int 0)))] @@ -11896,7 +11894,7 @@ }) (define_split - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand")) + [(set (strict_low_part (match_operand:QI 0 "register_operand")) (eq:QI (match_operator 1 "ix86_comparison_operator" [(reg FLAGS_REG) (const_int 0)]) (const_int 0)))]