why GCC does implicit promotion to unsigned char?
Hi, Consider code: char A; char B; char sum_A_B ( void ) { char sum = A + B; return sum; } Compile it on any backend (for example x86): gcc (SUSE Linux) 4.5.0 20100604 [gcc-4_5-branch revision 160292] gcc -m32 -O2 -S repro.c -fdump-tree-all-lineno-details Now look at repro.c.004t.gimple: sum_A_B () [repro.c : 5:1] { char A.0; unsigned char A.1; char B.2; unsigned char B.3; unsigned char D.1990; char D.1991; char sum; [repro.c : 6:8] A.0 = A; [repro.c : 6:8] A.1 = (unsigned char) A.0; [repro.c : 6:8] B.2 = B; [repro.c : 6:8] B.3 = (unsigned char) B.2; [repro.c : 6:8] D.1990 = A.1 + B.3; [repro.c : 6:8] sum = (char) D.1990; [repro.c : 8:3] D.1991 = sum; [repro.c : 8:3] return D.1991; } It looks really weird. Why gcc promotes char to unsigned char internally? This case is simple repro, but in my production code it is a reason of productivity overhead (vectorizer fails on such promotions). Thanks in advance for any responses. Previous discussion about inline assembler was really helpful. --- With best regards, Konstantin
Re: why GCC does implicit promotion to unsigned char?
Konstantin Vladimirov writes: > It looks really weird. Why gcc promotes char to unsigned char internally? Hmm, maybe not useful, but if you used "unsigned char" as the variable types or the -funsigned-char command-line option, it won't ('cause the variables will already be unsigned)... -miles -- Politics, n. A strife of interests masquerading as a contest of principles. The conduct of public affairs for private advantage.
Re: why GCC does implicit promotion to unsigned char?
On Thu, Jan 26, 2012 at 02:27:45PM +0400, Konstantin Vladimirov wrote: > Consider code: > > char A; > char B; > > char sum_A_B ( void ) > { > char sum = A + B; > > return sum; > } > [repro.c : 6:8] A.0 = A; > [repro.c : 6:8] A.1 = (unsigned char) A.0; > [repro.c : 6:8] B.2 = B; > [repro.c : 6:8] B.3 = (unsigned char) B.2; > [repro.c : 6:8] D.1990 = A.1 + B.3; > [repro.c : 6:8] sum = (char) D.1990; > [repro.c : 8:3] D.1991 = sum; > [repro.c : 8:3] return D.1991; > } > > It looks really weird. Why gcc promotes char to unsigned char internally? To avoid triggering undefined behavior. A + B in C for char A and B is (int) A + (int) B, so either we'd have to promote it to int and then demote, or we just cast it to unsigned and do the addition in 8-bit. If we don't do that, e.g. for A = 127 and B = 127 we'd trigger undefined behavior of signed addition. In unsigned char 127 + 127 is valid. Jakub
Re: why GCC does implicit promotion to unsigned char?
Hi, If I know what I am doing, and my code itself guarantees, that there will be no overflows and UB here, can I switch off this signed char to unsigned char expansion in favor of signed char to signed int expansion? --- With best regards, Konstantin On Thu, Jan 26, 2012 at 3:04 PM, Jakub Jelinek wrote: > On Thu, Jan 26, 2012 at 02:27:45PM +0400, Konstantin Vladimirov wrote: >> Consider code: >> >> char A; >> char B; >> >> char sum_A_B ( void ) >> { >> char sum = A + B; >> >> return sum; >> } >> [repro.c : 6:8] A.0 = A; >> [repro.c : 6:8] A.1 = (unsigned char) A.0; >> [repro.c : 6:8] B.2 = B; >> [repro.c : 6:8] B.3 = (unsigned char) B.2; >> [repro.c : 6:8] D.1990 = A.1 + B.3; >> [repro.c : 6:8] sum = (char) D.1990; >> [repro.c : 8:3] D.1991 = sum; >> [repro.c : 8:3] return D.1991; >> } >> >> It looks really weird. Why gcc promotes char to unsigned char internally? > > To avoid triggering undefined behavior. > A + B in C for char A and B is (int) A + (int) B, so either we'd have to > promote it to int and then demote, or we just cast it to unsigned and do the > addition in 8-bit. If we don't do that, e.g. for > A = 127 and B = 127 we'd trigger undefined behavior of signed addition. > In unsigned char 127 + 127 is valid. > > Jakub
Re: why GCC does implicit promotion to unsigned char?
On Thu, Jan 26, 2012 at 12:53 PM, Konstantin Vladimirov wrote: > Hi, > > If I know what I am doing, and my code itself guarantees, that there > will be no overflows and UB here, can I switch off this signed char to > unsigned char expansion in favor of signed char to signed int > expansion? No, you can't. Richard. > --- > With best regards, Konstantin > > On Thu, Jan 26, 2012 at 3:04 PM, Jakub Jelinek wrote: >> On Thu, Jan 26, 2012 at 02:27:45PM +0400, Konstantin Vladimirov wrote: >>> Consider code: >>> >>> char A; >>> char B; >>> >>> char sum_A_B ( void ) >>> { >>> char sum = A + B; >>> >>> return sum; >>> } >>> [repro.c : 6:8] A.0 = A; >>> [repro.c : 6:8] A.1 = (unsigned char) A.0; >>> [repro.c : 6:8] B.2 = B; >>> [repro.c : 6:8] B.3 = (unsigned char) B.2; >>> [repro.c : 6:8] D.1990 = A.1 + B.3; >>> [repro.c : 6:8] sum = (char) D.1990; >>> [repro.c : 8:3] D.1991 = sum; >>> [repro.c : 8:3] return D.1991; >>> } >>> >>> It looks really weird. Why gcc promotes char to unsigned char internally? >> >> To avoid triggering undefined behavior. >> A + B in C for char A and B is (int) A + (int) B, so either we'd have to >> promote it to int and then demote, or we just cast it to unsigned and do the >> addition in 8-bit. If we don't do that, e.g. for >> A = 127 and B = 127 we'd trigger undefined behavior of signed addition. >> In unsigned char 127 + 127 is valid. >> >> Jakub
Re: why GCC does implicit promotion to unsigned char?
On Thu, Jan 26, 2012 at 03:53:59PM +0400, Konstantin Vladimirov wrote: > If I know what I am doing, and my code itself guarantees, that there > will be no overflows and UB here, can I switch off this signed char to > unsigned char expansion in favor of signed char to signed int > expansion? Obviously promotion to signed int, doing addition there and demoting back to char would create much worse code when vectorized. The primary problem is that your GCC is too old, retry with 4.6+. In particular you are interested in http://gcc.gnu.org/PR44284 . Current GCC vectorizes it just fine. Jakub
-mavx option
I think gcc is missing an option since -mavx controls two different things. First, the generation of VEX-encoded instructions. Second, the use of ymm registers. The latter is not always available when the former is and using VEX-encoded instructions by themselves can have an advantage. Currently, when OSXAVE is not available (use xgetbv to test etc etc) then I cannot use code which gcc generates with -mavx even though I am only interested in the VEX encoding. Could we have a -mvex option which is automatically implied in -mavx?
Re: fixed_scalar_and_varying_struct_p and varies_p
On Wed, Jan 25, 2012 at 8:20 PM, Richard Sandiford wrote: > Richard Guenther writes: >> I'd say open a missed optimization bug with the testcase and go ahead >> with both patches. > > OK, I committed the patches yesterday and I've just opened PR 52000 > for the missed optimisation. Btw, looking at the m32c code what it does is valid regardless of MEM_SCALAR_P or MEM_IN_STRUCT_P - I don't see why they should be relevant. But it needs to cater for MEM_OFFSET and MEM_ALIAS_SET at least > Richard
Re: why GCC does implicit promotion to unsigned char?
On 26/01/2012 12:53, Konstantin Vladimirov wrote: Hi, If I know what I am doing, and my code itself guarantees, that there will be no overflows and UB here, can I switch off this signed char to unsigned char expansion in favor of signed char to signed int expansion? The big question here is why you are using an unqualified "char" for arithmetic in the first place. The signedness of plain "char" varies by target (some default to signed, some to unsigned) and by compiler flags. If you want to write code that uses signed chars, use "signed char". Or even better, use type "int8_t". However, as has been pointed out, the problem is that signed arithmetic doesn't wrap - it must be turned into unsigned arithmetic to make it safe. An alternative is to tell gcc that signed arithmetic is 2's compliment and wraps, by using the "-fwrapv" flag or "int8_t char sum_A_B(void) __attribute__((optimize("wrapv")));" on the specific function. mvh., David --- With best regards, Konstantin On Thu, Jan 26, 2012 at 3:04 PM, Jakub Jelinek wrote: On Thu, Jan 26, 2012 at 02:27:45PM +0400, Konstantin Vladimirov wrote: Consider code: char A; char B; char sum_A_B ( void ) { char sum = A + B; return sum; } [repro.c : 6:8] A.0 = A; [repro.c : 6:8] A.1 = (unsigned char) A.0; [repro.c : 6:8] B.2 = B; [repro.c : 6:8] B.3 = (unsigned char) B.2; [repro.c : 6:8] D.1990 = A.1 + B.3; [repro.c : 6:8] sum = (char) D.1990; [repro.c : 8:3] D.1991 = sum; [repro.c : 8:3] return D.1991; } It looks really weird. Why gcc promotes char to unsigned char internally? To avoid triggering undefined behavior. A + B in C for char A and B is (int) A + (int) B, so either we'd have to promote it to int and then demote, or we just cast it to unsigned and do the addition in 8-bit. If we don't do that, e.g. for A = 127 and B = 127 we'd trigger undefined behavior of signed addition. In unsigned char 127 + 127 is valid. Jakub
Re: -mavx option
On Thursday 26 of January 2012 09:52:22 Ulrich Drepper wrote: > I think gcc is missing an option since -mavx controls two different > things. First, the generation of VEX-encoded instructions. Second, > the use of ymm registers. The latter is not always available when the > former is and using VEX-encoded instructions by themselves can have an > advantage. Currently, when OSXAVE is not available (use xgetbv to > test etc etc) then I cannot use code which gcc generates with -mavx > even though I am only interested in the VEX encoding. > > Could we have a -mvex option which is automatically implied in -mavx? there's a -msse2avx option. is it enough?
gcc-4.5-20120126 is now available
Snapshot gcc-4.5-20120126 is now available on ftp://gcc.gnu.org/pub/gcc/snapshots/4.5-20120126/ and on various mirrors, see http://gcc.gnu.org/mirrors.html for details. This snapshot has been generated from the GCC 4.5 SVN branch with the following options: svn://gcc.gnu.org/svn/gcc/branches/gcc-4_5-branch revision 183585 You'll find: gcc-4.5-20120126.tar.bz2 Complete GCC MD5=a3e3762590c6514f02cfa01f4876995e SHA1=636513d3ab7d2dda56386a9e63a53327ed5bc72c Diffs from 4.5-20120119 are available in the diffs/ subdirectory. When a particular snapshot is ready for public consumption the LATEST-4.5 link is updated and a message is sent to the gcc list. Please do not use a snapshot before it has been announced that way.