This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] for PR23726
- From: Bjoern Haase <bjoern dot m dot haase at web dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 22 Dec 2007 16:09:56 +0100
- Subject: [PATCH] for PR23726
This pattch is meant to resolve PR23726
My new analysis leads me to the result that the key problem of the PR 23726
missed optimization is a target problem: Presently avr expands a divmod4
pattern that implements the support funciton calls directly. This pattern
refers directly to hard registers. The resulting RTL is too complex for CSE
and we don't identify this optimization.
The attached patch uses the same RTL for the support function calls. Only this
RTL is now generated only after combine by a define_insn_and_split pattern.
The insn part of this pattern is valid only for pseudos so that until split.
In order to assure this, I have added a new predicate.
I have tested the patch against the atmega128 simulation target without
regressions.
2007-12-11 Bjoern Haase <bjoern.m.haase@web.de>
PR target/23726
* config/avr/predicates.md (pseudo_register_operand): Add new predicate
for pseudos
* config/avr/avr.md (divmodqi4,udivmodqi4): replace define_expand by
define_insn_and_split, delay expansion of call patterns to split pass.
(divmodhi4,udivmodhi4,divmodsi4,udivmodsi4): likewise.
Index: predicates.md
===================================================================
--- predicates.md (Revision 130786)
+++ predicates.md (Arbeitskopie)
@@ -105,3 +105,9 @@
(and (match_code "mem")
(ior (match_test "register_operand (XEXP (op, 0), mode)")
(match_test "CONSTANT_ADDRESS_P (XEXP (op, 0))"))))
+
+
+;;
+(define_predicate "pseudo_register_operand"
+ (and (match_code "reg")
+ (match_test "!HARD_REGISTER_P (op)")))
Index: avr.md
===================================================================
--- avr.md (Revision 130786)
+++ avr.md (Arbeitskopie)
@@ -980,17 +980,30 @@
;; - we know exactly which registers are clobbered (for QI and HI
;; modes, some of the call-used registers are preserved)
;; - we get both the quotient and the remainder at no extra cost
-
-(define_expand "divmodqi4"
- [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
- (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
+;; - we split the patterns only after the first CSE passes because
+;; CSE has problems to operate on hard regs.
+;;
+(define_insn_and_split "divmodqi4"
+ [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "")
+ (div:QI (match_operand:QI 1 "pseudo_register_operand" "")
+ (match_operand:QI
2 "pseudo_register_operand" "")))
+ (set (match_operand:QI 3 "pseudo_register_operand" "")
+ (mod:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:QI 22))
+ (clobber (reg:QI 23))
+ (clobber (reg:QI 24))
+ (clobber (reg:QI 25))])]
+ ""
+ "this divmodqi4 pattern should have been splitted;"
+ ""
+ [(set (reg:QI 24) (match_dup 1))
+ (set (reg:QI 22) (match_dup 2))
(parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
(set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
(clobber (reg:QI 22))
(clobber (reg:QI 23))])
- (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))
- (set (match_operand:QI 3 "register_operand" "") (reg:QI 25))]
- ""
+ (set (match_dup 0) (reg:QI 24))
+ (set (match_dup 3) (reg:QI 25))]
"")
(define_insn "*divmodqi4_call"
@@ -1003,15 +1016,26 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-(define_expand "udivmodqi4"
- [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
- (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
+(define_insn_and_split "udivmodqi4"
+ [(parallel [(set (match_operand:QI 0 "pseudo_register_operand" "")
+ (udiv:QI (match_operand:QI 1 "pseudo_register_operand" "")
+ (match_operand:QI
2 "pseudo_register_operand" "")))
+ (set (match_operand:QI 3 "pseudo_register_operand" "")
+ (umod:QI (match_dup 1) (match_dup 2)))
+ (clobber (reg:QI 22))
+ (clobber (reg:QI 23))
+ (clobber (reg:QI 24))
+ (clobber (reg:QI 25))])]
+ ""
+ "this udivmodqi4 pattern should have been splitted;"
+ ""
+ [(set (reg:QI 24) (match_dup 1))
+ (set (reg:QI 22) (match_dup 2))
(parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
(set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
(clobber (reg:QI 23))])
- (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))
- (set (match_operand:QI 3 "register_operand" "") (reg:QI 25))]
- ""
+ (set (match_dup 0) (reg:QI 24))
+ (set (match_dup 3) (reg:QI 25))]
"")
(define_insn "*udivmodqi4_call"
@@ -1023,17 +1047,28 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-(define_expand "divmodhi4"
- [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
- (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
+(define_insn_and_split "divmodhi4"
+ [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "")
+ (div:HI (match_operand:HI 1 "pseudo_register_operand" "")
+ (match_operand:HI
2 "pseudo_register_operand" "")))
+ (set (match_operand:HI 3 "pseudo_register_operand" "")
+ (mod:HI (match_dup 1) (match_dup 2)))
+ (clobber (reg:QI 21))
+ (clobber (reg:HI 22))
+ (clobber (reg:HI 24))
+ (clobber (reg:HI 26))])]
+ ""
+ "this should have been splitted;"
+ ""
+ [(set (reg:HI 24) (match_dup 1))
+ (set (reg:HI 22) (match_dup 2))
(parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
(set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
(clobber (reg:HI 26))
(clobber (reg:QI 21))])
- (set (match_operand:HI 0 "register_operand" "") (reg:HI 22))
- (set (match_operand:HI 3 "register_operand" "") (reg:HI 24))]
- ""
- "")
+ (set (match_dup 0) (reg:HI 22))
+ (set (match_dup 3) (reg:HI 24))]
+ "")
(define_insn "*divmodhi4_call"
[(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
@@ -1045,16 +1080,27 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-(define_expand "udivmodhi4"
- [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
- (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
+(define_insn_and_split "udivmodhi4"
+ [(parallel [(set (match_operand:HI 0 "pseudo_register_operand" "")
+ (udiv:HI (match_operand:HI 1 "pseudo_register_operand" "")
+ (match_operand:HI
2 "pseudo_register_operand" "")))
+ (set (match_operand:HI 3 "pseudo_register_operand" "")
+ (umod:HI (match_dup 1) (match_dup 2)))
+ (clobber (reg:QI 21))
+ (clobber (reg:HI 22))
+ (clobber (reg:HI 24))
+ (clobber (reg:HI 26))])]
+ ""
+ "this udivmodhi4 pattern should have been splitted.;"
+ ""
+ [(set (reg:HI 24) (match_dup 1))
+ (set (reg:HI 22) (match_dup 2))
(parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
(set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
(clobber (reg:HI 26))
(clobber (reg:QI 21))])
- (set (match_operand:HI 0 "register_operand" "") (reg:HI 22))
- (set (match_operand:HI 3 "register_operand" "") (reg:HI 24))]
- ""
+ (set (match_dup 0) (reg:HI 22))
+ (set (match_dup 3) (reg:HI 24))]
"")
(define_insn "*udivmodhi4_call"
@@ -1067,16 +1113,27 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-(define_expand "divmodsi4"
- [(set (reg:SI 22) (match_operand:SI 1 "register_operand" ""))
- (set (reg:SI 18) (match_operand:SI 2 "register_operand" ""))
+(define_insn_and_split "divmodsi4"
+ [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "")
+ (div:SI (match_operand:SI 1 "pseudo_register_operand" "")
+ (match_operand:SI
2 "pseudo_register_operand" "")))
+ (set (match_operand:SI 3 "pseudo_register_operand" "")
+ (mod:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:SI 18))
+ (clobber (reg:SI 22))
+ (clobber (reg:HI 26))
+ (clobber (reg:HI 30))])]
+ ""
+ "this divmodsi4 pattern should have been splitted;"
+ ""
+ [(set (reg:SI 22) (match_dup 1))
+ (set (reg:SI 18) (match_dup 2))
(parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
(set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
(clobber (reg:HI 26))
(clobber (reg:HI 30))])
- (set (match_operand:SI 0 "register_operand" "") (reg:SI 18))
- (set (match_operand:SI 3 "register_operand" "") (reg:SI 22))]
- ""
+ (set (match_dup 0) (reg:SI 18))
+ (set (match_dup 3) (reg:SI 22))]
"")
(define_insn "*divmodsi4_call"
@@ -1089,16 +1146,27 @@
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
-(define_expand "udivmodsi4"
- [(set (reg:SI 22) (match_operand:SI 1 "register_operand" ""))
- (set (reg:SI 18) (match_operand:SI 2 "register_operand" ""))
+(define_insn_and_split "udivmodsi4"
+ [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "")
+ (udiv:SI (match_operand:SI 1 "pseudo_register_operand" "")
+ (match_operand:SI
2 "pseudo_register_operand" "")))
+ (set (match_operand:SI 3 "pseudo_register_operand" "")
+ (umod:SI (match_dup 1) (match_dup 2)))
+ (clobber (reg:SI 18))
+ (clobber (reg:SI 22))
+ (clobber (reg:HI 26))
+ (clobber (reg:HI 30))])]
+ ""
+ "this udivmodsi4 pattern should have been splitted;"
+ ""
+ [(set (reg:SI 22) (match_dup 1))
+ (set (reg:SI 18) (match_dup 2))
(parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
(set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
(clobber (reg:HI 26))
(clobber (reg:HI 30))])
- (set (match_operand:SI 0 "register_operand" "") (reg:SI 18))
- (set (match_operand:SI 3 "register_operand" "") (reg:SI 22))]
- ""
+ (set (match_dup 0) (reg:SI 18))
+ (set (match_dup 3) (reg:SI 22))]
"")
(define_insn "*udivmodsi4_call"