https://gcc.gnu.org/g:796aa9e3977bb3ba44b3f188f8de45b7b028f999
commit r16-4953-g796aa9e3977bb3ba44b3f188f8de45b7b028f999 Author: Guo Jie <[email protected]> Date: Sun Nov 2 11:32:07 2025 +0800 LoongArch: Make full use of load insns with unsigned extension gcc/ChangeLog: * config/loongarch/loongarch.md (and_load_zero_extend<mode>): New combiner. * config/loongarch/predicates.md (mask_operand): New predicate. gcc/testsuite/ChangeLog: * gcc.target/loongarch/mem-and-mask-opt.c: New test. Diff: --- gcc/config/loongarch/loongarch.md | 15 ++++++++++++++ gcc/config/loongarch/predicates.md | 5 +++++ .../gcc.target/loongarch/mem-and-mask-opt.c | 23 ++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index 9371134a69db..c61abcea3eda 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -1636,6 +1636,21 @@ operands[3] = tmp; }) +(define_insn "and_load_zero_extend<mode>" + [(set (match_operand:X 0 "register_operand" "=r,r,r,r,r,r") + (and:X (match_operand:X 1 "memory_operand" "%m,m,m,k,k,k") + (match_operand:X 2 "mask_operand" "Yb,Yh,Yw,Yb,Yh,Yw")))] + "" + "@ + ld.bu\t%0,%1 + ld.hu\t%0,%1 + ld.wu\t%0,%1 + ldx.bu\t%0,%1 + ldx.hu\t%0,%1 + ldx.wu\t%0,%1" + [(set_attr "move_type" "load,load,load,load,load,load") + (set_attr "mode" "<MODE>")]) + ;; We always avoid the shift operation in bstrins_<mode>_for_ior_mask ;; if possible, but the result may be sub-optimal when one of the masks ;; is (1 << N) - 1 and one of the src register is the dest register. diff --git a/gcc/config/loongarch/predicates.md b/gcc/config/loongarch/predicates.md index 34cf74d5d66e..8460618b501b 100644 --- a/gcc/config/loongarch/predicates.md +++ b/gcc/config/loongarch/predicates.md @@ -413,6 +413,11 @@ (match_operand 0 "low_bitmask_operand") (match_operand 0 "ins_zero_bitmask_operand"))) +(define_predicate "mask_operand" + (ior (match_operand 0 "qi_mask_operand") + (match_operand 0 "hi_mask_operand") + (match_operand 0 "si_mask_operand"))) + (define_predicate "const_call_insn_operand" (match_code "const,symbol_ref,label_ref") { diff --git a/gcc/testsuite/gcc.target/loongarch/mem-and-mask-opt.c b/gcc/testsuite/gcc.target/loongarch/mem-and-mask-opt.c new file mode 100644 index 000000000000..9b3a5cdbbac6 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/mem-and-mask-opt.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ +/* { dg-final { scan-assembler-not "bstrpick" } } */ +/* { dg-final { scan-assembler "ld\\.wu" } } */ + +struct st +{ + char const *name; +}; +struct fst +{ + struct st *groups; +}; + +struct fst *pfunc (int); + +const char * +test (int pc, unsigned group) +{ + struct fst *pci = pfunc (pc); + + return pci->groups[group].name; +}
