[PR98096] inline-asm: Take inout operands into account for access to labels by names.
authorVladimir N. Makarov <vmakarov@redhat.com>
Tue, 16 Feb 2021 15:27:56 +0000 (10:27 -0500)
committerVladimir N. Makarov <vmakarov@redhat.com>
Tue, 16 Feb 2021 15:30:10 +0000 (10:30 -0500)
GCC splits inout operands into output and new matched input operands
during gimplfication.  Addressing operands by name or number is not
problem as the new input operands are added at the end of existing
input operands.  However it became a problem for labels in asm goto
with output reloads.  Addressing labels should take into account the
new input operands.  The patch solves the problem.

gcc/ChangeLog:

PR inline-asm/98096
* stmt.c (resolve_operand_name_1): Take inout operands into account
for access to labels by names.
* doc/extend.texi: Describe counting operands for accessing labels.

gcc/testsuite/ChangeLog:

PR inline-asm/98096
* gcc.c-torture/compile/pr98096.c: New.

gcc/doc/extend.texi
gcc/stmt.c
gcc/testsuite/gcc.c-torture/compile/pr98096.c [new file with mode: 0644]

index e110cb0..6eb1d32 100644 (file)
@@ -10680,16 +10680,23 @@ should use @samp{+} constraint modifier meaning that the operand is
 input and output one.  With this modifier you will have the correct
 values on all possible paths from the @code{asm goto}.
 
-To reference a label in the assembler template,
-prefix it with @samp{%l} (lowercase @samp{L}) followed 
-by its (zero-based) position in @var{GotoLabels} plus the number of input 
-operands.  For example, if the @code{asm} has three inputs and references two 
-labels, refer to the first label as @samp{%l3} and the second as @samp{%l4}).
-
-Alternately, you can reference labels using the actual C label name enclosed
-in brackets.  For example, to reference a label named @code{carry}, you can
-use @samp{%l[carry]}.  The label must still be listed in the @var{GotoLabels}
-section when using this approach.
+To reference a label in the assembler template, prefix it with
+@samp{%l} (lowercase @samp{L}) followed by its (zero-based) position
+in @var{GotoLabels} plus the number of input and output operands.
+Output operand with constraint modifier @samp{+} is counted as two
+operands because it is considered as one output and one input operand.
+For example, if the @code{asm} has three inputs, one output operand
+with constraint modifier @samp{+} and one output operand with
+constraint modifier @samp{=} and references two labels, refer to the
+first label as @samp{%l6} and the second as @samp{%l7}).
+
+Alternately, you can reference labels using the actual C label name
+enclosed in brackets.  For example, to reference a label named
+@code{carry}, you can use @samp{%l[carry]}.  The label must still be
+listed in the @var{GotoLabels} section when using this approach.  It
+is better to use the named references for labels as in this case you
+can avoid counting input and output operands and special treatment of
+output operands with constraint modifier @samp{+}.
 
 Here is an example of @code{asm goto} for i386:
 
index bd836d8..f52ffaf 100644 (file)
@@ -611,7 +611,7 @@ static char *
 resolve_operand_name_1 (char *p, tree outputs, tree inputs, tree labels)
 {
   char *q;
-  int op;
+  int op, op_inout;
   tree t;
 
   /* Collect the operand name.  */
@@ -624,11 +624,14 @@ resolve_operand_name_1 (char *p, tree outputs, tree inputs, tree labels)
   *q = '\0';
 
   /* Resolve the name to a number.  */
-  for (op = 0, t = outputs; t ; t = TREE_CHAIN (t), op++)
+  for (op_inout = op = 0, t = outputs; t ; t = TREE_CHAIN (t), op++)
     {
       tree name = TREE_PURPOSE (TREE_PURPOSE (t));
       if (name && strcmp (TREE_STRING_POINTER (name), p) == 0)
        goto found;
+      tree constraint = TREE_VALUE (TREE_PURPOSE (t));
+      if (constraint && strchr (TREE_STRING_POINTER (constraint), '+') != NULL)
+        op_inout++;
     }
   for (t = inputs; t ; t = TREE_CHAIN (t), op++)
     {
@@ -636,6 +639,7 @@ resolve_operand_name_1 (char *p, tree outputs, tree inputs, tree labels)
       if (name && strcmp (TREE_STRING_POINTER (name), p) == 0)
        goto found;
     }
+  op += op_inout;
   for (t = labels; t ; t = TREE_CHAIN (t), op++)
     {
       tree name = TREE_PURPOSE (t);
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr98096.c b/gcc/testsuite/gcc.c-torture/compile/pr98096.c
new file mode 100644 (file)
index 0000000..95ad55c
--- /dev/null
@@ -0,0 +1,10 @@
+/* Test for correct naming of label operands in asm goto in case of presence of
+   input/output operands. */
+/* { dg-do compile } */
+int i, j;
+int f(void) {
+  asm goto ("# %0 %2" : "+r" (i) ::: jmp);
+  i += 2;
+  asm goto ("# %0 %1 %l[jmp]" : "+r" (i), "+r" (j) ::: jmp);
+ jmp: return i;
+}