diff options
author | Andy Hutchinson <hutchinsonandy@gcc.gnu.org> | 2009-10-24 15:36:40 +0000 |
---|---|---|
committer | Andy Hutchinson <hutchinsonandy@gcc.gnu.org> | 2009-10-24 15:36:40 +0000 |
commit | ed1f5d718b537106ca546813538abbc9ae733f10 (patch) | |
tree | ece8541554fb70badea5c95b1c2e0e7881fbd68d | |
parent | 8b583a0651c326c12cd2a3d6a4cfba7bf6b68963 (diff) | |
download | gcc-ed1f5d718b537106ca546813538abbc9ae733f10.zip gcc-ed1f5d718b537106ca546813538abbc9ae733f10.tar.gz gcc-ed1f5d718b537106ca546813538abbc9ae733f10.tar.bz2 |
re PR middle-end/19154 (miss-optimization of (x & pow2C) avr conditionals returning bool equivalent values)
PR middle-end/19154
* avr.md (QIDI): Add new mode iterator.
(sbrx_branch<mode>): Create new zero extract bit, test and jump
patterns for all QI-DI modes combinations.
(sbrx_and_branch<mode>): Create new and based bit test and jump
patterns for QI-SI modes.
avr.c (avr_out_sbxx_branch): Use only bit number.
From-SVN: r153530
-rw-r--r-- | gcc/config/avr/avr.c | 8 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 48 |
2 files changed, 23 insertions, 33 deletions
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 7c3234f..cb2d709 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -5877,12 +5877,12 @@ avr_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED, return 1; } -/* Output a branch that tests a single bit of a register (QI, HI or SImode) +/* Output a branch that tests a single bit of a register (QI, HI, SI or DImode) or memory location in the I/O space (QImode only). Operand 0: comparison operator (must be EQ or NE, compare bit to zero). Operand 1: register operand to test, or CONST_INT memory address. - Operand 2: bit number (for QImode operand) or mask (HImode, SImode). + Operand 2: bit number. Operand 3: label to jump to if the test is true. */ const char * @@ -5930,9 +5930,7 @@ avr_out_sbxx_branch (rtx insn, rtx operands[]) else /* HImode or SImode */ { static char buf[] = "sbrc %A1,0"; - int bit_nr = exact_log2 (INTVAL (operands[2]) - & GET_MODE_MASK (GET_MODE (operands[1]))); - + int bit_nr = INTVAL (operands[2]); buf[3] = (comp == EQ) ? 's' : 'c'; buf[6] = 'A' + (bit_nr >> 3); buf[9] = '0' + (bit_nr & 7); diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index b2d6b44..51fc1f9 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -118,6 +118,7 @@ ;; Define mode iterator (define_mode_iterator QISI [(QI "") (HI "") (SI "")]) +(define_mode_iterator QIDI [(QI "") (HI "") (SI "") (DI "")]) ;;======================================================================== ;; The following is used by nonlocal_goto and setjmp. @@ -2448,12 +2449,15 @@ ;; Test a single bit in a QI/HI/SImode register. -(define_insn "*sbrx_branch" +;; Combine will create zero extract patterns for single bit tests. +;; permit any mode in source pattern by using VOIDmode. + +(define_insn "*sbrx_branch<mode>" [(set (pc) (if_then_else (match_operator 0 "eqne_operator" - [(zero_extract:HI - (match_operand:QI 1 "register_operand" "r") + [(zero_extract:QIDI + (match_operand:VOID 1 "register_operand" "r") (const_int 1) (match_operand 2 "const_int_operand" "n")) (const_int 0)]) @@ -2470,39 +2474,27 @@ (const_int 4)))) (set_attr "cc" "clobber")]) -(define_insn "*sbrx_and_branchhi" - [(set (pc) - (if_then_else - (match_operator 0 "eqne_operator" - [(and:HI - (match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "single_one_operand" "n")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc)))] - "" - "* return avr_out_sbxx_branch (insn, operands);" - [(set (attr "length") - (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) - (le (minus (pc) (match_dup 3)) (const_int 2046))) - (const_int 2) - (if_then_else (eq_attr "mcu_mega" "no") - (const_int 2) - (const_int 4)))) - (set_attr "cc" "clobber")]) +;; Same test based on Bitwise AND RTL. Keep this incase gcc changes patterns. +;; or for old peepholes. +;; Fixme - bitwise Mask will not work for DImode -(define_insn "*sbrx_and_branchsi" +(define_insn "*sbrx_and_branch<mode>" [(set (pc) (if_then_else (match_operator 0 "eqne_operator" - [(and:SI - (match_operand:SI 1 "register_operand" "r") - (match_operand:SI 2 "single_one_operand" "n")) + [(and:QISI + (match_operand:QISI 1 "register_operand" "r") + (match_operand:QISI 2 "single_one_operand" "n")) (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc)))] "" - "* return avr_out_sbxx_branch (insn, operands);" +{ + HOST_WIDE_INT bitnumber; + bitnumber = exact_log2 (GET_MODE_MASK (<MODE>mode) & INTVAL (operands[2])); + operands[2] = GEN_INT (bitnumber); + return avr_out_sbxx_branch (insn, operands); +} [(set (attr "length") (if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046)) (le (minus (pc) (match_dup 3)) (const_int 2046))) |