mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 03:30:27 +08:00
re PR target/42210 (avr: optimizing assignment to a bit field)
PR target/42210 * config/avr/predicates.md (const1_operand, const_0_to_7_operand): New predicates. * config/avr/avr.md ("insv"): New insn expander. ("*movbitqi.1-6.a", "*movbitqi.1-6.b", "*movbitqi.0", "*insv.io", "*insv.not.io", "*insv.reg"): New insns. Co-Authored-By: Georg-Johann Lay <avr@gjlay.de> From-SVN: r174685
This commit is contained in:
parent
efcbfc1c35
commit
48f9d59afe
@ -1,3 +1,13 @@
|
||||
2011-06-06 Richard Henderson <rth@redhat.com>
|
||||
Georg-Johann Lay <avr@gjlay.de>
|
||||
|
||||
PR target/42210
|
||||
* config/avr/predicates.md (const1_operand, const_0_to_7_operand):
|
||||
New predicates.
|
||||
* config/avr/avr.md ("insv"): New insn expander.
|
||||
("*movbitqi.1-6.a", "*movbitqi.1-6.b", "*movbitqi.0", "*insv.io",
|
||||
"*insv.not.io", "*insv.reg"): New insns.
|
||||
|
||||
2011-06-06 Hans-Peter Nilsson <hp@bitrange.com>
|
||||
|
||||
PR target/49285
|
||||
|
@ -3389,6 +3389,119 @@
|
||||
[(set_attr "length" "3")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
|
||||
;; Some combiner patterns dealing with bits.
|
||||
;; See PR42210
|
||||
|
||||
;; Move bit $3.0 into bit $0.$4
|
||||
(define_insn "*movbitqi.1-6.a"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||
(ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
|
||||
(match_operand:QI 2 "single_zero_operand" "n"))
|
||||
(and:QI (ashift:QI (match_operand:QI 3 "register_operand" "r")
|
||||
(match_operand:QI 4 "const_0_to_7_operand" "n"))
|
||||
(match_operand:QI 5 "single_one_operand" "n"))))]
|
||||
"INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))
|
||||
&& INTVAL(operands[4]) == exact_log2 (INTVAL(operands[5]) & GET_MODE_MASK (QImode))"
|
||||
"bst %3,0\;bld %0,%4"
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "cc" "none")])
|
||||
|
||||
;; Move bit $3.0 into bit $0.$4
|
||||
;; Variation of above. Unfortunately, there is no canonicalized representation
|
||||
;; of moving around bits. So what we see here depends on how user writes down
|
||||
;; bit manipulations.
|
||||
(define_insn "*movbitqi.1-6.b"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||
(ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
|
||||
(match_operand:QI 2 "single_zero_operand" "n"))
|
||||
(ashift:QI (and:QI (match_operand:QI 3 "register_operand" "r")
|
||||
(const_int 1))
|
||||
(match_operand:QI 4 "const_0_to_7_operand" "n"))))]
|
||||
"INTVAL(operands[4]) == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
|
||||
"bst %3,0\;bld %0,%4"
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "cc" "none")])
|
||||
|
||||
;; Move bit $3.0 into bit $0.0.
|
||||
;; For bit 0, combiner generates slightly different pattern.
|
||||
(define_insn "*movbitqi.0"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||
(ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
|
||||
(match_operand:QI 2 "single_zero_operand" "n"))
|
||||
(and:QI (match_operand:QI 3 "register_operand" "r")
|
||||
(const_int 1))))]
|
||||
"0 == exact_log2 (~INTVAL(operands[2]) & GET_MODE_MASK (QImode))"
|
||||
"bst %3,0\;bld %0,0"
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "cc" "none")])
|
||||
|
||||
;; Move bit $2.0 into bit $0.7.
|
||||
;; For bit 7, combiner generates slightly different pattern
|
||||
(define_insn "*movbitqi.7"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r")
|
||||
(ior:QI (and:QI (match_operand:QI 1 "register_operand" "0")
|
||||
(const_int 127))
|
||||
(ashift:QI (match_operand:QI 2 "register_operand" "r")
|
||||
(const_int 7))))]
|
||||
""
|
||||
"bst %2,0\;bld %0,7"
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "cc" "none")])
|
||||
|
||||
;; Combiner transforms above four pattern into ZERO_EXTRACT if it sees MEM
|
||||
;; and input/output match. We provide a special pattern for this, because
|
||||
;; in contrast to a IN/BST/BLD/OUT sequence we need less registers and the
|
||||
;; operation on I/O is atomic.
|
||||
(define_insn "*insv.io"
|
||||
[(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n,n,n"))
|
||||
(const_int 1)
|
||||
(match_operand:QI 1 "const_0_to_7_operand" "n,n,n"))
|
||||
(match_operand:QI 2 "nonmemory_operand" "L,P,r"))]
|
||||
""
|
||||
"@
|
||||
cbi %m0-0x20,%1
|
||||
sbi %m0-0x20,%1
|
||||
sbrc %2,0\;sbi %m0-0x20,%1\;sbrs %2,0\;cbi %m0-0x20,%1"
|
||||
[(set_attr "length" "1,1,4")
|
||||
(set_attr "cc" "none")])
|
||||
|
||||
(define_insn "*insv.not.io"
|
||||
[(set (zero_extract:QI (mem:QI (match_operand 0 "low_io_address_operand" "n"))
|
||||
(const_int 1)
|
||||
(match_operand:QI 1 "const_0_to_7_operand" "n"))
|
||||
(not:QI (match_operand:QI 2 "register_operand" "r")))]
|
||||
""
|
||||
"sbrs %2,0\;sbi %m0-0x20,%1\;sbrc %2,0\;cbi %m0-0x20,%1"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "cc" "none")])
|
||||
|
||||
;; The insv expander.
|
||||
;; We only support 1-bit inserts
|
||||
(define_expand "insv"
|
||||
[(set (zero_extract:QI (match_operand:QI 0 "register_operand" "")
|
||||
(match_operand:QI 1 "const1_operand" "") ; width
|
||||
(match_operand:QI 2 "const_0_to_7_operand" "")) ; pos
|
||||
(match_operand:QI 3 "nonmemory_operand" ""))]
|
||||
"optimize"
|
||||
"")
|
||||
|
||||
;; Insert bit $2.0 into $0.$1
|
||||
(define_insn "*insv.reg"
|
||||
[(set (zero_extract:QI (match_operand:QI 0 "register_operand" "+r,d,d,l,l")
|
||||
(const_int 1)
|
||||
(match_operand:QI 1 "const_0_to_7_operand" "n,n,n,n,n"))
|
||||
(match_operand:QI 2 "nonmemory_operand" "r,L,P,L,P"))]
|
||||
""
|
||||
"@
|
||||
bst %2,0\;bld %0,%1
|
||||
andi %0,lo8(~(1<<%1))
|
||||
ori %0,lo8(1<<%1)
|
||||
clt\;bld %0,%1
|
||||
set\;bld %0,%1"
|
||||
[(set_attr "length" "2,1,1,2,2")
|
||||
(set_attr "cc" "none,set_zn,set_zn,none,none")])
|
||||
|
||||
|
||||
;; Some combine patterns that try to fix bad code when a value is composed
|
||||
;; from byte parts like in PR27663.
|
||||
|
@ -62,6 +62,17 @@
|
||||
(and (match_code "const_int,const_double")
|
||||
(match_test "op == CONST0_RTX (mode)")))
|
||||
|
||||
;; Return 1 if OP is the one constant integer for MODE.
|
||||
(define_predicate "const1_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "op == CONST1_RTX (mode)")))
|
||||
|
||||
|
||||
;; Return 1 if OP is constant integer 0..7 for MODE.
|
||||
(define_predicate "const_0_to_7_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (INTVAL (op), 0, 7)")))
|
||||
|
||||
;; Returns true if OP is either the constant zero or a register.
|
||||
(define_predicate "reg_or_0_operand"
|
||||
(ior (match_operand 0 "register_operand")
|
||||
|
Loading…
x
Reference in New Issue
Block a user