From 91f275c144165320850dffffdf18e3a1e059a66c Mon Sep 17 00:00:00 2001
From: Ajit Kumar Agarwal <ajitkum@xhdspdgnu.(none)>
Date: Fri, 6 Mar 2015 09:55:11 +0530
Subject: [PATCH] [Patch,microblaze]: Optimized usage of pcmp conditional instruction.

The changes are made in the patch for optimized usage of pcmpne/pcmpeq
instructions. The xor with register to register is replaced with pcmpeq
/pcmpne instructions and for immediate check still the xori will be used.
The purpose of the change is to acheive the aggressive usage of pcmpne
/pcmpeq instructions instead of xor being used for comparison.

ChangeLog:
2015-03-06  Ajit Agarwal  <ajitkum@xilinx.com>

	* config/microblaze/microblaze.md (cbranchsi4): Added immediate
	constraints.
	(cbranchsi4_reg): New.
	* config/microblaze/microblaze.c
	(microblaze_expand_conditional_branch_reg): New.
	* config/microblaze/microblaze-protos.h
	(microblaze_expand_conditional_branch_reg): New prototype.

Signed-off-by:Ajit Agarwal ajitkum@xilinx.com
---
 gcc/config/microblaze/microblaze-protos.h |    3 +-
 gcc/config/microblaze/microblaze.c        |   45 +++++++++++++++++++++++++++++
 gcc/config/microblaze/microblaze.md       |   23 +++++++++++---
 3 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/gcc/config/microblaze/microblaze-protos.h b/gcc/config/microblaze/microblaze-protos.h
index 57879b1..3ece34e 100644
--- a/gcc/config/microblaze/microblaze-protos.h
+++ b/gcc/config/microblaze/microblaze-protos.h
@@ -32,7 +32,8 @@ extern int microblaze_expand_shift (rtx *);
 extern bool microblaze_expand_move (machine_mode, rtx *);
 extern bool microblaze_expand_block_move (rtx, rtx, rtx, rtx);
 extern void microblaze_expand_divide (rtx *);
-extern void microblaze_expand_conditional_branch (machine_mode, rtx *); 
+extern void microblaze_expand_conditional_branch (machine_mode, rtx *);
+extern void microblaze_expand_conditional_branch_reg (enum machine_mode, rtx *);
 extern void microblaze_expand_conditional_branch_sf (rtx *); 
 extern int microblaze_can_use_return_insn (void);
 extern void print_operand (FILE *, rtx, int);
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 566b78c..9a03d83 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -3459,6 +3459,51 @@ microblaze_expand_conditional_branch (machine_mode mode, rtx operands[])
     }
 }
 
+void
+microblaze_expand_conditional_branch_reg (enum machine_mode mode,
+                                          rtx operands[])
+{
+  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);
+  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)
+    {
+      comp_reg = cmp_op0;
+      condition = gen_rtx_fmt_ee (signed_condition (code),
+                                  SImode, comp_reg, const0_rtx);
+      emit_jump_insn (gen_condjump (condition, label1));
+    }
+  else if (code == EQ)
+    {
+      emit_insn (gen_seq_internal_pat (comp_reg,
+                                       cmp_op0, cmp_op1));
+      condition = gen_rtx_EQ (SImode, comp_reg, const0_rtx);
+      emit_jump_insn (gen_condjump (condition, label1));
+    }
+  else if (code == NE)
+    {
+      emit_insn (gen_sne_internal_pat (comp_reg, cmp_op0,
+                                       cmp_op1));
+      condition = gen_rtx_NE (SImode, comp_reg, const0_rtx);
+      emit_jump_insn (gen_condjump (condition, label1));
+    }
+  else
+    {
+      /* Generate compare and branch in single instruction. */
+      cmp_op1 = force_reg (mode, cmp_op1);
+      condition = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
+      emit_jump_insn (gen_branch_compare (condition, cmp_op0,
+                                         cmp_op1, label1));
+    }
+}
 
 void
 microblaze_expand_conditional_branch_sf (rtx operands[])
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index 67e509c..2c442a5 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -1655,17 +1655,30 @@
 
 (define_expand "cbranchsi4"
   [(set (pc)
-	(if_then_else (match_operator 0 "ordered_comparison_operator"
-		       [(match_operand:SI 1 "register_operand")
-		        (match_operand:SI 2 "arith_operand")])
-		      (label_ref (match_operand 3 ""))
-		      (pc)))]
+        (if_then_else (match_operator 0 "ordered_comparison_operator"
+                       [(match_operand:SI 1 "register_operand")
+                        (match_operand:SI 2 "arith_operand" "I,i")])
+                      (label_ref (match_operand 3 ""))
+                      (pc)))]
   ""
 {
   microblaze_expand_conditional_branch (SImode, operands);
   DONE;
 })
 
+(define_expand "cbranchsi4_reg"
+  [(set (pc)
+        (if_then_else (match_operator 0 "ordered_comparison_operator"
+                       [(match_operand:SI 1 "register_operand")
+                        (match_operand:SI 2 "register_operand")])
+                      (label_ref (match_operand 3 ""))
+                      (pc)))]
+  ""
+{
+  microblaze_expand_conditional_branch_reg (SImode, operands);
+  DONE;
+})
+
 (define_expand "cbranchsf4"
   [(set (pc)
 	(if_then_else (match_operator 0 "ordered_comparison_operator"
-- 
1.7.1

