This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 1/3] cond-optab merge target-independent bits


Thank you very much for the review!  I'm applying the suggested changes
right now.

Can you please review the SPARC bits?  They represent quite a nice
cleanup, I attach them so that you do not have to go through the
archives.  I can send you offlist the assembly output diffs for
-march=v8/-m32, -march=v9/-m32, -m64.

Paolo
        * config/sparc/sparc.c (sparc_compare_op0, sparc_compare_op1): Delete.
        (gen_compare_reg): Accept comparison, extract part of it to...
        (gen_compare_reg_1): ... this. 
        (gen_compare_operator): Delete.
        (gen_v9_scc): Accept separate destination, comparison code and arms.
        Do not use sparc_compare_op0/sparc_compare_op1.
        (emit_scc_insn, emit_conditional_branch_insn): New.
        (emit_v9_brxx): Make static.  Remove useless assertion.
        (sparc_emit_float_lib_cmp): Return RTL instead of calling emit_cmp_insn.
        (sparc_expand_compare_and_swap_12): Use gen_compare_reg_1+cbranchcc4.
        * config/sparc/sparc-protos.h (gen_compare_reg,
        sparc_emit_float_lib_cmp): Adjust prototype.
        (emit_scc_insn, emit_conditional_branch_insn): New.
        (gen_v9_scc, emit_v9_brxx_insn, gen_compare_operator): Delete.
        * config/sparc/sparc.h (sparc_compare_op0, sparc_compare_op1): Delete.
        * config/sparc/sparc.md (P, I, F, V32, V32I, V64, V64I): Move all
        iterators to the top.
        (cmpsi, cmpdi, cmpsf, cmpdf, cmptf, seqsi_special_extend,
        snesi_special_extend, sCC, bCC): Delete.
        (cstoresi4, cstoredi4, cstore<F:mode>4, cbranchcc4, cbranchsi4,
        cbranchdi4, cbranch<F:mode>4): New.
        (mov<I:mode>cc, mov<F:mode>cc): Handle sparc_emit_float_lib_cmp
        here.  Use gen_compare_reg instead of gen_compare_operator.
        (conditional_trap): Replace with...
        (ctrapsi4, ctrapdi4): ... this.
        (stack_protect_test): Use cbranchcc4.

Index: sparc.md
===================================================================
--- sparc.md	(.../trunk/gcc/config/sparc)	(revisione 146553)
+++ sparc.md	(.../branches/cond-optab/gcc/config/sparc)	(revisione 146803)
@@ -76,6 +76,18 @@
    (UNSPECV_LDSTUB		10)
   ])
 
+
+(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
+(define_mode_iterator I [QI HI SI DI])
+(define_mode_iterator F [SF DF TF])
+
+;; We don't define V1SI because SI should work just fine.
+(define_mode_iterator V32 [SF V2HI V4QI])
+(define_mode_iterator V32I [SI V2HI V4QI])
+
+(define_mode_iterator V64 [DF V2SI V4HI V8QI])
+(define_mode_iterator V64I [DI V2SI V4HI V8QI])
+
 ;; The upper 32 fp regs on the v9 can't hold SFmode values.  To deal with this
 ;; a second register class, EXTRA_FP_REGS, exists for the v9 chip.  The name
 ;; is a bit of a misnomer as it covers all 64 fp regs.  The corresponding
@@ -330,84 +342,11 @@
 
 ;; Compare instructions.
 
-;; We generate RTL for comparisons and branches by having the cmpxx 
-;; patterns store away the operands.  Then, the scc and bcc patterns
-;; emit RTL for both the compare and the branch.
-;;
-;; We do this because we want to generate different code for an sne and
-;; seq insn.  In those cases, if the second operand of the compare is not
-;; const0_rtx, we want to compute the xor of the two operands and test
-;; it against zero.
-;;
-;; We start with the DEFINE_EXPANDs, then the DEFINE_INSNs to match
-;; the patterns.  Finally, we have the DEFINE_SPLITs for some of the scc
-;; insns that actually require more than one machine instruction.
-
-(define_expand "cmpsi"
-  [(set (reg:CC 100)
-	(compare:CC (match_operand:SI 0 "compare_operand" "")
-		    (match_operand:SI 1 "arith_operand" "")))]
-  ""
-{
-  if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
-    operands[0] = force_reg (SImode, operands[0]);
-
-  sparc_compare_op0 = operands[0];
-  sparc_compare_op1 = operands[1];
-  DONE;
-})
-
-(define_expand "cmpdi"
-  [(set (reg:CCX 100)
-	(compare:CCX (match_operand:DI 0 "compare_operand" "")
-		     (match_operand:DI 1 "arith_operand" "")))]
-  "TARGET_ARCH64"
-{
-  if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
-    operands[0] = force_reg (DImode, operands[0]);
-
-  sparc_compare_op0 = operands[0];
-  sparc_compare_op1 = operands[1];
-  DONE;
-})
-
-(define_expand "cmpsf"
-  ;; The 96 here isn't ever used by anyone.
-  [(set (reg:CCFP 96)
-	(compare:CCFP (match_operand:SF 0 "register_operand" "")
-		      (match_operand:SF 1 "register_operand" "")))]
-  "TARGET_FPU"
-{
-  sparc_compare_op0 = operands[0];
-  sparc_compare_op1 = operands[1];
-  DONE;
-})
-
-(define_expand "cmpdf"
-  ;; The 96 here isn't ever used by anyone.
-  [(set (reg:CCFP 96)
-	(compare:CCFP (match_operand:DF 0 "register_operand" "")
-		      (match_operand:DF 1 "register_operand" "")))]
-  "TARGET_FPU"
-{
-  sparc_compare_op0 = operands[0];
-  sparc_compare_op1 = operands[1];
-  DONE;
-})
-
-(define_expand "cmptf"
-  ;; The 96 here isn't ever used by anyone.
-  [(set (reg:CCFP 96)
-	(compare:CCFP (match_operand:TF 0 "register_operand" "")
-		      (match_operand:TF 1 "register_operand" "")))]
-  "TARGET_FPU"
-{
-  sparc_compare_op0 = operands[0];
-  sparc_compare_op1 = operands[1];
-  DONE;
-})
+;; These are just the DEFINE_INSNs to match the patterns and the
+;; DEFINE_SPLITs for some of the scc insns that actually require
+;; more than one machine instruction.  DEFINE_EXPANDs are further down.
 
-;; Now the compare DEFINE_INSNs.
+;; The compare DEFINE_INSNs.
 
 (define_insn "*cmpsi_insn"
   [(set (reg:CC 100)
@@ -499,12 +438,41 @@
 }
   [(set_attr "type" "fpcmp")])
 
-;; Next come the scc insns.  For seq, sne, sgeu, and sltu, we can do this
-;; without jumps using the addx/subx instructions.  For seq/sne on v9 we use
-;; the same code as v8 (the addx/subx method has more applications).  The
-;; exception to this is "reg != 0" which can be done in one instruction on v9
-;; (so we do it).  For the rest, on v9 we use conditional moves; on v8, we do
-;; branches.
+;; Next come the scc insns.
+
+(define_expand "cstoresi4"
+  [(use (match_operator 1 "comparison_operator"
+         [(match_operand:SI 2 "compare_operand" "")
+          (match_operand:SI 3 "arith_operand" "")]))
+   (clobber (match_operand:SI 0 "register_operand"))]
+  ""
+{
+  if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx)
+    operands[1] = force_reg (SImode, operands[1]);
+  if (emit_scc_insn (operands)) DONE; else FAIL;
+})
+
+(define_expand "cstoredi4"
+  [(use (match_operator 1 "comparison_operator"
+         [(match_operand:DI 2 "compare_operand" "")
+          (match_operand:DI 3 "arith_operand" "")]))
+   (clobber (match_operand:SI 0 "register_operand"))]
+  "TARGET_ARCH64"
+{
+  if (GET_CODE (operands[1]) == ZERO_EXTRACT && operands[2] != const0_rtx)
+    operands[1] = force_reg (DImode, operands[1]);
+  if (emit_scc_insn (operands)) DONE; else FAIL;
+})
+
+(define_expand "cstore<F:mode>4"
+  [(use (match_operator 1 "comparison_operator"
+         [(match_operand:F 2 "register_operand" "")
+          (match_operand:F 3 "register_operand" "")]))
+   (clobber (match_operand:SI 0 "register_operand"))]
+  "TARGET_FPU"
+  { if (emit_scc_insn (operands)) DONE; else FAIL; })
+
+
 
 ;; Seq_special[_xxx] and sne_special[_xxx] clobber the CC reg, because they
 ;; generate addcc/subcc instructions.
@@ -565,315 +533,6 @@
   "TARGET_ARCH64"
   { operands[3] = gen_reg_rtx (DImode); })
 
-(define_expand "seqsi_special_extend"
-  [(set (match_dup 3)
-	(xor:SI (match_operand:SI 1 "register_operand" "")
-		(match_operand:SI 2 "register_operand" "")))
-   (parallel [(set (match_operand:DI 0 "register_operand" "")
-		   (eq:DI (match_dup 3) (const_int 0)))
-	      (clobber (reg:CC 100))])]
-  "TARGET_ARCH64"
-  { operands[3] = gen_reg_rtx (SImode); })
-
-(define_expand "snesi_special_extend"
-  [(set (match_dup 3)
-	(xor:SI (match_operand:SI 1 "register_operand" "")
-		(match_operand:SI 2 "register_operand" "")))
-   (parallel [(set (match_operand:DI 0 "register_operand" "")
-		   (ne:DI (match_dup 3) (const_int 0)))
-	      (clobber (reg:CC 100))])]
-  "TARGET_ARCH64"
-  { operands[3] = gen_reg_rtx (SImode); })
-
-;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
-;; However, the code handles both SImode and DImode.
-(define_expand "seq"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(eq:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == SImode)
-    {
-      rtx pat;
-
-      if (GET_MODE (operands[0]) == SImode)
-	pat = gen_seqsi_special (operands[0], sparc_compare_op0,
-				 sparc_compare_op1);
-      else if (! TARGET_ARCH64)
-	FAIL;
-      else
-	pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
-					sparc_compare_op1);
-      emit_insn (pat);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == DImode)
-    {
-      rtx pat;
-
-      if (! TARGET_ARCH64)
-	FAIL;
-      else if (GET_MODE (operands[0]) == SImode)
-	pat = gen_seqdi_special_trunc (operands[0], sparc_compare_op0,
-				       sparc_compare_op1);
-      else
-	pat = gen_seqdi_special (operands[0], sparc_compare_op0,
-				 sparc_compare_op1);
-      emit_insn (pat);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
-      gcc_assert (code == NE);
-      emit_insn (gen_sne (operands[0]));
-      DONE;
-    }
-  else if (TARGET_V9)
-    {
-      if (gen_v9_scc (EQ, operands))
-	DONE;
-      /* fall through */
-    }
-  FAIL;
-})
-
-;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
-;; However, the code handles both SImode and DImode.
-(define_expand "sne"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(ne:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == SImode)
-    {
-      rtx pat;
-
-      if (GET_MODE (operands[0]) == SImode)
-	pat = gen_snesi_special (operands[0], sparc_compare_op0,
-				 sparc_compare_op1);
-      else if (! TARGET_ARCH64)
-	FAIL;
-      else
-	pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
-					sparc_compare_op1);
-      emit_insn (pat);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == DImode)
-    {
-      rtx pat;
-
-      if (! TARGET_ARCH64)
-	FAIL;
-      else if (GET_MODE (operands[0]) == SImode)
-	pat = gen_snedi_special_trunc (operands[0], sparc_compare_op0,
-				       sparc_compare_op1);
-      else
-	pat = gen_snedi_special (operands[0], sparc_compare_op0,
-				 sparc_compare_op1);
-      emit_insn (pat);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
-      gcc_assert (code == NE);
-      emit_insn (gen_sne (operands[0]));
-      DONE;
-    }
-  else if (TARGET_V9)
-    {
-      if (gen_v9_scc (NE, operands))
-	DONE;
-      /* fall through */
-    }
-  FAIL;
-})
-
-(define_expand "sgt"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(gt:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
-      gcc_assert (code == NE);
-      emit_insn (gen_sne (operands[0]));
-      DONE;
-    }
-  else if (TARGET_V9)
-    {
-      if (gen_v9_scc (GT, operands))
-	DONE;
-      /* fall through */
-    }
-  FAIL;
-})
-
-(define_expand "slt"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(lt:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
-      gcc_assert (code == NE);
-      emit_insn (gen_sne (operands[0]));
-      DONE;
-    }
-  else if (TARGET_V9)
-    {
-      if (gen_v9_scc (LT, operands))
-	DONE;
-      /* fall through */
-    }
-  FAIL;
-})
-
-(define_expand "sge"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(ge:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
-      gcc_assert (code == NE);
-      emit_insn (gen_sne (operands[0]));
-      DONE;
-    }
-  else if (TARGET_V9)
-    {
-      if (gen_v9_scc (GE, operands))
-	DONE;
-      /* fall through */
-    }
-  FAIL;
-})
-
-(define_expand "sle"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(le:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
-      gcc_assert (code == NE);
-      emit_insn (gen_sne (operands[0]));
-      DONE;
-    }
-  else if (TARGET_V9)
-    {
-      if (gen_v9_scc (LE, operands))
-	DONE;
-      /* fall through */
-    }
-  FAIL;
-})
-
-(define_expand "sgtu"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(gtu:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (! TARGET_V9)
-    {
-      rtx tem, pat;
-
-      /* We can do ltu easily, so if both operands are registers, swap them and
-	 do a LTU.  */
-      if ((GET_CODE (sparc_compare_op0) == REG
-	   || GET_CODE (sparc_compare_op0) == SUBREG)
-	  && (GET_CODE (sparc_compare_op1) == REG
-	      || GET_CODE (sparc_compare_op1) == SUBREG))
-	{
-	  tem = sparc_compare_op0;
-	  sparc_compare_op0 = sparc_compare_op1;
-	  sparc_compare_op1 = tem;
-	  pat = gen_sltu (operands[0]);
-          if (pat == NULL_RTX)
-            FAIL;
-          emit_insn (pat);
-	  DONE;
-	}
-    }
-  else
-    {
-      if (gen_v9_scc (GTU, operands))
-	DONE;
-    }
-  FAIL;
-})
-
-(define_expand "sltu"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(ltu:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (TARGET_V9)
-    {
-      if (gen_v9_scc (LTU, operands))
-	DONE;
-    }
-  operands[1] = gen_compare_reg (LTU);
-})
-
-(define_expand "sgeu"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(geu:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (TARGET_V9)
-    {
-      if (gen_v9_scc (GEU, operands))
-	DONE;
-    }
-  operands[1] = gen_compare_reg (GEU);
-})
-
-(define_expand "sleu"
-  [(set (match_operand:SI 0 "int_register_operand" "")
-	(leu:SI (match_dup 1) (const_int 0)))]
-  ""
-{
-  if (! TARGET_V9)
-    {
-      rtx tem, pat;
-
-      /* We can do geu easily, so if both operands are registers, swap them and
-	 do a GEU.  */
-      if ((GET_CODE (sparc_compare_op0) == REG
-	   || GET_CODE (sparc_compare_op0) == SUBREG)
-	  && (GET_CODE (sparc_compare_op1) == REG
-	      || GET_CODE (sparc_compare_op1) == SUBREG))
-	{
-	  tem = sparc_compare_op0;
-	  sparc_compare_op0 = sparc_compare_op1;
-	  sparc_compare_op1 = tem;
-	  pat = gen_sgeu (operands[0]);
-          if (pat == NULL_RTX)
-            FAIL;
-          emit_insn (pat);
-	  DONE;
-	}
-    }
-  else
-    {
-      if (gen_v9_scc (LEU, operands))
-	DONE;
-    }
-  FAIL;
-})
 
 ;; Now the DEFINE_INSNs for the scc cases.
 
@@ -1265,344 +924,51 @@
 
 ;; These control RTL generation for conditional jump insns
 
-;; The quad-word fp compare library routines all return nonzero to indicate
-;; true, which is different from the equivalent libgcc routines, so we must
-;; handle them specially here.
-
-(define_expand "beq"
-  [(set (pc)
-	(if_then_else (eq (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
-      && GET_CODE (sparc_compare_op0) == REG
-      && GET_MODE (sparc_compare_op0) == DImode)
-    {
-      emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (EQ);
-})
-
-(define_expand "bne"
-  [(set (pc)
-	(if_then_else (ne (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
-      && GET_CODE (sparc_compare_op0) == REG
-      && GET_MODE (sparc_compare_op0) == DImode)
-    {
-      emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (NE);
-})
-
-(define_expand "bgt"
-  [(set (pc)
-	(if_then_else (gt (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
-      && GET_CODE (sparc_compare_op0) == REG
-      && GET_MODE (sparc_compare_op0) == DImode)
-    {
-      emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (GT);
-})
-
-(define_expand "bgtu"
-  [(set (pc)
-	(if_then_else (gtu (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  operands[1] = gen_compare_reg (GTU);
-})
-
-(define_expand "blt"
-  [(set (pc)
-	(if_then_else (lt (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
-      && GET_CODE (sparc_compare_op0) == REG
-      && GET_MODE (sparc_compare_op0) == DImode)
-    {
-      emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (LT);
-})
-
-(define_expand "bltu"
-  [(set (pc)
-	(if_then_else (ltu (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  operands[1] = gen_compare_reg (LTU);
-})
-
-(define_expand "bge"
+(define_expand "cbranchcc4"
   [(set (pc)
-	(if_then_else (ge (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
+	(if_then_else (match_operator 0 "comparison_operator"
+		          [(match_operand 1 "compare_operand" "")
+		           (match_operand 2 "const_zero_operand" "")])
+		      (label_ref (match_operand 3 "" ""))
 		      (pc)))]
   ""
-{
-  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
-      && GET_CODE (sparc_compare_op0) == REG
-      && GET_MODE (sparc_compare_op0) == DImode)
-    {
-      emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (GE);
-})
-
-(define_expand "bgeu"
-  [(set (pc)
-	(if_then_else (geu (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  operands[1] = gen_compare_reg (GEU);
-})
-
-(define_expand "ble"
-  [(set (pc)
-	(if_then_else (le (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
-      && GET_CODE (sparc_compare_op0) == REG
-      && GET_MODE (sparc_compare_op0) == DImode)
-    {
-      emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
-      DONE;
-    }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (LE);
-})
-
-(define_expand "bleu"
-  [(set (pc)
-	(if_then_else (leu (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  operands[1] = gen_compare_reg (LEU);
-})
-
-(define_expand "bunordered"
-  [(set (pc)
-	(if_then_else (unordered (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNORDERED);
-      gcc_assert (code == EQ);
-      emit_jump_insn (gen_beq (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (UNORDERED);
-})
-
-(define_expand "bordered"
-  [(set (pc)
-	(if_then_else (ordered (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (ORDERED);
-})
-
-(define_expand "bungt"
-  [(set (pc)
-	(if_then_else (ungt (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
-      gcc_assert (code == GT);
-      emit_jump_insn (gen_bgt (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (UNGT);
-})
+  "")
 
-(define_expand "bunlt"
-  [(set (pc)
-	(if_then_else (unlt (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
+(define_expand "cbranchsi4"
+  [(use (match_operator 0 "comparison_operator"
+         [(match_operand:SI 1 "compare_operand" "")
+          (match_operand:SI 2 "arith_operand" "")]))
+   (use (match_operand 3 ""))]
   ""
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (UNLT);
+  if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
+    operands[0] = force_reg (SImode, operands[0]);
+  emit_conditional_branch_insn (operands);
+  DONE;
 })
 
-(define_expand "buneq"
-  [(set (pc)
-	(if_then_else (uneq (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
+(define_expand "cbranchdi4"
+  [(use (match_operator 0 "comparison_operator"
+         [(match_operand:DI 1 "compare_operand" "")
+          (match_operand:DI 2 "arith_operand" "")]))
+   (use (match_operand 3 ""))]
+  "TARGET_ARCH64"
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
-      gcc_assert (code == EQ);
-      emit_jump_insn (gen_beq (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (UNEQ);
+  if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
+    operands[0] = force_reg (DImode, operands[0]);
+  emit_conditional_branch_insn (operands);
+  DONE;
 })
 
-(define_expand "bunge"
-  [(set (pc)
-	(if_then_else (unge (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (UNGE);
-})
+(define_expand "cbranch<F:mode>4"
+  [(use (match_operator 0 "comparison_operator"
+         [(match_operand:F 1 "register_operand" "")
+          (match_operand:F 2 "register_operand" "")]))
+   (use (match_operand 3 ""))]
+  "TARGET_FPU"
+  { emit_conditional_branch_insn (operands); DONE; })
 
-(define_expand "bunle"
-  [(set (pc)
-	(if_then_else (unle (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (UNLE);
-})
 
-(define_expand "bltgt"
-  [(set (pc)
-	(if_then_else (ltgt (match_dup 1) (const_int 0))
-		      (label_ref (match_operand 0 "" ""))
-		      (pc)))]
-  ""
-{
-  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
-    {
-      enum rtx_code code
-        = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT);
-      gcc_assert (code == NE);
-      emit_jump_insn (gen_bne (operands[0]));
-      DONE;
-    }
-  operands[1] = gen_compare_reg (LTGT);
-})
-
 ;; Now match both normal and inverted jump.
 
 ;; XXX fpcmp nop braindamage
@@ -1745,8 +1111,6 @@
    (set_attr "branch_type" "reg")])
 
 
-(define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
-
 ;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic
 ;; value subject to a PC-relative relocation.  Operand 2 is a helper function
 ;; that adds the PC value at the call point to operand 0.
@@ -2383,9 +1747,6 @@
 
 ;; Floating point and vector move instructions
 
-;; We don't define V1SI because SI should work just fine.
-(define_mode_iterator V32 [SF V2HI V4QI])
-
 ;; Yes, you guessed it right, the former movsf expander.
 (define_expand "mov<V32:mode>"
   [(set (match_operand:V32 0 "nonimmediate_operand" "")
@@ -2520,8 +1881,6 @@
   [(set (match_dup 0) (high:SF (match_dup 1)))
    (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
 
-(define_mode_iterator V64 [DF V2SI V4HI V8QI])
-
 ;; Yes, you again guessed it right, the former movdf expander.
 (define_expand "mov<V64:mode>"
   [(set (match_operand:V64 0 "nonimmediate_operand" "")
@@ -3063,8 +2422,6 @@
 ;; 3 contains the constant if one is present, but we handle either for
 ;; generality (sparc.c puts a constant in operand 2).
 
-(define_mode_iterator I [QI HI SI DI])
-
 (define_expand "mov<I:mode>cc"
   [(set (match_operand:I 0 "register_operand" "")
 	(if_then_else:I (match_operand 1 "comparison_operator" "")
@@ -3073,21 +2430,27 @@
   "TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
 {
   enum rtx_code code = GET_CODE (operands[1]);
+  rtx cc_reg;
 
-  if (GET_MODE (sparc_compare_op0) == DImode
+  if (GET_MODE (XEXP (operands[1], 0)) == DImode
       && ! TARGET_ARCH64)
     FAIL;
 
-  if (sparc_compare_op1 == const0_rtx
-      && GET_CODE (sparc_compare_op0) == REG
-      && GET_MODE (sparc_compare_op0) == DImode
+  if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
+    operands[1]
+      = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
+				  GET_CODE (operands[1]));
+
+  if (XEXP (operands[1], 1) == const0_rtx
+      && GET_CODE (XEXP (operands[1], 0)) == REG
+      && GET_MODE (XEXP (operands[1], 0)) == DImode
       && v9_regcmp_p (code))
-    operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx);
+    cc_reg = XEXP (operands[1], 0);
   else
-    operands[1] = gen_compare_operator (code);
-})
+    cc_reg = gen_compare_reg (operands[1]);
 
-(define_mode_iterator F [SF DF TF])
+  operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
+})
 
 (define_expand "mov<F:mode>cc"
   [(set (match_operand:F 0 "register_operand" "")
@@ -3097,18 +2460,26 @@
   "TARGET_V9 && TARGET_FPU"
 {
   enum rtx_code code = GET_CODE (operands[1]);
+  rtx cc_reg;
 
-  if (GET_MODE (sparc_compare_op0) == DImode
+  if (GET_MODE (XEXP (operands[1], 0)) == DImode
       && ! TARGET_ARCH64)
     FAIL;
 
-  if (sparc_compare_op1 == const0_rtx
-      && GET_CODE (sparc_compare_op0) == REG
-      && GET_MODE (sparc_compare_op0) == DImode
+  if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
+    operands[1]
+      = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
+				  GET_CODE (operands[1]));
+
+  if (XEXP (operands[1], 1) == const0_rtx
+      && GET_CODE (XEXP (operands[1], 0)) == REG
+      && GET_MODE (XEXP (operands[1], 0)) == DImode
       && v9_regcmp_p (code))
-    operands[1] = gen_rtx_fmt_ee (code, DImode, sparc_compare_op0, const0_rtx);
+    cc_reg = XEXP (operands[1], 0);
   else
-    operands[1] = gen_compare_operator (code);
+    cc_reg = gen_compare_reg (operands[1]);
+
+  operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
 })
 
 ;; Conditional move define_insns
@@ -5123,9 +4494,6 @@
 ;; We define DImode `and' so with DImode `not' we can get
 ;; DImode `andn'.  Other combinations are possible.
 
-(define_mode_iterator V64I [DI V2SI V4HI V8QI])
-(define_mode_iterator V32I [SI V2HI V4QI])
-
 (define_expand "and<V64I:mode>3"
   [(set (match_operand:V64I 0 "register_operand" "")
 	(and:V64I (match_operand:V64I 1 "arith_double_operand" "")
@@ -7424,14 +6792,28 @@
   "ta\t5"
   [(set_attr "type" "trap")])
 
-(define_expand "conditional_trap"
-  [(trap_if (match_operator 0 "noov_compare_operator" [(match_dup 2) (match_dup 3)])
-	    (match_operand:SI 1 "arith_operand" ""))]
+(define_expand "ctrapsi4"
+  [(trap_if (match_operator 0 "noov_compare_operator"
+	     [(match_operand:SI 1 "compare_operand" "")
+	      (match_operand:SI 2 "arith_operand" "")])
+	   (match_operand 3 ""))]
   ""
-  "operands[2] = gen_compare_reg (GET_CODE (operands[0]));
-   if (GET_MODE (operands[2]) != CCmode && GET_MODE (operands[2]) != CCXmode)
+  "operands[1] = gen_compare_reg (operands[0]);
+   if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode)
      FAIL;
-   operands[3] = const0_rtx;")
+   operands[2] = const0_rtx;")
+
+(define_expand "ctrapdi4"
+  [(trap_if (match_operator 0 "noov_compare_operator"
+	     [(match_operand:DI 1 "compare_operand" "")
+	      (match_operand:DI 2 "arith_operand" "")])
+	   (match_operand 3 ""))]
+  "TARGET_ARCH64"
+  "operands[1] = gen_compare_reg (operands[0]);
+   if (GET_MODE (operands[1]) != CCmode && GET_MODE (operands[1]) != CCXmode)
+     FAIL;
+   operands[2] = const0_rtx;")
+
 
 (define_insn ""
   [(trap_if (match_operator 0 "noov_compare_operator" [(reg:CC 100) (const_int 0)])
@@ -8061,6 +7443,7 @@
    (match_operand 2 "" "")]
   ""
 {
+  rtx result, test;
 #ifdef TARGET_THREAD_SSP_OFFSET
   rtx tlsreg = gen_rtx_REG (Pmode, 7);
   rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
@@ -8068,18 +7451,18 @@
 #endif
   if (TARGET_ARCH64)
     {
-      rtx temp = gen_reg_rtx (Pmode);
-      emit_insn (gen_stack_protect_testdi (temp, operands[0], operands[1]));
-      sparc_compare_op0 = temp;
-      sparc_compare_op1 = const0_rtx;
+      result = gen_reg_rtx (Pmode);
+      emit_insn (gen_stack_protect_testdi (result, operands[0], operands[1]));
+      test = gen_rtx_EQ (VOIDmode, result, const0_rtx);
+      emit_jump_insn (gen_cbranchdi4 (test, result, const0_rtx, operands[2]));
     }
   else
     {
       emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
-      sparc_compare_op0 = gen_rtx_REG (CCmode, SPARC_ICC_REG);
-      sparc_compare_op1 = const0_rtx;
+      result = gen_rtx_REG (CCmode, SPARC_ICC_REG);
+      test = gen_rtx_EQ (VOIDmode, result, const0_rtx);
+      emit_jump_insn (gen_cbranchcc4 (test, result, const0_rtx, operands[2]));
     }
-  emit_jump_insn (gen_beq (operands[2]));
   DONE;
 })
 
Index: sparc-protos.h
===================================================================
--- sparc-protos.h	(.../trunk/gcc/config/sparc)	(revisione 146553)
+++ sparc-protos.h	(.../branches/cond-optab/gcc/config/sparc)	(revisione 146803)
@@ -54,16 +54,14 @@ extern void sparc_output_scratch_registe
 #ifdef RTX_CODE
 extern enum machine_mode select_cc_mode (enum rtx_code, rtx, rtx);
 /* Define the function that build the compare insn for scc and bcc.  */
-extern rtx gen_compare_reg (enum rtx_code code);
-extern rtx gen_compare_operator (enum rtx_code code);
-extern enum rtx_code sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code);
+extern rtx gen_compare_reg (rtx cmp);
+extern rtx sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code);
 extern void sparc_emit_floatunsdi (rtx [2], enum machine_mode);
 extern void sparc_emit_fixunsdi (rtx [2], enum machine_mode);
 extern void emit_tfmode_binop (enum rtx_code, rtx *);
 extern void emit_tfmode_unop (enum rtx_code, rtx *);
 extern void emit_tfmode_cvt (enum rtx_code, rtx *);
 /* This function handles all v9 scc insns */
-extern int gen_v9_scc (enum rtx_code, rtx *);
 extern void sparc_initialize_trampoline (rtx, rtx, rtx);
 extern void sparc64_initialize_trampoline (rtx, rtx, rtx);
 extern bool legitimate_constant_p (rtx);
@@ -87,7 +85,8 @@ extern const char *output_return (rtx);
 extern const char *output_sibcall (rtx, rtx);
 extern const char *output_v8plus_shift (rtx *, rtx, const char *);
 extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx);
-extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx);
+extern bool emit_scc_insn (rtx []);
+extern void emit_conditional_branch_insn (rtx []);
 extern void print_operand (FILE *, rtx, int);
 extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
 extern int arith_double_4096_operand (rtx, enum machine_mode);
Index: sparc.c
===================================================================
--- sparc.c	(.../trunk/gcc/config/sparc)	(revisione 146553)
+++ sparc.c	(.../branches/cond-optab/gcc/config/sparc)	(revisione 146803)
@@ -280,10 +280,6 @@ static GTY(()) alias_set_type sparc_sr_a
 /* The alias set for the structure return value.  */
 static GTY(()) alias_set_type struct_value_alias_set;
 
-/* Save the operands last given to a compare for use when we
-   generate a scc or bcc insn.  */
-rtx sparc_compare_op0, sparc_compare_op1;
-
 /* Vector to say how input registers are mapped to output registers.
    HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
    eliminate it.  You must use -fomit-frame-pointer to get that.  */
@@ -2003,17 +1999,15 @@ select_cc_mode (enum rtx_code op, rtx x,
 
 /* Emit the compare insn and return the CC reg for a CODE comparison.  */
 
-rtx
-gen_compare_reg (enum rtx_code code)
+static rtx
+gen_compare_reg_1 (enum rtx_code code, rtx x, rtx y)
 {
   enum machine_mode mode;
-  rtx x, y, cc_reg;
+  rtx cc_reg;
 
-  if (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_CC)
-    return sparc_compare_op0;
+  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
+    return x;
 
-  x = sparc_compare_op0;
-  y = sparc_compare_op1;
   mode = SELECT_CC_MODE (code, x, y);
 
   /* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
@@ -2069,25 +2063,16 @@ gen_compare_reg (enum rtx_code code)
   return cc_reg;
 }
 
-/* Same as above but return the whole compare operator.  */
-
 rtx
-gen_compare_operator (enum rtx_code code)
+gen_compare_reg (rtx cmp)
 {
-  rtx cc_reg;
-
-  if (GET_MODE (sparc_compare_op0) == TFmode && !TARGET_HARD_QUAD)
-    code
-      = sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, code);
-
-  cc_reg = gen_compare_reg (code);
-  return gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
+  return gen_compare_reg_1 (GET_CODE (cmp), XEXP (cmp, 0), XEXP (cmp, 1));
 }
 
 /* This function is used for v9 only.
    CODE is the code for an Scc's comparison.
-   OPERANDS[0] is the target of the Scc insn.
-   OPERANDS[1] is the value we compare against const0_rtx (which hasn't
+   DEST is the target of the Scc insn.
+   X is the value we compare against const0_rtx (which hasn't
    been generated yet).
 
    This function is needed to turn
@@ -2102,53 +2087,50 @@ gen_compare_operator (enum rtx_code code
 
    IE: The instruction recognizer needs to see the mode of the comparison to
    find the right instruction. We could use "gt:DI" right in the
-   define_expand, but leaving it out allows us to handle DI, SI, etc.
-
-   We refer to the global sparc compare operands sparc_compare_op0 and
-   sparc_compare_op1.  */
+   define_expand, but leaving it out allows us to handle DI, SI, etc.  */
 
-int
-gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
+static int
+gen_v9_scc (rtx dest, enum rtx_code compare_code, rtx x, rtx y)
 {
   if (! TARGET_ARCH64
-      && (GET_MODE (sparc_compare_op0) == DImode
-	  || GET_MODE (operands[0]) == DImode))
+      && (GET_MODE (x) == DImode
+	  || GET_MODE (dest) == DImode))
     return 0;
 
   /* Try to use the movrCC insns.  */
   if (TARGET_ARCH64
-      && GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT
-      && sparc_compare_op1 == const0_rtx
+      && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
+      && y == const0_rtx
       && v9_regcmp_p (compare_code))
     {
-      rtx op0 = sparc_compare_op0;
+      rtx op0 = x;
       rtx temp;
 
       /* Special case for op0 != 0.  This can be done with one instruction if
-	 operands[0] == sparc_compare_op0.  */
+	 dest == x.  */
 
       if (compare_code == NE
-	  && GET_MODE (operands[0]) == DImode
-	  && rtx_equal_p (op0, operands[0]))
+	  && GET_MODE (dest) == DImode
+	  && rtx_equal_p (op0, dest))
 	{
-	  emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+	  emit_insn (gen_rtx_SET (VOIDmode, dest,
 			      gen_rtx_IF_THEN_ELSE (DImode,
 				       gen_rtx_fmt_ee (compare_code, DImode,
 						       op0, const0_rtx),
 				       const1_rtx,
-				       operands[0])));
+				       dest)));
 	  return 1;
 	}
 
-      if (reg_overlap_mentioned_p (operands[0], op0))
+      if (reg_overlap_mentioned_p (dest, op0))
 	{
-	  /* Handle the case where operands[0] == sparc_compare_op0.
+	  /* Handle the case where dest == x.
 	     We "early clobber" the result.  */
-	  op0 = gen_reg_rtx (GET_MODE (sparc_compare_op0));
-	  emit_move_insn (op0, sparc_compare_op0);
+	  op0 = gen_reg_rtx (GET_MODE (x));
+	  emit_move_insn (op0, x);
 	}
 
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
+      emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx));
       if (GET_MODE (op0) != DImode)
 	{
 	  temp = gen_reg_rtx (DImode);
@@ -2156,47 +2138,137 @@ gen_v9_scc (enum rtx_code compare_code, 
 	}
       else
 	temp = op0;
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-			  gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+      emit_insn (gen_rtx_SET (VOIDmode, dest,
+			  gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
 				   gen_rtx_fmt_ee (compare_code, DImode,
 						   temp, const0_rtx),
 				   const1_rtx,
-				   operands[0])));
+				   dest)));
       return 1;
     }
   else
     {
-      operands[1] = gen_compare_reg (compare_code);
+      x = gen_compare_reg_1 (compare_code, x, y);
+      y = const0_rtx;
 
-      switch (GET_MODE (operands[1]))
-	{
-	  case CCmode :
-	  case CCXmode :
-	  case CCFPEmode :
-	  case CCFPmode :
-	    break;
-	  default :
-	    gcc_unreachable ();
-	}
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
-      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
-			  gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+      gcc_assert (GET_MODE (x) != CC_NOOVmode
+		  && GET_MODE (x) != CCX_NOOVmode);
+
+      emit_insn (gen_rtx_SET (VOIDmode, dest, const0_rtx));
+      emit_insn (gen_rtx_SET (VOIDmode, dest,
+			  gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
 				   gen_rtx_fmt_ee (compare_code,
-						   GET_MODE (operands[1]),
-						   operands[1], const0_rtx),
-				    const1_rtx, operands[0])));
+						   GET_MODE (x), x, y),
+				    const1_rtx, dest)));
       return 1;
     }
 }
 
+
+/* Emit an scc insn.  For seq, sne, sgeu, and sltu, we can do this
+   without jumps using the addx/subx instructions.  */
+
+bool
+emit_scc_insn (rtx operands[])
+{
+  rtx tem;
+  rtx x;
+  rtx y;
+  enum rtx_code code;
+
+  /* The quad-word fp compare library routines all return nonzero to indicate
+     true, which is different from the equivalent libgcc routines, so we must
+     handle them specially here.  */
+  if (GET_MODE (operands[2]) == TFmode && ! TARGET_HARD_QUAD)
+    {
+      operands[1] = sparc_emit_float_lib_cmp (operands[2], operands[3],
+					      GET_CODE (operands[1]));
+      operands[2] = XEXP (operands[1], 0);
+      operands[3] = XEXP (operands[1], 1);
+    }
+
+  code = GET_CODE (operands[1]);
+  x = operands[2];
+  y = operands[3];
+
+  /* For seq/sne on v9 we use the same code as v8 (the addx/subx method has
+     more applications).  The exception to this is "reg != 0" which can
+     be done in one instruction on v9 (so we do it).  */
+  if (code == EQ)
+    {
+      if (GET_MODE (x) == SImode)
+        {
+          rtx pat = gen_seqsi_special (operands[0], x, y);
+          emit_insn (pat);
+          return true;
+        }
+      else if (GET_MODE (x) == DImode)
+        {
+          rtx pat = gen_seqdi_special_trunc (operands[0], x, y);
+          emit_insn (pat);
+          return true;
+        }
+    }
+
+  if (code == NE)
+    {
+      if (GET_MODE (x) == SImode)
+        {
+          rtx pat = gen_snesi_special (operands[0], x, y);
+          emit_insn (pat);
+          return true;
+        }
+      else if (GET_MODE (x) == DImode)
+        {
+          rtx pat = gen_snedi_special_trunc (operands[0], x, y);
+          emit_insn (pat);
+          return true;
+        }
+    }
+
+  /* For the rest, on v9 we can use conditional moves.  */
+
+  if (TARGET_V9)
+    {
+      if (gen_v9_scc (operands[0], code, x, y))
+        return true;
+    }
+
+    /* We can do LTU and GEU using the addx/subx instructions too.  And
+       for GTU/LEU, if both operands are registers swap them and fall
+       back to the easy case.  */
+  if (code == GTU || code == LEU)
+    {
+      if ((GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
+          && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG))
+        {
+          tem = x;
+          x = y;
+          y = tem;
+          code = swap_condition (code);
+        }
+    }
+
+  if (code == LTU || code == GEU)
+    {
+      emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+			      gen_rtx_fmt_ee (code, SImode, 
+					      gen_compare_reg_1 (code, x, y),
+					      const0_rtx)));
+      return true;
+    }
+
+  /* Nope, do branches.  */
+  return false;
+}
+
 /* Emit a conditional jump insn for the v9 architecture using comparison code
    CODE and jump target LABEL.
    This function exists to take advantage of the v9 brxx insns.  */
 
-void
+static void
 emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label)
 {
-  gcc_assert (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) != MODE_CC);
   emit_jump_insn (gen_rtx_SET (VOIDmode,
 			   pc_rtx,
 			   gen_rtx_IF_THEN_ELSE (VOIDmode,
@@ -2206,6 +2278,37 @@ emit_v9_brxx_insn (enum rtx_code code, r
 				    pc_rtx)));
 }
 
+void
+emit_conditional_branch_insn (rtx operands[])
+{
+  /* The quad-word fp compare library routines all return nonzero to indicate
+     true, which is different from the equivalent libgcc routines, so we must
+     handle them specially here.  */
+  if (GET_MODE (operands[1]) == TFmode && ! TARGET_HARD_QUAD)
+    {
+      operands[0] = sparc_emit_float_lib_cmp (operands[1], operands[2],
+					      GET_CODE (operands[0]));
+      operands[1] = XEXP (operands[0], 0);
+      operands[2] = XEXP (operands[0], 1);
+    }
+
+  if (TARGET_ARCH64 && operands[2] == const0_rtx
+      && GET_CODE (operands[1]) == REG
+      && GET_MODE (operands[1]) == DImode)
+    {
+      emit_v9_brxx_insn (GET_CODE (operands[0]), operands[1], operands[3]);
+      return;
+    }
+
+  operands[1] = gen_compare_reg (operands[0]);
+  operands[2] = const0_rtx;
+  operands[0] = gen_rtx_fmt_ee (GET_CODE (operands[0]), VOIDmode,
+				operands[1], operands[2]);
+  emit_jump_insn (gen_cbranchcc4 (operands[0], operands[1], operands[2],
+				  operands[3]));
+}
+
+
 /* Generate a DFmode part of a hard TFmode register.
    REG is the TFmode hard register, LOW is 1 for the
    low 64bit of the register and 0 otherwise.
@@ -6112,7 +6215,7 @@ output_cbranch (rtx op, rtx dest, int la
    values as arguments instead of the TFmode registers themselves,
    that's why we cannot call emit_float_lib_cmp.  */
 
-enum rtx_code
+rtx
 sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
 {
   const char *qpfunc;
@@ -6203,32 +6306,24 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, 
   switch (comparison)
     {
     default:
-      new_comparison = NE;
-      emit_cmp_insn (result, const0_rtx, new_comparison, NULL_RTX, mode, 0);
-      break;
+      return gen_rtx_NE (VOIDmode, result, const0_rtx);
     case ORDERED:
     case UNORDERED:
       new_comparison = (comparison == UNORDERED ? EQ : NE);
-      emit_cmp_insn (result, GEN_INT(3), new_comparison, NULL_RTX, mode, 0);
-      break;
+      return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, GEN_INT(3));
     case UNGT:
     case UNGE:
       new_comparison = (comparison == UNGT ? GT : NE);
-      emit_cmp_insn (result, const1_rtx, new_comparison, NULL_RTX, mode, 0);
-      break;
+      return gen_rtx_fmt_ee (new_comparison, VOIDmode, result, const1_rtx);
     case UNLE:
-      new_comparison = NE;
-      emit_cmp_insn (result, const2_rtx, new_comparison, NULL_RTX, mode, 0);
-      break;
+      return gen_rtx_NE (VOIDmode, result, const2_rtx);
     case UNLT:
       tem = gen_reg_rtx (mode);
       if (TARGET_ARCH32)
 	emit_insn (gen_andsi3 (tem, result, const1_rtx));
       else
 	emit_insn (gen_anddi3 (tem, result, const1_rtx));
-      new_comparison = NE;
-      emit_cmp_insn (tem, const0_rtx, new_comparison, NULL_RTX, mode, 0);
-      break;
+      return gen_rtx_NE (VOIDmode, tem, const0_rtx);
     case UNEQ:
     case LTGT:
       tem = gen_reg_rtx (mode);
@@ -6242,11 +6337,10 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, 
       else
 	emit_insn (gen_anddi3 (tem2, tem, const2_rtx));
       new_comparison = (comparison == UNEQ ? EQ : NE);
-      emit_cmp_insn (tem2, const0_rtx, new_comparison, NULL_RTX, mode, 0);
-      break;
+      return gen_rtx_fmt_ee (new_comparison, VOIDmode, tem2, const0_rtx);
     }
 
-  return new_comparison;
+  gcc_unreachable ();
 }
 
 /* Generate an unsigned DImode to FP conversion.  This is the same code
@@ -9017,15 +9111,12 @@ sparc_expand_compare_and_swap_12 (rtx re
 			  gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
 				       res)));
 
-  sparc_compare_op0 = resv;
-  sparc_compare_op1 = val;
-  cc = gen_compare_reg (NE);
-
+  cc = gen_compare_reg_1 (NE, resv, val);
   emit_insn (gen_rtx_SET (VOIDmode, val, resv));
 
-  sparc_compare_op0 = cc;
-  sparc_compare_op1 = const0_rtx;
-  emit_jump_insn (gen_bne (loop_label));
+  /* Use cbranchcc4 to separate the compare and branch!  */
+  emit_jump_insn (gen_cbranchcc4 (gen_rtx_NE (VOIDmode, cc, const0_rtx),
+				  cc, const0_rtx, loop_label));
 
   emit_label (end_label);
 
Index: sparc.h
===================================================================
--- sparc.h	(.../trunk/gcc/config/sparc)	(revisione 146553)
+++ sparc.h	(.../branches/cond-optab/gcc/config/sparc)	(revisione 146803)
@@ -1558,12 +1558,6 @@ function_arg_padding ((MODE), (TYPE))
   && (GET_MODE_ALIGNMENT (MODE) == 128		\
       || ((TYPE) && TYPE_ALIGN (TYPE) == 128)))	\
  ? 128 : PARM_BOUNDARY)
-
-/* Define the information needed to generate branch and scc insns.  This is
-   stored from the compare operation.  */
-
-extern GTY(()) rtx sparc_compare_op0;
-extern GTY(()) rtx sparc_compare_op1;
 
 
 /* Generate the special assembly code needed to tell the assembler whatever

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]