[Bug c/43782] Erroneous expansion of __asm__() directive
--- Comment #7 from beebe at math dot utah dot edu 2010-04-30 00:23 --- Subject: Re: Erroneous expansion of __asm__() directive I accept the explanation of the problem with my sample __asm__() directive, and I think that we can close my bug report at http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43782 Since I corrected the test code to put the destination register last, I have written an extensive test suite to check all of the other uses of __asm__() directives in my code, and satisfied myself that there was only one problem instance. I also verified that after the change, the 49 gcc compiler versions that I tested now produce the correct answer, as do icc, nvcc, opencc, pathcc, pgcc, suncc, and upc; they all recognize the __asm__() directive on x86_64. However, I strongly recommend some updates in the gcc manual and possibly also the gas manual. I went through both in detail, and found that the gcc documentation, which is where any programmer would expect gcc's __asm__() directive to be documented, makes NO MENTION WHATSOEVER of the operand order in ``5.37 Assembler Instructions with C Expression Operands''. Elsewhere in the gcc manual, there is only this brief description `-masm=DIALECT' Output asm instructions using selected DIALECT. Supported choices are `intel' or `att' (the default one). Darwin does not support `intel'. but nothing more. In the gas manual, there is an explanation in the section * i386-Syntax:: ATT Syntax versus Intel Syntax that gcc uses the ATT src,dst order on all platforms. For any programmer used to reading or writing assembly code (outside of gcc) for the Intel and AMD processor families over the last 30 years, that is the opposite of expectation and instruction-set reference manuals. The gas manual also has a critical section * i386-Bugs:: ATT Syntax bugs that affects the coding of subtraction instructions. I believe that the gcc manual's description of the __asm__() directive should carry a prominent cross reference to those two sections, and a clear statement that the default operand order is consistent across platforms, but may differ from vendor instruction-set manuals. One respondent suggested: You can also write the asm using sqrtsd {%1, %0|%0, %1} and then it will work with both the default ATT syntax and -masm=intel. However, the vertical-bar syntax is not documented at all in the __asm__() directive description in the gcc manual. That too needs improvement. --- - Nelson H. F. BeebeTel: +1 801 581 5254 - - University of UtahFAX: +1 801 581 4148 - - Department of Mathematics, 110 LCBInternet e-mail: be...@math.utah.edu - - 155 S 1400 E RM 233 be...@acm.org be...@computer.org - - Salt Lake City, UT 84112-0090, USAURL: http://www.math.utah.edu/~beebe/ - --- -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43782
[Bug c/43782] Erroneous expansion of __asm__() directive
--- Comment #3 from beebe at math dot utah dot edu 2010-04-19 14:34 --- Subject: Re: Erroneous expansion of __asm__() directive Oh I forgot to mention, sqrt will use sqrtsd and will be inlined so you don't need to use inline-asm yourself. The test code that I sent is an extract of a larger system; its use of __asm__() is intentional. --- - Nelson H. F. BeebeTel: +1 801 581 5254 - - University of UtahFAX: +1 801 581 4148 - - Department of Mathematics, 110 LCBInternet e-mail: be...@math.utah.edu - - 155 S 1400 E RM 233 be...@acm.org be...@computer.org - - Salt Lake City, UT 84112-0090, USAURL: http://www.math.utah.edu/~beebe/ - --- -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43782
[Bug c/43782] Erroneous expansion of __asm__() directive
--- Comment #4 from beebe at math dot utah dot edu 2010-04-19 14:35 --- Subject: Re: Erroneous expansion of __asm__() directive That is wrong because with ATT style x86 asm, the src is first and the dest is second. That cannot be the case: you cannot change the operand order after three years of it working one way! --- - Nelson H. F. BeebeTel: +1 801 581 5254 - - University of UtahFAX: +1 801 581 4148 - - Department of Mathematics, 110 LCBInternet e-mail: be...@math.utah.edu - - 155 S 1400 E RM 233 be...@acm.org be...@computer.org - - Salt Lake City, UT 84112-0090, USAURL: http://www.math.utah.edu/~beebe/ - --- -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43782
[Bug c/43782] New: Erroneous expansion of __asm__() directive
Between gcc-4.5-20090903 (correct) and gcc-4.5-20091008 (wrong), a bug was introduced in the expansion of _asm__() directives on AMD64. The bug has been reproduced also in gcc-4.5-20100107 and yesterday's first release of gcc-4.6-20100416. Here is test program, with leading comments that reflect its test results: /*** Demonstrate a bug in the handling of __asm__() in recent gcc-4.5 and gcc-4.6 releases on AMD64: gcc-4.1-20070723 mysqrt(4) = 2 gcc-4.1-20071126 mysqrt(4) = 2 gcc-4.1-20071231 mysqrt(4) = 2 gcc-4.1-20080211 mysqrt(4) = 2 gcc-4.1-20080218 mysqrt(4) = 2 gcc-4.1-20080407 mysqrt(4) = 2 gcc-4.1-20080630 mysqrt(4) = 2 gcc-4.2-20061031 mysqrt(4) = 2 gcc-4.2-20070124 mysqrt(4) = 2 gcc-4.2-20070207 mysqrt(4) = 2 gcc-4.2-20070815 mysqrt(4) = 2 gcc-4.2-20070905 mysqrt(4) = 2 gcc-4.2-20071128 mysqrt(4) = 2 gcc-4.2-20071219 mysqrt(4) = 2 gcc-4.2-20071226 mysqrt(4) = 2 gcc-4.2-20080102 mysqrt(4) = 2 gcc-4.2-20080213 mysqrt(4) = 2 gcc-4.2-20080220 mysqrt(4) = 2 gcc-4.2-20080409 mysqrt(4) = 2 gcc-4.2-20080806 mysqrt(4) = 2 gcc-4.2-20081015 mysqrt(4) = 2 gcc-4.2-20081126 mysqrt(4) = 2 gcc-4.2-20090121 mysqrt(4) = 2 gcc-4.2-20090325 mysqrt(4) = 2 gcc-4.3-20061118 mysqrt(4) = 2 gcc-4.3-20070209 mysqrt(4) = 2 gcc-4.3-20070511 mysqrt(4) = 2 gcc-4.3-20070720 mysqrt(4) = 2 gcc-4.3-20070914 mysqrt(4) = 2 gcc-4.3-20081016 mysqrt(4) = 2 gcc-4.3-20081127 mysqrt(4) = 2 gcc-4.3-20090122 mysqrt(4) = 2 gcc-4.3-20090524 mysqrt(4) = 2 gcc-4.3-20090816 mysqrt(4) = 2 gcc-4.3-20100103 mysqrt(4) = 2 gcc-4.4-20081017 mysqrt(4) = 2 gcc-4.4-20081128 mysqrt(4) = 2 gcc-4.4-20090123 mysqrt(4) = 2 gcc-4.4-20090526 mysqrt(4) = 2 gcc-4.4-20090818 mysqrt(4) = 2 gcc-4.4-20090908 mysqrt(4) = 2 gcc-4.4-20100105 mysqrt(4) = 2 gcc-4.4-20100112 mysqrt(4) = 2 gcc-4.5-20090528 mysqrt(4) = 2 gcc-4.5-20090820 mysqrt(4) = 2 gcc-4.5-20090903 mysqrt(4) = 2 gcc-4.5-20091008 mysqrt(4) = 0 gcc-4.5-20100107 mysqrt(4) = 0 gcc-4.6-20100416 mysqrt(4) = 0 ***/ #include stdio.h #include stdlib.h double mysqrt(double x) { double result; __asm__ __volatile__(sqrtsd %0, %1 : =x (result) : x (x)); /* use AMD64 SSE2 instruction */ return (result); } int main(void) { double x, y; x = 4.0; y = mysqrt(x); (void)printf(mysqrt(%g) = %.17g\n, x, y); return (EXIT_SUCCESS); } -- Summary: Erroneous expansion of __asm__() directive Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: beebe at math dot utah dot edu GCC build triplet: x86_64-unknown-linux-gnu GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: x86_64-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43782
[Bug c/43730] New: internal compiler error: in expand_builtin_interclass_mathfn, at builtins.c:2313
Compilation of this test file with versions of gcc-4.5 dated 20090528 to 20100107 produce a fatal internal compiler error; comparable versions of gcc-4.3 and gcc-4.4 do not have this problem: % cat bug003.c extern int (isinfl)(long double); int bugfun(long double x, long double y) { int result; if (isinfl(x)) result = isinfl(y); else { int kx, ky; kx = ky = 1; result = (kx == ky); } return (result); } % gcc-4.5-20100107 -g -c bug003.c bug003.c: In function 'bugfun': bug003.c:9:9: internal compiler error: in expand_builtin_interclass_mathfn, at builtins.c:2313 Please submit a full bug report, with preprocessed source if appropriate. See http://gcc.gnu.org/bugs.html for instructions. A test with gcc-4.5-20090528 on IA-32 (triplets i686-pc-linux-gnu) produces a similar report: % gcc-4.5-20090528 -g -c bug003.c bug003.c: In function 'bugfun': bug003.c:9: internal compiler error: in expand_builtin_interclass_mathfn, at builtins.c:2297 -- Summary: internal compiler error: in expand_builtin_interclass_mathfn, at builtins.c:2313 Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: beebe at math dot utah dot edu GCC build triplet: x86_64-unknown-linux-gnu GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: x86_64-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43730
[Bug c/31385] New: gcc fails to find spill register for decimal arithmetic
In compilation of a large library of code for decimal floating-point arithmetic, I found that compilations with -g would succeed, but most would fail with -O1, -O2, or -O3 on IA-32. I've taken a single example and chopped away extraneous code to produce a standalone file that exhibits the compiler error: % cat bug002.c typedef _Decimal32 fp_t; extern fp_t g(fp_t); fp_t bug(fp_t x) { fp_t result; int n; fp_t f, f3, y, z; n = 0; y = 1.DF; f = g(x); if (f 0.DF) f = -f; f3 = 2.DF; z = (y + y + f / (y * y)); y = (z + z) / (9.DF) + f3 / (z * z); result = y; return (result); } % gcc --version gcc (GCC) 4.3.0 20070316 (experimental) % gcc -c -O1 bug002.c bug002.c: In function 'bug': bug002.c:27: error: unable to find a register to spill in class 'GENERAL_REGS' bug002.c:27: error: this is the insn: (insn 25 24 26 3 (set (subreg:SI (reg/v:SD 59 [ f ]) 0) (plus:SI (subreg:SI (reg/v:SD 59 [ f ]) 0) (const_int -2147483648 [0x8000]))) 144 {*lea_1} (nil) (nil)) bug002.c:27: internal compiler error: in spill_failure, at reload1.c:1944 -- Summary: gcc fails to find spill register for decimal arithmetic Product: gcc Version: 4.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: beebe at math dot utah dot edu GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: i686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31385
[Bug c/31321] New: gcc fails to compile simple long double initializers
gcc-4.3-20070316 and gcc-4.2-20070307 both fail to compile this one-line file on Mac OS X 10.4.9 (up to current Apple patch levels): % cat foo.c static const long double X = (27.0L) / (35.0L); % gcc-4.3-20070316 -c foo.c foo.c:1: error: initializer element is not constant If the divisor is changed to 32.0L, it compiles, as does any similar statement where the right-hand side can be evaluated exactly. The compilers were built like this: nice time env LDFLAGS=-L/usr/local/lib \ ../gcc-4.3-20070316/configure \ --enable-decimal-float \ --enable-languages=c,c++ \ --with-gmp=/usr/local \ --with-mpfr=/usr/local nice time make bootstrap Similar code with float and double initializers compiles without problems. -- Summary: gcc fails to compile simple long double initializers Product: gcc Version: 4.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: beebe at math dot utah dot edu GCC build triplet: powerpc-apple-darwin8.9.0 GCC host triplet: powerpc-apple-darwin8.9.0 GCC target triplet: powerpc-apple-darwin8.9.0 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31321
[Bug c/30992] New: Scaling error in decimal floating-point arithmetic blows conversions to integers
The function DFP_TO_INT() in gcc/config/dfp-bit.c has the job of converting decimal floating point values to integers. It does this by calling the decNumberFromString() function from the IBM decnumber library, but with an incorrect argument. Fortunately, the patch is just one character: % diff -c gcc-4.3-20070209/gcc/config/dfp-bit.c /local/build/gcc/gcc-4.3-20070209/gcc/config *** gcc-4.3-20070209/gcc/config/dfp-bit.c Mon Jan 29 16:01:35 2007 --- /local/build/gcc/gcc-4.3-20070209/gcc/config/dfp-bit.c Thu Feb 15 12:41:12 2007 *** *** 450,456 /* Rescale if the exponent is less than zero. */ decNumberToIntegralValue (n2, n1, context); /* Get a value to use for the quantize call. */ ! decNumberFromString (qval, (char *) 1.0, context); /* Force the exponent to zero. */ decNumberQuantize (n1, n2, qval, context); /* Get a string, which at this point will not include an exponent. */ --- 450,456 /* Rescale if the exponent is less than zero. */ decNumberToIntegralValue (n2, n1, context); /* Get a value to use for the quantize call. */ ! decNumberFromString (qval, (char *) 1., context); /* Force the exponent to zero. */ decNumberQuantize (n1, n2, qval, context); /* Get a string, which at this point will not include an exponent. */ Without this patch, the range of numbers that can be correctly converted to integers is sharply reduced: most conversions of large values are wrong. For example, the value x = 1048576.0DF is exactly representable as a _Decimal32 value and as a 32-bit int, but the bad code converts it to an int value of 2147483647, and a long int value of 9223372036854775807. With the patch, integer conversions are now correct for all floating-point values for which exact integer counterparts exist. The bug exists in all versions of dfp-bit.c in gcc-4.2 and gcc-4.3 distributions. As an aside, I now have a complete C99 library for decimal arithmetic working under gcc-4.2 and gcc-4.3 on AMD64, thanks to the prototype support for decimal arithmetic in gcc. I look forward to the decimal support working on other platforms. -- Summary: Scaling error in decimal floating-point arithmetic blows conversions to integers Product: gcc Version: 4.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: beebe at math dot utah dot edu GCC build triplet: x86_64-unknown-linux-gnu GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: x86_64-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30992
[Bug c/30013] New: Multiple flaws in decimal floating-point arithmetic conversions fixed
)(_Decimal128)(%.21Lg) = %.21Lg = %La\n, x, (long double)y, (long double)y); (void)printf(\n); y = (long double)(float)(_Decimal32)x; (void)printf( (long double)(float)(_Decimal32)(%.21Lg) = %.21Lg = %La\n, x, y, y); y = (long double)(float)(_Decimal64)x; (void)printf( (long double)(float)(_Decimal64)(%.21Lg) = %.21Lg = %La\n, x, y, y); y = (long double)(float)(_Decimal128)x; (void)printf((long double)(float)(_Decimal128)(%.21Lg) = %.21Lg = %La\n, x, y, y); (void)printf(\n); y = (long double)(double)(_Decimal32)x; (void)printf( (long double)(double)(_Decimal32)(%.21Lg) = %.21Lg = %La\n, x, y, y); y = (long double)(double)(_Decimal64)x; (void)printf( (long double)(double)(_Decimal64)(%.21Lg) = %.21Lg = %La\n, x, y, y); y = (long double)(double)(_Decimal128)x; (void)printf((long double)(double)(_Decimal128)(%.21Lg) = %.21Lg = %La\n, x, y, y); (void)printf(\n); y = (long double)(_Decimal32)x; (void)printf( (long double)(_Decimal32)(%.21Lg) = %.21Lg = %La\n, x, y, y); y = (long double)(_Decimal64)x; (void)printf( (long double)(_Decimal64)(%.21Lg) = %.21Lg = %La\n, x, y, y); y = (long double)(_Decimal128)x; (void)printf((long double)(_Decimal128)(%.21Lg) = %.21Lg = %La\n, x, y, y); } int main(int argc, char* argv[]) { test(3.141592653589793238462643383279502884L); return (EXIT_SUCCESS); } -- Summary: Multiple flaws in decimal floating-point arithmetic conversions fixed Product: gcc Version: 4.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: beebe at math dot utah dot edu GCC build triplet: x86_64-unknown-linux-gnu GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: x86_64-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30013