diff options
author | Guo Jie <guojie@loongson.cn> | 2023-11-23 11:04:17 +0800 |
---|---|---|
committer | Lulu Cheng <chenglulu@loongson.cn> | 2023-11-27 10:47:36 +0800 |
commit | 96577dfae97e49a052c0b4d9843fb10f89632fd9 (patch) | |
tree | 77ba052d5ad94a4bd471b931516b1b7c07742387 | |
parent | df8dfd78379c33f788535a7813f07677d53966bf (diff) | |
download | gcc-96577dfae97e49a052c0b4d9843fb10f89632fd9.zip gcc-96577dfae97e49a052c0b4d9843fb10f89632fd9.tar.gz gcc-96577dfae97e49a052c0b4d9843fb10f89632fd9.tar.bz2 |
LoongArch: Optimize the loading of immediate numbers with the same high and low 32-bit values
For the following immediate load operation in gcc/testsuite/gcc.target/loongarch/imm-load1.c:
long long r = 0x0101010101010101;
Before this patch:
lu12i.w $r15,16842752>>12
ori $r15,$r15,257
lu32i.d $r15,0x1010100000000>>32
lu52i.d $r15,$r15,0x100000000000000>>52
After this patch:
lu12i.w $r15,16842752>>12
ori $r15,$r15,257
bstrins.d $r15,$r15,63,32
gcc/ChangeLog:
* config/loongarch/loongarch.cc
(enum loongarch_load_imm_method): Add new method.
(loongarch_build_integer): Add relevant implementations for
new method.
(loongarch_move_integer): Ditto.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/imm-load1.c: Change old check.
-rw-r--r-- | gcc/config/loongarch/loongarch.cc | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/loongarch/imm-load1.c | 3 |
2 files changed, 23 insertions, 2 deletions
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 33357c6..c95fc83 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -142,12 +142,16 @@ struct loongarch_address_info METHOD_LU52I: Load 52-63 bit of the immediate number. + + METHOD_MIRROR: + Copy 0-31 bit of the immediate number to 32-63bit. */ enum loongarch_load_imm_method { METHOD_NORMAL, METHOD_LU32I, - METHOD_LU52I + METHOD_LU52I, + METHOD_MIRROR }; struct loongarch_integer_op @@ -1556,11 +1560,23 @@ loongarch_build_integer (struct loongarch_integer_op *codes, int sign31 = (value & (HOST_WIDE_INT_1U << 31)) >> 31; int sign51 = (value & (HOST_WIDE_INT_1U << 51)) >> 51; + + uint32_t hival = (uint32_t) (value >> 32); + uint32_t loval = (uint32_t) value; + /* Determine whether the upper 32 bits are sign-extended from the lower 32 bits. If it is, the instructions to load the high order can be ommitted. */ if (lu32i[sign31] && lu52i[sign31]) return cost; + /* If the lower 32 bits are the same as the upper 32 bits, just copy + the lower 32 bits to the upper 32 bits. */ + else if (loval == hival) + { + codes[cost].method = METHOD_MIRROR; + codes[cost].curr_value = value; + return cost + 1; + } /* Determine whether bits 32-51 are sign-extended from the lower 32 bits. If so, directly load 52-63 bits. */ else if (lu32i[sign31]) @@ -3234,6 +3250,10 @@ loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value) gen_rtx_AND (DImode, x, GEN_INT (0xfffffffffffff)), GEN_INT (codes[i].value)); break; + case METHOD_MIRROR: + gcc_assert (mode == DImode); + emit_insn (gen_insvdi (x, GEN_INT (32), GEN_INT (32), x)); + break; default: gcc_unreachable (); } diff --git a/gcc/testsuite/gcc.target/loongarch/imm-load1.c b/gcc/testsuite/gcc.target/loongarch/imm-load1.c index 2ff0297..f64cc29 100644 --- a/gcc/testsuite/gcc.target/loongarch/imm-load1.c +++ b/gcc/testsuite/gcc.target/loongarch/imm-load1.c @@ -1,6 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-mabi=lp64d -O2" } */ -/* { dg-final { scan-assembler "test:.*lu52i\.d.*\n\taddi\.w.*\n\.L2:" } } */ +/* { dg-final { scan-assembler-not "test:.*lu52i\.d.*\n\taddi\.w.*\n\.L2:" } } */ +/* { dg-final { scan-assembler "test:.*lu12i\.w.*\n\tbstrins\.d.*\n\.L2:" } } */ extern long long b[10]; |