The aarch64 ISA specification allows a left shift amount to be applied after extension in the range of 0 to 4 (encoded in the imm3 field).
This is true for at least the following instructions: * ADD (extend register) * ADDS (extended register) * SUB (extended register) The result of this patch can be seen, when compiling the following code: uint64_t myadd(uint64_t a, uint64_t b) { return a+(((uint8_t)b)<<4); } Without the patch the following sequence will be generated: 0000000000000000 <myadd>: 0: d37c1c21 ubfiz x1, x1, #4, #8 4: 8b000020 add x0, x1, x0 8: d65f03c0 ret With the patch the ubfiz will be merged into the add instruction: 0000000000000000 <myadd>: 0: 8b211000 add x0, x0, w1, uxtb #4 4: d65f03c0 ret Tested with "make check" and no regressions found. *** gcc/ChangeLog *** 2018-xx-xx Christoph Muellner <christoph.muell...@theobroma-systems.com> Philipp Tomsich <philipp.toms...@theobroma-systems.com> * config/aarch64/aarch64.c (aarch64_uxt_size): Correct the maximum shift amount for shifted operands. *** gcc/testsuite/ChangeLog *** 2018-xx-xx Christoph Muellner <christoph.muell...@theobroma-systems.com> Philipp Tomsich <philipp.toms...@theobroma-systems.com> * gcc.target/aarch64/extend.c: Adjust the testcases to cover the changed shift amount. Signed-off-by: Christoph Muellner <christoph.muell...@theobroma-systems.com> --- gcc/config/aarch64/aarch64.c | 2 +- gcc/testsuite/gcc.target/aarch64/extend.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 90bbc57..27b53f4 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -8226,7 +8226,7 @@ aarch64_output_casesi (rtx *operands) int aarch64_uxt_size (int shift, HOST_WIDE_INT mask) { - if (shift >= 0 && shift <= 3) + if (shift >= 0 && shift <= 4) { int size; for (size = 8; size <= 32; size *= 2) diff --git a/gcc/testsuite/gcc.target/aarch64/extend.c b/gcc/testsuite/gcc.target/aarch64/extend.c index f399e55..19b120d 100644 --- a/gcc/testsuite/gcc.target/aarch64/extend.c +++ b/gcc/testsuite/gcc.target/aarch64/extend.c @@ -37,6 +37,13 @@ adddi_uxtw (unsigned long long a, unsigned int i) } unsigned long long +adddi_uxtw4 (unsigned long long a, unsigned int i) +{ + /* { dg-final { scan-assembler "add\tx\[0-9\]+,.*uxtw #?4" } } */ + return a + ((unsigned long long)i << 4); +} + +unsigned long long adddi_uxtw0 (unsigned long long a, unsigned int i) { /* { dg-final { scan-assembler "add\tx\[0-9\]+,.*uxtw\n" } } */ @@ -51,6 +58,13 @@ adddi_sxtw (long long a, int i) } long long +adddi_sxtw4 (long long a, int i) +{ + /* { dg-final { scan-assembler "add\tx\[0-9\]+,.*sxtw #?4" } } */ + return a + ((long long)i << 4); +} + +long long adddi_sxtw0 (long long a, int i) { /* { dg-final { scan-assembler "add\tx\[0-9\]+,.*sxtw\n" } } */ @@ -65,6 +79,13 @@ subdi_uxtw (unsigned long long a, unsigned int i) } unsigned long long +subdi_uxtw4 (unsigned long long a, unsigned int i) +{ + /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*uxtw #?4" } } */ + return a - ((unsigned long long)i << 4); +} + +unsigned long long subdi_uxtw0 (unsigned long long a, unsigned int i) { /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*uxtw\n" } } */ @@ -79,6 +100,13 @@ subdi_sxtw (long long a, int i) } long long +subdi_sxtw4 (long long a, int i) +{ + /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*sxtw #?4" } } */ + return a - ((long long)i << 4); +} + +long long subdi_sxtw0 (long long a, int i) { /* { dg-final { scan-assembler "sub\tx\[0-9\]+,.*sxtw\n" } } */ -- 2.9.5