diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2018-02-14 12:33:37 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2018-02-14 12:33:37 +0000 |
commit | 06e972705d2459498212969adac45c592c7a02bb (patch) | |
tree | c3a5987c8817bdf9a6c1352ffa17c07cecf511c4 /gcc/config/rx/rx.md | |
parent | d1fe6124618d472815cf46d9a8cf23e7d4a49cbe (diff) | |
download | gcc-06e972705d2459498212969adac45c592c7a02bb.tar.gz |
re PR target/83831 ([RX] Unused bclr,bnot,bset insns)
gcc/
PR target/83831
* config/rx/rx-protos.h (rx_reg_dead_or_unused_after_insn,
rx_copy_reg_dead_or_unused_notes, rx_fuse_in_memory_bitop): New
declarations.
(set_of_reg): New struct.
(rx_find_set_of_reg, rx_find_use_of_reg): New functions.
* config/rx/rx.c (rx_reg_dead_or_unused_after_insn,
rx_copy_reg_dead_or_unused_notes, rx_fuse_in_memory_bitop): New
functions.
* config/rx/rx.md (andsi3, iorsi3, xorsi3): Convert to insn_and_split.
Split into bitclr, bitset, bitinvert patterns if appropriate.
(*bitset, *bitinvert, *bitclr): Convert to named insn_and_split and
use rx_fuse_in_memory_bitop.
(*bitset_in_memory, *bitinvert_in_memory, *bitclr_in_memory): Convert
to named insn, correct maximum insn length.
gcc/testsuite/
PR target/83831
* gcc.target/rx/pr83831.c: New tests.
From-SVN: r257655
Diffstat (limited to 'gcc/config/rx/rx.md')
-rw-r--r-- | gcc/config/rx/rx.md | 112 |
1 files changed, 89 insertions, 23 deletions
diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 3fb2ac854b0..116d4d4a939 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -1094,7 +1094,7 @@ DONE; }) -(define_insn "andsi3" +(define_insn_and_split "andsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) @@ -1110,6 +1110,21 @@ and\t%1, %0 and\t%2, %1, %0 and\t%Q2, %0" + "&& RX_REG_P (operands[1]) && CONST_INT_P (operands[2]) + && pow2p_hwi (~UINTVAL (operands[2]))" + [(const_int 0)] +{ + /* For negated single bit constants use the bclr insn for smaller code. */ + + if (!rx_reg_dead_or_unused_after_insn (curr_insn, CC_REG)) + FAIL; + + rx_copy_reg_dead_or_unused_notes (operands[1], curr_insn, + emit_insn (gen_bitclr (operands[0], + GEN_INT (exact_log2 (~UINTVAL (operands[2]))), + operands[1]))); + DONE; +} [(set_attr "timings" "11,11,11,11,11,11,11,11,33") (set_attr "length" "2,2,3,4,5,6,2,5,5")] ) @@ -1383,7 +1398,7 @@ [(set_attr "length" "2,3")] ) -(define_insn "iorsi3" +(define_insn_and_split "iorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r") (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0") (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))) @@ -1399,6 +1414,21 @@ or\t%1, %0 or\t%2, %1, %0 or\t%Q2, %0" + "&& RX_REG_P (operands[1]) && CONST_INT_P (operands[2]) + && pow2p_hwi (UINTVAL (operands[2]))" + [(const_int 0)] +{ + /* For single bit constants use the bset insn for smaller code. */ + + if (!rx_reg_dead_or_unused_after_insn (curr_insn, CC_REG)) + FAIL; + + rx_copy_reg_dead_or_unused_notes (operands[1], curr_insn, + emit_insn (gen_bitset (operands[0], + GEN_INT (exact_log2 (UINTVAL (operands[2]))), + operands[1]))); + DONE; +} [(set_attr "timings" "11,11,11,11,11,11,11,11,33") (set_attr "length" "2,2,3,4,5,6,2,3,5")] ) @@ -1704,7 +1734,7 @@ DONE; }) -(define_insn "xorsi3" +(define_insn_and_split "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r") (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0") (match_operand:SI 2 "rx_source_operand" @@ -1712,6 +1742,21 @@ (clobber (reg:CC CC_REG))] "" "xor\t%Q2, %0" + "&& RX_REG_P (operands[1]) && CONST_INT_P (operands[2]) + && pow2p_hwi (UINTVAL (operands[2]))" + [(const_int 0)] +{ + /* For single bit constants use the bnot insn for smaller code. */ + + if (!rx_reg_dead_or_unused_after_insn (curr_insn, CC_REG)) + FAIL; + + rx_copy_reg_dead_or_unused_notes (operands[1], curr_insn, + emit_insn (gen_bitinvert (operands[0], + GEN_INT (exact_log2 (UINTVAL (operands[2]))), + operands[1]))); + DONE; +} [(set_attr "timings" "11,11,11,11,11,33") (set_attr "length" "3,4,5,6,7,6")] ) @@ -1960,50 +2005,63 @@ ;; Bit manipulation instructions. -;; ??? The *_in_memory patterns will not be matched without further help. -;; At one time we had the insv expander generate them, but I suspect that -;; in general we get better performance by exposing the register load to -;; the optimizers. -;; -;; An alternate solution would be to re-organize these patterns such -;; that allow both register and memory operands. This would allow the -;; register allocator to spill and not load the register operand. This -;; would be possible only for operations for which we have a constant -;; bit offset, so that we can adjust the address by ofs/8 and replace -;; the offset in the insn by ofs%8. - -(define_insn "*bitset" +;; The *_in_memory patterns will not be matched automatically, not even with +;; combiner bridge patterns. Especially when the memory operands have a +;; displacement, the resulting patterns look too complex. +;; Instead we manually look around the matched insn to see if there is a +;; preceeding memory load and a following memory store of the modified register +;; which can be fused into the single *_in_memory insn. +;; Do that before register allocation, as it can eliminate one temporary +;; register that needs to be allocated. + +(define_insn_and_split "bitset" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI (ashift:SI (const_int 1) (match_operand:SI 1 "rx_shift_operand" "ri")) (match_operand:SI 2 "register_operand" "0")))] "" "bset\t%1, %0" + "&& can_create_pseudo_p ()" + [(const_int 0)] +{ + if (rx_fuse_in_memory_bitop (operands, curr_insn, &gen_bitset_in_memory)) + DONE; + else + FAIL; +} [(set_attr "length" "3")] ) -(define_insn "*bitset_in_memory" +(define_insn "bitset_in_memory" [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") (ior:QI (ashift:QI (const_int 1) (match_operand:QI 1 "nonmemory_operand" "ri")) (match_dup 0)))] "" "bset\t%1, %0.B" - [(set_attr "length" "3") + [(set_attr "length" "5") (set_attr "timings" "33")] ) -(define_insn "*bitinvert" +(define_insn_and_split "bitinvert" [(set (match_operand:SI 0 "register_operand" "=r") (xor:SI (ashift:SI (const_int 1) (match_operand:SI 1 "rx_shift_operand" "ri")) (match_operand:SI 2 "register_operand" "0")))] "" "bnot\t%1, %0" + "&& can_create_pseudo_p ()" + [(const_int 0)] +{ + if (rx_fuse_in_memory_bitop (operands, curr_insn, &gen_bitinvert_in_memory)) + DONE; + else + FAIL; +} [(set_attr "length" "3")] ) -(define_insn "*bitinvert_in_memory" +(define_insn "bitinvert_in_memory" [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") (xor:QI (ashift:QI (const_int 1) (match_operand:QI 1 "nonmemory_operand" "ri")) @@ -2014,7 +2072,7 @@ (set_attr "timings" "33")] ) -(define_insn "*bitclr" +(define_insn_and_split "bitclr" [(set (match_operand:SI 0 "register_operand" "=r") (and:SI (not:SI (ashift:SI @@ -2023,10 +2081,18 @@ (match_operand:SI 2 "register_operand" "0")))] "" "bclr\t%1, %0" + "&& can_create_pseudo_p ()" + [(const_int 0)] +{ + if (rx_fuse_in_memory_bitop (operands, curr_insn, &gen_bitclr_in_memory)) + DONE; + else + FAIL; +} [(set_attr "length" "3")] ) -(define_insn "*bitclr_in_memory" +(define_insn "bitclr_in_memory" [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q") (and:QI (not:QI (ashift:QI @@ -2035,7 +2101,7 @@ (match_dup 0)))] "" "bclr\t%1, %0.B" - [(set_attr "length" "3") + [(set_attr "length" "5") (set_attr "timings" "33")] ) |