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
This commit is contained in:
Andy Hutchinson 2009-10-24 15:36:40 +00:00
parent 8b583a0651
commit ed1f5d718b
2 changed files with 23 additions and 33 deletions

View File

@ -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);

View File

@ -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)))