On Thu, Jul 07, 2016 at 02:58:17AM +0000, Segher Boessenkool wrote:
> Similar to PR70098, which is about integers in floating point registers,
> we can have the completely analogous problem with vector registers as well
> now that we allow integers in vector registers.  So, this patch solves it
> in the same way.  This only works for targets with direct move.
> 
> To recap: register allocation can decide to put an integer mode value in
> a floating point or vector register.  If that register is used in a bd*z
> instruction, which is a jump instruction, reload can not do an output
> reload on it (it does not do output reloads on any jump insns), so the
> float or vector register will remain, and we have to allow it here or
> recog will ICE.  Later on we will split this to valid instructions,
> including a move from that fp/vec register to an int register; it is this
> move that will still fail (PR70098) if we do not have direct move enabled.

BTW, both pr70098 and pr71763 are triggered by combine, not
loop-doloop as I was thinking earlier.  See rtl dumps for the
testcases.  I doubt the "optimization" done by combine here is worth
keeping, since loop-doloop.c ought to already handle the benficial
inner loop use of ctr.  Elsewhere we typically end up with an insn
that needs splitting back to the original sequence.  So we could avoid
creating trouble for ourselves with the following patch.

Bootstrap and regression test powerpc64le-linux and powerpc64-linux in
progress.

        * config/rs6000/rs6000.md (UNSPEC_DONT_COMBINE): New unspec.
        (ctr<mode>): Add unspec.
        (ctr<mode>_internal* and splitters): Likewise.  Renumber.

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 7d9c660..b2d1118 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -148,6 +148,7 @@
    UNSPEC_IEEE128_MOVE
    UNSPEC_IEEE128_CONVERT
    UNSPEC_SIGNBIT
+   UNSPEC_DONT_COMBINE
   ])
 
 ;;
@@ -12185,6 +12186,7 @@
              (set (match_dup 0)
                   (plus:P (match_dup 0)
                            (const_int -1)))
+             (unspec [(const_int 0)] UNSPEC_DONT_COMBINE)
              (clobber (match_scratch:CC 2 ""))
              (clobber (match_scratch:P 3 ""))])]
   ""
@@ -12205,6 +12207,7 @@
    (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
        (plus:P (match_dup 1)
                 (const_int -1)))
+   (unspec [(const_int 0)] UNSPEC_DONT_COMBINE)
    (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
    (clobber (match_scratch:P 4 "=X,X,&r,r"))]
   ""
@@ -12229,6 +12232,7 @@
    (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
        (plus:P (match_dup 1)
                 (const_int -1)))
+   (unspec [(const_int 0)] UNSPEC_DONT_COMBINE)
    (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
    (clobber (match_scratch:P 4 "=X,X,&r,r"))]
   ""
@@ -12246,7 +12250,7 @@
 
 ;; Similar but use EQ
 
-(define_insn "*ctr<mode>_internal5"
+(define_insn "*ctr<mode>_internal3"
   [(set (pc)
        (if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b")
                          (const_int 1))
@@ -12255,6 +12259,7 @@
    (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
        (plus:P (match_dup 1)
                 (const_int -1)))
+   (unspec [(const_int 0)] UNSPEC_DONT_COMBINE)
    (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
    (clobber (match_scratch:P 4 "=X,X,&r,r"))]
   ""
@@ -12270,7 +12275,7 @@
   [(set_attr "type" "branch")
    (set_attr "length" "*,16,20,20")])
 
-(define_insn "*ctr<mode>_internal6"
+(define_insn "*ctr<mode>_internal4"
   [(set (pc)
        (if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b")
                          (const_int 1))
@@ -12279,6 +12284,7 @@
    (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
        (plus:P (match_dup 1)
                 (const_int -1)))
+   (unspec [(const_int 0)] UNSPEC_DONT_COMBINE)
    (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
    (clobber (match_scratch:P 4 "=X,X,&r,r"))]
   ""
@@ -12305,6 +12311,7 @@
                      (match_operand 6 "" "")))
    (set (match_operand:P 0 "int_reg_operand" "")
        (plus:P (match_dup 1) (const_int -1)))
+   (unspec [(const_int 0)] UNSPEC_DONT_COMBINE)
    (clobber (match_scratch:CC 3 ""))
    (clobber (match_scratch:P 4 ""))]
   "reload_completed"
@@ -12330,6 +12337,7 @@
                      (match_operand 6 "" "")))
    (set (match_operand:P 0 "nonimmediate_operand" "")
        (plus:P (match_dup 1) (const_int -1)))
+   (unspec [(const_int 0)] UNSPEC_DONT_COMBINE)
    (clobber (match_scratch:CC 3 ""))
    (clobber (match_scratch:P 4 ""))]
   "reload_completed && ! gpc_reg_operand (operands[0], SImode)"

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to