[PATCH] LoongArch: improve building large integers
"Ben Shi" <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
From fcc4ad1c054a0d6d1ae009cafa977c4ad547e897 Mon Sep 17 00:00:00 2001 From: Ben Shi <[email protected]> Date: Fri, 6 Feb 2026 10:39:15 +0800 Subject: [PATCH] LoongArch: improve building large integers To: Lulu Cheng <[email protected]> An ordinary 64-bit integer usually costs 4 instructions to be built. Some integers can be simplified to 3 instructions, that the upper 32-bit can be built with a single 'BSTRINS.D' instead of a pair of 'LU32I.D' and 'LU52I.D'. If these integers are in the pattern: 1. Bit-31 is one. 2. Upper 32-bit is in the pattern of '11..1100..0011..11'. gcc/ChangeLog: * config/loongarch/loongarch.cc: Add a new special case in 'loongarch_build_integer' and a new method 'METHOD_BSTRINS'. * testsuite/gcc.target/loongarch/la64/imm-load-2.c: New test. Signed-off-by: Ben Shi <[email protected]> --- gcc/config/loongarch/loongarch.cc | 30 ++++++++++++++++++- .../gcc.target/loongarch/la64/imm-load-2.c | 11 +++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/loongarch/la64/imm-load-2.c diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 0831da018ff..57e4dd09849 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -152,7 +152,8 @@ enum loongarch_load_imm_method METHOD_NORMAL, METHOD_LU32I, METHOD_LU52I, - METHOD_MIRROR + METHOD_MIRROR, + METHOD_BSTRINS, }; struct loongarch_integer_op @@ -1640,6 +1641,24 @@ loongarch_build_integer (struct loongarch_integer_op *codes, codes[cost].curr_value = value; return cost + 1; } + /* If bit-31 is one, while the upper 32-bit is in the form of + '11..1100..0011...11', use 'BSTRINS.D' instead of a pair of + 'LU32I.D' and 'LU52I.D'. */ + else if (sign31 && hival) + { + int hb = HOST_BITS_PER_WIDE_INT - clz_hwi (~value); + int lb = ctz_hwi (~hival) + 32; + gcc_assert (lb >= 0 && lb < hb); + /* Skip if leading bits are zeros, since a single 'LU32I.D' or + 'LU52I.D' can be emitted for the upper 32-bit. */ + if (hb < HOST_BITS_PER_WIDE_INT && hb - lb == popcount_hwi (~hival)) + { + codes[cost].method = METHOD_BSTRINS; + codes[cost].value = (hb << 16) | lb; + codes[cost].curr_value = value; + return cost + 1; + } + } codes[cost].method = METHOD_LU32I; codes[cost].value = (value & LU32I_B) | (sign51 ? LU52I_B : 0); @@ -3663,6 +3682,15 @@ loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value) gcc_assert (mode == DImode); emit_insn (gen_insvdi (x, GEN_INT (32), GEN_INT (32), x)); break; + case METHOD_BSTRINS: + { + gcc_assert (mode == DImode); + unsigned HOST_WIDE_INT one = 1; + int lb = codes[i].value & 0xffff; + int hb = codes[i].value >> 16; + x = gen_rtx_AND (DImode, x, GEN_INT (~((one << hb) - (one << lb)))); + break; + } default: gcc_unreachable (); } diff --git a/gcc/testsuite/gcc.target/loongarch/la64/imm-load-2.c b/gcc/testsuite/gcc.target/loongarch/la64/imm-load-2.c new file mode 100644 index 00000000000..356eb43f229 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/la64/imm-load-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O2 -fdump-rtl-split1" } */ +/* { dg-final { scan-assembler-not "test:.*>>.*test" } } */ + +long int +test (void) +{ + return 0xfe0003ffaaaaccccl; +} +/* { dg-final { scan-rtl-dump-times "scanning new insn with uid" 3 "split1" } } */ + -- 2.39.3</[email protected]></[email protected]></[email protected]>