Welcome, Guest. Please login or register.

Author Topic: GCC asm() warning suppression options?  (Read 19982 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline Trev

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 1550
  • Country: 00
    • Show only replies by Trev
Re: GCC asm() warning suppression options?
« Reply #29 on: June 28, 2009, 07:41:24 PM »
Quote from: Karlos;513702

That said, I've gone back to the single function(s) and just made it handle all values of N:


I think your solution is best anyway, as values equivalent to 0 and 16 won't be reduced by the specialized templates, and you won't get the expected result.

I also think your idea of letting N < 0 (if signed inputs are allowed) and N > 31 fail at compile time is a good idea if you're worried about source typos.

For fun, though, I still think a general purpose rotation template is a cool idea. ;-) It's too bad C++ won't let you create custom operators without using macros or some other magic. You could throw in <<<, >>>, ^<<, ^>>, or whatever you want. Actually, would it be that difficult to add those to gcc? I don't know. Nothing wrong with non-standard extensions as long as they're well documented.
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16878
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: GCC asm() warning suppression options?
« Reply #30 on: June 28, 2009, 07:41:46 PM »
IIRC, d0-d7 and a0-a7 are understood as register specifications for M68K backend with asm(). I'll see if "d 0" works.

To be fair, I can live with the warning as it always seems to generate the correct code. It was just a bit annoying.
int p; // A
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16878
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: GCC asm() warning suppression options?
« Reply #31 on: June 28, 2009, 07:50:41 PM »
Quote from: Trev;513751
I think your solution is best anyway, as values equivalent to 0 and 16 won't be reduced by the specialized templates, and you won't get the expected result.

I also think your idea of letting N < 0 (if signed inputs are allowed) and N > 31 fail at compile time is a good idea if you're worried about source typos.


Actually, the revised version essentially treats everything as modulo . I could remove it :)

Quote
For fun, though, I still think a general purpose rotation template is a cool idea. ;-)


Feel free to use the code for inspiration :lol: It wouldn't be difficult to make it take a signed shift. Don't forget to throw in a dynamic version (for variable shifts too), though here checking for the sign of the shift exposes the runtime weakness in the plan. The check would probably take more cycles than the operation performed.

Quote
It's too bad C++ won't let you create custom operators without using macros or some other magic. You could throw in <<<, >>>, ^<<, ^>>, or whatever you want. Actually, would it be that difficult to add those to gcc? I don't know. Nothing wrong with non-standard extensions as long as they're well documented.


Well, inventing new operators has a lot of hidden traps. You only have to look at the post/pre increment/decrement operators to see how gnarly that could get.

The thing is, rotate is a commonly supported CPU operation. I can't see why C wouldn't have an operator for it originally.
int p; // A
 

Offline Trev

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 1550
  • Country: 00
    • Show only replies by Trev
Re: GCC asm() warning suppression options?
« Reply #32 on: June 28, 2009, 09:52:28 PM »
Looking at Microsoft's implementation, 8-bit and 16-bit rotations are intrinsics, and 32-bit and 64-bit rotations are functions. The functions are implemented using the traditional bitwise shift and bitwise or combination.

16-bit rotations are actually implemented using 32-bit registers, but the result is truncated:

x86
Code: [Select]
   volatile unsigned char a    = _rotl8(1, 1);
013213DE  mov         al,1
013213E0  rol         al,1
013213E2  mov         byte ptr [a],al
    volatile unsigned short b   = _rotl16(1, 1);
013213E5  mov         eax,1
013213EA  rol         ax,1
013213ED  mov         word ptr [b],ax
    volatile unsigned c         = _rotl(1, 1);
013213F1  push        1    
013213F3  push        1    
013213F5  call        @ILT+155(__rotl) (13210A0h)
013213FA  add         esp,8
013213FD  mov         dword ptr [c],eax
    volatile unsigned long d    = _lrotl(1, 1);
01321400  push        1    
01321402  push        1    
01321404  call        @ILT+65(__lrotl) (1321046h)
01321409  add         esp,8
0132140C  mov         dword ptr [d],eax
    volatile unsigned __int64 e = _rotl64(1, 1);
0132140F  push        1    
01321411  push        0    
01321413  push        1    
01321415  call        @ILT+280(__rotl64) (132111Dh)
0132141A  add         esp,0Ch
0132141D  mov         dword ptr [e],eax
01321420  mov         dword ptr [ebp-38h],edx

x64
Code: [Select]
   volatile unsigned char a    = _rotl8(1, 1);
000000013FBF102A  mov         al,1
000000013FBF102C  rol         al,1
000000013FBF102E  mov         byte ptr [a],al
    volatile unsigned short b   = _rotl16(1, 1);
000000013FBF1032  mov         ax,1
000000013FBF1036  rol         ax,1
000000013FBF1039  mov         word ptr [b],ax
    volatile unsigned c         = _rotl(1, 1);
000000013FBF103E  mov         edx,1
000000013FBF1043  mov         ecx,1
000000013FBF1048  call        _rotl (13FBF10A8h)
000000013FBF104D  mov         dword ptr [c],eax
    volatile unsigned long d    = _lrotl(1, 1);
000000013FBF1051  mov         edx,1
000000013FBF1056  mov         ecx,1
000000013FBF105B  call        _lrotl (13FBF10A2h)
000000013FBF1060  mov         dword ptr [d],eax
    volatile unsigned __int64 e = _rotl64(1, 1);
000000013FBF1064  mov         edx,1
000000013FBF1069  mov         ecx,1
000000013FBF106E  call        _rotl64 (13FBF109Ch)
000000013FBF1073  mov         qword ptr [e],rax

The good news--for Visual C++, anyway--is that the shift-or combination is correctly optimized into a rotate. Microsoft reduces with N&31 as well:

Code: [Select]
___rotl PROC ; COMDAT

; 8    :     shift &= 0x1f;
; 9    :     val = (val>>(0x20 - shift)) | (val << shift);

  00000 b8 01 00 00 00 mov eax, 1
  00005 d1 c0 rol eax, 1

; 10   :     return val;
; 11   : }

  00007 c3 ret 0
___rotl ENDP

Anyhow, just food for thought. I know GCC's m68k optimizer needs work, even in current versions.
« Last Edit: June 28, 2009, 10:05:42 PM by Trev »
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16878
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: GCC asm() warning suppression options?
« Reply #33 on: June 28, 2009, 10:09:17 PM »
Thanks to the power of templated inline assembler, it doesn't matter how bad the m68k optimizer is, you've basically taken matters into your own hands :lol:

The things we do for cycles, eh?
int p; // A
 

Offline Trev

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 1550
  • Country: 00
    • Show only replies by Trev
Re: GCC asm() warning suppression options?
« Reply #34 on: June 29, 2009, 11:19:07 PM »
Quote from: Karlos;513766
Thanks to the power of templated inline assembler, it doesn't matter how bad the m68k optimizer is, you've basically taken matters into your own hands :lol:

The things we do for cycles, eh?


Too true, but our compilers should be smart enough to know a rotation when they see it. I've got a marathon gcc-4.4.0 m68k build going at home. Taking hours--on a Core i7. That's what I get for not limiting newlib and g++ to m680x0 CPUs. (Plus, shouldn't we have schnazzy parallel compilers by now? Even a loopback distcc would be nice.) So, we'll see if newer GCCs are any better at optimizing rotatations.

EDIT: Oh, I guess we have 'make -j n', but it's not very robust.
« Last Edit: June 29, 2009, 11:23:40 PM by Trev »
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16878
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: GCC asm() warning suppression options?
« Reply #35 on: June 29, 2009, 11:29:10 PM »
I use make -j=4 on my quad core and never had any problems with it :)

-edit-

Quote
So, we'll see if newer GCCs are any better at optimizing rotatations.

You're building gcc 4.4 for an m68k backend just to check this? That's hardcore :D

Blimey, time to hit the sack :-/
« Last Edit: June 29, 2009, 11:40:11 PM by Karlos »
int p; // A
 

Offline Trev

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 1550
  • Country: 00
    • Show only replies by Trev
Re: GCC asm() warning suppression options?
« Reply #36 on: June 30, 2009, 05:50:28 AM »
Quote from: Karlos;513878
You're building gcc 4.4 for an m68k backend just to check this? That's hardcore :D

Hardcore boredom, maybe. ;-) gcc 4.4.0 is definitely smarter than gcc 2.95.3:

intput:

Code: [Select]
static inline unsigned _rotl(unsigned val, int shift)
{
    shift &= 0x1f;
    val = (val>>(0x20 - shift)) | (val << shift);
    return val;
}

int main(void)
{
    volatile unsigned val = 1;
    volatile unsigned a = _rotl(val, 1);
    return 0;
}

output:

Code: [Select]
00000000
:
   0:   4e56 fff8       linkw %fp,#-8
   4:   7001            moveq #1,%d0
   6:   2d40 fffc       movel %d0,%fp@(-4)
   a:   202e fffc       movel %fp@(-4),%d0
   e:   721f            moveq #31,%d1
  [b]10:   e2b8            rorl %d1,%d0[/b]
  12:   2d40 fff8       movel %d0,%fp@(-8)
  16:   4280            clrl %d0
  18:   4e5e            unlk %fp
  1a:   4e75            rts

It's even decided that a register based rotate right is faster than an immediate rotate left, I guess. Or maybe not. I can't get it to produce a rotate left. I guess gcc isn't an ambiturner.

In this case, at least, the optimizer does OK. I don't know anything about gcc internals, but maybe the optimization occurs at the RTL level based on the capabilities of the underlying architecture. That would mean an optimization should apply regardless of the architecture, as long as the architecture supports it.

But why doesn't it rotate left? The execution times are the same for both. Correction: The execution times are the same if the bit count is the same: 8+2n for register operand, 12+2n for immediate operand. What am I missing?

I compiled with an m68k-elf target, but now the m68k-amigaos gods are calling. I know there are some gcc 4.x.x builds out there somewhere, but I haven't used one. I'd also like to see ixemul and libnix go away and be replaced with newlib or another current library.

If necessary, one could even target specific releases, e.g. m68k-*-amigaos1.2, m68k-*-amigaos2.0, m68k-*-amigaos3.0, et al. It depends on how tightly coupled the tool chain is to the target environment. The main differences from a tool chain perspective, though, should be in the hunks supported. Everything else could be handled as it is today, and newlib, crt0.s, and amiga.lib could be written to run optimally on arbitrary releases. Having that magic at compile time, though, would result in much tighter binaries.
« Last Edit: June 30, 2009, 06:10:53 AM by Trev »
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16878
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: GCC asm() warning suppression options?
« Reply #37 on: June 30, 2009, 10:13:03 AM »
Quote
It's even decided that a register based rotate right is faster than an immediate rotate left, I guess. Or maybe not. I can't get it to produce a rotate left. I guess gcc isn't an ambiturner.

Hmm, unusual. I'm pretty sure an immediate left shift of 1 place ought to be faster than a register based shift right of 31 since you spare yourself the cost of the additional move.l #31, d1. It also reduces register pressure too, which could make all the difference in real code.

Probably in the test code here there's no need for it to do that.

-edit-

Incidentally, you might want to compile that test code with -fomit-frame-pointer ;)
« Last Edit: June 30, 2009, 10:20:15 AM by Karlos »
int p; // A
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show only replies by Piru
    • http://www.iki.fi/sintonen/
Re: GCC asm() warning suppression options?
« Reply #38 on: June 30, 2009, 02:24:28 PM »
Quote from: Trev;513877
EDIT: Oh, I guess we have 'make -j n', but it's not very robust.
Code: [Select]
if [ -a /proc/cpuinfo ]; then
    export CONCURRENCY_LEVEL=$(($(grep -c processor /proc/cpuinfo) * 2 + 1))
    export MAKEOPTS=&quot;-j${CONCURRENCY_LEVEL}&quot;
fi
Why wouldn't it be robust?
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show only replies by Piru
    • http://www.iki.fi/sintonen/
Re: GCC asm() warning suppression options?
« Reply #39 on: June 30, 2009, 02:32:31 PM »
Quote from: Trev;513912
The main differences from a tool chain perspective, though, should be in the hunks supported. Everything else could be handled as it is today, and newlib, crt0.s, and amiga.lib could be written to run optimally on arbitrary releases. Having that magic at compile time, though, would result in much tighter binaries.

Well, some 32bit relocs could be made 16bit, that doesn't account for much in most binaries.
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16878
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: GCC asm() warning suppression options?
« Reply #40 on: June 30, 2009, 02:34:52 PM »
Quote from: Piru;513958
Code: [Select]
if [ -a /proc/cpuinfo ]; then
    export CONCURRENCY_LEVEL=$(($(grep -c processor /proc/cpuinfo) * 2 + 1))
    export MAKEOPTS=&quot;-j${CONCURRENCY_LEVEL}&quot;
fi

Why wouldn't it be robust?


Perhaps the Makefiles are subtly flawed? There could be bits that have to be compiled before others that may not be guaranteed with concurrent jobs?

Just guessing here.
int p; // A
 

Offline Piru

  • \' union select name,pwd--
  • Hero Member
  • *****
  • Join Date: Aug 2002
  • Posts: 6946
    • Show only replies by Piru
    • http://www.iki.fi/sintonen/
Re: GCC asm() warning suppression options?
« Reply #41 on: June 30, 2009, 02:59:24 PM »
Quote from: Karlos;513961
Perhaps the Makefiles are subtly flawed? There could be bits that have to be compiled before others that may not be guaranteed with concurrent jobs?

Just guessing here.

Well that's not it. The concurrent jobs are only used for things that can be concurrent. Obviously make cannot change the order of commands being executed, that'd never work.
 

Offline Trev

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 1550
  • Country: 00
    • Show only replies by Trev
Re: GCC asm() warning suppression options?
« Reply #42 on: June 30, 2009, 04:33:14 PM »
Quote from: Piru;513963
Well that's not it. The concurrent jobs are only used for things that can be concurrent. Obviously make cannot change the order of commands being executed, that'd never work.


You have to trust that your target makefile is essentially thread-safe, i.e. all dependencies are properly documented for synchronization, no race conditions exist in similar commands used by different rules, etc.
 

Offline Trev

  • Hero Member
  • *****
  • Join Date: May 2003
  • Posts: 1550
  • Country: 00
    • Show only replies by Trev
Re: GCC asm() warning suppression options?
« Reply #43 on: June 30, 2009, 04:41:32 PM »
Quote from: Karlos;513934
Hmm, unusual. I'm pretty sure an immediate left shift of 1 place ought to be faster than a register based shift right of 31 since you spare yourself the cost of the additional move.l #31, d1. It also reduces register pressure too, which could make all the difference in real code.

Probably in the test code here there's no need for it to do that.


Yeah, I'm really not sure why, since ror.l #n,Dn and ror.l Dx,Dn execute in the same number of cycles assuming n == Dx. Barring outside influences, the only reason to use a register is for a shift >8 or <24 (>8 in the opposite direction), as you've done in your template. Right?

Quote
Incidentally, you might want to compile that test code with -fomit-frame-pointer ;)


Well, sure, but it's not actually going to run anywhere and it doesn't change the output of the test itself. :-P
 

Offline KarlosTopic starter

  • Sockologist
  • Global Moderator
  • Hero Member
  • *****
  • Join Date: Nov 2002
  • Posts: 16878
  • Country: gb
  • Thanked: 5 times
    • Show only replies by Karlos
Re: GCC asm() warning suppression options?
« Reply #44 from previous page: June 30, 2009, 04:59:04 PM »
Quote from: Trev;513971
You have to trust that your target makefile is essentially thread-safe, i.e. all dependencies are properly documented for synchronization, no race conditions exist in similar commands used by different rules, etc.

That's basically what I was trying to suggest. I've not built anything as large as gcc and the toolchain with multiple concurrent jobs, but I can imagine concurrency issues can exist.

-edit-

Quote
Yeah, I'm really not sure why, since ror.l #n,Dn and ror.l Dx,Dn execute in the same number of cycles assuming n == Dx. Barring outside influences, the only reason to use a register is for a shift >8 or <24 (>8 in the opposite direction), as you've done in your template. Right?

Well, you could probably do it with two successive rotates, but I figured that the register method might be better than a pair of rotates. Having said that, I didn't test the latter. You'd swap a move for a rotate but you'd gain a free register overall.

I'll have to look into that.
« Last Edit: June 30, 2009, 05:02:21 PM by Karlos »
int p; // A