Hello! RTL store motion pass transforms:
(insn 19 18 20 4 (parallel [ (set (mem/c:SI (symbol_ref:SI ("bar_arg") [flags 0x2] <var_decl 0x7f68136f2b40 bar_arg>) [1 bar_arg+0 S4 A32]) (fix:SI (reg:DF 89))) (clobber (scratch:XF)) ]) "stdarg-3.c":63:7 156 {fix_truncsi_i387_fisttp} (expr_list:REG_DEAD (reg:DF 89) (nil))) to an unrecognisable insn: (insn 33 18 20 4 (set (reg:SI 93 [ bar_arg ]) (fix:SI (reg:DF 89))) "stdarg-3.c":63:7 -1 (expr_list:REG_DEAD (reg:DF 89) (nil))) The problem is with can_assign_to_reg_without_clobbers_p in gcse.c, where we have: /* If the test insn is valid and doesn't need clobbers, and the target also has no objections, we're good. */ if (icode >= 0 && (num_clobbers == 0 || !added_clobbers_hard_reg_p (icode)) && ! (targetm.cannot_copy_insn_p && targetm.cannot_copy_insn_p (test_insn))) can_assign = true; The test instruction is created as: (insn 26 0 0 (set (reg:SI 152) (fix:SI (reg:DF 89))) -1 (nil)) which is (correctly) recognized as (define_insn "fix_trunc<mode>_i387_fisttp" [(set (match_operand:SWI248x 0 "nonimmediate_operand" "=m") (fix:SWI248x (match_operand 1 "register_operand" "f"))) (clobber (match_scratch:XF 2 "=&f"))] However, recog also reports that 1 clobber needs to be added. The instruction is recognized nevertheless due to "|| !added_clobbers_hard_reg_p (icode)" bypass. The recognized insn doesn't clobber hard reg, but it also needs a clobber of a scratch reg to be recognized. The solution is to recognize the replacement insn in replace_store_insn. We are sure that the new instruction is valid (it passed can_assign_to_reg_without_clobbers_p when analysed), but we need to add clobbers, as is the case with the {fix_truncsi_i387_fisttp}. The call to recog will provide the number of necessary clobbers for recognized insn, so we are able to wrap the original pattern with a PARALLEL comprising required clobbers. 2019-01-22 Uroš Bizjak <ubiz...@gmail.com> PR target/88948 * store-motion.c: Include insn-config.h and recog.h (replace_store_insn): Recognize new store insn and add clobbers if needed. testsuite/ChangeLog: 2019-01-22 Uroš Bizjak <ubiz...@gmail.com> PR target/88948 * gcc.target/i386/pr88948.c: New test. Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. OK for mainline? Uros.
Index: store-motion.c =================================================================== --- store-motion.c (revision 268157) +++ store-motion.c (working copy) @@ -27,6 +27,8 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "toplev.h" +#include "insn-config.h" +#include "recog.h" #include "cfgrtl.h" #include "cfganal.h" #include "lcm.h" @@ -910,11 +912,28 @@ replace_store_insn (rtx reg, rtx_insn *del, basic_ struct st_expr *smexpr) { rtx_insn *insn; + rtx pat; + int insn_code_number; + int num_clobbers_to_add = 0; rtx mem, note, set; mem = smexpr->pattern; insn = gen_move_insn (reg, SET_SRC (single_set (del))); + pat = PATTERN (insn); + insn_code_number = recog (pat, insn, &num_clobbers_to_add); + + if (num_clobbers_to_add) + { + rtx newpat + = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_clobbers_to_add + 1)); + + XVECEXP (newpat, 0, 0) = pat; + add_clobbers (newpat, insn_code_number); + + PATTERN (insn) = newpat; + } + unsigned int i; rtx_insn *temp; FOR_EACH_VEC_ELT_REVERSE (smexpr->antic_stores, i, temp) Index: testsuite/gcc.target/i386/pr88948.c =================================================================== --- testsuite/gcc.target/i386/pr88948.c (nonexistent) +++ testsuite/gcc.target/i386/pr88948.c (working copy) @@ -0,0 +1,5 @@ +/* PR rtl-optimization/88948 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fgcse-sm -msse3 -mfpmath=387" } */ + +#include "../../gcc.c-torture/execute/stdarg-3.c"