This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: RFC: Simplify rules for ctz/clz patterns and RTL
- From: Joern Rennecke <joernr at arc dot com>
- To: Zack Weinberg <zack at codesourcery dot com>
- Cc: To: gcc at gcc dot gnu dot org
- Date: Wed, 15 Aug 2007 22:52:46 +0100
- Subject: Re: RFC: Simplify rules for ctz/clz patterns and RTL
- References: <20070813153815.GD27480@elsdt-razorfish.arc.com> <46C34C06.3000103@codesourcery.com>
On Wed, Aug 15, 2007 at 11:55:02AM -0700, Zack Weinberg wrote:
> Joern Rennecke wrote:
> >The operation the nsb instruction of the SHmedia instruction set performs
> >is 'count number of sign bit copies'.
> >[...]
>
> It sounds like the SH should probably be lumped in with the x86 as not
> doing "canonical behavior". Conveniently enough for my grand plan, it
> already uses an UNSPEC for the actual instruction :-)
>
> What is the result of the instruction for (64-bit) all-bits-zero or
> all-bits-one? 64?
No, it is 63. There is one essential sign bit and 63 more copies.
> Assuming so, it occurs to me that the result of an
> unsigned clz() on any negative 64-bit value will be zero; thus, you
> could get a "canonical" clz out of nsb by doing (pseudo-assembly)
>
> mov result, 0
> cmp/pz arg
> bf 1f
> nsb result, arg
> 1:
We are talking about SHmedia code here. cmp/pz and bf are not SHmedia
instructions. Loading a zero into result would be movi 0,result .
If you want to special-case the negative input, that would be:
shari arg,31,tmp
nsb arg,result
cmvne tmp,tmp,result
addi result,1,result
> Similarly, the x & (x-1) operation
It's x ^ (x-1) (xor) or x &~(x-1) (andc)
> used to set up for ctz/ffs in terms
> of clz will leave the high bit set *only* for x == 0x8000 0000 0000
> 0000; which can be tested for as x == (x&(x-1)) and the nsb skipped.
>
> Would these sequences be slower than the current logic?
currently we have for ffs:
addi arg,-1,tmp
xor arg,tmp,tmp
shlri tmp,1,tmp
nsb tmp,tmp
addi tmp,-64,tmp
cmveq arg,r63,tmp
sub r63,tmp,result
Using the above sequence, we get the more register-hungry:
addi arg,-1,tmp
xor arg,tmp,tmp
shari tmp,31,tmp2
nsb tmp,tmp
cmvne tmp2,tmp2,tmp
addi tmp,1-64,tmp
sub r63,tmp,result
you propose:
pt after_nsb,trtmp
addi arg,-1,tmp
andc arg,tmp,tmp
movi -1,tmp2
beq arg,tmp,trtmp
nsb tmp,tmp2
after_nsb:
addi tmp2,-63,tmp
sub r63,tmp,result
or is that:
pt after_nsb,trtmp
addi arg,-1,tmp
xor arg,tmp,tmp
bgt r63,tmp,trtmp
nsb tmp,tmp
after_nsb:
addi tmp,-63,tmp
sub r63,tmp,result
At any rate, the introduction of the branch makes the code worse.
But for the ARC, it would make an interesting shortcut. Although norm can't
be conditionalized, we can use the -1 from the xor to save on a long
immediate for 32 bit ffs.
sub_s tmp,arg,1
xor.f tmp,tmp,arg ; for -Os this can be xor_s and
norm result,tmp ; then norm.f produces the flag.
mov.mi result,tmp
rsub result,31,result
> >The ARC700 has a NORM instruction, which again counts the number of
> >sign bit copies. There is a variant NORM.F which sets the N flag if the
> >input is negative.
>
> Sorry, I don't recognize the ARC700 - which GCC back end is that?
It belongs in config/arc ; however, proper ARC700 support is not in the
FSF mainline yet.
We are working on it.
> It
> might be worth teaching optabs.c about sign-bit-count operations, but
> only if we have more than one architecture that can use it.
The NORM instruction is also available as an optional extension operation
for ARCtangent-A5 and ARC600.