summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2016-06-19 12:47:45 -0700
committerH.J. Lu <hjl.tools@gmail.com>2016-06-20 16:49:43 -0700
commit13dd60ab323090f75f7d014d271aea71f4e5c26d (patch)
treea5c9f388c28d227d8c03a735aa30e9a09c192027
parent0b4b12fd4a13c8d5292151f1e832cc71e28fa39d (diff)
downloadgcc-hjl/pr71549.tar.gz
Convert V1TImode register to TImode in debug insnhjl/pr71549
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 references TImode register which will be converted to V1TImode. gcc/ PR target/71549 * config/i386/i386.c (timode_scalar_chain::fix_debug_reg_uses): New member function to convert V1TImode register to SUBREG TImode in debug insn. (timode_scalar_chain::convert_insn): Call fix_debug_reg_uses after changing register mode to V1TImode. gcc/testsuite/ PR target/71549 * gcc.target/i386/pr71549.c: New test.
-rw-r--r--gcc/config/i386/i386.c38
-rw-r--r--gcc/testsuite/gcc.target/i386/pr71549.c24
2 files changed, 61 insertions, 1 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 56a5b9c3296..0dd09ce23a9 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3139,6 +3139,7 @@ class timode_scalar_chain : public scalar_chain
private:
void mark_dual_mode_def (df_ref def);
+ void fix_debug_reg_uses (rtx reg);
void convert_insn (rtx_insn *insn);
/* We don't convert registers to difference size. */
void convert_registers () {}
@@ -3790,6 +3791,39 @@ dimode_scalar_chain::convert_insn (rtx_insn *insn)
df_insn_rescan (insn);
}
+/* Fix uses of converted REG in debug insns. */
+
+void
+timode_scalar_chain::fix_debug_reg_uses (rtx reg)
+{
+ if (!flag_var_tracking)
+ return;
+
+ df_ref ref;
+ for (ref = DF_REG_USE_CHAIN (REGNO (reg));
+ ref;
+ ref = DF_REF_NEXT_REG (ref))
+ {
+ rtx_insn *insn = DF_REF_INSN (ref);
+ if (DEBUG_INSN_P (insn))
+ {
+ /* It may be a debug insn with a TImode variable in
+ register. */
+ rtx val = PATTERN (insn);
+ if (GET_MODE (val) != TImode)
+ continue;
+ gcc_assert (GET_CODE (val) == VAR_LOCATION);
+ rtx loc = PAT_VAR_LOCATION_LOC (val);
+ gcc_assert (REG_P (loc)
+ && GET_MODE (loc) == V1TImode);
+ /* Convert V1TImode register, which has been updated by a SET
+ insn before, to SUBREG TImode. */
+ PAT_VAR_LOCATION_LOC (val) = gen_rtx_SUBREG (TImode, loc, 0);
+ df_insn_rescan (insn);
+ }
+ }
+}
+
/* Convert INSN from TImode to V1T1mode. */
void
@@ -3806,8 +3840,10 @@ timode_scalar_chain::convert_insn (rtx_insn *insn)
rtx tmp = find_reg_equal_equiv_note (insn);
if (tmp)
PUT_MODE (XEXP (tmp, 0), V1TImode);
+ PUT_MODE (dst, V1TImode);
+ fix_debug_reg_uses (dst);
}
- /* FALLTHRU */
+ break;
case MEM:
PUT_MODE (dst, V1TImode);
break;
diff --git a/gcc/testsuite/gcc.target/i386/pr71549.c b/gcc/testsuite/gcc.target/i386/pr71549.c
new file mode 100644
index 00000000000..8aac891b232
--- /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;
+}