LoongArch: Use bstrins for "value & (-1u << const)"

A move/bstrins pair is as fast as a (addi.w|lu12i.w|lu32i.d|lu52i.d)/and
pair, and twice fast as a srli/slli pair.  When the src reg and the dst
reg happens to be the same, the move instruction can be optimized away.

gcc/ChangeLog:

	* config/loongarch/predicates.md (high_bitmask_operand): New
	predicate.
	* config/loongarch/constraints.md (Yy): New constriant.
	* config/loongarch/loongarch.md (and<mode>3_align): New
	define_insn_and_split.

gcc/testsuite/ChangeLog:

	* gcc.target/loongarch/bstrins-1.c: New test.
	* gcc.target/loongarch/bstrins-2.c: New test.
This commit is contained in:
Xi Ruoyao
2024-06-09 14:43:48 +08:00
parent 53c703888e
commit d0da347a1d
5 changed files with 49 additions and 0 deletions

View File

@@ -94,6 +94,7 @@
;; "A constant @code{move_operand} that can be safely loaded using
;; @code{la}."
;; "Yx"
;; "Yy"
;; "Z" -
;; "ZC"
;; "A memory operand whose address is formed by a base register and offset
@@ -291,6 +292,10 @@
"@internal"
(match_operand 0 "low_bitmask_operand"))
(define_constraint "Yy"
"@internal"
(match_operand 0 "high_bitmask_operand"))
(define_constraint "YI"
"@internal
A replicated vector const in which the replicated value is in the range

View File

@@ -1542,6 +1542,23 @@
[(set_attr "move_type" "pick_ins")
(set_attr "mode" "<MODE>")])
(define_insn_and_split "and<mode>3_align"
[(set (match_operand:GPR 0 "register_operand" "=r")
(and:GPR (match_operand:GPR 1 "register_operand" "r")
(match_operand:GPR 2 "high_bitmask_operand" "Yy")))]
""
"#"
""
[(set (match_dup 0) (match_dup 1))
(set (zero_extract:GPR (match_dup 0) (match_dup 2) (const_int 0))
(const_int 0))]
{
int len;
len = low_bitmask_len (<MODE>mode, ~INTVAL (operands[2]));
operands[2] = GEN_INT (len);
})
(define_insn_and_split "*bstrins_<mode>_for_mask"
[(set (match_operand:GPR 0 "register_operand" "=r")
(and:GPR (match_operand:GPR 1 "register_operand" "r")

View File

@@ -293,6 +293,10 @@
(and (match_code "const_int")
(match_test "low_bitmask_len (mode, INTVAL (op)) > 12")))
(define_predicate "high_bitmask_operand"
(and (match_code "const_int")
(match_test "low_bitmask_len (mode, ~INTVAL (op)) > 0")))
(define_predicate "d_operand"
(and (match_code "reg")
(match_test "GP_REG_P (REGNO (op))")))

View File

@@ -0,0 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
/* { dg-final { scan-assembler "bstrins\\.d\t\\\$r4,\\\$r0,4,0" } } */
long
x (long a)
{
return a & -32;
}

View File

@@ -0,0 +1,14 @@
/* { dg-do compile } */
/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
/* { dg-final { scan-assembler "bstrins\\.d\t\\\$r\[0-9\]+,\\\$r0,4,0" } } */
struct aligned_buffer {
_Alignas(32) char x[1024];
};
extern int f(char *);
int g(void)
{
struct aligned_buffer buf;
return f(buf.x);
}