On 05/02/2018 04:05 PM, Jim Wilson wrote:
> This improves the code for a switch statement on targets that sign-extend
> function arguments, such as RISC-V.  Given a simple testcase
> 
> extern void asdf(int);
> void foo(int x) {
>   switch (x) {
>   case 0: asdf(10); break;
>   case 1: asdf(11); break;
>   case 2: asdf(12); break;
>   case 3: asdf(13); break;
>   case 4: asdf(14); break;
>   }
> }
> 
> Compiled for a 64-bit target, we get for the tablejump
> 
>       li      a5,4
>       bgtu    a0,a5,.L1
>       slli    a0,a0,32
>       lui     a5,%hi(.L4)
>       addi    a5,a5,%lo(.L4)
>       srli    a0,a0,30
>       add     a0,a0,a5
>       lw      a5,0(a0)
>       jr      a5
> 
> There is some unnecessary shifting here.  a0 (x) gets shifted left by 32 then
> shifted right by 30 to zero-extend it and multiply by 4 for the table index.
> However, after the unsigned greater than branch, we know the value is between
> 0 and 4.  We also know that a 32-bit int is passed as a 64-bit sign-extended
> long for this target.  Thus we get the same exact value if we sign-extend
> instead of zero-extend, and the code is one instruction shorter.  We get a 
> slli
> by 2 instead of the slli 32/srli 30.
> 
> The following patch implements this optimization.  It checks for a range that
> does not have the sign-bit set, and an index value that is already sign
> extended, and then does a sign extend instead of an zero extend.
> 
> This has been tested with a riscv{32,64}-{elf,linux} builds and testsuite 
> runs.
> There were no regressions.  It was also tested with an x86_64-linux build and
> testsuite run.
> 
> Ok?
> 
> Jim
> 
>       gcc/
>       * expr.c (do_tablejump): When converting index to Pmode, if we have a
>       sign extended promoted subreg, and the range does not have the sign bit
>       set, then do a sign extend.
OK.

Jeff

Reply via email to