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