summaryrefslogtreecommitdiff
path: root/gcc/config/rx/rx.md
diff options
context:
space:
mode:
authorOleg Endo <olegendo@gcc.gnu.org>2018-02-14 12:33:37 +0000
committerOleg Endo <olegendo@gcc.gnu.org>2018-02-14 12:33:37 +0000
commit06e972705d2459498212969adac45c592c7a02bb (patch)
treec3a5987c8817bdf9a6c1352ffa17c07cecf511c4 /gcc/config/rx/rx.md
parentd1fe6124618d472815cf46d9a8cf23e7d4a49cbe (diff)
downloadgcc-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.md112
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")]
)