Skip to content

Commit

Permalink
xtensa: Optimize '(x & CST1_POW2) != 0 ? CST2_POW2 : 0'
Browse files Browse the repository at this point in the history
This patch decreses one machine instruction from "single bit extraction
with shifting" operation, and tries to eliminate the conditional
branch if CST2_POW2 doesn't fit into signed 12 bits with the help
of ifcvt optimization.

    /* example #1 */
    int test0(int x) {
      return (x & 1048576) != 0 ? 1024 : 0;
    }
    extern int foo(void);
    int test1(void) {
      return (foo() & 1048576) != 0 ? 16777216 : 0;
    }

    ;; before
    test0:
	movi	a9, 0x400
	srai	a2, a2, 10
	and	a2, a2, a9
	ret.n
    test1:
	addi	sp, sp, -16
	s32i.n	a0, sp, 12
	call0	foo
	extui	a2, a2, 20, 1
	slli	a2, a2, 20
	beqz.n	a2, .L2
	movi.n	a2, 1
	slli	a2, a2, 24
    .L2:
	l32i.n	a0, sp, 12
	addi	sp, sp, 16
	ret.n

    ;; after
    test0:
	extui	a2, a2, 20, 1
	slli	a2, a2, 10
	ret.n
    test1:
	addi	sp, sp, -16
	s32i.n	a0, sp, 12
	call0	foo
	l32i.n	a0, sp, 12
	extui	a2, a2, 20, 1
	slli	a2, a2, 24
	addi	sp, sp, 16
	ret.n

In addition, if the left shift amount ('exact_log2(CST2_POW2)') is
between 1 through 3 and a either addition or subtraction with another
register follows, emit a ADDX[248] or SUBX[248] machine instruction
instead of separate left shift and add/subtract ones.

    /* example #2 */
    int test2(int x, int y) {
      return ((x & 1048576) != 0 ? 4 : 0) + y;
    }
    int test3(int x, int y) {
      return ((x & 2) != 0 ? 8 : 0) - y;
    }

    ;; before
    test2:
	movi.n	a9, 4
	srai	a2, a2, 18
	and	a2, a2, a9
	add.n	a2, a2, a3
	ret.n
    test3:
	movi.n	a9, 8
	slli	a2, a2, 2
	and	a2, a2, a9
	sub	a2, a2, a3
	ret.n

    ;; after
    test2:
	extui	a2, a2, 20, 1
	addx4	a2, a2, a3
	ret.n
    test3:
	extui	a2, a2, 1, 1
	subx8	a2, a2, a3
	ret.n

gcc/ChangeLog:

	* config/xtensa/predicates.md (addsub_operator): New.
	* config/xtensa/xtensa.md (*extzvsi-1bit_ashlsi3,
	*extzvsi-1bit_addsubx): New insn_and_split patterns.
	* config/xtensa/xtensa.cc (xtensa_rtx_costs):
	Add a special case about ifcvt 'noce_try_cmove()' to handle
	constant loads that do not fit into signed 12 bits in the
	patterns added above.
  • Loading branch information
jjsuwa-sys3175 authored and jcmvbkbc committed May 23, 2023
1 parent b6b8870 commit e33d2dc
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
3 changes: 3 additions & 0 deletions gcc/config/xtensa/predicates.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@
(define_predicate "logical_shift_operator"
(match_code "ashift,lshiftrt"))

(define_predicate "addsub_operator"
(match_code "plus,minus"))

(define_predicate "xtensa_cstoresi_operator"
(match_code "eq,ne,gt,ge,lt,le"))

Expand Down
3 changes: 2 additions & 1 deletion gcc/config/xtensa/xtensa.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4355,7 +4355,8 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int outer_code,
switch (outer_code)
{
case SET:
if (xtensa_simm12b (INTVAL (x)))
if (xtensa_simm12b (INTVAL (x))
|| (current_pass && current_pass->tv_id == TV_IFCVT))
{
*total = speed ? COSTS_N_INSNS (1) : 0;
return true;
Expand Down
83 changes: 83 additions & 0 deletions gcc/config/xtensa/xtensa.md
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,89 @@
(set_attr "mode" "SI")
(set_attr "length" "3")])

(define_insn_and_split "*extzvsi-1bit_ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=a")
(and:SI (match_operator:SI 4 "logical_shift_operator"
[(match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")])
(match_operand:SI 3 "const_int_operand" "i")))]
"exact_log2 (INTVAL (operands[3])) > 0"
"#"
"&& 1"
[(set (match_dup 0)
(zero_extract:SI (match_dup 1)
(const_int 1)
(match_dup 2)))
(set (match_dup 0)
(ashift:SI (match_dup 0)
(match_dup 3)))]
{
int pos = INTVAL (operands[2]),
shift = floor_log2 (INTVAL (operands[3]));
switch (GET_CODE (operands[4]))
{
case ASHIFT:
pos = shift - pos;
break;
case LSHIFTRT:
pos = shift + pos;
break;
default:
gcc_unreachable ();
}
if (BITS_BIG_ENDIAN)
pos = (32 - (1 + pos)) & 0x1f;
operands[2] = GEN_INT (pos);
operands[3] = GEN_INT (shift);
}
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(set_attr "length" "6")])

(define_insn_and_split "*extzvsi-1bit_addsubx"
[(set (match_operand:SI 0 "register_operand" "=a")
(match_operator:SI 5 "addsub_operator"
[(and:SI (match_operator:SI 6 "logical_shift_operator"
[(match_operand:SI 1 "register_operand" "r")
(match_operand:SI 3 "const_int_operand" "i")])
(match_operand:SI 4 "const_int_operand" "i"))
(match_operand:SI 2 "register_operand" "r")]))]
"TARGET_ADDX
&& IN_RANGE (exact_log2 (INTVAL (operands[4])), 1, 3)"
"#"
"&& 1"
[(set (match_dup 0)
(zero_extract:SI (match_dup 1)
(const_int 1)
(match_dup 3)))
(set (match_dup 0)
(match_op_dup 5
[(ashift:SI (match_dup 0)
(match_dup 4))
(match_dup 2)]))]
{
int pos = INTVAL (operands[3]),
shift = floor_log2 (INTVAL (operands[4]));
switch (GET_CODE (operands[6]))
{
case ASHIFT:
pos = shift - pos;
break;
case LSHIFTRT:
pos = shift + pos;
break;
default:
gcc_unreachable ();
}
if (BITS_BIG_ENDIAN)
pos = (32 - (1 + pos)) & 0x1f;
operands[3] = GEN_INT (pos);
operands[4] = GEN_INT (shift);
}
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(set_attr "length" "6")])


;; Conversions.

Expand Down

0 comments on commit e33d2dc

Please sign in to comment.