rs6000.md (cceq_ior_compare): Remove * so I can use it to generate rtl.
authorAaron Sawdey <acsawdey@linux.vnet.ibm.com>
Mon, 8 Jan 2018 15:07:06 +0000 (15:07 +0000)
committerAaron Sawdey <acsawdey@gcc.gnu.org>
Mon, 8 Jan 2018 15:07:06 +0000 (09:07 -0600)
2018-01-08  Aaron Sawdey  <acsawdey@linux.vnet.ibm.com>

* config/rs6000/rs6000.md (cceq_ior_compare): Remove * so I can use it
to generate rtl.
(cceq_ior_compare_complement): Give it a name so I can use it, and
change boolean_or_operator predicate to boolean_operator so it can
be used to generate a crand.
(eqne): New code iterator.
(bd/bd_neg): New code_attrs.
(<bd>_<mode>): New name for ctr<mode>_internal[12] now combined into
a single define_insn.
(<bd>tf_<mode>): A new insn pattern for the conditional form branch
decrement (bdnzt/bdnzf/bdzt/bdzf).
* config/rs6000/rs6000.c (rs6000_legitimate_combined_insn): Updated
with the new names of the branch decrement patterns, and added the
names of the branch decrement conditional patterns.

From-SVN: r256344

gcc/ChangeLog
gcc/config/rs6000/rs6000.md

index f8d2b34ea72a3e07adf25fee2674f4b205cd07f3..b5aeb0ec51965a16738f8f95a98ba464c043c664 100644 (file)
@@ -1,3 +1,20 @@
+2018-01-08  Aaron Sawdey  <acsawdey@linux.vnet.ibm.com>
+
+       * config/rs6000/rs6000.md (cceq_ior_compare): Remove * so I can use it
+       to generate rtl.
+       (cceq_ior_compare_complement): Give it a name so I can use it, and
+       change boolean_or_operator predicate to boolean_operator so it can
+       be used to generate a crand.
+       (eqne): New code iterator.
+       (bd/bd_neg): New code_attrs.
+       (<bd>_<mode>): New name for ctr<mode>_internal[12] now combined into
+       a single define_insn.
+       (<bd>tf_<mode>): A new insn pattern for the conditional form branch
+       decrement (bdnzt/bdnzf/bdzt/bdzf).
+       * config/rs6000/rs6000.c (rs6000_legitimate_combined_insn): Updated
+       with the new names of the branch decrement patterns, and added the
+       names of the branch decrement conditional patterns.
+
 2018-01-08  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/83563
index 2cbfbfc45174258563df7ebe8e783cf259df658e..3d3ead4ec4906e3e6c61db2329b52a33dc756028 100644 (file)
 ; which are generated by the branch logic.
 ; Prefer destructive operations where BT = BB (for crXX BT,BA,BB)
 
-(define_insn "*cceq_ior_compare"
+(define_insn "cceq_ior_compare"
   [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
         (compare:CCEQ (match_operator:SI 1 "boolean_operator"
                        [(match_operator:SI 2
 
 ; Why is the constant -1 here, but 1 in the previous pattern?
 ; Because ~1 has all but the low bit set.
-(define_insn ""
+(define_insn "cceq_ior_compare_complement"
   [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y")
-        (compare:CCEQ (match_operator:SI 1 "boolean_or_operator"
+        (compare:CCEQ (match_operator:SI 1 "boolean_operator"
                        [(not:SI (match_operator:SI 2
                                      "branch_positive_comparison_operator"
                                      [(match_operand 3
 ;; rs6000_legitimate_combined_insn prevents combine creating any of
 ;; the ctr<mode> insns.
 
-(define_insn "ctr<mode>_internal1"
-  [(set (pc)
-       (if_then_else (ne (match_operand:P 1 "register_operand" "c,*b,*b,*b")
-                         (const_int 1))
-                     (label_ref (match_operand 0))
-                     (pc)))
-   (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
-       (plus:P (match_dup 1)
-               (const_int -1)))
-   (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
-   (clobber (match_scratch:P 4 "=X,X,&r,r"))]
-  ""
-{
-  if (which_alternative != 0)
-    return "#";
-  else if (get_attr_length (insn) == 4)
-    return "bdnz %l0";
-  else
-    return "bdz $+8\;b %l0";
-}
-  [(set_attr "type" "branch")
-   (set_attr "length" "*,16,20,20")])
-
-;; Similar but use EQ
+(define_code_iterator eqne [eq ne])
+(define_code_attr bd [(eq "bdz") (ne "bdnz")])
+(define_code_attr bd_neg [(eq "bdnz") (ne "bdz")])
 
-(define_insn "ctr<mode>_internal2"
+(define_insn "<bd>_<mode>"
   [(set (pc)
-       (if_then_else (eq (match_operand:P 1 "register_operand" "c,*b,*b,*b")
+       (if_then_else (eqne (match_operand:P 1 "register_operand" "c,*b,*b,*b")
                          (const_int 1))
                      (label_ref (match_operand 0))
                      (pc)))
   if (which_alternative != 0)
     return "#";
   else if (get_attr_length (insn) == 4)
-    return "bdz %l0";
+    return "<bd> %l0";
   else
-    return "bdnz $+8\;b %l0";
+    return "<bd_neg> $+8\;b %l0";
 }
   [(set_attr "type" "branch")
    (set_attr "length" "*,16,20,20")])
 
-;; Now the splitters if we could not allocate the CTR register
-
+;; Now the splitter if we could not allocate the CTR register
 (define_split
   [(set (pc)
        (if_then_else (match_operator 2 "comparison_operator"
                                       (const_int 1)])
                      (match_operand 5)
                      (match_operand 6)))
-   (set (match_operand:P 0 "int_reg_operand")
+   (set (match_operand:P 0 "nonimmediate_operand")
        (plus:P (match_dup 1)
                (const_int -1)))
    (clobber (match_scratch:CC 3))
    (clobber (match_scratch:P 4))]
   "reload_completed"
-  [(set (match_dup 3)
-       (compare:CC (match_dup 1)
-                   (const_int 1)))
-   (set (match_dup 0)
-       (plus:P (match_dup 1)
-               (const_int -1)))
-   (set (pc)
+  [(set (pc)
        (if_then_else (match_dup 7)
                      (match_dup 5)
                      (match_dup 6)))]
 {
   operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode, operands[3],
                                const0_rtx);
+  emit_insn (gen_rtx_SET (operands[3],
+                         gen_rtx_COMPARE (CCmode, operands[1], const1_rtx)));
+  if (gpc_reg_operand (operands[0], <MODE>mode))
+    emit_insn (gen_add<mode>3 (operands[0], operands[1], constm1_rtx));
+  else
+    {
+      emit_insn (gen_add<mode>3 (operands[4], operands[1], constm1_rtx));
+      emit_move_insn (operands[0], operands[4]);
+    } 
+    /* No DONE so branch comes from the pattern.  */
 })
 
-(define_split
+;; patterns for bdnzt/bdnzf/bdzt/bdzf
+;; Note that in the case of long branches we have to decompose this into
+;; bdnz+bc. This is because bdnzt has an implied AND between the ctr condition
+;; and the CR bit, which means there is no way to conveniently invert the
+;; comparison as is done with plain bdnz/bdz.
+
+(define_insn "<bd>tf_<mode>"
   [(set (pc)
-       (if_then_else (match_operator 2 "comparison_operator"
-                                     [(match_operand:P 1 "gpc_reg_operand")
-                                      (const_int 1)])
-                     (match_operand 5)
-                     (match_operand 6)))
-   (set (match_operand:P 0 "nonimmediate_operand")
-       (plus:P (match_dup 1)
-               (const_int -1)))
-   (clobber (match_scratch:CC 3))
-   (clobber (match_scratch:P 4))]
-  "reload_completed && !gpc_reg_operand (operands[0], SImode)"
-  [(set (match_dup 3)
-       (compare:CC (match_dup 1)
-                   (const_int 1)))
-   (set (match_dup 4)
+       (if_then_else
+         (and
+            (eqne (match_operand:P 1 "register_operand" "c,*b,*b,*b")
+                  (const_int 1))
+            (match_operator 3 "branch_comparison_operator"
+                     [(match_operand 4 "cc_reg_operand" "y,y,y,y")
+                      (const_int 0)]))
+         (label_ref (match_operand 0))
+         (pc)))
+   (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*d*wi*c*l")
        (plus:P (match_dup 1)
                (const_int -1)))
-   (set (match_dup 0)
-       (match_dup 4))
-   (set (pc)
-       (if_then_else (match_dup 7)
-                     (match_dup 5)
-                     (match_dup 6)))]
+   (clobber (match_scratch:P 5 "=X,X,&r,r"))
+   (clobber (match_scratch:CC 6 "=X,&y,&y,&y"))
+   (clobber (match_scratch:CCEQ 7 "=X,&y,&y,&y"))]
+  ""
 {
-  operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode, operands[3],
-                               const0_rtx);
+  if (which_alternative != 0)
+    return "#";
+  else if (get_attr_length (insn) == 4)
+    {
+      if (branch_positive_comparison_operator (operands[3],
+                                              GET_MODE (operands[3])))
+       return "<bd>t %j3,%l0";
+      else
+       return "<bd>f %j3,%l0";
+    }
+  else
+    {
+      static char seq[96];
+      char *bcs = output_cbranch (operands[3], "$+8", 1, insn);
+      sprintf(seq, "<bd_neg> $+12\;%s;b %%l0", bcs);
+      return seq;
+    }
+}
+  [(set_attr "type" "branch")
+   (set_attr "length" "*,16,20,20")])
+
+;; Now the splitter if we could not allocate the CTR register
+(define_split
+  [(set (pc)
+       (if_then_else
+         (and
+            (match_operator 1 "comparison_operator"
+                            [(match_operand:P 0 "gpc_reg_operand")
+                             (const_int 1)])
+            (match_operator 3 "branch_comparison_operator"
+                     [(match_operand 2 "cc_reg_operand")
+                      (const_int 0)]))
+         (match_operand 4)
+         (match_operand 5)))
+   (set (match_operand:P 6 "int_reg_operand")
+       (plus:P (match_dup 0)
+               (const_int -1)))
+   (clobber (match_scratch:P 7))
+   (clobber (match_scratch:CC 8))
+   (clobber (match_scratch:CCEQ 9))]
+  "reload_completed"
+[(pc)]
+{
+  rtx ctr = operands[0];
+  rtx ctrcmp = operands[1];
+  rtx ccin = operands[2];
+  rtx cccmp = operands[3];
+  rtx dst1 = operands[4];
+  rtx dst2 = operands[5];
+  rtx ctrout = operands[6];
+  rtx ctrtmp = operands[7];
+  enum rtx_code cmpcode = GET_CODE (ctrcmp);
+  bool ispos = branch_positive_comparison_operator (ctrcmp, GET_MODE (ctrcmp));
+  if (!ispos)
+    cmpcode = reverse_condition (cmpcode);
+  /* Generate crand/crandc here.  */
+  emit_insn (gen_rtx_SET (operands[8],
+                         gen_rtx_COMPARE (CCmode, ctr, const1_rtx)));
+  rtx ctrcmpcc = gen_rtx_fmt_ee (cmpcode, SImode, operands[8], const0_rtx);
+
+  rtx andexpr = gen_rtx_AND (SImode, ctrcmpcc, cccmp);
+  if (ispos)
+     emit_insn (gen_cceq_ior_compare (operands[9], andexpr, ctrcmpcc,
+                                     operands[8], cccmp, ccin));
+  else
+     emit_insn (gen_cceq_ior_compare_complement (operands[9], andexpr, ctrcmpcc,
+                                                operands[8], cccmp, ccin));
+  if (gpc_reg_operand (operands[0], <MODE>mode))
+     emit_insn (gen_add<mode>3 (ctrout, ctr, constm1_rtx));
+  else
+    {
+      emit_insn (gen_add<mode>3 (ctrtmp, ctr, constm1_rtx));
+      emit_move_insn (ctrout, ctrtmp);
+    }
+  rtx cmp = gen_rtx_EQ (CCEQmode, operands[9], const0_rtx);
+  emit_jump_insn (gen_rtx_SET (pc_rtx,
+                              gen_rtx_IF_THEN_ELSE (VOIDmode, cmp,
+                                                    dst1, dst2)));
+  DONE;
 })
+
 \f
 (define_insn "trap"
   [(trap_if (const_int 1) (const_int 0))]