On 10/29/2015 1:47 PM, Richard Henderson wrote:
On 10/27/2015 02:05 PM, Jeff Law wrote:
On 10/25/2015 09:41 PM, David Wohlferd wrote:
Does gcc's inline asm support multi-alternative constraints? Or are
they only supported for md?
dw
PS If it *is* supported, then the docs need some work.
I think Richard corrected me last I spoke on this topic :-) They *are*
supported. ie, something like this should work on a ciscy target.
asm("add %0,%1" : "=r,m"(x) : "rim,ri"(y))
Correct.
They are supported, so long as the assembly can use the same text for all
alternatives. Thus multiple alternatives in inline asm is basically useless
for RISC targets, but occasionally useful for CISC targets.
Aha. Thank you for the info.
Ok, I have discarded the other patch. I'm not sure what this means for
10396, since that seemed to be the solution there.
I have updated the non-md text with (most of) the changes I think it
needs (attached). These changes are pleasantly minor, mostly just
adding some example text and a bit of formatting.
However. Trying to actually use the information on this page is turning
up some problems.
First, it could use a bit more clarity in the text that describes how
gcc chooses among the alternatives. There are apparently 3 criteria
that affect this decision: # of statements needed to copy params, order
of alternatives, and flags. But it appears that they aren't all
weighted equally. For example no number of '?' seem to be able to
override an alternative that causes a reload (change the example below
to use eax instead of ebx). But before I try to re-phrase this
paragraph, I'm hoping someone can provide more details. What exactly
are the rules here?
Second, attempting to use ! and $ isn't working the way the docs led me
to expect (actually, I can't make them work at all). Starting with this
(contrived) i386 code, gcc selects the second alternative (using -O2 for
x64). This makes sense to me.
int main()
{
int x = 3;
int y = 17;
asm("or %1,%0" : "+r,b"(x) : "r,i"(y));
return x;
}
It took two '?' in front of the 'b' to convince gcc to use the first
alternative. This seems reasonable, and shows that the first
alternative is indeed viable.
The problem started when I tried to replace the '??' with '!'. Being
"severe," I figured one '!' should do the work of two '?'. But even
using multiple '!' doesn't cause it to switch to the first alternative.
Parsing the current docs:
"! - Disparage severely the alternative that the '!' appears in. This
alternative can still be used if it fits without reloading, but if
reloading is needed, some other alternative will be used. "
The alternative I am trying to disparage uses ebx. Using that register
causes a push/pop. That seems to me like "reloading is needed," so I
expected that by definition the other alternative would be used. Even
if reloading isn't a factor (or if I don't understand it correctly), the
alternative '!' is applied to should still be "severely" disparaged (ie
at least as much as 2 '?'). But apparently it's not.
Using '^' does change the selection if I use two of them. But according
to the docs, '^' *only* applies if "the operand with the '^' needs a
reload." Since the '^' is having an effect, doesn't that imply that
there is a reload associated with the second alternative? But if there
is, why didn't '!' work as expected?
'$' also doesn't affect the selection, probably for the same reasons as '!'.
I don't know if ! and $ are broken, or if the docs just aren't
explaining them well enough. But something isn't working here.
Lastly, while it is a core concept to compiler-writers, 'reloads' isn't
really a compiler-user concept. Perhaps some of these flags aren't user
manual appropriate (I'm looking at you !^$).
dw
PS
Current text: https://gcc.gnu.org/onlinedocs/gcc/Multi-Alternative.html
Proposed text: http://limegreensocks.com/gcc/Multi_002dAlternative.html
Index: md.texi
===================================================================
--- md.texi (revision 229470)
+++ md.texi (working copy)
@@ -1465,6 +1465,8 @@
constraint for an operand is made from the letters for this operand
from the first alternative, a comma, the letters for this operand from
the second alternative, a comma, and so on until the last alternative.
+All operands for a single instruction must have the same number of
+alternatives.
@ifset INTERNALS
Here is how it is done for fullword logical-or on the 68000:
@@ -1483,8 +1485,20 @@
@samp{%} in the constraints apply to all the alternatives; their
meaning is explained in the next section (@pxref{Class Preferences}).
@end ifset
+@ifclear INTERNALS
+So the first alternative for the 68000's logical-or could be written as
+@code{"+m" (output) : "ir" (input)}. The second could be @code{"+r"
+(output): "irm" (input)}. However, the fact that two memory locations
+cannot be used in a single instruction prevents simply using @code{"+rm"
+(output) : "irm" (input)}. Using multi-alternatives, this might be
+written as @code{"+m,r" (output) : "ir,irm" (input)}. This describes
+all the available alternatives to GCC, allowing it to choose the most
+efficient one for the current conditions.
+@end ifclear
+
@c FIXME Is this ? and ! stuff of use in asm()? If not, hide unless INTERNAL
+@ifset INTERNALS
If all the operands fit any one alternative, the instruction is valid.
Otherwise, for each alternative, the compiler counts how many instructions
must be added to copy the operands so that that alternative applies.
@@ -1491,35 +1505,55 @@
The alternative requiring the least copying is chosen. If two alternatives
need the same amount of copying, the one that comes first is chosen.
These choices can be altered with the @samp{?} and @samp{!} characters:
+@end ifset
+@ifclear INTERNALS
+To choose among the alternatives, the compiler counts how many
+instructions must be added to copy the operands to match the alternative.
+The alternative requiring the least amount of copying is chosen. If two
+alternatives need the same amount of copying, the one that comes first is
+chosen. This weighting can be modified using the flags below.
-@table @code
+For example to (slightly) encourage the compiler to use the register form
+of the logical-or instruction, you could list it first: @code{"+r,m"
+(output) : "irm,ir" (input)}. To discourage GCC from using the memory
+form, you could add one or more @samp{?} to that alternative:
+@code{"+r,??m" (output) : "irm,ir" (input)}.
+
+GCC provides no way within the template to determine which alternative was
+chosen. However you may be able to wrap your @code{asm} statements with
+builtins such as @code{__builtin_constant_p} to achieve the desired results.
+@end ifclear
+
+@multitable
+@headitem Flag @tab Meaning
@cindex @samp{?} in constraint
@cindex question mark
@item ?
+@tab
Disparage slightly the alternative that the @samp{?} appears in,
as a choice when no alternative applies exactly. The compiler regards
this alternative as one unit more costly for each @samp{?} that appears
in it.
-
@cindex @samp{!} in constraint
@cindex exclamation point
@item !
+@tab
Disparage severely the alternative that the @samp{!} appears in.
This alternative can still be used if it fits without reloading,
but if reloading is needed, some other alternative will be used.
-
@cindex @samp{^} in constraint
@cindex caret
@item ^
+@tab
This constraint is analogous to @samp{?} but it disparages slightly
the alternative only if the operand with the @samp{^} needs a reload.
-
@cindex @samp{$} in constraint
@cindex dollar sign
@item $
+@tab
This constraint is analogous to @samp{!} but it disparages severely
the alternative only if the operand with the @samp{$} needs a reload.
-@end table
+@end multitable
@ifset INTERNALS
When an insn pattern has multiple alternatives in its constraints, often