diff options
author | Sinan <sinan.lin@linux.alibaba.com> | 2022-11-28 12:41:17 -0700 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro.com> | 2022-11-28 12:43:20 -0700 |
commit | 940d5b56990fdf171f49517ae102673817b9c869 (patch) | |
tree | 07b9435ef1f585358c1e8f4574ec2cd0c8757aaf /gcc | |
parent | 868fc62791b6b0f10484cc6fa15f81911418e605 (diff) | |
download | gcc-940d5b56990fdf171f49517ae102673817b9c869.zip gcc-940d5b56990fdf171f49517ae102673817b9c869.tar.gz gcc-940d5b56990fdf171f49517ae102673817b9c869.tar.bz2 |
riscv: improve cost model for loading 64bit constant in rv32
The motivation of this patch is to correct the wrong estimation of the number of instructions needed for loading a 64bit constant in rv32 in the current cost model(riscv_interger_cost). According to the current implementation, if a constant requires more than 3 instructions(riscv_const_insn and riscv_legitimate_constant_p), then the constant will be put into constant pool when expanding gimple to rtl(legitimate_constant_p hook and emit_move_insn). So the inaccurate cost model leads to the suboptimal codegen in rv32 and the wrong estimation part could be corrected through this fix.
e.g. the current codegen for loading 0x839290001 in rv32
lui a5,%hi(.LC0)
lw a0,%lo(.LC0)(a5)
lw a1,%lo(.LC0+4)(a5)
.LC0:
.word 958988289
.word 8
output after this patch
li a0,958988288
addi a0,a0,1
li a1,8
gcc/ChangeLog:
* config/riscv/riscv.cc (riscv_build_integer): Improve some cases
of loading 64bit constants for rv32.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/rv32-load-64bit-constant.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/riscv/riscv.cc | 24 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/rv32-load-64bit-constant.c | 40 |
2 files changed, 64 insertions, 0 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index ab02a81..05bdba5 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -625,6 +625,30 @@ riscv_build_integer (struct riscv_integer_op *codes, HOST_WIDE_INT value, } } + if (!TARGET_64BIT + && (value > INT32_MAX || value < INT32_MIN)) + { + unsigned HOST_WIDE_INT loval = sext_hwi (value, 32); + unsigned HOST_WIDE_INT hival = sext_hwi ((value - loval) >> 32, 32); + struct riscv_integer_op alt_codes[RISCV_MAX_INTEGER_OPS]; + struct riscv_integer_op hicode[RISCV_MAX_INTEGER_OPS]; + int hi_cost, lo_cost; + + hi_cost = riscv_build_integer_1 (hicode, hival, mode); + if (hi_cost < cost) + { + lo_cost = riscv_build_integer_1 (alt_codes, loval, mode); + if (lo_cost + hi_cost < cost) + { + memcpy (codes, alt_codes, + lo_cost * sizeof (struct riscv_integer_op)); + memcpy (codes + lo_cost, hicode, + hi_cost * sizeof (struct riscv_integer_op)); + cost = lo_cost + hi_cost; + } + } + } + return cost; } diff --git a/gcc/testsuite/gcc.target/riscv/rv32-load-64bit-constant.c b/gcc/testsuite/gcc.target/riscv/rv32-load-64bit-constant.c new file mode 100644 index 0000000..954e1dd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rv32-load-64bit-constant.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32im -mabi=ilp32" } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } } */ + + +/* This test only applies to RV32. Some of 64bit constants in this test will be put +into the constant pool in RV64, since RV64 might need one extra instruction to load +64bit constant. */ + +unsigned long long +rv32_mov_64bit_int1 (void) +{ + return 0x739290001LL; +} + +unsigned long long +rv32_mov_64bit_int2 (void) +{ + return 0x839290001LL; +} + +unsigned long long +rv32_mov_64bit_int3 (void) +{ + return 0x3929000139290000LL; +} + +unsigned long long +rv32_mov_64bit_int4 (void) +{ + return 0x3929001139290000LL; +} + +unsigned long long +rv32_mov_64bit_int5 (void) +{ + return 0x14736def39290000LL; +} + +/* { dg-final { scan-assembler-not "lw\t" } } */ |