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.

---
 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(+)
 create mode 100644 gcc/testsuite/gcc.target/loongarch/mem-and-mask-opt.c

diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index 625f30ca265..d5c01b99ae9 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 34cf74d5d66..8460618b501 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 00000000000..9b3a5cdbbac
--- /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;
+}
-- 
2.38.1

Reply via email to