predicates.md: Add cmp_op predicate.
authorDavid Holsgrove <david.holsgrove@xilinx.com>
Sun, 23 Feb 2014 18:36:38 +0000 (18:36 +0000)
committerMichael Eager <eager@gcc.gnu.org>
Sun, 23 Feb 2014 18:36:38 +0000 (18:36 +0000)
2014-02-23  David Holsgrove <david.holsgrove@xilinx.com>

* config/microblaze/predicates.md: Add cmp_op predicate.
* config/microblaze/microblaze.md: Add branch_compare instruction
which uses cmp_op predicate and emits cmp insn before branch.
* config/microblaze/microblaze.c (microblaze_emit_compare): Rename
to microblaze_expand_conditional_branch and consolidate logic.
(microblaze_expand_conditional_branch): emit branch_compare
insn instead of handling cmp op separate from branch insn.

From-SVN: r208055

gcc/ChangeLog
gcc/config/microblaze/microblaze.c
gcc/config/microblaze/microblaze.md
gcc/config/microblaze/predicates.md

index 7830f3b1c5d21c9e7d27628ee4c92d9943c4ac62..6204106d47068d52ba70b6f9811044aca31cb91f 100644 (file)
@@ -1,3 +1,13 @@
+2014-02-23  David Holsgrove <david.holsgrove@xilinx.com>
+
+       * config/microblaze/predicates.md: Add cmp_op predicate.
+       * config/microblaze/microblaze.md: Add branch_compare instruction 
+       which uses cmp_op predicate and emits cmp insn before branch.
+       * config/microblaze/microblaze.c (microblaze_emit_compare): Rename 
+       to microblaze_expand_conditional_branch and consolidate logic.
+       (microblaze_expand_conditional_branch): emit branch_compare
+       insn instead of handling cmp op separate from branch insn.
+
 2014-02-23  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        * config/rs6000/rs6000.c (rs6000_emit_le_vsx_move): Relax assert
 
 2014-02-23  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
-        * config/rs6000/altivec.md (altivec_lve<VI_char>x): Replace
-        define_insn with define_expand and new define_insn
-        *altivec_lve<VI_char>x_internal.
-        (altivec_stve<VI_char>x): Replace define_insn with define_expand
-        and new define_insn *altivec_stve<VI_char>x_internal.
-        * config/rs6000/rs6000-protos.h (altivec_expand_stvex_be): New
-        prototype.
-        * config/rs6000/rs6000.c (altivec_expand_lvx_be): Document use by
-        lve*x built-ins.
-        (altivec_expand_stvex_be): New function.
+       * config/rs6000/altivec.md (altivec_lve<VI_char>x): Replace
+       define_insn with define_expand and new define_insn
+       *altivec_lve<VI_char>x_internal.
+       (altivec_stve<VI_char>x): Replace define_insn with define_expand
+       and new define_insn *altivec_stve<VI_char>x_internal.
+       * config/rs6000/rs6000-protos.h (altivec_expand_stvex_be): New
+       prototype.
+       * config/rs6000/rs6000.c (altivec_expand_lvx_be): Document use by
+       lve*x built-ins.
+       (altivec_expand_stvex_be): New function.
 
 2014-02-22  Joern Rennecke  <joern.rennecke@embecosm.com>
 
index cd2a788caaeaeeb5b80de2d23fa6d799c747668a..985d26a40cad0fce0e770c025af7198de7d09ca4 100644 (file)
@@ -3257,65 +3257,45 @@ microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
   emit_move_insn (mem, fnaddr);
 }
 \f
-/* Emit instruction to perform compare.  
-   cmp is (compare_op op0 op1).  */
-static rtx
-microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code)
+/* Generate conditional branch -- first, generate test condition,
+   second, generate correct branch instruction.  */
+
+void
+microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
 {
-  rtx cmp_op0 = XEXP (cmp, 0);
-  rtx cmp_op1 = XEXP (cmp, 1);
+  enum rtx_code code = GET_CODE (operands[0]);
+  rtx cmp_op0 = operands[1];
+  rtx cmp_op1 = operands[2];
+  rtx label1 = operands[3];
   rtx comp_reg = gen_reg_rtx (SImode);
-  enum rtx_code code = *cmp_code;
-  
+  rtx condition;
+
   gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
 
   /* If comparing against zero, just test source reg.  */
-  if (cmp_op1 == const0_rtx) 
-    return cmp_op0;
+  if (cmp_op1 == const0_rtx)
+    {
+      comp_reg = cmp_op0;
+      condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx);
+      emit_jump_insn (gen_condjump (condition, label1));
+    }
 
-  if (code == EQ || code == NE)
+  else if (code == EQ || code == NE)
     {
       /* Use xor for equal/not-equal comparison.  */
       emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
+      condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx);
+      emit_jump_insn (gen_condjump (condition, label1));
     }
-  else if (code == GT || code == GTU || code == LE || code == LEU)
-    {
-      /* MicroBlaze compare is not symmetrical.  */
-      /* Swap argument order.  */
-      cmp_op1 = force_reg (mode, cmp_op1);
-      if (code == GT || code == LE) 
-        emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1));
-      else
-        emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1));
-      /* Translate test condition.  */
-      *cmp_code = swap_condition (code);
-    }
-  else /* if (code == GE || code == GEU || code == LT || code == LTU) */
+  else
     {
+      /* Generate compare and branch in single instruction. */
       cmp_op1 = force_reg (mode, cmp_op1);
-      if (code == GE || code == LT) 
-        emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0));
-      else
-        emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0));
+      condition = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
+      emit_jump_insn (gen_branch_compare(condition, cmp_op0, cmp_op1, label1));
     }
-
-  return comp_reg;
 }
 
-/* Generate conditional branch -- first, generate test condition,
-   second, generate correct branch instruction.  */
-
-void
-microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
-{
-  enum rtx_code code = GET_CODE (operands[0]);
-  rtx comp;
-  rtx condition;
-
-  comp = microblaze_emit_compare (mode, operands[0], &code);
-  condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx);
-  emit_jump_insn (gen_condjump (condition, operands[3]));
-}
 
 void
 microblaze_expand_conditional_branch_sf (rtx operands[])
index 01c49e002799c23ee7c287f17c96267784862e20..0e43a65586a6865675a75f0ecbc527a1df7c269a 100644 (file)
   (set_attr "length"   "4")]
 )              
 
-(define_insn "signed_compare"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (unspec
-               [(match_operand:SI 1 "register_operand" "d")
-                (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMP))]
-  ""
-  "cmp\t%0,%1,%2"
-  [(set_attr "type"    "arith")
-  (set_attr "mode"     "SI")
-  (set_attr "length"   "4")])
-
-(define_insn "unsigned_compare"
-  [(set (match_operand:SI 0 "register_operand" "=d")
-       (unspec 
-               [(match_operand:SI 1 "register_operand" "d")
-                (match_operand:SI 2 "register_operand" "d")] UNSPEC_CMPU))]
-  ""
-  "cmpu\t%0,%1,%2"
-  [(set_attr "type"    "arith")
-  (set_attr "mode"     "SI")
-  (set_attr "length"   "4")])
-
 ;;----------------------------------------------------------------
 ;; Setting a register from an floating point comparison. 
 ;;----------------------------------------------------------------
    (set_attr "length"  "4")]
 )
 
+(define_insn "branch_compare"
+  [(set (pc)
+        (if_then_else (match_operator:SI 0 "cmp_op"
+                                         [(match_operand:SI 1 "register_operand" "d")
+                                          (match_operand:SI 2 "register_operand" "d")
+                                         ])
+                      (label_ref (match_operand 3))
+                      (pc)))
+  (clobber(reg:SI R_TMP))]
+  ""
+  {
+    operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
+    enum rtx_code code = GET_CODE (operands[0]);
+
+    if (code == GT || code == LE)
+      {
+        output_asm_insn ("cmp\tr18,%z1,%z2", operands);
+        code = swap_condition (code);
+      }
+    else if (code == GTU || code == LEU)
+      {
+        output_asm_insn ("cmpu\tr18,%z1,%z2", operands);
+        code = swap_condition (code);
+      }
+    else if (code == GE || code == LT)
+      {
+        output_asm_insn ("cmp\tr18,%z2,%z1", operands);
+      }
+    else if (code == GEU || code == LTU)
+      {
+        output_asm_insn ("cmpu\tr18,%z2,%z1", operands);
+      }
+
+    operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx);
+    return "b%C0i%?\tr18,%3";
+  }
+  [(set_attr "type"     "branch")
+   (set_attr "mode"     "none")
+   (set_attr "length"   "12")]
+)
+
 ;;----------------------------------------------------------------
 ;; Unconditional branches
 ;;----------------------------------------------------------------
index f34453ca8eef2f764dcbab48b05a4f377b6d16cd..bfdf4ea810b4573250dee5a390c04bd3fcbdb1ee 100644 (file)
 ;; Test for valid PIC call operand
 (define_predicate "call_insn_plt_operand"
   (match_test "PLT_ADDR_P (op)"))
+
+;; Return if the code of this rtx pattern is a comparison.
+(define_predicate "cmp_op"
+  (match_code "gt,ge,gtu,geu,lt,le,ltu,leu"))