From 72d78655a91bb2f89ac4432cfd6374380d6f9987 Mon Sep 17 00:00:00 2001 From: "Vladimir N. Makarov" Date: Tue, 16 Feb 2021 10:27:56 -0500 Subject: [PATCH] [PR98096] inline-asm: Take inout operands into account for access to labels by names. 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 | 27 ++++++++++++------- gcc/stmt.c | 8 ++++-- gcc/testsuite/gcc.c-torture/compile/pr98096.c | 10 +++++++ 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr98096.c diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index e110cb01061..6eb1d327e97 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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: diff --git a/gcc/stmt.c b/gcc/stmt.c index bd836d8f65f..f52ffaf8e75 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -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 index 00000000000..95ad55c81aa --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr98096.c @@ -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; +} -- 2.30.2