[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 Uroš Bizjak changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |FIXED --- Comment #18 from Uroš Bizjak --- (In reply to David from comment #16) > Still, if I were Richard, I'd be closing this bug. If someone has > optimization issues with his solution, that's a new bug. This was implemented some time ago.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #16 from David gccbugzilla at limegreensocks dot com --- I've tried it now and it seems to do good things. This code: int main(int argc, char *argv[]) { char x; asm(setc : =@ccc(x)); if (!x) return 6; else return argc; } produces this output (-O3): movl$6, %eax /APP # 6 ./r.cpp 1 setc # 0 2 /NO_APP cmovc %ebx, %eax addq$32, %rsp popq%rbx ret Although a minor variation (change return argc to return 7) ends up doing setc+cmpb, so it's not a perfect solution. Still, if I were Richard, I'd be closing this bug. If someone has optimization issues with his solution, that's a new bug.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #17 from Jeremy gcc.hall at gmail dot com --- Did you mean stc rather than setc ??? But yes, it looks like its working well. On 20 July 2015 at 10:05, gccbugzilla at limegreensocks dot com gcc-bugzi...@gcc.gnu.org wrote: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #16 from David gccbugzilla at limegreensocks dot com --- I've tried it now and it seems to do good things. This code: int main(int argc, char *argv[]) { char x; asm(setc : =@ccc(x)); if (!x) return 6; else return argc; } produces this output (-O3): movl$6, %eax /APP # 6 ./r.cpp 1 setc # 0 2 /NO_APP cmovc %ebx, %eax addq$32, %rsp popq%rbx ret Although a minor variation (change return argc to return 7) ends up doing setc+cmpb, so it's not a perfect solution. Still, if I were Richard, I'd be closing this bug. If someone has optimization issues with his solution, that's a new bug. -- You are receiving this mail because: You are on the CC list for the bug.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #15 from Jeremy gcc.hall at gmail dot com --- Perhaps the optimizer can reduce seta; test; jnz to ja since the compiler now knows the intention. In which case this is a great solution. On 17 July 2015 at 22:24, gccbugzilla at limegreensocks dot com gcc-bugzi...@gcc.gnu.org wrote: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #14 from David gccbugzilla at limegreensocks dot com --- (In reply to Jeremy from comment #12) It probably does a setcc on x86 which doesn't really gain much I don't have a 6.0 build to test with yet, but I don't believe that's quite correct. Looking at the testsuite that got checked in with it, we see both: asm-flag-2.c: /* { dg-final { scan-assembler seta } } */ asm-flag-3.c: /* { dg-final { scan-assembler ja } } */ -- You are receiving this mail because: You are on the CC list for the bug.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #12 from Jeremy gcc.hall at gmail dot com --- Hi David, That's very interesting. Its not in gcc 5.2.0 released yesterday though. It probably does a setcc on x86 which doesn't really gain much, but on ARM it could be useful. More useful (as of gcc 5.0) is the new __builtin_xxx_overflow which uses the overflow flag directly. So for int16_t operands for example: if( __builtin_add_overflow( a, b, result) ) printf( overflow); it would emit addw; jno. Jeremy On 17 July 2015 at 06:41, gccbugzilla at limegreensocks dot com gcc-bugzi...@gcc.gnu.org wrote: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #11 from David gccbugzilla at limegreensocks dot com --- Apparently this feature has been checked in: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#FlagOutputOperands -- You are receiving this mail because: You are on the CC list for the bug.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #13 from Andrew Pinski pinskia at gcc dot gnu.org --- (In reply to Jeremy from comment #12) Hi David, That's very interesting. Its not in gcc 5.2.0 released yesterday though. That is because 5.2 is a patch release off of the 5 branch. It was added to gcc 6 and above. It probably does a setcc on x86 which doesn't really gain much, but on ARM it could be useful. More useful (as of gcc 5.0) is the new __builtin_xxx_overflow which uses the overflow flag directly. So for int16_t operands for example: if( __builtin_add_overflow( a, b, result) ) printf( overflow); it would emit addw; jno. Jeremy On 17 July 2015 at 06:41, gccbugzilla at limegreensocks dot com gcc-bugzi...@gcc.gnu.org wrote: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #11 from David gccbugzilla at limegreensocks dot com --- Apparently this feature has been checked in: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#FlagOutputOperands -- You are receiving this mail because: You are on the CC list for the bug.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #14 from David gccbugzilla at limegreensocks dot com --- (In reply to Jeremy from comment #12) It probably does a setcc on x86 which doesn't really gain much I don't have a 6.0 build to test with yet, but I don't believe that's quite correct. Looking at the testsuite that got checked in with it, we see both: asm-flag-2.c: /* { dg-final { scan-assembler seta } } */ asm-flag-3.c: /* { dg-final { scan-assembler ja } } */
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #10 from David gccbugzilla at limegreensocks dot com --- There was some discussion of this on the gcc mailing list. Not sure what became of it: https://gcc.gnu.org/ml/gcc/2015-05/msg6.html
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #11 from David gccbugzilla at limegreensocks dot com --- Apparently this feature has been checked in: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#FlagOutputOperands
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #8 from Jeremy gcc.hall at gmail dot com --- Asm goto does not allow any outputs, which does limit its usefulness.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #9 from Ryan Johnson scovich at gmail dot com --- (In reply to Andi Kleen from comment #7) You can do many of these things these days with asm goto, however it typically requires non-structured control flow (goto labels). I filed this bug after determining that asm goto was unsuitable for this purpose. Goto labels are not a problem per se (actually kind of slick), but asm goto requires all outputs to pass through memory and so is only good for control flow (not computation plus exceptional case). It also requires the actual branching and all attendant glue to happen in assembly. Both limitations increase bulk and hamper the optimizer, and go against (what I thought was) the intention that inline asm normally be used for very small snippets of code the compiler can't handle. At some point you may as well just setcc and do a new comparison/branch outside the asm block; less bug-prone and would probably yield faster and cleaner code, too.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 Andi Kleen andi-gcc at firstfloor dot org changed: What|Removed |Added CC||andi-gcc at firstfloor dot org --- Comment #7 from Andi Kleen andi-gcc at firstfloor dot org --- You can do many of these things these days with asm goto, however it typically requires non-structured control flow (goto labels) https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#GotoLabels
[Bug inline-asm/49611] Inline asm should support input/output of flags
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.
[Bug inline-asm/49611] Inline asm should support input/output of flags
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #6 from Ryan Johnson scovich at gmail dot com --- (In reply to Jeremy from comment #5) 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. Interesting! Ironically, limiting it to one flag opens the way to cleanly specify branching based on multiple flags. The optimizer just needs to recognize that when it sees two otherwise-equivalent (non-volatile) asm statements with different asm_return attribute, it's really just one asm statement that sets multiple flags. Thus: #ifdef USE_ASM #define CMP(a,b) asm(cmp %0 %1 : : r(a), r(b)) #define BELOW(a,b) (__attribute__((asm_return(cc_carry))) CMP(a,b)) #define EQUAL(a,b) (__attribute__((asm_return(cc_zero))) CMP(a,b)) #else #define BELOW(a,b) ((a) (b)) #define EQUAL(a,b) ((a) == (b)) #endif int do_it(unsigned int a, unsigned int b, int c, int d, int e, int f) { int x; if (BELOW(a,b)) x = c+d; else if (EQUAL(a,b)) x = d+e; else x = c+e; return x+f; } Would produce the same assembly code output---with only one comparison---whether USE_ASM was defined or not. Even more fun would be if the optimizer could recognize conditionals that depend on multiple flags (like x86 less or equal) and turn this: if ((__attribute__((asm_return(cc_zero))) CMP(a,b) || __attribute__((asm_return(cc_overflow))) CMP(a,b) != __attribute__((asm_return(cc_sign))) CMP(a,b)) do_less_or_equal(); do_something_else(); into: cmp %[a] %[b] jg 1f call do_less_or_equal 1: call do_something_else Much of the flag-wrangling machinery seems to already exist, because the compiler emits the above asm if you replace the inline asm with either a = b or a b || a == b (assuming now that a and b are signed ints).
[Bug inline-asm/49611] Inline asm should support input/output of flags
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 Jeroen van Bemmel jbemmel at zonnet dot nl changed: What|Removed |Added CC||jbemmel at zonnet dot nl --- Comment #4 from Jeroen van Bemmel jbemmel at zonnet dot nl 2012-06-28 16:06:18 UTC --- Ideally, there would be some way to express that a given asm goto block depends on the flags, to prevent GCC from reordering flags-changing instructions and breaking the code. As a compromise, GCC could simply assume by default that asm goto blocks depend on the flags. Like Ryan, I believe that most people using asm goto would use it for such a purpose, and any missed optimization opportunities are a small price to pay for correct code.
[Bug inline-asm/49611] Inline asm should support input/output of flags
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #3 from Ryan Johnson scovich at gmail dot com 2012-04-12 16:39:32 UTC --- FYI: based on a discussion from quite some time ago [1], it seems that the Linux kernel folks would be tickled pink to have this feature, and discussed several potential ways to implement it. [1] http://lkml.indiana.edu/hypermail/linux/kernel/0111.2/0256.html
[Bug inline-asm/49611] Inline asm should support input/output of flags
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #2 from Ryan Johnson scovich at gmail dot com 2011-07-04 20:32:01 UTC --- (In reply to comment #1) Making this work reliably is probably more work than making GCC use the flags from more cases from regular C code. Does that mean each such case would need to be identified individually and then hard-wired into i386.md? The existence of modes like CCGC, CCGOC, CCNO, etc. in i386-modes.def made me hope that some high-level mechanism existed for reasoning about the semantics of condition codes. Or does that mechanism exist, and is just difficult to expose to inline asm for some reason?
[Bug inline-asm/49611] Inline asm should support input/output of flags
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49611 --- Comment #1 from Richard Guenther rguenth at gcc dot gnu.org 2011-07-02 12:36:44 UTC --- Making this work reliably is probably more work than making GCC use the flags from more cases from regular C code.