[rl78] various tweaks
diff mbox

Message ID 201309202242.r8KMgSg7003093@greed.delorie.com
State New
Headers show

Commit Message

DJ Delorie Sept. 20, 2013, 10:42 p.m. UTC
Mostly whitespace and comment tweaks, with a few random bug fixes.
Committed.

Note: the net result of our recent batch of patches is an
approximately 50% speed improvement :-)

	* config/rl78/rl78.c: Various whitespace and comment tweaks.
	(need_to_save): Save bank 0 on interrupts.
	(characterize_address): Strip far address wrappers.
	(rl78_as_legitimate_address): Likewise.
	(transcode_memory_rtx): Likewise.
	(rl78_peep_movhi_p): Disable this peephole after devirt.
	(rl78_propogate_register_origins): Forget all origins when a
	CLOBBER is seen.
	* config/rl78/rl78-virt.md: Various whitespace tweaks.
	* config/rl78/rl78-real.md: Various whitespace tweaks.  Additional
	peephole2's.
	* config/rl78/rl78.md (sel_rb): Disable for G10 just in case.
	* config/rl78/rl78-expand.md (movqi): Check for subregs of consts.
	* config/rl78/rl78.h (LINK_SPEC): Pass -gc-sections unless
	relocating.
	* config/rl78/constraints.md: Various whitespace and paren tweaks.

Patch
diff mbox

Index: config/rl78/rl78.h
===================================================================
--- config/rl78/rl78.h	(revision 202798)
+++ config/rl78/rl78.h	(working copy)
@@ -49,12 +49,13 @@ 
 %{mg10} \
 "
 
 #undef  LINK_SPEC
 #define LINK_SPEC "\
 %{mrelax:-relax} \
+%{!r:--gc-sections} \
 "
 
 #undef  LIB_SPEC
 #define LIB_SPEC "					\
 --start-group						\
 -lc							\
Index: config/rl78/constraints.md
===================================================================
--- config/rl78/constraints.md	(revision 202798)
+++ config/rl78/constraints.md	(working copy)
@@ -59,33 +59,37 @@ 
 
 (define_constraint "Iv08"
   "@internal
    Integer constant equal to 8."
   (and (match_code "const_int")
        (match_test "IN_RANGE (ival, 8, 8)")))
+
 (define_constraint "Iv16"
   "@internal
    Integer constant equal to 16."
   (and (match_code "const_int")
        (match_test "IN_RANGE (ival, 16, 16)")))
+
 (define_constraint "Iv24"
   "@internal
    Integer constant equal to 24."
   (and (match_code "const_int")
        (match_test "IN_RANGE (ival, 24, 24)")))
 
 (define_constraint "Is09"
   "@internal
    Integer constant in the range 9 @dots{} 15 (for shifts)."
   (and (match_code "const_int")
        (match_test "IN_RANGE (ival, 9, 15)")))
+
 (define_constraint "Is17"
   "@internal
    Integer constant in the range 17 @dots{} 23 (for shifts)."
   (and (match_code "const_int")
        (match_test "IN_RANGE (ival, 17, 23)")))
+
 (define_constraint "Is25"
   "@internal
    Integer constant in the range 25 @dots{} 31 (for shifts)."
   (and (match_code "const_int")
        (match_test "IN_RANGE (ival, 25, 31)")))
 
@@ -213,13 +217,13 @@ 
        (ior (match_test "CONSTANT_P (XEXP (op, 0))")
 	    (match_test "GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF"))
 	    )
   )
 (define_memory_constraint "Wab"
   "es:[addr]"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Cab (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Cab (rl78_es_base (op)))
                || satisfies_constraint_Cab (op)")
   )
 
 (define_memory_constraint "Cbc"
   "word16[BC]"
   (and (match_code "mem")
@@ -231,49 +235,49 @@ 
 		       (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == BC_REG"))
 		       (match_test "uword_operand (XEXP (XEXP (op, 0), 1), VOIDmode)"))))
        )
   )
 (define_memory_constraint "Wbc"
   "es:word16[BC]"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Cbc (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Cbc (rl78_es_base (op)))
                || satisfies_constraint_Cbc (op)")
   )
 
 (define_memory_constraint "Cde"
   "[DE]"
   (and (match_code "mem")
        (and (match_code "reg" "0")
 	    (match_test "REGNO (XEXP (op, 0)) == DE_REG")))
   )
 (define_memory_constraint "Wde"
   "es:[DE]"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Cde (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Cde (rl78_es_base (op)))
                || satisfies_constraint_Cde (op)")
   )
 
 (define_memory_constraint "Cca"
   "[AX..HL] for calls"
   (and (match_code "mem")
        (and (match_code "reg" "0")
 	    (match_test "REGNO (XEXP (op, 0)) <= HL_REG")))
   )
 (define_memory_constraint "Wca"
   "es:[AX..HL] for calls"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Cca (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Cca (rl78_es_base (op)))
                || satisfies_constraint_Cca (op)")
   )
 
 (define_memory_constraint "Ccv"
   "[AX..HL,r8-r31] for calls"
   (and (match_code "mem")
        (and (match_code "reg" "0")
-	    (match_test "REGNO (XEXP (op, 0)) < 31")))
+	    (match_test "REGNO (XEXP (op, 0)) < 32")))
   )
 (define_memory_constraint "Wcv"
-  "es:[AX..HL,r8-r23] for calls"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Ccv (rl78_es_base (op))
+  "es:[AX..HL,r8-r31] for calls"
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Ccv (rl78_es_base (op)))
                || satisfies_constraint_Ccv (op)")
   )
 
 (define_memory_constraint "Cd2"
   "word16[DE]"
   (and (match_code "mem")
@@ -285,25 +289,25 @@ 
 		       (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == DE_REG"))
 		       (match_test "uword_operand (XEXP (XEXP (op, 0), 1), VOIDmode)"))))
        )
   )
 (define_memory_constraint "Wd2"
   "es:word16[DE]"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Cd2 (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Cd2 (rl78_es_base (op)))
                || satisfies_constraint_Cd2 (op)")
   )
 
 (define_memory_constraint "Chl"
   "[HL]"
   (and (match_code "mem")
        (and (match_code "reg" "0")
 	    (match_test "REGNO (XEXP (op, 0)) == HL_REG")))
   )
 (define_memory_constraint "Whl"
   "es:[HL]"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Chl (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Chl (rl78_es_base (op)))
                || satisfies_constraint_Chl (op)")
   )
 
 (define_memory_constraint "Ch1"
   "byte8[HL]"
   (and (match_code "mem")
@@ -311,24 +315,24 @@ 
 	    (and (and (match_code "reg" "00")
 		      (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == HL_REG"))
 		      (match_test "ubyte_operand (XEXP (XEXP (op, 0), 1), VOIDmode)"))))
   )
 (define_memory_constraint "Wh1"
   "es:byte8[HL]"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Ch1 (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Ch1 (rl78_es_base (op)))
                || satisfies_constraint_Ch1 (op)")
   )
 
 (define_memory_constraint "Chb"
   "[HL+B]"
   (and (match_code "mem")
        (match_test "rl78_hl_b_c_addr_p (XEXP (op, 0))"))
   )
 (define_memory_constraint "Whb"
   "es:[HL+B]"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Chb (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Chb (rl78_es_base (op)))
                || satisfies_constraint_Chb (op)")
   )
 
 (define_memory_constraint "Cs1"
   "word8[SP]"
   (and (match_code "mem")
@@ -340,13 +344,13 @@ 
 		       (match_test "REGNO (XEXP (XEXP (op, 0), 0)) == SP_REG"))
 		       (match_test "ubyte_operand (XEXP (XEXP (op, 0), 1), VOIDmode)"))))
        )
   )
 (define_memory_constraint "Ws1"
   "es:word8[SP]"
-  (match_test "rl78_es_addr (op) && satisfies_constraint_Cs1 (rl78_es_base (op))
+  (match_test "(rl78_es_addr (op) && satisfies_constraint_Cs1 (rl78_es_base (op)))
                || satisfies_constraint_Cs1 (op)")
   )
 
 (define_memory_constraint "Wfr"
   "ES/CS far pointer"
   (and (match_code "mem")
Index: config/rl78/rl78-expand.md
===================================================================
--- config/rl78/rl78-expand.md	(revision 202798)
+++ config/rl78/rl78-expand.md	(working copy)
@@ -40,20 +40,12 @@ 
     if (GET_CODE (operand1) == SUBREG
 	&& GET_CODE (XEXP (operand1, 0)) == CONST
         && GET_CODE (XEXP (XEXP (operand1, 0), 0)) == PLUS
         && GET_CODE (XEXP (XEXP (XEXP (operand1, 0), 0), 0)) == SYMBOL_REF)
       FAIL;
 
-    /* Similarly for (SUBREG (CONST (PLUS (SYMBOL_REF)))).
-       cf. g++.dg/abi/packed.C.  */
-    if (GET_CODE (operand1) == SUBREG
-	&& GET_CODE (XEXP (operand1, 0)) == CONST
-        && GET_CODE (XEXP (XEXP (operand1, 0), 0)) == PLUS
-        && GET_CODE (XEXP (XEXP (XEXP (operand1, 0), 0), 0)) == SYMBOL_REF)
-      FAIL;
-
     if (CONST_INT_P (operand1) && ! IN_RANGE (INTVAL (operand1), (-1 << 8) + 1, (1 << 8) - 1))
       FAIL;
   }
 )
 
 (define_expand "movhi"
Index: config/rl78/rl78.md
===================================================================
--- config/rl78/rl78.md	(revision 202798)
+++ config/rl78/rl78.md	(working copy)
@@ -139,13 +139,13 @@ 
    pop\t%v0
    pop\t%v0 ; %0"
 )
 
 (define_insn "sel_rb"
   [(unspec_volatile [(match_operand 0 "immediate_operand" "")] UNS_SET_RB)]
-  ""
+  "!TARGET_G10"
   "sel\trb%u0"
   )
 
 (define_insn "trampoline_init"
   [(set (match_operand 0 "register_operand" "=Z08W")
 	(unspec_volatile [(match_operand 1 "register_operand" "Z08W")
Index: config/rl78/rl78-real.md
===================================================================
--- config/rl78/rl78-real.md	(revision 202798)
+++ config/rl78/rl78-real.md	(working copy)
@@ -309,13 +309,13 @@ 
   "rl78_real_insns_ok ()"
   "@
    call\t!!%A1
    call\t%A1"
   )
 
-(define_insn "cbranchqi4_real_signed"
+(define_insn "*cbranchqi4_real_signed"
   [(set (pc) (if_then_else
 	      (match_operator 0 "rl78_cmp_operator_signed"
 			      [(match_operand:QI 1 "general_operand" "A,A,A")
 			       (match_operand:QI 2 "general_operand" "ISqi,i,v")])
               (label_ref (match_operand 3 "" ""))
 	      (pc)))]
@@ -323,13 +323,12 @@ 
   "@
    cmp\t%1, %2 \;xor1 CY,%1.7\;not1 CY\;sk%c0 \;br\t!!%3
    cmp\t%1, %2 \;xor1 CY,%1.7\;sk%c0 \;br\t!!%3
    cmp\t%1, %2 \;xor1 CY,%1.7\;xor1 CY,%2.7\;sk%c0 \;br\t!!%3"
   )
 
-
 (define_insn "*cbranchqi4_real"
   [(set (pc) (if_then_else
 	      (match_operator 0 "rl78_cmp_operator_real"
 			      [(match_operand:QI 1 "general_operand" "Wabvaxbc,a,              v,bcdehl")
 			       (match_operand:QI 2 "general_operand" "M,       irvWabWhlWh1Whb,i,a")])
               (label_ref (match_operand 3 "" ""))
@@ -339,13 +338,13 @@ 
    cmp0\t%1 \;sk%c0 \;br\t!!%3
    cmp\t%1, %2 \;sk%c0 \;br\t!!%3
    cmp\t%1, %2 \;sk%c0 \;br\t!!%3
    cmp\t%1, %2 \;sk%c0 \;br\t!!%3"
   )
 
-(define_insn "cbranchhi4_real_signed"
+(define_insn "*cbranchhi4_real_signed"
   [(set (pc) (if_then_else
 	      (match_operator 0 "rl78_cmp_operator_signed"
 			      [(match_operand:HI 1 "general_operand" "A,A,A,vR")
 			       (match_operand:HI 2 "general_operand" "IShi,i,v,1")])
               (label_ref (match_operand 3))
 	      (pc)))]
@@ -378,13 +377,13 @@ 
 	      (pc)
               (label_ref (match_operand          3 "" ""))))]
   "rl78_real_insns_ok ()"
   "cmpw\t%1, %2 \;sk%c0 \;br\t!!%3"
   )
 
-(define_insn "cbranchsi4_real_lt"
+(define_insn "*cbranchsi4_real_lt"
   [(set (pc) (if_then_else
 	      (lt (match_operand:SI 0 "general_operand" "U,vWabWhlWh1")
 		  (const_int 0))
               (label_ref (match_operand 1 "" ""))
 	      (pc)))
    (clobber (reg:HI AX_REG))
@@ -392,13 +391,13 @@ 
   "rl78_real_insns_ok ()"
   "@
    mov a, %E0 \;mov1 CY,a.7 \;sknc \;br\t!!%1
    mov1 CY,%E0.7 \;sknc \;br\t!!%1"
   )
 
-(define_insn "cbranchsi4_real_ge"
+(define_insn "*cbranchsi4_real_ge"
   [(set (pc) (if_then_else
 	      (ge (match_operand:SI 0 "general_operand" "U,vWabWhlWh1")
 		  (const_int 0))
               (label_ref (match_operand 1 "" ""))
 	      (pc)))
    (clobber (reg:HI AX_REG))
@@ -406,13 +405,13 @@ 
   "rl78_real_insns_ok ()"
   "@
    mov a, %E0 \;mov1 CY,a.7 \;skc \;br\t!!%1
    mov1 CY,%E0.7 \;skc \;br\t!!%1"
   )
 
-(define_insn "cbranchsi4_real_signed"
+(define_insn "*cbranchsi4_real_signed"
   [(set (pc) (if_then_else
 	      (match_operator 0 "rl78_cmp_operator_signed"
 			      [(match_operand:SI 1 "nonimmediate_operand" "vU,vU,vU")
 			       (match_operand:SI 2 "nonmemory_operand" "ISsi,i,v")])
               (label_ref (match_operand 3 "" ""))
 	      (pc)))
@@ -422,13 +421,13 @@ 
   "@
    movw ax,%H1 \;cmpw  ax, %H2 \;xor1 CY,a.7\;not1 CY\;      movw ax,%h1 \;sknz \;cmpw  ax, %h2 \;sk%c0 \;br\t!!%3
    movw ax,%H1 \;cmpw  ax, %H2 \;xor1 CY,a.7\;               movw ax,%h1 \;sknz \;cmpw  ax, %h2 \;sk%c0 \;br\t!!%3
    movw ax,%H1 \;cmpw  ax, %H2 \;xor1 CY,a.7\;xor1 CY,%E2.7\;movw ax,%h1 \;sknz \;cmpw  ax, %h2 \;sk%c0 \;br\t!!%3"
   )
 
-(define_insn "cbranchsi4_real"
+(define_insn "*cbranchsi4_real"
   [(set (pc) (if_then_else
 	      (match_operator 0 "rl78_cmp_operator_real"
 			      [(match_operand:SI 1 "general_operand" "vUi")
 			       (match_operand:SI 2 "general_operand" "iWhlWh1v")])
               (label_ref (match_operand 3 "" ""))
 	      (pc)))
@@ -488,29 +487,65 @@ 
 ;; NOTE: These peepholes are fragile.  They rely upon GCC generating
 ;; a specific sequence on insns, based upon examination of test code.
 ;; Improvements to GCC or using code other than the test code can result
 ;; in the peephole not matching and the optimization being missed.
 
 (define_peephole2
-  [(set (match_operand:QI 1 "register_operand") (reg:QI A_REG))
-   (set (match_dup 1) (and:QI (match_dup 1) (match_operand 2 "immediate_operand")))
-   (set (pc) (if_then_else (eq (match_dup 1) (const_int 0))
-			   (label_ref (match_operand 3 ""))
+  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+   (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+   (set (pc) (if_then_else (eq (match_dup 0) (const_int 0))
+			   (label_ref (match_operand 2 ""))
+			   (pc)))]
+  "peep2_regno_dead_p (3, REGNO (operands[0]))
+   && exact_log2 (INTVAL (operands[1])) >= 0"
+  [(set (pc) (if_then_else (eq (and (reg:QI A_REG) (match_dup 1)) (const_int 0))
+			   (label_ref (match_dup 2))
 			   (pc)))]
-  "peep2_regno_dead_p (3, REGNO (operands[1]))
-   && exact_log2 (INTVAL (operands[2])) >= 0"
-  [(set (pc) (if_then_else (eq (and (reg:QI A_REG) (match_dup 2)) (const_int 0))
-			   (label_ref (match_dup 3)) (pc)))]
   )
 
 (define_peephole2
-  [(set (match_operand:QI 1 "register_operand") (reg:QI A_REG))
-   (set (match_dup 1) (and:QI (match_dup 1) (match_operand 2 "immediate_operand")))
-   (set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
-			   (label_ref (match_operand 3 ""))
+  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+   (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+   (set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
+			   (label_ref (match_operand 2 ""))
 			   (pc)))]
-  "peep2_regno_dead_p (3, REGNO (operands[1]))
-   && exact_log2 (INTVAL (operands[2])) >= 0"
-  [(set (pc) (if_then_else (ne (and (reg:QI A_REG) (match_dup 2)) (const_int 0))
-			   (label_ref (match_dup 3)) (pc)))]
+  "peep2_regno_dead_p (3, REGNO (operands[0]))
+   && exact_log2 (INTVAL (operands[1])) >= 0"
+  [(set (pc) (if_then_else (ne (and (reg:QI A_REG) (match_dup 1)) (const_int 0))
+			   (label_ref (match_dup 2))
+			   (pc)))]
+  )
+
+;; Eliminate needless register copies.
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand") (match_operand:HI 1 "register_operand"))
+   (set (match_operand:HI 2 "register_operand") (match_dup 0))]
+  "peep2_regno_dead_p (2, REGNO (operands[0]))
+   && (REGNO (operands[1]) < 8 || REGNO (operands[2]) < 8)"
+  [(set (match_dup 2) (match_dup 1))]
+  )
+
+;; Eliminate needless register copying when performing bit manipulations.
+(define_peephole2
+  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+   (set (match_dup 0) (ior:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+   (set (reg:QI A_REG) (match_dup 0))]
+  "peep2_regno_dead_p (3, REGNO (operands[0]))"
+  [(set (reg:QI A_REG) (ior:QI (reg:QI A_REG) (match_dup 1)))]
+  )
+
+(define_peephole2
+  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+   (set (match_dup 0) (xor:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+   (set (reg:QI A_REG) (match_dup 0))]
+  "peep2_regno_dead_p (3, REGNO (operands[0]))"
+  [(set (reg:QI A_REG) (xor:QI (reg:QI A_REG) (match_dup 1)))]
+  )
+
+(define_peephole2
+  [(set (match_operand:QI 0 "register_operand") (reg:QI A_REG))
+   (set (match_dup 0) (and:QI (match_dup 0) (match_operand 1 "immediate_operand")))
+   (set (reg:QI A_REG) (match_dup 0))]
+  "peep2_regno_dead_p (3, REGNO (operands[0]))"
+  [(set (reg:QI A_REG) (and:QI (reg:QI A_REG) (match_dup 1)))]
   )
 
Index: config/rl78/rl78-virt.md
===================================================================
--- config/rl78/rl78-virt.md	(revision 202798)
+++ config/rl78/rl78-virt.md	(working copy)
@@ -309,13 +309,13 @@ 
 	      (match_operand 2 "" "")))]
   "rl78_virt_insns_ok ()"
   "v.call\t%1"
   [(set_attr "valloc" "op1")]
   )
 
-(define_insn "cbranchqi4_virt_signed"
+(define_insn "*cbranchqi4_virt_signed"
   [(set (pc) (if_then_else
 	      (match_operator 0 "rl78_cmp_operator_signed"
 			      [(match_operand:QI 1 "general_operand" "vim")
 			       (match_operand:QI 2 "nonmemory_operand" "vi")])
               (label_ref (match_operand 3 "" ""))
 	      (pc)))]
@@ -333,13 +333,13 @@ 
 	      (pc)))]
   "rl78_virt_insns_ok ()"
   "v.cmp\t%1, %2\\n\tv.b%c0\t%3"
   [(set_attr "valloc" "cmp")]
   )
 
-(define_insn "cbranchhi4_virt_signed"
+(define_insn "*cbranchhi4_virt_signed"
   [(set (pc) (if_then_else
 	      (match_operator 0 "rl78_cmp_operator_signed"
 			      [(match_operand:HI 1 "general_operand" "vim")
 			       (match_operand:HI 2 "nonmemory_operand" "vi")])
               (label_ref (match_operand 3 "" ""))
 	      (pc)))]
@@ -357,13 +357,13 @@ 
 	      (pc)))]
   "rl78_virt_insns_ok ()"
   "v.cmpw\t%1, %2\\n\tv.b%c0\t%3"
   [(set_attr "valloc" "cmp")]
   )
 
-(define_insn "cbranchsi4_virt"
+(define_insn "*cbranchsi4_virt"
   [(set (pc) (if_then_else
 	      (match_operator 0 "rl78_cmp_operator"
 			      [(match_operand:SI 1 "general_operand" "vim")
 			       (match_operand:SI 2 "nonmemory_operand" "vi")])
               (label_ref (match_operand 3 "" ""))
 	      (pc)))
Index: config/rl78/rl78.c
===================================================================
--- config/rl78/rl78.c	(revision 202798)
+++ config/rl78/rl78.c	(working copy)
@@ -167,12 +167,15 @@  public:
 rtl_opt_pass *
 make_pass_rl78_devirt (gcc::context *ctxt)
 {
   return new pass_rl78_devirt (ctxt);
 }
 
+/* Redundant move elimination pass.  Must be run after the basic block
+   reordering pass for the best effect.  */
+
 static unsigned int
 move_elim_pass (void)
 {
   rtx insn, ninsn, prev = NULL_RTX;
 
   for (insn = get_insns (); insn; insn = ninsn)
@@ -311,13 +314,14 @@  rl78_option_override (void)
 
   init_machine_status = rl78_init_machine_status;
 
   if (TARGET_ALLREGS)
     {
       int i;
-      for (i=24; i<32; i++)
+
+      for (i = 24; i < 32; i++)
 	fixed_regs[i] = 0;
     }
 }
 
 /* Most registers are 8 bits.  Some are 16 bits because, for example,
    gcc doesn't like dealing with $FP as a register pair.  This table
@@ -439,19 +443,21 @@  rl78_expand_movsi (rtx *operands)
     {
       emit_move_insn (op00, op10);
       emit_move_insn (op02, op12);
     }
 }
 
+/* Generate code to move an SImode value.  */
 void
 rl78_split_movsi (rtx *operands)
 {
   rtx op00, op02, op10, op12;
 
   op00 = rl78_subreg (HImode, operands[0], SImode, 0);
   op02 = rl78_subreg (HImode, operands[0], SImode, 2);
+
   if (GET_CODE (operands[1]) == CONST
       || GET_CODE (operands[1]) == SYMBOL_REF)
     {
       op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
       op10 = gen_rtx_CONST (HImode, op10);
       op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
@@ -478,13 +484,12 @@  rl78_split_movsi (rtx *operands)
       operands[4] = op10;
       operands[3] = op02;
       operands[5] = op12;
     }
 }
 
-
 /* Used by various two-operand expanders which cannot accept all
    operands in the "far" namespace.  Force some such operands into
    registers so that each pattern has at most one far operand.  */
 int
 rl78_force_nonfar_2 (rtx *operands, rtx (*gen)(rtx,rtx))
 {
@@ -552,12 +557,16 @@  rl78_can_eliminate (const int from ATTRI
    current function.  */
 static bool
 need_to_save (unsigned int regno)
 {
   if (is_interrupt_func (cfun->decl))
     {
+      /* We don't know what devirt will need */
+      if (regno < 8)
+	return true;
+
        /* We don't need to save registers that have
 	  been reserved for interrupt handlers.  */
       if (regno > 23)
 	return false;
 
       /* If the handler is a non-leaf function then it may call
@@ -693,12 +702,16 @@  static bool
 characterize_address (rtx x, rtx *base, rtx *index, rtx *addend)
 {
   *base = NULL_RTX;
   *index = NULL_RTX;
   *addend = NULL_RTX;
 
+  if (GET_CODE (x) == UNSPEC
+      && XINT (x, 1) == UNS_ES_ADDR)
+    x = XVECEXP (x, 0, 1);
+
   if (GET_CODE (x) == REG)
     {
       *base = x;
       return true;
     }
 
@@ -867,19 +880,23 @@  rl78_is_legitimate_constant (enum machin
 
 bool
 rl78_as_legitimate_address (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x,
 			    bool strict ATTRIBUTE_UNUSED, addr_space_t as ATTRIBUTE_UNUSED)
 {
   rtx base, index, addend;
+  bool is_far_addr = false;
 
   if (GET_CODE (x) == UNSPEC
       && XINT (x, 1) == UNS_ES_ADDR)
-    x = XVECEXP (x, 0, 1);
+    {
+      x = XVECEXP (x, 0, 1);
+      is_far_addr = true;
+    }
 
   if (as == ADDR_SPACE_GENERIC
-      && GET_MODE (x) == SImode)
+      && (GET_MODE (x) == SImode || is_far_addr))
     return false;
 
   if (! characterize_address (x, &base, &index, &addend))
     return false;
 
   /* We can't extract the high/low portions of a PLUS address
@@ -1059,22 +1076,25 @@  rl78_expand_prologue (void)
       {
 	if (TARGET_G10)
 	  {
 	    emit_move_insn (gen_rtx_REG (HImode, 0), gen_rtx_REG (HImode, i*2));
 	    F (emit_insn (gen_push (gen_rtx_REG (HImode, 0))));
 	  }
-	else {
-	  int need_bank = i/4;
-	  if (need_bank != rb)
-	    {
-	      emit_insn (gen_sel_rb (GEN_INT (need_bank)));
-	      rb = need_bank;
-	    }
-	  F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
-	}
+	else
+	  {
+	    int need_bank = i/4;
+
+	    if (need_bank != rb)
+	      {
+		emit_insn (gen_sel_rb (GEN_INT (need_bank)));
+		rb = need_bank;
+	      }
+	    F (emit_insn (gen_push (gen_rtx_REG (HImode, i*2))));
+	  }
       }
+
   if (rb != 0)
     emit_insn (gen_sel_rb (GEN_INT (0)));
 
   if (frame_pointer_needed)
     {
       F (emit_move_insn (gen_rtx_REG (HImode, AX_REG),
@@ -1672,12 +1692,15 @@  rl78_peep_movhi_p (rtx *operands)
   int i;
   rtx m, a;
 
   /* (set (op0) (op1))
      (set (op2) (op3)) */
 
+  if (! rl78_virt_insns_ok ())
+    return false;
+
 #if DEBUG_PEEP
   fprintf (stderr, "\033[33m");
   debug_rtx (operands[0]);
   debug_rtx (operands[1]);
   debug_rtx (operands[2]);
   debug_rtx (operands[3]);
@@ -1944,13 +1967,12 @@  get_content_index (rtx loc)
 
   return NOT_KNOWN;
 }
 
 /* Return a string describing content INDEX in mode MODE.
    WARNING: Can return a pointer to a static buffer.  */
-
 static const char *
 get_content_name (unsigned char index, enum machine_mode mode)
 {
   static char buffer [128];
 
   if (index == NOT_KNOWN)
@@ -2152,24 +2174,24 @@  insn_ok_now (rtx insn)
 	  if (SET_P (pattern))
 	    record_content (SET_DEST (pattern), SET_SRC (pattern));
 
 	  /* We need to detect far addresses that haven't been
 	     converted to es/lo16 format.  */
 	  for (i=0; i<recog_data.n_operands; i++)
-	    if (GET_CODE (OP(i)) == MEM
-		&& GET_MODE (XEXP (OP(i), 0)) == SImode
-		&& GET_CODE (XEXP (OP(i), 0)) != UNSPEC)
+	    if (GET_CODE (OP (i)) == MEM
+		&& GET_MODE (XEXP (OP (i), 0)) == SImode
+		&& GET_CODE (XEXP (OP (i), 0)) != UNSPEC)
 	      return false;
 
 	  return true;
 	}
     }
   else
     {
       /* We need to re-recog the insn with virtual registers to get
-	 the operands */
+	 the operands.  */
       cfun->machine->virt_insns_ok = 1;
       if (recog (pattern, insn, 0) > -1)
 	{
 	  extract_insn (insn);
 	  if (constrain_operands (0))
 	    {
@@ -2203,28 +2225,28 @@  insn_ok_now (rtx insn)
 #define FAILED gcc_unreachable ()
 #define MAYBE_OK(insn) if (insn_ok_now (insn)) return;
 #define MUST_BE_OK(insn) if (insn_ok_now (insn)) return; FAILED
 #endif
 
 /* Registers into which we move the contents of virtual registers.  */
-#define X gen_rtx_REG (QImode, 0)
-#define A gen_rtx_REG (QImode, 1)
-#define C gen_rtx_REG (QImode, 2)
-#define B gen_rtx_REG (QImode, 3)
-#define E gen_rtx_REG (QImode, 4)
-#define D gen_rtx_REG (QImode, 5)
-#define L gen_rtx_REG (QImode, 6)
-#define H gen_rtx_REG (QImode, 7)
-
-#define AX gen_rtx_REG (HImode, 0)
-#define BC gen_rtx_REG (HImode, 2)
-#define DE gen_rtx_REG (HImode, 4)
-#define HL gen_rtx_REG (HImode, 6)
+#define X gen_rtx_REG (QImode, X_REG)
+#define A gen_rtx_REG (QImode, A_REG)
+#define C gen_rtx_REG (QImode, C_REG)
+#define B gen_rtx_REG (QImode, B_REG)
+#define E gen_rtx_REG (QImode, E_REG)
+#define D gen_rtx_REG (QImode, D_REG)
+#define L gen_rtx_REG (QImode, L_REG)
+#define H gen_rtx_REG (QImode, H_REG)
+
+#define AX gen_rtx_REG (HImode, AX_REG)
+#define BC gen_rtx_REG (HImode, BC_REG)
+#define DE gen_rtx_REG (HImode, DE_REG)
+#define HL gen_rtx_REG (HImode, HL_REG)
 
 /* Returns TRUE if R is a virtual register.  */
-static bool
+static inline bool
 is_virtual_register (rtx r)
 {
   return (GET_CODE (r) == REG
 	  && REGNO (r) >= 8
 	  && REGNO (r) < 32);
 }
@@ -2361,12 +2383,13 @@  gen_and_emit_move (rtx to, rtx from, rtx
 
       if (before)
 	record_content (to, from);
       else
 	add_postponed_content_update (to, from);
     }
+
   return before ? to : from;
 }
 
 /* If M is MEM(REG) or MEM(PLUS(REG,INT)) and REG is virtual then
    copy it into NEWBASE and return the updated MEM.  Otherwise just
    return M.  Any needed insns are emitted before BEFORE.  */
@@ -2379,22 +2402,26 @@  transcode_memory_rtx (rtx m, rtx newbase
 
   if (! MEM_P (m))
     return m;
 
   if (GET_MODE (XEXP (m, 0)) == SImode)
     {
+      rtx new_m;
       rtx seg = rl78_hi8 (XEXP (m, 0));
+
 #if DEBUG_ALLOC
       fprintf (stderr, "setting ES:\n");
       debug_rtx(seg);
 #endif
       emit_insn_before (EM (gen_movqi (A, seg)), before);
       emit_insn_before (EM (gen_movqi_es (A)), before);
       record_content (A, NULL_RTX);
 
-      m = change_address (m, GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
+      new_m = gen_rtx_MEM (GET_MODE (m), rl78_lo16 (XEXP (m, 0)));
+      MEM_COPY_ATTRIBUTES (new_m, m);
+      m = new_m;
       need_es = 1;
     }
 
   characterize_address (XEXP (m, 0), & base, & index, & addendr);
   gcc_assert (index == NULL_RTX);
 
@@ -2462,13 +2489,12 @@  transcode_memory_rtx (rtx m, rtx newbase
 #endif
   return m;
 }
 
 /* Copy SRC to accumulator (A or AX), placing any generated insns
    before BEFORE.  Returns accumulator RTX.  */
-
 static rtx
 move_to_acc (int opno, rtx before)
 {
   rtx src = OP (opno);
   enum machine_mode mode = GET_MODE (src);
 
@@ -2497,13 +2523,12 @@  force_into_acc (rtx src, rtx before)
   emit_insn_before (move, before);
   record_content (AX, NULL_RTX);
 }
 
 /* Copy accumulator (A or AX) to DEST, placing any generated insns
    after AFTER.  Returns accumulator RTX.  */
-
 static rtx
 move_from_acc (unsigned int opno, rtx after)
 {
   rtx dest = OP (opno);
   enum machine_mode mode = GET_MODE (dest);
 
@@ -2512,13 +2537,12 @@  move_from_acc (unsigned int opno, rtx af
 
   return gen_and_emit_move (dest, mode == QImode ? A : AX, after, false);
 }
 
 /* Copy accumulator (A or AX) to REGNO, placing any generated insns
    before BEFORE.  Returns reg RTX.  */
-
 static rtx
 move_acc_to_reg (rtx acc, int regno, rtx before)
 {
   enum machine_mode mode = GET_MODE (acc);
   rtx reg;
 
@@ -2526,13 +2550,12 @@  move_acc_to_reg (rtx acc, int regno, rtx
 
   return gen_and_emit_move (reg, acc, before, true);
 }
 
 /* Copy SRC to X, placing any generated insns before BEFORE.
    Returns X RTX.  */
-
 static rtx
 move_to_x (int opno, rtx before)
 {
   rtx src = OP (opno);
   enum machine_mode mode = GET_MODE (src);
   rtx reg;
@@ -2541,22 +2564,21 @@  move_to_x (int opno, rtx before)
     mode = recog_data.operand_mode[opno];
   reg = (mode == QImode) ? X : AX;
 
   if (mode == QImode || ! is_virtual_register (OP (opno)))
     {
       OP (opno) = move_to_acc (opno, before);
-      OP (opno) = move_acc_to_reg (OP(opno), X_REG, before);
+      OP (opno) = move_acc_to_reg (OP (opno), X_REG, before);
       return reg;
     }
 
   return gen_and_emit_move (reg, src, before, true);
 }
 
-/* Copy OP(opno) to H or HL, placing any generated insns before BEFORE.
+/* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
    Returns H/HL RTX.  */
-
 static rtx
 move_to_hl (int opno, rtx before)
 {
   rtx src = OP (opno);
   enum machine_mode mode = GET_MODE (src);
   rtx reg;
@@ -2572,15 +2594,14 @@  move_to_hl (int opno, rtx before)
       return reg;
     }
 
   return gen_and_emit_move (reg, src, before, true);
 }
 
-/* Copy OP(opno) to E or DE, placing any generated insns before BEFORE.
+/* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
    Returns E/DE RTX.  */
-
 static rtx
 move_to_de (int opno, rtx before)
 {
   rtx src = OP (opno);
   enum machine_mode mode = GET_MODE (src);
   rtx reg;
@@ -2799,13 +2820,12 @@  rl78_alloc_physical_registers_op2 (rtx i
 		 we have inserted useless insns into the stream.  */
 	      MUST_BE_OK (insn);
 	    }
 	}
     }
 
-
   OP (0) = move_from_acc (0, insn);
 
   tmp_id = get_max_insn_count ();
   saved_op1 = OP (1);
 
   if (rtx_equal_p (OP (1), OP (2)))
@@ -2835,13 +2855,12 @@  rl78_alloc_physical_registers_op2 (rtx i
   OP (2) = hl_used ? move_to_de (2, first) : move_to_hl (2, first);
   
   MUST_BE_OK (insn);
 }
 
 /* Devirtualize an insn of the form SET (PC) (MEM/REG).  */
-
 static void
 rl78_alloc_physical_registers_ro1 (rtx insn)
 {
   OP (0) = transcode_memory_rtx (OP (0), BC, insn);
 
   MAYBE_OK (insn);
@@ -2849,31 +2868,30 @@  rl78_alloc_physical_registers_ro1 (rtx i
   OP (0) = move_to_acc (0, insn);
 
   MUST_BE_OK (insn);
 }
 
 /* Devirtualize a compare insn.  */
-
 static void
 rl78_alloc_physical_registers_cmp (rtx insn)
 {
   int tmp_id;
   rtx saved_op1;
   rtx prev = prev_nonnote_nondebug_insn (insn);
   rtx first;
 
   OP (1) = transcode_memory_rtx (OP (1), DE, insn);
   OP (2) = transcode_memory_rtx (OP (2), HL, insn);
 
-  /* HI compares have to have OP(1) in AX, but QI
+  /* HI compares have to have OP (1) in AX, but QI
      compares do not, so it is worth checking here.  */
   MAYBE_OK (insn);
 
-  /* For an HImode compare, OP(1) must always be in AX.
-     But if OP(1) is a REG (and not AX), then we can avoid
-     a reload of OP(1) if we reload OP(2) into AX and invert
+  /* For an HImode compare, OP (1) must always be in AX.
+     But if OP (1) is a REG (and not AX), then we can avoid
+     a reload of OP (1) if we reload OP (2) into AX and invert
      the comparison.  */
   if (REG_P (OP (1))
       && REGNO (OP (1)) != AX_REG
       && GET_MODE (OP (1)) == HImode
       && MEM_P (OP (2)))
     {
@@ -2943,13 +2961,12 @@  rl78_alloc_physical_registers_cmp (rtx i
   OP (2) = move_to_hl (2, first);
 
   MUST_BE_OK (insn);
 }
 
 /* Like op2, but AX = A op X.  */
-
 static void
 rl78_alloc_physical_registers_umul (rtx insn)
 {
   rtx prev = prev_nonnote_nondebug_insn (insn);
   rtx first;
   int tmp_id;
@@ -3051,12 +3068,13 @@  rl78_alloc_address_registers_macax (rtx 
 	      OP (op) = transcode_memory_rtx (OP (op), BC, insn);
 	      break;
 	    }
 	  which ++;
 	}
     }
+
   MUST_BE_OK (insn);
 }
 
 /* Scan all insns and devirtualize them.  */
 static void
 rl78_alloc_physical_registers (void)
@@ -3173,12 +3191,13 @@  rl78_alloc_physical_registers (void)
 
       if (JUMP_P (insn) || CALL_P (insn) || GET_CODE (pattern) == CALL)
 	clear_content_memory ();
       else
 	process_postponed_content_update ();
     }
+
 #if DEBUG_ALLOC
   fprintf (stderr, "\033[0m");
 #endif
 }
 
 /* Add REG_DEAD notes using DEAD[reg] for rtx S which is part of INSN.
@@ -3541,12 +3560,22 @@  rl78_propogate_register_origins (void)
 			    origins[i] = i;
 			    age[i] = 0;
 			  }
 		    }
 		}
 	    }
+	  else if (GET_CODE (pat) == CLOBBER)
+	    {
+	      if (REG_P (XEXP (pat, 0)))
+		{
+		  unsigned int reg = REGNO (XEXP (pat, 0));
+
+		  origins[reg] = reg;
+		  age[reg] = 0;
+		}
+	    }
 	}
     }
 }
 
 /* Remove any SETs where the destination is unneeded.  */
 static void
@@ -3690,9 +3719,10 @@  static bool rl78_rtx_costs (rtx   x,
 static enum machine_mode
 rl78_unwind_word_mode (void)
 {
   return HImode;
 }
 
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-rl78.h"