aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/mips/mips.c18
-rw-r--r--gcc/recog.c44
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr48774.c1
-rw-r--r--gcc/testsuite/gcc.target/mips/pr52125.c20
7 files changed, 96 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1140054..b2540ec 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-01-23 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR target/52125
+ * rtl.h (get_referenced_operands): Declare.
+ * recog.c (get_referenced_operands): New function.
+ * config/mips/mips.c (mips_reorg_process_insns): Check which asm
+ operands have been referenced when recording LO_SUM references.
+
2014-01-22 David Holsgrove <david.holsgrove@xilinx.com>
* config/microblaze/microblaze.md: Correct bswaphi2 insn.
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 6c6fe61..5bad0f8 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -16097,7 +16097,23 @@ mips_reorg_process_insns (void)
for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
FOR_EACH_SUBINSN (subinsn, insn)
if (USEFUL_INSN_P (subinsn))
- for_each_rtx (&PATTERN (subinsn), mips_record_lo_sum, &htab);
+ {
+ rtx body = PATTERN (insn);
+ int noperands = asm_noperands (body);
+ if (noperands >= 0)
+ {
+ rtx *ops = XALLOCAVEC (rtx, noperands);
+ bool *used = XALLOCAVEC (bool, noperands);
+ const char *string = decode_asm_operands (body, ops, NULL, NULL,
+ NULL, NULL);
+ get_referenced_operands (string, used, noperands);
+ for (int i = 0; i < noperands; ++i)
+ if (used[i])
+ for_each_rtx (&ops[i], mips_record_lo_sum, &htab);
+ }
+ else
+ for_each_rtx (&PATTERN (subinsn), mips_record_lo_sum, &htab);
+ }
last_insn = 0;
hilo_delay = 2;
diff --git a/gcc/recog.c b/gcc/recog.c
index b81214c..e2caf9859 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1620,6 +1620,50 @@ decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
return ASM_OPERANDS_TEMPLATE (asmop);
}
+/* Parse inline assembly string STRING and determine which operands are
+ referenced by % markers. For the first NOPERANDS operands, set USED[I]
+ to true if operand I is referenced.
+
+ This is intended to distinguish barrier-like asms such as:
+
+ asm ("" : "=m" (...));
+
+ from real references such as:
+
+ asm ("sw\t$0, %0" : "=m" (...)); */
+
+void
+get_referenced_operands (const char *string, bool *used,
+ unsigned int noperands)
+{
+ memset (used, 0, sizeof (bool) * noperands);
+ const char *p = string;
+ while (*p)
+ switch (*p)
+ {
+ case '%':
+ p += 1;
+ /* A letter followed by a digit indicates an operand number. */
+ if (ISALPHA (p[0]) && ISDIGIT (p[1]))
+ p += 1;
+ if (ISDIGIT (*p))
+ {
+ char *endptr;
+ unsigned long opnum = strtoul (p, &endptr, 10);
+ if (endptr != p && opnum < noperands)
+ used[opnum] = true;
+ p = endptr;
+ }
+ else
+ p += 1;
+ break;
+
+ default:
+ p++;
+ break;
+ }
+}
+
/* Check if an asm_operand matches its constraints.
Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 10ee818..f1cda4c 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2169,6 +2169,7 @@ extern rtx extract_asm_operands (rtx);
extern int asm_noperands (const_rtx);
extern const char *decode_asm_operands (rtx, rtx *, rtx **, const char **,
enum machine_mode *, location_t *);
+extern void get_referenced_operands (const char *, bool *, unsigned int);
extern enum reg_class reg_preferred_class (int);
extern enum reg_class reg_alternate_class (int);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4cc8d9f..4c085c6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2014-01-23 Richard Sandiford <rdsandiford@googlemail.com>
+
+ PR target/52125
+ * gcc.dg/pr48774.c: Remove skip for mips_rel.
+ * gcc.target/mips/pr52125.c: New test.
+
2014-01-22 Marek Polacek <polacek@redhat.com>
PR c/59891
diff --git a/gcc/testsuite/gcc.dg/pr48774.c b/gcc/testsuite/gcc.dg/pr48774.c
index abd8c23..91ce361 100644
--- a/gcc/testsuite/gcc.dg/pr48774.c
+++ b/gcc/testsuite/gcc.dg/pr48774.c
@@ -1,6 +1,5 @@
/* PR target/48774 */
/* { dg-do run } */
-/* { dg-skip-if "PR 52125" { mips_rel } { "*" } { "" } } */
/* { dg-options "-O2 -funroll-loops" } */
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/mips/pr52125.c b/gcc/testsuite/gcc.target/mips/pr52125.c
new file mode 100644
index 0000000..cfa8d68
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/pr52125.c
@@ -0,0 +1,20 @@
+/* { dg-options "addressing=absolute" } */
+
+int a, b, c, d;
+
+NOMIPS16 void
+foo (void)
+{
+ asm ("%1 %z3"
+ : "=m" (a), "=m" (b)
+ : "m" (c), "m" (d));
+}
+
+/* { dg-final { scan-assembler-not "%hi\\(a\\)" } } */
+/* { dg-final { scan-assembler-not "%lo\\(a\\)" } } */
+/* { dg-final { scan-assembler "%hi\\(b\\)" } } */
+/* { dg-final { scan-assembler "%lo\\(b\\)" } } */
+/* { dg-final { scan-assembler-not "%hi\\(c\\)" } } */
+/* { dg-final { scan-assembler-not "%lo\\(c\\)" } } */
+/* { dg-final { scan-assembler "%hi\\(d\\)" } } */
+/* { dg-final { scan-assembler "%lo\\(d\\)" } } */