aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Hutchinson <hutchinsonandy@gcc.gnu.org>2009-10-24 15:36:40 +0000
committerAndy Hutchinson <hutchinsonandy@gcc.gnu.org>2009-10-24 15:36:40 +0000
commited1f5d718b537106ca546813538abbc9ae733f10 (patch)
treeece8541554fb70badea5c95b1c2e0e7881fbd68d
parent8b583a0651c326c12cd2a3d6a4cfba7bf6b68963 (diff)
downloadgcc-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.c8
-rw-r--r--gcc/config/avr/avr.md48
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)))