https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611

Jeremy <gcc.hall at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |gcc.hall at gmail dot com

--- Comment #5 from Jeremy <gcc.hall at gmail dot com> ---
It may not be possible, but perhaps a simpler thing might be for
the asm() to notionally "return" a single boolean value which
reflects ONE flag only.

By default this could be the ZF flag (which is probably the most
useful).  It would not generate any extra code at all. Thus:

   if( asm( "test %%eax,%%eax" ))

would emit:

   test eax,eax
   jz

rather than the usual route involving setcc and a second test.

The actual flag notionally returned could be changed with an attribute:

  __attribute__ ((asm_return(cc_carry)))
  __attribute__ ((asm_return(cc_overflow)))
  __attribute__ ((asm_return(cc_zero)))
  __attribute__ ((asm_return(cc_sign)))
  __attribute__ ((asm_return(cc_parity)))

or shorter, for example:

  __attribute__ ((cc_carry))

The inverse condition is simply expressed with  !asm(...)

The new code would also allow:

  bool zero = asm( "test %%eax,%%eax" );

where the compiler would emit setz.
or

  x = asm( "test %%eax,%%eax" ) ? 10 : 20;

where the compiler might emit cmovz.

It would not break any existing code because nothing yet expects a return from
an asm,
neither would it preclude exporting all the flags with "=cc" in the future.

It would be a hard error if a flag is not supported by the current platform as
code cannnot be generated.
GCC does not examine the asm template string, if the flag is not set then the
result is UB, just like use of an undefined variable.

A final, more useful, example:

  // Implement "left *= right" reporting signed integer overflow
#define checked_multiply(left,right) \
    __attribute__ ((asm_return(cc_overflow))) \
    asm( "imul %1,%0" : "+r" (left) : "r" (right) )

allowing an efficient implementation of:

   if( checked_multiply( a, b ) )
   {
      handle overflow
   }


Possible documentation follows... 
========================
Return Value

If you are using the asm_return attribute, you are informing the compiler that
a comparison has already been done in your assembler code, and the flags have
been set appropriately.  The compiler can now use those flags to perform
conditional jumps, conditional assignments, etc.  Which conditional operator
should be used is determined by which value is specified to asm_return.  For
example on i386:

if( __attribute__(asm_return(cc_carry)) asm() )
  printf ("Carry yes\n");
else
  printf ("Carry no\n");

indicates that the asm template has set a value in the Carry flag, and GCC
should use the jc/jnc instructions to jump to the correct location. Similarly:

int a = __attribute__(asm_return(cc_zero)) asm() ?  23 : 42;

could use the i386 cmovz instruction to perform the assignment.  And

bool DidOverflow = __attribute__(asm_return(cc_overflow)) asm();

could use i386's seto.

Which flags (if any) are supported depend upon your platform (see Asm
Attributes). If no asm_return attribute is specified, it is an error to attempt
to use the return value from the asm.  It is acceptable for code to ignore the
returned flags.

========================

Reply via email to