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