Commit e389ba30 by Andrew Burgess Committed by Andrew Burgess

arc/nps400: New peephole2 pattern allow more cmem loads

In the case where we access a single bit from a value and use this in a
EQ/NE comparison, GCC will convert this into a sign-extend and GE/LT
comparison.

Normally this would be fine, however, if the value is in CMEM memory,
then we don't have a sign-extending load available (using the special
short CMEM load instructions), and instead we end up using a long form
load with LIMM, which is less efficient.

This peephole optimisation looks for the sign-extend followed by GE/LT
pattern and converts this back into a load and EQ/NE comparison.

gcc/ChangeLog:

	* config/arc/arc.md (cmem bit/sign-extend peephole2): New peephole
	to make better use of cmem loads in the case where a single bit is
	being accessed.
	* config/arc/predicates.md (ge_lt_comparison_operator): New
	predicate.

gcc/testsuite/ChangeLog:

	* gcc.target/arc/cmem-bit-1.c: New file.
	* gcc.target/arc/cmem-bit-2.c: New file.
	* gcc.target/arc/cmem-bit-3.c: New file.
	* gcc.target/arc/cmem-bit-4.c: New file.

From-SVN: r242572
parent 9775c1a5
2016-11-17 Andrew Burgess <andrew.burgess@embecosm.com>
* config/arc/arc.md (cmem bit/sign-extend peephole2): New peephole
to make better use of cmem loads in the case where a single bit is
being accessed.
* config/arc/predicates.md (ge_lt_comparison_operator): New
predicate.
2016-11-17 Andrew Senkevich <andrew.senkevich@intel.com>
* config/i386/i386.c (processor_features): Add F_AVX5124VNNIW,
......@@ -1465,6 +1465,49 @@
[(set_attr "type" "cmove,cmove")
(set_attr "length" "4,8")])
;; When there's a mask of a single bit, and then a compare to 0 or 1,
;; if the single bit is the sign bit, then GCC likes to convert this
;; into a sign extend and a compare less than, or greater to zero.
;; This is usually fine, except for the NXP400 where we have access to
;; a bit test instruction, along with a special short load instruction
;; (from CMEM), that doesn't support sign-extension on load.
;;
;; This peephole optimisation attempts to restore the use of bit-test
;; in those cases where it is useful to do so.
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(sign_extend:SI
(match_operand:QI 1 "any_mem_operand" "")))
(set (reg:CC_ZN CC_REG)
(compare:CC_ZN (match_dup 0)
(const_int 0)))
(set (pc)
(if_then_else (match_operator 2 "ge_lt_comparison_operator"
[(reg:CC_ZN CC_REG) (const_int 0)])
(match_operand 3 "" "")
(match_operand 4 "" "")))]
"TARGET_NPS_CMEM
&& cmem_address (XEXP (operands[1], 0), SImode)
&& peep2_reg_dead_p (2, operands[0])
&& peep2_regno_dead_p (3, CC_REG)"
[(set (match_dup 0)
(zero_extend:SI
(match_dup 1)))
(set (reg:CC_ZN CC_REG)
(compare:CC_ZN (zero_extract:SI
(match_dup 0)
(const_int 1)
(const_int 7))
(const_int 0)))
(set (pc)
(if_then_else (match_dup 2)
(match_dup 3)
(match_dup 4)))]
"if (GET_CODE (operands[2]) == GE)
operands[2] = gen_rtx_EQ (VOIDmode, gen_rtx_REG (CC_ZNmode, 61), const0_rtx);
else
operands[2] = gen_rtx_NE (VOIDmode, gen_rtx_REG (CC_ZNmode, 61), const0_rtx);")
; Try to generate more short moves, and/or less limms, by substituting a
; conditional move with a conditional sub.
(define_peephole2
......
......@@ -452,6 +452,9 @@
(define_predicate "equality_comparison_operator"
(match_code "eq, ne"))
(define_predicate "ge_lt_comparison_operator"
(match_code "ge, lt"))
(define_predicate "brcc_nolimm_operator"
(ior (match_test "REG_P (XEXP (op, 1))")
(and (match_code "eq, ne, lt, ge, ltu, geu")
......
2016-11-17 Andrew Burgess <andrew.burgess@embecosm.com>
* gcc.target/arc/cmem-bit-1.c: New file.
* gcc.target/arc/cmem-bit-2.c: New file.
* gcc.target/arc/cmem-bit-3.c: New file.
* gcc.target/arc/cmem-bit-4.c: New file.
2016-11-17 Andrew Senkevich <andrew.senkevich@intel.com>
* gcc.target/i386/builtin_target.c: Handle new "avx5124vnniw",
......
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -mcmem -O2" } */
struct strange_bool
{
unsigned char bool_bit :1;
unsigned char other_bits :7;
};
struct strange_bool a_strange_bool __attribute__((section(".cmem")));
extern void bar();
void foo() {
if (a_strange_bool.bool_bit)
bar();
}
/* { dg-final { scan-assembler "xldb r\[0-9\]+,\\\[@a_strange_bool\\\]" } } */
/* { dg-final { scan-assembler "btst_s r\[0-9\]+,7" { target arceb-*-* } } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -mcmem -O2" } */
struct strange_bool
{
unsigned short bool_bit :1;
unsigned short other_bits :15;
};
struct strange_bool a_strange_bool __attribute__((section(".cmem")));
extern void bar();
void foo() {
if (a_strange_bool.bool_bit)
bar();
}
/* { dg-final { scan-assembler "xldb r\[0-9\]+,\\\[@a_strange_bool\\\]" } } */
/* { dg-final { scan-assembler "btst_s r\[0-9\]+,7" { target arceb-*-* } } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -mcmem -O2" } */
struct strange_bool
{
unsigned int bool_bit :1;
unsigned int other_bits :31;
};
struct strange_bool a_strange_bool __attribute__((section(".cmem")));
extern void bar();
void foo() {
if (a_strange_bool.bool_bit)
bar();
}
/* { dg-final { scan-assembler "xldb r\[0-9\]+,\\\[@a_strange_bool\\\]" } } */
/* { dg-final { scan-assembler "btst_s r\[0-9\]+,7" { target arceb-*-* } } } */
/* { dg-do compile } */
/* { dg-options "-mcpu=nps400 -mcmem -O2" } */
struct strange_bool
{
unsigned long long bool_bit :1;
unsigned long long other_bits :61;
};
struct strange_bool a_strange_bool __attribute__((section(".cmem")));
extern void bar();
void foo() {
if (a_strange_bool.bool_bit)
bar();
}
/* { dg-final { scan-assembler "xldb r\[0-9\]+,\\\[@a_strange_bool\\\]" } } */
/* { dg-final { scan-assembler "btst_s r\[0-9\]+,7" { target arceb-*-* } } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment