TImode register referenced in debug insn can be converted to V1TImode
by scalar to vector optimization.  We need to convert a debug insn if
it has a variable in a TImode register.

Tested on x86-64.  OK for trunk?


H.J.
----
gcc/

        PR target/71549
        * config/i386/i386.c (timode_scalar_to_vector_candidate_p):
        Return true if debug insn has a variable in TImode register.
        (timode_remove_non_convertible_regs): Skip debug insn.
        (scalar_chain::convert_insn): Change return type to bool.
        (scalar_chain::add_insn): Don't check registers in debug insn.
        (dimode_scalar_chain::convert_insn): Change return type to bool
        and always return true.
        (timode_scalar_chain::convert_insn): Change return type to bool.
        Convert V1TImode register to SUBREG TImode in debug insn.  Return
        false if debug insn isn't converted.  Otherwise, return true.
        (scalar_chain::convert): Increment converted_insns only if
        convert_insn returns true.

gcc/testsuite/

        PR target/71549
        * gcc.target/i386/pr71549.c: New test.
---
 gcc/config/i386/i386.c                  | 58 ++++++++++++++++++++++++++++-----
 gcc/testsuite/gcc.target/i386/pr71549.c | 24 ++++++++++++++
 2 files changed, 74 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr71549.c

diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 56a5b9c..e17fc53 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -2845,6 +2845,16 @@ dimode_scalar_to_vector_candidate_p (rtx_insn *insn)
 static bool
 timode_scalar_to_vector_candidate_p (rtx_insn *insn)
 {
+  if (DEBUG_INSN_P (insn))
+    {
+      /* If a variable is put in a TImode register, which may be
+        converted to V1TImode, we need to convert this debug insn.  */
+      rtx val = PATTERN (insn);
+      return (GET_MODE (val) == TImode
+             && GET_CODE (val) == VAR_LOCATION
+             && REG_P (PAT_VAR_LOCATION_LOC (val)));
+    }
+
   rtx def_set = single_set (insn);
 
   if (!def_set)
@@ -3012,7 +3022,12 @@ timode_remove_non_convertible_regs (bitmap candidates)
 
   EXECUTE_IF_SET_IN_BITMAP (candidates, 0, id, bi)
     {
-      rtx def_set = single_set (DF_INSN_UID_GET (id)->insn);
+      rtx_insn *insn = DF_INSN_UID_GET (id)->insn;
+      /* Debug insn isn't a SET insn.  */
+      if (DEBUG_INSN_P (insn))
+       continue;
+
+      rtx def_set = single_set (insn);
       rtx dest = SET_DEST (def_set);
       rtx src = SET_SRC (def_set);
 
@@ -3111,7 +3126,7 @@ class scalar_chain
   void add_insn (bitmap candidates, unsigned insn_uid);
   void analyze_register_chain (bitmap candidates, df_ref ref);
   virtual void mark_dual_mode_def (df_ref def) = 0;
-  virtual void convert_insn (rtx_insn *insn) = 0;
+  virtual bool convert_insn (rtx_insn *insn) = 0;
   virtual void convert_registers () = 0;
 };
 
@@ -3123,7 +3138,7 @@ class dimode_scalar_chain : public scalar_chain
   void mark_dual_mode_def (df_ref def);
   rtx replace_with_subreg (rtx x, rtx reg, rtx subreg);
   void replace_with_subreg_in_insn (rtx_insn *insn, rtx reg, rtx subreg);
-  void convert_insn (rtx_insn *insn);
+  bool convert_insn (rtx_insn *insn);
   void convert_op (rtx *op, rtx_insn *insn);
   void convert_reg (unsigned regno);
   void make_vector_copies (unsigned regno);
@@ -3139,7 +3154,7 @@ class timode_scalar_chain : public scalar_chain
 
  private:
   void mark_dual_mode_def (df_ref def);
-  void convert_insn (rtx_insn *insn);
+  bool convert_insn (rtx_insn *insn);
   /* We don't convert registers to difference size.  */
   void convert_registers () {}
 };
@@ -3276,6 +3291,10 @@ scalar_chain::add_insn (bitmap candidates, unsigned int 
insn_uid)
   bitmap_set_bit (insns, insn_uid);
 
   rtx_insn *insn = DF_INSN_UID_GET (insn_uid)->insn;
+  /* Debug insn isn't a SET insn.  */
+  if (DEBUG_INSN_P (insn))
+    return;
+
   rtx def_set = single_set (insn);
   if (def_set && REG_P (SET_DEST (def_set))
       && !HARD_REGISTER_P (SET_DEST (def_set)))
@@ -3708,7 +3727,7 @@ dimode_scalar_chain::convert_op (rtx *op, rtx_insn *insn)
 
 /* Convert INSN to vector mode.  */
 
-void
+bool
 dimode_scalar_chain::convert_insn (rtx_insn *insn)
 {
   rtx def_set = single_set (insn);
@@ -3788,13 +3807,34 @@ dimode_scalar_chain::convert_insn (rtx_insn *insn)
   INSN_CODE (insn) = -1;
   recog_memoized (insn);
   df_insn_rescan (insn);
+
+  return true;
 }
 
 /* Convert INSN from TImode to V1T1mode.  */
 
-void
+bool
 timode_scalar_chain::convert_insn (rtx_insn *insn)
 {
+  if (DEBUG_INSN_P (insn))
+    {
+      /* It must be a debug insn with a TImode variable in register.  */
+      rtx val = PATTERN (insn);
+      gcc_assert (GET_MODE (val) == TImode
+                 && GET_CODE (val) == VAR_LOCATION);
+      rtx loc = PAT_VAR_LOCATION_LOC (val);
+      gcc_assert (REG_P (loc));
+      /* Convert V1TImode register, which has been updated by a SET
+        insn before, to SUBREG TImode.  */
+      if (GET_MODE (loc) == V1TImode)
+       {
+         PAT_VAR_LOCATION_LOC (val) = gen_rtx_SUBREG (TImode, loc, 0);
+         df_insn_rescan (insn);
+         return true;
+       }
+      return false;
+    }
+
   rtx def_set = single_set (insn);
   rtx src = SET_SRC (def_set);
   rtx dst = SET_DEST (def_set);
@@ -3858,6 +3898,8 @@ timode_scalar_chain::convert_insn (rtx_insn *insn)
   INSN_CODE (insn) = -1;
   recog_memoized (insn);
   df_insn_rescan (insn);
+
+  return true;
 }
 
 void
@@ -3893,8 +3935,8 @@ scalar_chain::convert ()
 
   EXECUTE_IF_SET_IN_BITMAP (insns, 0, id, bi)
     {
-      convert_insn (DF_INSN_UID_GET (id)->insn);
-      converted_insns++;
+      if (convert_insn (DF_INSN_UID_GET (id)->insn))
+       converted_insns++;
     }
 
   return converted_insns;
diff --git a/gcc/testsuite/gcc.target/i386/pr71549.c 
b/gcc/testsuite/gcc.target/i386/pr71549.c
new file mode 100644
index 0000000..8aac891
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr71549.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -g" } */
+
+struct S1
+{
+  int f0;
+  int f1;
+  int f2;
+  int:4;
+} a, b;
+
+void
+fn1 (struct S1 p1)
+{
+  a = p1;
+  int c = p1.f0;
+}
+
+int
+main ()
+{
+  fn1 (b);
+  return 0;
+}
-- 
2.5.5

Reply via email to