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"

Reply via email to