diff mbox

Fix asm X constraint (PR inline-asm/59155)

Message ID AM4PR07MB157116B6325547B97D4C148CE4400@AM4PR07MB1571.eurprd07.prod.outlook.com
State New
Headers show

Commit Message

Bernd Edlinger May 25, 2016, 12:58 p.m. UTC
Hi!

This restricts the X constraint in asm statements, which
can be easily folded by combine in something completely
invalid.

It is necessary to allow scratch here, because on i386
the md_asm_adjust hook inserts them.

The second test case fails because lra does not
allow all register for anything_ok operands (aka X)
and later it fails to match the two X constraints
in case '0': if (curr_alt[m] == NO_REGS) break.

There is also an identical bug in the reload pass,
but I do not know how to fix that, as it is almost
used nowhere today.


Boot-strapped and regression-tested on x86_64-pc-linux-gnu.
OK for trunk?


Thanks
Bernd.
gcc:
2016-05-23  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR inline-asm/59155
	* lra-constraints.c (process_alt_operands): Allow ALL_REGS.
	* recog.c (asm_operand_ok): Handle X constraint.

testsuite:
2016-05-23  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	PR inline-asm/59155
	* gcc.dg/torture/pr59155-1.c: New test.
	* gcc.dg/torture/pr59155-2.c: New test.
	* gcc.dg/torture/pr59155-3.c: New test.

Comments

Bernd Edlinger June 6, 2016, 1:32 p.m. UTC | #1
Ping...

see https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02010.html

Thanks
Bernd.


On 05/25/16 14:58, Bernd Edlinger wrote:
> Hi!
>
> This restricts the X constraint in asm statements, which
> can be easily folded by combine in something completely
> invalid.
>
> It is necessary to allow scratch here, because on i386
> the md_asm_adjust hook inserts them.
>
> The second test case fails because lra does not
> allow all register for anything_ok operands (aka X)
> and later it fails to match the two X constraints
> in case '0': if (curr_alt[m] == NO_REGS) break.
>
> There is also an identical bug in the reload pass,
> but I do not know how to fix that, as it is almost
> used nowhere today.
>
>
> Boot-strapped and regression-tested on x86_64-pc-linux-gnu.
> OK for trunk?
>
>
> Thanks
> Bernd.
>
Vladimir Makarov June 6, 2016, 5:04 p.m. UTC | #2
On 06/06/2016 09:32 AM, Bernd Edlinger wrote:
> Ping...
>
> see https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02010.html
>
>
Thank you for working on the PR and sorry for the delay with LRA part of 
review.

Change in lra-constraints.c is ok for me with the following change. 
Instead of just

-	      curr_alt[nop] = NO_REGS;
+	      curr_alt[nop] = ALL_REGS;
  	      CLEAR_HARD_REG_SET (curr_alt_set[nop]);

I'd like to see

-	      curr_alt[nop] = NO_REGS;
+	      curr_alt[nop] = ALL_REGS;
- 	      CLEAR_HARD_REG_SET (curr_alt_set[nop]);
+             COPY_HARD_REG_SET (curr_alt_set[nop], reg_class_contents[ALL_REGS]);

Also I don't see /* { dg-do compile } */ in the tests (I don't know what dejagnu does when there is no any dejagnu actions in the test).
But with the addition '/* { dg-do compile } */' the test pr59155-2.c is ok for me too.

As for recog.c, I can not approve this as I am not a maintainer of it.
I only can say that the code looks questionable to me.
Jeff Law June 6, 2016, 5:54 p.m. UTC | #3
On 06/06/2016 11:04 AM, Vladimir Makarov wrote:
> On 06/06/2016 09:32 AM, Bernd Edlinger wrote:
>> Ping...
>>
>> see https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02010.html
>>
>>
> Thank you for working on the PR and sorry for the delay with LRA part of
> review.
>
> Change in lra-constraints.c is ok for me with the following change.
> Instead of just
>
> -          curr_alt[nop] = NO_REGS;
> +          curr_alt[nop] = ALL_REGS;
>            CLEAR_HARD_REG_SET (curr_alt_set[nop]);
>
> I'd like to see
>
> -          curr_alt[nop] = NO_REGS;
> +          curr_alt[nop] = ALL_REGS;
> -           CLEAR_HARD_REG_SET (curr_alt_set[nop]);
> +             COPY_HARD_REG_SET (curr_alt_set[nop],
> reg_class_contents[ALL_REGS]);
>
> Also I don't see /* { dg-do compile } */ in the tests (I don't know what
> dejagnu does when there is no any dejagnu actions in the test).
> But with the addition '/* { dg-do compile } */' the test pr59155-2.c is
> ok for me too.
>
> As for recog.c, I can not approve this as I am not a maintainer of it.
> I only can say that the code looks questionable to me.
I think the question on the recog part is a matter of how we choose to 
interpret what the "X" constraint means.

Does it literally mean accept anything, or accept some subset expressions?

I tend to think the former, which means that things like 
reg_overlap_mentioned_p or its callers have to be bullet-proofed.

jeff
Jakub Jelinek June 6, 2016, 6:01 p.m. UTC | #4
On Mon, Jun 06, 2016 at 11:54:04AM -0600, Jeff Law wrote:
> >As for recog.c, I can not approve this as I am not a maintainer of it.
> >I only can say that the code looks questionable to me.
> I think the question on the recog part is a matter of how we choose to
> interpret what the "X" constraint means.
> 
> Does it literally mean accept anything, or accept some subset expressions?
> 
> I tend to think the former, which means that things like
> reg_overlap_mentioned_p or its callers have to be bullet-proofed.

I think it is a bad idea to accept really anything, even for debug insns,
which initially accepted arbitrarily large RTL expressions (and still accept
stuff like subregs otherwise considered invalid etc.) we found it is highly
undesirable, as it is not very good idea for the compile time complexity
etc., so now we are trying to limit the complexity of the expressions there
by splitting up more complex expressions into smaller ones using temporaries.
So, even accept anything should always be accept anything reasonable,
because most of the RTL passes don't really expect arbitrarily deep
expressions, or expressions where the same reg can appear thousands of times
etc.

	Jakub
Jeff Law June 6, 2016, 6:04 p.m. UTC | #5
On 06/06/2016 12:01 PM, Jakub Jelinek wrote:
> On Mon, Jun 06, 2016 at 11:54:04AM -0600, Jeff Law wrote:
>>> As for recog.c, I can not approve this as I am not a maintainer of it.
>>> I only can say that the code looks questionable to me.
>> I think the question on the recog part is a matter of how we choose to
>> interpret what the "X" constraint means.
>>
>> Does it literally mean accept anything, or accept some subset expressions?
>>
>> I tend to think the former, which means that things like
>> reg_overlap_mentioned_p or its callers have to be bullet-proofed.
>
> I think it is a bad idea to accept really anything, even for debug insns,
> which initially accepted arbitrarily large RTL expressions (and still accept
> stuff like subregs otherwise considered invalid etc.) we found it is highly
> undesirable, as it is not very good idea for the compile time complexity
> etc., so now we are trying to limit the complexity of the expressions there
> by splitting up more complex expressions into smaller ones using temporaries.
> So, even accept anything should always be accept anything reasonable,
> because most of the RTL passes don't really expect arbitrarily deep
> expressions, or expressions where the same reg can appear thousands of times
> etc.
The problem is how do you define this subset of expressions you're going 
to accept and those which you are going to reject.

I first pondered accepting RTL leaf nodes (reg, subreg, constants) and 
rejecting everything else.  But I couldn't convince myself that some 
port might reasonably expect (plus (x) (y)) to match the "X" constraint.

jeff
Jakub Jelinek June 6, 2016, 6:08 p.m. UTC | #6
On Mon, Jun 06, 2016 at 12:04:04PM -0600, Jeff Law wrote:
> On 06/06/2016 12:01 PM, Jakub Jelinek wrote:
> >On Mon, Jun 06, 2016 at 11:54:04AM -0600, Jeff Law wrote:
> >>>As for recog.c, I can not approve this as I am not a maintainer of it.
> >>>I only can say that the code looks questionable to me.
> >>I think the question on the recog part is a matter of how we choose to
> >>interpret what the "X" constraint means.
> >>
> >>Does it literally mean accept anything, or accept some subset expressions?
> >>
> >>I tend to think the former, which means that things like
> >>reg_overlap_mentioned_p or its callers have to be bullet-proofed.
> >
> >I think it is a bad idea to accept really anything, even for debug insns,
> >which initially accepted arbitrarily large RTL expressions (and still accept
> >stuff like subregs otherwise considered invalid etc.) we found it is highly
> >undesirable, as it is not very good idea for the compile time complexity
> >etc., so now we are trying to limit the complexity of the expressions there
> >by splitting up more complex expressions into smaller ones using temporaries.
> >So, even accept anything should always be accept anything reasonable,
> >because most of the RTL passes don't really expect arbitrarily deep
> >expressions, or expressions where the same reg can appear thousands of times
> >etc.
> The problem is how do you define this subset of expressions you're going to
> accept and those which you are going to reject.
> 
> I first pondered accepting RTL leaf nodes (reg, subreg, constants) and
> rejecting everything else.  But I couldn't convince myself that some port
> might reasonably expect (plus (x) (y)) to match the "X" constraint.

It is always going to be arbitrary.
Perhaps RTL leaf nodes (if including MEM, then perhaps with valid address
only), and unary/binary/ternary RTL expressions with RTL leaf node operands?
Or union of what is accepted by any other constraint?
Or "g" plus any constants?

	Jakub
Marc Glisse June 6, 2016, 7:27 p.m. UTC | #7
On Mon, 6 Jun 2016, Jakub Jelinek wrote:

> On Mon, Jun 06, 2016 at 12:04:04PM -0600, Jeff Law wrote:
>> On 06/06/2016 12:01 PM, Jakub Jelinek wrote:
>>> On Mon, Jun 06, 2016 at 11:54:04AM -0600, Jeff Law wrote:
>>>>> As for recog.c, I can not approve this as I am not a maintainer of it.
>>>>> I only can say that the code looks questionable to me.
>>>> I think the question on the recog part is a matter of how we choose to
>>>> interpret what the "X" constraint means.
>>>>
>>>> Does it literally mean accept anything, or accept some subset expressions?
>>>>
>>>> I tend to think the former, which means that things like
>>>> reg_overlap_mentioned_p or its callers have to be bullet-proofed.
>>>
>>> I think it is a bad idea to accept really anything, even for debug insns,
>>> which initially accepted arbitrarily large RTL expressions (and still accept
>>> stuff like subregs otherwise considered invalid etc.) we found it is highly
>>> undesirable, as it is not very good idea for the compile time complexity
>>> etc., so now we are trying to limit the complexity of the expressions there
>>> by splitting up more complex expressions into smaller ones using temporaries.
>>> So, even accept anything should always be accept anything reasonable,
>>> because most of the RTL passes don't really expect arbitrarily deep
>>> expressions, or expressions where the same reg can appear thousands of times
>>> etc.
>> The problem is how do you define this subset of expressions you're going to
>> accept and those which you are going to reject.
>>
>> I first pondered accepting RTL leaf nodes (reg, subreg, constants) and
>> rejecting everything else.  But I couldn't convince myself that some port
>> might reasonably expect (plus (x) (y)) to match the "X" constraint.
>
> It is always going to be arbitrary.
> Perhaps RTL leaf nodes (if including MEM, then perhaps with valid address
> only), and unary/binary/ternary RTL expressions with RTL leaf node operands?
> Or union of what is accepted by any other constraint?
> Or "g" plus any constants?

The last one would miss floating point registers (no 2 platforms use the 
same letter for those, hence my quest for something more generic).

The goal of the experiment is described in PR59159 (for which "+X" is 
unlikely to be the right answer, in particular because it is meaningless 
for constants). I don't know in what context people use the "X" 
constraint, or even better "=X"...
Jakub Jelinek June 6, 2016, 7:40 p.m. UTC | #8
On Mon, Jun 06, 2016 at 09:27:56PM +0200, Marc Glisse wrote:
> The last one would miss floating point registers (no 2 platforms use the
> same letter for those, hence my quest for something more generic).
> 
> The goal of the experiment is described in PR59159 (for which "+X" is
> unlikely to be the right answer, in particular because it is meaningless for
> constants). I don't know in what context people use the "X" constraint, or
> even better "=X"...

X constraint has been added mainly for uses in match_scratch like:
(clobber (match_scratch:SI 2 "=X,X,X,&r"))
or when the predicate takes care of everything and it is not needed to
specify anything further:
  [(set (match_operand:SWI12 0 "push_operand" "=X")
        (match_operand:SWI12 1 "nonmemory_no_elim_operand" "rn"))]
Using it in inline asm generally has resulted in lots of issues, including
ICEs etc., so nothing I'd recommend to use.

	Jakub
Bernd Edlinger June 7, 2016, 5:58 p.m. UTC | #9
On 06/06/16 20:08, Jakub Jelinek wrote:
> On Mon, Jun 06, 2016 at 12:04:04PM -0600, Jeff Law wrote:
>> On 06/06/2016 12:01 PM, Jakub Jelinek wrote:
>>> On Mon, Jun 06, 2016 at 11:54:04AM -0600, Jeff Law wrote:
>>>>> As for recog.c, I can not approve this as I am not a maintainer of it.
>>>>> I only can say that the code looks questionable to me.
>>>> I think the question on the recog part is a matter of how we choose to
>>>> interpret what the "X" constraint means.
>>>>
>>>> Does it literally mean accept anything, or accept some subset expressions?
>>>>
>>>> I tend to think the former, which means that things like
>>>> reg_overlap_mentioned_p or its callers have to be bullet-proofed.

AFACT this is not the only place where overly complex RTL trees can
cause an ICE.

>>>
>>> I think it is a bad idea to accept really anything, even for debug insns,
>>> which initially accepted arbitrarily large RTL expressions (and still accept
>>> stuff like subregs otherwise considered invalid etc.) we found it is highly
>>> undesirable, as it is not very good idea for the compile time complexity
>>> etc., so now we are trying to limit the complexity of the expressions there
>>> by splitting up more complex expressions into smaller ones using temporaries.
>>> So, even accept anything should always be accept anything reasonable,
>>> because most of the RTL passes don't really expect arbitrarily deep
>>> expressions, or expressions where the same reg can appear thousands of times
>>> etc.
>> The problem is how do you define this subset of expressions you're going to
>> accept and those which you are going to reject.
>>
>> I first pondered accepting RTL leaf nodes (reg, subreg, constants) and
>> rejecting everything else.  But I couldn't convince myself that some port
>> might reasonably expect (plus (x) (y)) to match the "X" constraint.
>
> It is always going to be arbitrary.
> Perhaps RTL leaf nodes (if including MEM, then perhaps with valid address
> only), and unary/binary/ternary RTL expressions with RTL leaf node operands?
> Or union of what is accepted by any other constraint?
> Or "g" plus any constants?

Yes. That is what I think too, "X" is probably not used often in
practice, but if it is allowed, it should at least not result in an ICE.

"X" should allow to feed "whatsoever" valid C expressions to the asm
input, and using the %-expression in the assembler string should not
cause an ICE.

And "X" really means different "whatsoever" things in asm statements
and in .md files, even md.texi has different text for internally used
"X" constraint and assembler "X" constraint, so that should be OK.

According to md.texi
"g" should already mean:

@item @samp{g}
Any register, memory or immediate integer operand is allowed, except for
registers that are not general registers.

Which is the same as general_operand(op, VOIDmode). And in other words,
that should be everything that is in "r", "m" and "i" constraints.


However if I compare commond.md ...

(define_constraint "i"
   "Matches a general integer constant."
   (and (match_test "CONSTANT_P (op)")
        (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))

... against recog.c, general_operand seems to allow less i.e. checks
targetm.legitimate_constant_p additionally.  So that is something
I don't really understand, I mean if a constant is not a "legitimate"
constant by the target's definition, why should it be safe to use
in later in targetm.asm_out.print_operand?



Bernd.
Jeff Law June 9, 2016, 4:28 p.m. UTC | #10
On 06/07/2016 11:58 AM, Bernd Edlinger wrote:
>
> AFACT this is not the only place where overly complex RTL trees can
> cause an ICE.
That wouldn't surprise me at all -- but the design of RTL is such that 
it can be arbitrarily complex.  Essentially, routines can not make 
assumptions about the complexity of the RTL they're given -- except for 
any guards/pre-conditions set up in the caller.

>
> Yes. That is what I think too, "X" is probably not used often in
> practice, but if it is allowed, it should at least not result in an ICE.
There's no disagreement about "X" should never result in an ICE.

The question is whether or not "X" truly means an arbitrary piece of RTL 
or some tighter subset of RTL.   I guess one could also raise the 
question of whether or not "X" should ever be exposed to asms.

"X"'s original intent IIRC was to specify that for a particular 
alternative the operand didn't matter and would never be used.  This 
comes up with scratch registers for example.


>
> "X" should allow to feed "whatsoever" valid C expressions to the asm
> input, and using the %-expression in the assembler string should not
> cause an ICE.
Actually it doesn't even have to be a valid C expression.  It might have 
started as a C expression from an ASM statement, but been modified by 
various RTL optimization passes into something that isn't necessarily a 
valid C expression.



> However if I compare commond.md ...
>
> (define_constraint "i"
>    "Matches a general integer constant."
>    (and (match_test "CONSTANT_P (op)")
>         (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
>
> ... against recog.c, general_operand seems to allow less i.e. checks
> targetm.legitimate_constant_p additionally.  So that is something
> I don't really understand, I mean if a constant is not a "legitimate"
> constant by the target's definition, why should it be safe to use
> in later in targetm.asm_out.print_operand?
Legitimacy in this context is usually something related to operands that 
have to be reloaded for PIC code generation.  They may print just fine, 
but from a code generation standpoint they require special handling. 
One could argue that this is inconsistent and it ought to be cleaned up, 
but that's separate from the "X" issue.

jeff
Jeff Law June 9, 2016, 4:30 p.m. UTC | #11
On 06/06/2016 01:40 PM, Jakub Jelinek wrote:
> On Mon, Jun 06, 2016 at 09:27:56PM +0200, Marc Glisse wrote:
>> The last one would miss floating point registers (no 2 platforms use the
>> same letter for those, hence my quest for something more generic).
>>
>> The goal of the experiment is described in PR59159 (for which "+X" is
>> unlikely to be the right answer, in particular because it is meaningless for
>> constants). I don't know in what context people use the "X" constraint, or
>> even better "=X"...
>
> X constraint has been added mainly for uses in match_scratch like:
> (clobber (match_scratch:SI 2 "=X,X,X,&r"))
> or when the predicate takes care of everything and it is not needed to
> specify anything further:
>   [(set (match_operand:SWI12 0 "push_operand" "=X")
>         (match_operand:SWI12 1 "nonmemory_no_elim_operand" "rn"))]
> Using it in inline asm generally has resulted in lots of issues, including
> ICEs etc., so nothing I'd recommend to use.
So would it make sense to define it as not available for use in ASMs?  I 
realize that's potentially a user-visible change, but it might be a 
reasonable one to make.

jeff
Jakub Jelinek June 9, 2016, 4:43 p.m. UTC | #12
On Thu, Jun 09, 2016 at 10:30:13AM -0600, Jeff Law wrote:
> On 06/06/2016 01:40 PM, Jakub Jelinek wrote:
> >On Mon, Jun 06, 2016 at 09:27:56PM +0200, Marc Glisse wrote:
> >>The last one would miss floating point registers (no 2 platforms use the
> >>same letter for those, hence my quest for something more generic).
> >>
> >>The goal of the experiment is described in PR59159 (for which "+X" is
> >>unlikely to be the right answer, in particular because it is meaningless for
> >>constants). I don't know in what context people use the "X" constraint, or
> >>even better "=X"...
> >
> >X constraint has been added mainly for uses in match_scratch like:
> >(clobber (match_scratch:SI 2 "=X,X,X,&r"))
> >or when the predicate takes care of everything and it is not needed to
> >specify anything further:
> >  [(set (match_operand:SWI12 0 "push_operand" "=X")
> >        (match_operand:SWI12 1 "nonmemory_no_elim_operand" "rn"))]
> >Using it in inline asm generally has resulted in lots of issues, including
> >ICEs etc., so nothing I'd recommend to use.
> So would it make sense to define it as not available for use in ASMs?  I
> realize that's potentially a user-visible change, but it might be a
> reasonable one to make.

Yes, I'm all in favor in disabling X constraint for inline asm.
Especially if people actually try to print it as well, rather than make it
unused.  That is a sure path to ICEs.

	Jakub
Jakub Jelinek June 9, 2016, 4:45 p.m. UTC | #13
On Thu, Jun 09, 2016 at 06:43:04PM +0200, Jakub Jelinek wrote:
> Yes, I'm all in favor in disabling X constraint for inline asm.
> Especially if people actually try to print it as well, rather than make it
> unused.  That is a sure path to ICEs.

Though, on the other side, even our documentation mentions
asm volatile ("mtfsf 255,%1" : "=X"(sum): "f"(fpenv));
So perhaps we need to error just in case such an argument is printed?

	Jakub
Bernd Edlinger June 10, 2016, 2:13 p.m. UTC | #14
On 06/09/16 18:45, Jakub Jelinek wrote:
> On Thu, Jun 09, 2016 at 06:43:04PM +0200, Jakub Jelinek wrote:
>> Yes, I'm all in favor in disabling X constraint for inline asm.
>> Especially if people actually try to print it as well, rather than make it
>> unused.  That is a sure path to ICEs.
>
> Though, on the other side, even our documentation mentions
> asm volatile ("mtfsf 255,%1" : "=X"(sum): "f"(fpenv));
> So perhaps we need to error just in case such an argument is printed?

note that "=X" is also introduced internally in this asm statement:

asm ("cmpl  %2, 0" : "=@ccz"(z), "=@ccb"(b): "r"(i));

see i386.c, ix86_md_asm_adjust.

The first =@cc is replaced by "=Bf" constraint but any
further =@cc are replaced by "=X" and scratch operand.

Printing the "=X" scratch is harmless, but printing the "=Bf" causes
another ICE, I shall submit a follow up patch for that:
asm ("# %0" : "=@ccz"(z));

test.c:6:1: internal compiler error: in print_reg, at 
config/i386/i386.c:17193
  }
  ^
0xedfc30 print_reg(rtx_def*, int, _IO_FILE*)
	../../gcc-trunk/gcc/config/i386/i386.c:17189
0xf048a4 ix86_print_operand(_IO_FILE*, rtx_def*, int)
	../../gcc-trunk/gcc/config/i386/i386.c:17867
0x8bf87c output_operand(rtx_def*, int)
	../../gcc-trunk/gcc/final.c:3847
0x8c00ee output_asm_insn(char const*, rtx_def**)
	../../gcc-trunk/gcc/final.c:3763
0x8c1f9c final_scan_insn(rtx_insn*, _IO_FILE*, int, int, int*)
	../../gcc-trunk/gcc/final.c:2628
0x8c25c9 final(rtx_insn*, _IO_FILE*, int)
	../../gcc-trunk/gcc/final.c:2045
0x8c2da9 rest_of_handle_final
	../../gcc-trunk/gcc/final.c:4445
0x8c2da9 execute
	../../gcc-trunk/gcc/final.c:4520


Well, regarding the X constraint, I do think that
it's definitely OK to use different rules if it is
used in asms vs. when if it is used internally in .md files.

The patch handles X in asms to be just a synonym to the g constraint,
except that g allows only GENERAL_REGS and X allows ALL_REGS.

What I am not sure of, is if X should allow more than g in terms of
CONSTANT_P.  I think it should not, because probably the CONSTANT_P
handling in general_operand is likely smarter than that of the i
constraint.


Bernd.
Jeff Law June 20, 2016, 10:06 p.m. UTC | #15
On 06/09/2016 10:45 AM, Jakub Jelinek wrote:
> On Thu, Jun 09, 2016 at 06:43:04PM +0200, Jakub Jelinek wrote:
>> Yes, I'm all in favor in disabling X constraint for inline asm.
>> Especially if people actually try to print it as well, rather than make it
>> unused.  That is a sure path to ICEs.
>
> Though, on the other side, even our documentation mentions
> asm volatile ("mtfsf 255,%1" : "=X"(sum): "f"(fpenv));
> So perhaps we need to error just in case such an argument is printed?
Are you thinking to scan the output string for %<N> for the appropriate 
<N>?  That shouldn't be too hard.  But that's not sufficient to address 
the problem Bernd is trying to tackle AFAICT.


Jeff
Bernd Edlinger June 21, 2016, 1:52 a.m. UTC | #16
On 06/21/16 00:06, Jeff Law wrote:
> On 06/09/2016 10:45 AM, Jakub Jelinek wrote:
>> On Thu, Jun 09, 2016 at 06:43:04PM +0200, Jakub Jelinek wrote:
>>> Yes, I'm all in favor in disabling X constraint for inline asm.
>>> Especially if people actually try to print it as well, rather than
>>> make it
>>> unused.  That is a sure path to ICEs.
>>
>> Though, on the other side, even our documentation mentions
>> asm volatile ("mtfsf 255,%1" : "=X"(sum): "f"(fpenv));
>> So perhaps we need to error just in case such an argument is printed?
> Are you thinking to scan the output string for %<N> for the appropriate
> <N>?  That shouldn't be too hard.  But that's not sufficient to address
> the problem Bernd is trying to tackle AFAICT.

Correct.

And furthermore, the use case with matching X input & output that Marc
wanted to use, seems to be a valid one.  Because "+X" allows more
registers than "+g" or "+r", it should create less register pressure.
And although it is probably unpredictable if a register of the
class "ALL_REGISTERS" will work for an assembler instruction, it is
still interesting to print it in an assembler comment.


Bernd.
diff mbox

Patch

Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c	(revision 236569)
+++ gcc/lra-constraints.c	(working copy)
@@ -1854,7 +1854,7 @@  process_alt_operands (int only_alternative)
 	  if (curr_static_id->operand_alternative[opalt_num].anything_ok)
 	    {
 	      /* Fast track for no constraints at all.	*/
-	      curr_alt[nop] = NO_REGS;
+	      curr_alt[nop] = ALL_REGS;
 	      CLEAR_HARD_REG_SET (curr_alt_set[nop]);
 	      curr_alt_win[nop] = true;
 	      curr_alt_match_win[nop] = false;
Index: gcc/recog.c
===================================================================
--- gcc/recog.c	(revision 236569)
+++ gcc/recog.c	(working copy)
@@ -1757,6 +1757,10 @@  asm_operand_ok (rtx op, const char *constraint, co
 	    result = 1;
 	  break;
 
+	case 'X':
+	  if (scratch_operand (op, VOIDmode))
+	    result = 1;
+	  /* ... fall through ...  */
 	case 'g':
 	  if (general_operand (op, VOIDmode))
 	    result = 1;
Index: gcc/testsuite/gcc.dg/torture/pr59155-1.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr59155-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr59155-1.c	(working copy)
@@ -0,0 +1,7 @@ 
+double f(double x){
+  asm volatile("":"+X"(x));
+  return x;
+}
+double g(double x,double y){
+  return f(f(x)+f(y));
+}
Index: gcc/testsuite/gcc.dg/torture/pr59155-2.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr59155-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr59155-2.c	(working copy)
@@ -0,0 +1,7 @@ 
+double f(double x){
+  asm volatile("":"+X"(x));
+  return x;
+}
+double g(){
+  return f(1.);
+}
Index: gcc/testsuite/gcc.dg/torture/pr59155-3.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr59155-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr59155-3.c	(working copy)
@@ -0,0 +1,27 @@ 
+void
+noprop1 (int **x, int y, int z)
+{
+  int *ptr = *x + y * z / 11;
+  asm volatile ("noprop1 %0" : : "X" (*ptr));
+}
+
+void
+noprop2 (int **x, int y, int z)
+{
+  int *ptr = *x + y * z / 11;
+  asm volatile ("noprop2 %0" : : "X" (ptr));
+}
+
+int *global_var;
+
+void
+const1 (void)
+{
+  asm volatile ("const1 %0" : : "X" (global_var));
+}
+
+void
+const2 (void)
+{
+  asm volatile ("const2 %0" : : "X" (*global_var));
+}