===================================================================
@@ -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);
===================================================================
@@ -1620,6 +1620,50 @@ decode_asm_operands (rtx body, rtx *oper
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. */
===================================================================
@@ -16095,7 +16095,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;
===================================================================
@@ -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);
===================================================================
@@ -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\\)" } } */