[patch, ia64, committed] Path to modify integer division code.

Steve Ellcey sje@cup.hp.com
Mon Jun 1 16:48:00 GMT 2009


This patch rewrites the integer division code for IA64 to be more like
the floating point division code (pre-reload for better instruction
scheduling) and moves it from ia64.md to div.md.  I also moved the
remainder of the floating point division code from ia64.md to div.md
and removed a number of instructions that are no longer used from ia64.md.

Tested on IA64 HP-UX and Linux and checked in.

Steve Ellcey
sje@cup.hp.com


2009-06-01  Steve Ellcey  <sje@cup.hp.com>

	* ia64.md (floatdirf2, fix_truncrfdi, floatunsdirf,
	fixuns_truncrfdi2): New.
	(fix_truncxfdi2_alts, fixuns_truncxfdi2_alts,
	*nmaddsf4_alts, *nmadddf4_alts, *nmadddf4_truncsf_alts,
	*mulxf3_alts, *mulxf3_truncsf_alts, *mulxf3_truncdf_alts,
	*maddxf4_alts, *maddxf4_alts_truncsf, *maddxf4_alts_truncdf,
	*nmaddxf4_alts, *nmaddxf4_truncsf_alts, *nmaddxf4_truncdf_alts,
	*recip_approx): Remove.
	(divsi3 modsi3, udivsi3, umodsi3, divsi3_internal, divdi3,
	moddi3, udivdi3, umoddi3, divdi3_internal_lat, divdi3_internal_thr,
	divsf3, sqrtsf2, divdf3, sqrtdf2, divxf3, sqrtxf2): Modify and
	move to div.md.
	* div.md (fix_truncrfdi2_alts, fixuns_truncrfdi2_alt,
	setf_exp_rf): New.


Index: gcc/config/ia64/ia64.md
===================================================================
--- gcc/config/ia64/ia64.md	(revision 148026)
+++ gcc/config/ia64/ia64.md	(working copy)
@@ -1234,6 +1234,13 @@ (define_insn "truncxfdf2"
 
 ;; Convert between signed integer types and floating point.
 
+(define_insn "floatdirf2"
+  [(set (match_operand:RF 0 "fr_register_operand" "=f")
+	(float:RF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+  ""
+  "fcvt.xf %0 = %F1"
+  [(set_attr "itanium_class" "fcvtfx")])
+
 (define_insn "floatdixf2"
   [(set (match_operand:XF 0 "fr_register_operand" "=f")
 	(float:XF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
@@ -1262,12 +1269,11 @@ (define_insn "fix_truncxfdi2"
   "fcvt.fx.trunc %0 = %F1"
   [(set_attr "itanium_class" "fcvtfx")])
 
-(define_insn "fix_truncxfdi2_alts"
+(define_insn "fix_truncrfdi2"
   [(set (match_operand:DI 0 "fr_register_operand" "=f")
-	(fix:DI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))
-   (use (match_operand:SI 2 "const_int_operand" ""))]
+	(fix:DI (match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")))]
   ""
-  "fcvt.fx.trunc.s%2 %0 = %F1"
+  "fcvt.fx.trunc %0 = %F1"
   [(set_attr "itanium_class" "fcvtfx")])
 
 ;; Convert between unsigned integer types and floating point.
@@ -1293,6 +1299,13 @@ (define_insn "floatunsdixf2"
   "fcvt.xuf %0 = %F1"
   [(set_attr "itanium_class" "fcvtfx")])
 
+(define_insn "floatunsdirf2"
+  [(set (match_operand:RF 0 "fr_register_operand" "=f")
+	(unsigned_float:RF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+  ""
+  "fcvt.xuf %0 = %F1"
+  [(set_attr "itanium_class" "fcvtfx")])
+
 (define_insn "fixuns_truncsfdi2"
   [(set (match_operand:DI 0 "fr_register_operand" "=f")
 	(unsigned_fix:DI (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
@@ -1314,12 +1327,11 @@ (define_insn "fixuns_truncxfdi2"
   "fcvt.fxu.trunc %0 = %F1"
   [(set_attr "itanium_class" "fcvtfx")])
 
-(define_insn "fixuns_truncxfdi2_alts"
+(define_insn "fixuns_truncrfdi2"
   [(set (match_operand:DI 0 "fr_register_operand" "=f")
-	(unsigned_fix:DI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))
-   (use (match_operand:SI 2 "const_int_operand" ""))]
+	(unsigned_fix:DI (match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")))]
   ""
-  "fcvt.fxu.trunc.s%2 %0 = %F1"
+  "fcvt.fxu.trunc %0 = %F1"
   [(set_attr "itanium_class" "fcvtfx")])
 
 ;; ::::::::::::::::::::
@@ -2176,169 +2188,6 @@ (define_expand "umaxsi3"
 			 (match_dup 1) (match_dup 2)))]
   ""
   { operands[3] = gen_reg_rtx (BImode); })
-
-(define_expand "divsi3"
-  [(set (match_operand:SI 0 "register_operand" "")
-	(div:SI (match_operand:SI 1 "general_operand" "")
-		(match_operand:SI 2 "general_operand" "")))]
-  "TARGET_INLINE_INT_DIV"
-{
-  rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp;
-
-  op0_xf = gen_reg_rtx (XFmode);
-  op0_di = gen_reg_rtx (DImode);
-
-  if (CONSTANT_P (operands[1]))
-    operands[1] = force_reg (SImode, operands[1]);
-  op1_xf = gen_reg_rtx (XFmode);
-  expand_float (op1_xf, operands[1], 0);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_reg (SImode, operands[2]);
-  op2_xf = gen_reg_rtx (XFmode);
-  expand_float (op2_xf, operands[2], 0);
-
-  /* 2^-34 */
-  twon34_exp = gen_reg_rtx (DImode);
-  emit_move_insn (twon34_exp, GEN_INT (65501));
-  twon34 = gen_reg_rtx (XFmode);
-  emit_insn (gen_setf_exp_xf (twon34, twon34_exp));
-
-  emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
-			    CONST1_RTX (SImode)));
-  
-  emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
-
-  emit_insn (gen_fix_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
-  emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
-  DONE;
-})
-
-(define_expand "modsi3"
-  [(set (match_operand:SI 0 "register_operand" "")
-	(mod:SI (match_operand:SI 1 "general_operand" "")
-		(match_operand:SI 2 "general_operand" "")))]
-  "TARGET_INLINE_INT_DIV"
-{
-  rtx op2_neg, op1_di, div;
-
-  div = gen_reg_rtx (SImode);
-  emit_insn (gen_divsi3 (div, operands[1], operands[2]));
-
-  op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
-
-  /* This is a trick to get us to reuse the value that we're sure to
-     have already copied to the FP regs.  */
-  op1_di = gen_reg_rtx (DImode);
-  convert_move (op1_di, operands[1], 0);
-
-  emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
-			  gen_lowpart (SImode, op1_di)));
-  DONE;
-})
-
-(define_expand "udivsi3"
-  [(set (match_operand:SI 0 "register_operand" "")
-	(udiv:SI (match_operand:SI 1 "general_operand" "")
-		 (match_operand:SI 2 "general_operand" "")))]
-  "TARGET_INLINE_INT_DIV"
-{
-  rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp;
-
-  op0_xf = gen_reg_rtx (XFmode);
-  op0_di = gen_reg_rtx (DImode);
-
-  if (CONSTANT_P (operands[1]))
-    operands[1] = force_reg (SImode, operands[1]);
-  op1_xf = gen_reg_rtx (XFmode);
-  expand_float (op1_xf, operands[1], 1);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_reg (SImode, operands[2]);
-  op2_xf = gen_reg_rtx (XFmode);
-  expand_float (op2_xf, operands[2], 1);
-
-  /* 2^-34 */
-  twon34_exp = gen_reg_rtx (DImode);
-  emit_move_insn (twon34_exp, GEN_INT (65501));
-  twon34 = gen_reg_rtx (XFmode);
-  emit_insn (gen_setf_exp_xf (twon34, twon34_exp));
-
-  emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
-			    CONST1_RTX (SImode)));
-  
-  emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
-
-  emit_insn (gen_fixuns_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
-  emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
-  DONE;
-})
-
-(define_expand "umodsi3"
-  [(set (match_operand:SI 0 "register_operand" "")
-	(umod:SI (match_operand:SI 1 "general_operand" "")
-		 (match_operand:SI 2 "general_operand" "")))]
-  "TARGET_INLINE_INT_DIV"
-{
-  rtx op2_neg, op1_di, div;
-
-  div = gen_reg_rtx (SImode);
-  emit_insn (gen_udivsi3 (div, operands[1], operands[2]));
-
-  op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
-
-  /* This is a trick to get us to reuse the value that we're sure to
-     have already copied to the FP regs.  */
-  op1_di = gen_reg_rtx (DImode);
-  convert_move (op1_di, operands[1], 1);
-
-  emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
-			  gen_lowpart (SImode, op1_di)));
-  DONE;
-})
-
-(define_insn_and_split "divsi3_internal"
-  [(set (match_operand:XF 0 "fr_register_operand" "=&f")
-	(float:XF (div:SI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
-			  (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG"))))
-   (clobber (match_scratch:XF 4 "=&f"))
-   (clobber (match_scratch:XF 5 "=&f"))
-   (clobber (match_scratch:BI 6 "=c"))
-   (use (match_operand:XF 3 "fr_register_operand" "f"))]
-  "TARGET_INLINE_INT_DIV"
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0) (unspec:XF [(const_int 1) (match_dup 2)]
-					    UNSPEC_FR_RECIP_APPROX_RES))
-	      (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
-					    UNSPEC_FR_RECIP_APPROX))
-	      (use (const_int 1))])
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 5)
-		     (minus:XF (match_dup 7)
-			       (mult:XF (match_dup 2) (match_dup 0))))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 4)
-		     (plus:XF (mult:XF (match_dup 5) (match_dup 4))
-			      (match_dup 4)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 5)
-		     (plus:XF (mult:XF (match_dup 5) (match_dup 5))
-			      (match_dup 3)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 0)
-		     (plus:XF (mult:XF (match_dup 5) (match_dup 4))
-			      (match_dup 4)))
-		(use (const_int 1))]))
-  ] 
-  "operands[7] = CONST1_RTX (XFmode);"
-  [(set_attr "predicable" "no")])
 
 ;; ::::::::::::::::::::
 ;; ::
@@ -2612,215 +2461,6 @@ (define_insn "*getf_exp_xf"
   ""
   "getf.exp %0 = %F1"
   [(set_attr "itanium_class" "frfr")])
-
-(define_expand "divdi3"
-  [(set (match_operand:DI 0 "register_operand" "")
-	(div:DI (match_operand:DI 1 "general_operand" "")
-		(match_operand:DI 2 "general_operand" "")))]
-  "TARGET_INLINE_INT_DIV"
-{
-  rtx op1_xf, op2_xf, op0_xf;
-
-  op0_xf = gen_reg_rtx (XFmode);
-
-  if (CONSTANT_P (operands[1]))
-    operands[1] = force_reg (DImode, operands[1]);
-  op1_xf = gen_reg_rtx (XFmode);
-  expand_float (op1_xf, operands[1], 0);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_reg (DImode, operands[2]);
-  op2_xf = gen_reg_rtx (XFmode);
-  expand_float (op2_xf, operands[2], 0);
-
-  emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
-			    CONST1_RTX (DImode)));
-
-  if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
-    emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
-  else
-    emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
-
-  emit_insn (gen_fix_truncxfdi2_alts (operands[0], op0_xf, const1_rtx));
-  DONE;
-})
-
-(define_expand "moddi3"
-  [(set (match_operand:DI 0 "register_operand" "")
-	(mod:SI (match_operand:DI 1 "general_operand" "")
-		(match_operand:DI 2 "general_operand" "")))]
-  "TARGET_INLINE_INT_DIV"
-{
-  rtx op2_neg, div;
-
-  div = gen_reg_rtx (DImode);
-  emit_insn (gen_divdi3 (div, operands[1], operands[2]));
-
-  op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
-
-  emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
-  DONE;
-})
-
-(define_expand "udivdi3"
-  [(set (match_operand:DI 0 "register_operand" "")
-	(udiv:DI (match_operand:DI 1 "general_operand" "")
-		 (match_operand:DI 2 "general_operand" "")))]
-  "TARGET_INLINE_INT_DIV"
-{
-  rtx op1_xf, op2_xf, op0_xf;
-
-  op0_xf = gen_reg_rtx (XFmode);
-
-  if (CONSTANT_P (operands[1]))
-    operands[1] = force_reg (DImode, operands[1]);
-  op1_xf = gen_reg_rtx (XFmode);
-  expand_float (op1_xf, operands[1], 1);
-
-  if (CONSTANT_P (operands[2]))
-    operands[2] = force_reg (DImode, operands[2]);
-  op2_xf = gen_reg_rtx (XFmode);
-  expand_float (op2_xf, operands[2], 1);
-
-  emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
-			    CONST1_RTX (DImode)));
-
-  if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
-    emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
-  else
-    emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
-
-  emit_insn (gen_fixuns_truncxfdi2_alts (operands[0], op0_xf, const1_rtx));
-  DONE;
-})
-
-(define_expand "umoddi3"
-  [(set (match_operand:DI 0 "register_operand" "")
-	(umod:DI (match_operand:DI 1 "general_operand" "")
-		 (match_operand:DI 2 "general_operand" "")))]
-  "TARGET_INLINE_INT_DIV"
-{
-  rtx op2_neg, div;
-
-  div = gen_reg_rtx (DImode);
-  emit_insn (gen_udivdi3 (div, operands[1], operands[2]));
-
-  op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
-
-  emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
-  DONE;
-})
-
-(define_insn_and_split "divdi3_internal_lat"
-  [(set (match_operand:XF 0 "fr_register_operand" "=&f")
-	(float:XF (div:SI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
-			  (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG"))))
-   (clobber (match_scratch:XF 3 "=&f"))
-   (clobber (match_scratch:XF 4 "=&f"))
-   (clobber (match_scratch:XF 5 "=&f"))
-   (clobber (match_scratch:BI 6 "=c"))]
-  "TARGET_INLINE_INT_DIV == INL_MIN_LAT"
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0) (unspec:XF [(const_int 1) (match_dup 2)]
-					    UNSPEC_FR_RECIP_APPROX_RES))
-	      (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
-					    UNSPEC_FR_RECIP_APPROX))
-	      (use (const_int 1))])
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 3)
-		     (minus:XF (match_dup 7)
-			       (mult:XF (match_dup 2) (match_dup 0))))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 5) (mult:XF (match_dup 3) (match_dup 3)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 4)
-		     (plus:XF (mult:XF (match_dup 3) (match_dup 4))
-			      (match_dup 4)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 0)
-		     (plus:XF (mult:XF (match_dup 3) (match_dup 0))
-			      (match_dup 0)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 3)
-		     (plus:XF (mult:XF (match_dup 5) (match_dup 4))
-			      (match_dup 4)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 0)
-		     (plus:XF (mult:XF (match_dup 5) (match_dup 0))
-			      (match_dup 0)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 4)
-		     (minus:XF (match_dup 1)
-			       (mult:XF (match_dup 2) (match_dup 3))))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 6) (const_int 0))
-     (parallel [(set (match_dup 0)
-		     (plus:XF (mult:XF (match_dup 4) (match_dup 0))
-			      (match_dup 3)))
-		(use (const_int 1))]))
-  ] 
-  "operands[7] = CONST1_RTX (XFmode);"
-  [(set_attr "predicable" "no")])
-
-(define_insn_and_split "divdi3_internal_thr"
-  [(set (match_operand:XF 0 "fr_register_operand" "=&f")
-	(float:XF (div:SI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
-			  (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG"))))
-   (clobber (match_scratch:XF 3 "=&f"))
-   (clobber (match_scratch:XF 4 "=f"))
-   (clobber (match_scratch:BI 5 "=c"))]
-  "TARGET_INLINE_INT_DIV == INL_MAX_THR"
-  "#"
-  "&& reload_completed"
-  [(parallel [(set (match_dup 0) (unspec:XF [(const_int 1) (match_dup 2)]
-					    UNSPEC_FR_RECIP_APPROX_RES))
-	      (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)] 
-					    UNSPEC_FR_RECIP_APPROX))
-	      (use (const_int 1))])
-   (cond_exec (ne (match_dup 5) (const_int 0))
-     (parallel [(set (match_dup 3)
-		     (minus:XF (match_dup 6)
-			       (mult:XF (match_dup 2) (match_dup 0))))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 5) (const_int 0))
-     (parallel [(set (match_dup 0)
-		     (plus:XF (mult:XF (match_dup 3) (match_dup 0))
-			      (match_dup 0)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 5) (const_int 0))
-     (parallel [(set (match_dup 3) (mult:XF (match_dup 3) (match_dup 3)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 5) (const_int 0))
-     (parallel [(set (match_dup 0)
-		     (plus:XF (mult:XF (match_dup 3) (match_dup 0))
-			      (match_dup 0)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 5) (const_int 0))
-     (parallel [(set (match_dup 3) (mult:XF (match_dup 0) (match_dup 1)))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 5) (const_int 0))
-     (parallel [(set (match_dup 4)
-		     (minus:XF (match_dup 1)
-			       (mult:XF (match_dup 2) (match_dup 3))))
-		(use (const_int 1))]))
-   (cond_exec (ne (match_dup 5) (const_int 0))
-     (parallel [(set (match_dup 0)
-		     (plus:XF (mult:XF (match_dup 4) (match_dup 0))
-			      (match_dup 3)))
-		(use (const_int 1))]))
-  ] 
-  "operands[6] = CONST1_RTX (XFmode);"
-  [(set_attr "predicable" "no")])
 
 ;; ::::::::::::::::::::
 ;; ::
@@ -3135,56 +2775,6 @@ (define_insn "*nmaddsf4"
   "TARGET_FUSED_MADD"
   "fnma.s %0 = %F1, %F2, %F3"
   [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmaddsf4_alts"
-  [(set (match_operand:SF 0 "fr_register_operand" "=f")
-	(minus:SF (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG") 
-		  (mult:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
-			   (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG"))))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fnma.s.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_expand "divsf3"
-  [(set (match_operand:SF 0 "fr_register_operand" "")
-	(div:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "")
-		(match_operand:SF 2 "fr_reg_or_fp01_operand" "")))]
-  "TARGET_INLINE_FLOAT_DIV"
-{
-  rtx insn;
-  if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
-    insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
-  else
-    insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
-  emit_insn (insn);
-  DONE;
-})
-
-(define_insn "setf_exp_xf"
-  [(set (match_operand:XF 0 "fr_register_operand" "=f")
-        (unspec:XF [(match_operand:DI 1 "register_operand" "r")]
-                  UNSPEC_SETF_EXP))]
-  ""
-  "setf.exp %0 = %1"
-  [(set_attr "itanium_class" "frfr")])
-
-
-;; Inline square root.
-
-(define_expand "sqrtsf2"
-  [(set (match_operand:SF 0 "fr_register_operand" "=&f")
-	(sqrt:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
-  "TARGET_INLINE_SQRT"
-{
-  rtx insn;
-  if (TARGET_INLINE_SQRT == INL_MIN_LAT)
-    insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
-  else
-    insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
-  emit_insn (insn);
-  DONE;
-})
 
 ;; ::::::::::::::::::::
 ;; ::
@@ -3362,16 +2952,6 @@ (define_insn "*nmadddf4"
   "fnma.d %0 = %F1, %F2, %F3"
   [(set_attr "itanium_class" "fmac")])
 
-(define_insn "*nmadddf4_alts"
-  [(set (match_operand:DF 0 "fr_register_operand" "=f")
-	(minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
-		  (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
-			   (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fnma.d.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
 (define_insn "*nmadddf4_truncsf"
   [(set (match_operand:SF 0 "fr_register_operand" "=f")
 	(float_truncate:SF
@@ -3381,50 +2961,6 @@ (define_insn "*nmadddf4_truncsf"
   "TARGET_FUSED_MADD"
   "fnma.s %0 = %F1, %F2, %F3"
   [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmadddf4_truncsf_alts"
-  [(set (match_operand:SF 0 "fr_register_operand" "=f")
-	(float_truncate:SF
-	(minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
-		  (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
-			   (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fnma.s.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_expand "divdf3"
-  [(set (match_operand:DF 0 "fr_register_operand" "")
-	(div:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "")
-		(match_operand:DF 2 "fr_reg_or_fp01_operand" "")))]
-  "TARGET_INLINE_FLOAT_DIV"
-{
-  rtx insn;
-  if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
-    insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
-  else
-    insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
-  emit_insn (insn);
-  DONE;
-})
-
-;; Inline square root.
-
-(define_expand "sqrtdf2"
-  [(set (match_operand:DF 0 "fr_register_operand" "=&f")
-	(sqrt:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
-  "TARGET_INLINE_SQRT"
-{
-  rtx insn;
-#if 0
-  if (TARGET_INLINE_SQRT == INL_MIN_LAT)
-    insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
-  else
-#endif
-  insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
-  emit_insn (insn);
-  DONE;
-})
 
 ;; ::::::::::::::::::::
 ;; ::
@@ -3510,35 +3046,6 @@ (define_insn "*mulxf3_truncdf"
   "fmpy.d %0 = %F1, %F2"
   [(set_attr "itanium_class" "fmac")])
 
-(define_insn "*mulxf3_alts"
-  [(set (match_operand:XF 0 "fr_register_operand" "=f")
-	(mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-		 (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
-   (use (match_operand:SI 3 "const_int_operand" ""))]
-  ""
-  "fmpy.s%3 %0 = %F1, %F2"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*mulxf3_truncsf_alts"
-  [(set (match_operand:SF 0 "fr_register_operand" "=f")
-	(float_truncate:SF
-	  (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-		   (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))
-   (use (match_operand:SI 3 "const_int_operand" ""))]
-  ""
-  "fmpy.s.s%3 %0 = %F1, %F2"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*mulxf3_truncdf_alts"
-  [(set (match_operand:DF 0 "fr_register_operand" "=f")
-	(float_truncate:DF
-	  (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-		   (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))
-   (use (match_operand:SI 3 "const_int_operand" ""))]
-  ""
-  "fmpy.d.s%3 %0 = %F1, %F2"
-  [(set_attr "itanium_class" "fmac")])
-
 (define_insn "absxf2"
   [(set (match_operand:XF 0 "fr_register_operand" "=f")
 	(abs:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")))]
@@ -3623,38 +3130,6 @@ (define_insn "*maddxf4_truncdf"
   "fma.d %0 = %F1, %F2, %F3"
   [(set_attr "itanium_class" "fmac")])
 
-(define_insn "*maddxf4_alts"
-  [(set (match_operand:XF 0 "fr_register_operand" "=f")
-	(plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-			  (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
-		 (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fma.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*maddxf4_alts_truncsf"
-  [(set (match_operand:SF 0 "fr_register_operand" "=f")
-	(float_truncate:SF
-	  (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-			    (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
-		   (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fma.s.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*maddxf4_alts_truncdf"
-  [(set (match_operand:DF 0 "fr_register_operand" "=f")
-	(float_truncate:DF
-	  (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-			    (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
-		   (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fma.d.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
 (define_insn "*msubxf4"
   [(set (match_operand:XF 0 "fr_register_operand" "=f")
 	(minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
@@ -3743,81 +3218,6 @@ (define_insn "*nmaddxf4_truncdf"
   "TARGET_FUSED_MADD"
   "fnma.d %0 = %F1, %F2, %F3"
   [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmaddxf4_alts"
-  [(set (match_operand:XF 0 "fr_register_operand" "=f")
-	(minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
-		  (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-			   (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
-   )))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fnma.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmaddxf4_truncsf_alts"
-  [(set (match_operand:SF 0 "fr_register_operand" "=f")
-	(float_truncate:SF
-	  (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG") 
-		    (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-			     (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
-   ))))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fnma.s.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmaddxf4_truncdf_alts"
-  [(set (match_operand:DF 0 "fr_register_operand" "=f")
-	(float_truncate:DF
-	  (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG") 
-		    (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
-			     (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
-   ))))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "fnma.d.s%4 %0 = %F1, %F2, %F3"
-  [(set_attr "itanium_class" "fmac")])
-
-(define_expand "divxf3"
-  [(set (match_operand:XF 0 "fr_register_operand" "")
-	(div:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "")
-		(match_operand:XF 2 "fr_reg_or_fp01_operand" "")))]
-  "TARGET_INLINE_FLOAT_DIV"
-{
-  /* There is only one divxf3 sequence, not two like for divsf and divdf.  */
-  emit_insn (gen_divxf3_internal (operands[0], operands[1], operands[2]));
-  DONE;
-})
-
-;; Inline square root.
-
-(define_expand "sqrtxf2"
-  [(set (match_operand:XF 0 "fr_register_operand" "=&f")
-	(sqrt:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))]
-  "TARGET_INLINE_SQRT"
-{
-  rtx insn;
-  insn = gen_sqrtxf2_internal (operands[0], operands[1]);
-  emit_insn (insn);
-  DONE;
-})
-
-;; ??? frcpa works like cmp.foo.unc.
-
-(define_insn "*recip_approx"
-  [(set (match_operand:XF 0 "fr_register_operand" "=f")
-	(unspec:XF [(const_int 1)
-		    (match_operand:XF 3 "fr_reg_or_fp01_operand" "fG")]
-		   UNSPEC_FR_RECIP_APPROX_RES))
-   (set (match_operand:BI 1 "register_operand" "=c")
-	(unspec:BI [(match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
-		    (match_dup 3)] UNSPEC_FR_RECIP_APPROX))
-   (use (match_operand:SI 4 "const_int_operand" ""))]
-  ""
-  "frcpa.s%4 %0, %1 = %F2, %F3"
-  [(set_attr "itanium_class" "fmisc")
-   (set_attr "predicable" "no")])
 
 ;; ::::::::::::::::::::
 ;; ::
Index: gcc/config/ia64/div.md
===================================================================
--- gcc/config/ia64/div.md	(revision 148026)
+++ gcc/config/ia64/div.md	(working copy)
@@ -222,6 +222,32 @@ (define_split
      operands[2] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
 })
 
+;; Float to integer truncations using an alternative status register. 
+
+(define_insn "fix_truncrfdi2_alts"
+  [(set (match_operand:DI 0 "fr_register_operand" "=f")
+        (fix:DI (match_operand:RF 1 "fr_register_operand" "f")))
+   (use (match_operand:SI 2 "const_int_operand" ""))]
+  ""
+  "fcvt.fx.trunc.s%2 %0 = %1"
+  [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fixuns_truncrfdi2_alts"
+  [(set (match_operand:DI 0 "fr_register_operand" "=f")
+        (unsigned_fix:DI (match_operand:RF 1 "fr_register_operand" "f")))
+   (use (match_operand:SI 2 "const_int_operand" ""))]
+  ""
+  "fcvt.fxu.trunc.s%2 %0 = %1"
+  [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "setf_exp_rf"
+  [(set (match_operand:RF 0 "fr_register_operand" "=f")
+        (unspec:RF [(match_operand:DI 1 "register_operand" "r")]
+                  UNSPEC_SETF_EXP))]
+  ""
+  "setf.exp %0 = %1"
+  [(set_attr "itanium_class" "frfr")])
+
 ;; Reciprocal approximation
 
 (define_insn "recip_approx_rf"
@@ -237,6 +263,23 @@ (define_insn "recip_approx_rf"
   [(set_attr "itanium_class" "fmisc")
    (set_attr "predicable" "no")])
 
+;; Single precision floating point division
+
+(define_expand "divsf3"
+  [(set (match_operand:SF 0 "fr_register_operand" "")
+	(div:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "")
+		(match_operand:SF 2 "fr_reg_or_fp01_operand" "")))]
+  "TARGET_INLINE_FLOAT_DIV"
+{
+  rtx insn;
+  if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
+    insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
+  else
+    insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
+  emit_insn (insn);
+  DONE;
+})
+
 ;; Single precision floating point division (maximum throughput algorithm).
 
 (define_expand "divsf3_internal_thr"
@@ -334,6 +377,22 @@ (define_expand "divsf3_internal_lat"
   DONE;
 })
 
+;; Double precision floating point division
+
+(define_expand "divdf3"
+  [(set (match_operand:DF 0 "fr_register_operand" "")
+	(div:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "")
+		(match_operand:DF 2 "fr_reg_or_fp01_operand" "")))]
+  "TARGET_INLINE_FLOAT_DIV"
+{
+  rtx insn;
+  if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
+    insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
+  else
+    insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
+  emit_insn (insn);
+  DONE;
+})
 
 ;; Double precision floating point division (maximum throughput algorithm).
 
@@ -454,7 +513,7 @@ (define_expand "divdf3_internal_lat"
 
 ;; Extended precision floating point division.
 
-(define_expand "divxf3_internal"
+(define_expand "divxf3"
   [(set (match_operand:XF 0 "fr_register_operand" "")
         (div:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "")
                 (match_operand:XF 2 "fr_reg_or_fp01_operand" "")))]
@@ -520,6 +579,340 @@ (define_expand "divxf3_internal"
 })
 
 
+;; Integer division operations
+
+(define_expand "divsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(div:SI (match_operand:SI 1 "general_operand" "")
+		(match_operand:SI 2 "general_operand" "")))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx op1_rf, op2_rf, op0_rf, op0_di;
+
+  op0_rf = gen_reg_rtx (RFmode);
+  op0_di = gen_reg_rtx (DImode);
+
+  if (! register_operand (operands[1], SImode))
+    operands[1] = force_reg (SImode, operands[1]);
+  op1_rf = gen_reg_rtx (RFmode);
+  expand_float (op1_rf, operands[1], 0);
+
+  if (! register_operand (operands[2], SImode))
+    operands[2] = force_reg (SImode, operands[2]);
+  op2_rf = gen_reg_rtx (RFmode);
+  expand_float (op2_rf, operands[2], 0);
+
+  emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
+			    CONST1_RTX (SImode)));
+  
+  emit_insn (gen_divsi3_internal (op0_rf, op1_rf, op2_rf));
+
+  emit_insn (gen_fix_truncrfdi2_alts (op0_di, op0_rf, const1_rtx));
+  emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
+  DONE;
+})
+
+(define_expand "modsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(mod:SI (match_operand:SI 1 "general_operand" "")
+		(match_operand:SI 2 "general_operand" "")))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx op2_neg, op1_di, div;
+
+  div = gen_reg_rtx (SImode);
+  emit_insn (gen_divsi3 (div, operands[1], operands[2]));
+
+  op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
+
+  /* This is a trick to get us to reuse the value that we're sure to
+     have already copied to the FP regs.  */
+  op1_di = gen_reg_rtx (DImode);
+  convert_move (op1_di, operands[1], 0);
+
+  emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
+			  gen_lowpart (SImode, op1_di)));
+  DONE;
+})
+
+(define_expand "udivsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(udiv:SI (match_operand:SI 1 "general_operand" "")
+		 (match_operand:SI 2 "general_operand" "")))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx op1_rf, op2_rf, op0_rf, op0_di;
+
+  op0_rf = gen_reg_rtx (RFmode);
+  op0_di = gen_reg_rtx (DImode);
+
+  if (! register_operand (operands[1], SImode))
+    operands[1] = force_reg (SImode, operands[1]);
+  op1_rf = gen_reg_rtx (RFmode);
+  expand_float (op1_rf, operands[1], 1);
+
+  if (! register_operand (operands[2], SImode))
+    operands[2] = force_reg (SImode, operands[2]);
+  op2_rf = gen_reg_rtx (RFmode);
+  expand_float (op2_rf, operands[2], 1);
+
+  emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
+                            CONST1_RTX (SImode)));
+  
+  emit_insn (gen_divsi3_internal (op0_rf, op1_rf, op2_rf));
+
+  emit_insn (gen_fixuns_truncrfdi2_alts (op0_di, op0_rf, const1_rtx));
+  emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
+  DONE;
+})
+
+(define_expand "umodsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(umod:SI (match_operand:SI 1 "general_operand" "")
+		 (match_operand:SI 2 "general_operand" "")))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx op2_neg, op1_di, div;
+
+  div = gen_reg_rtx (SImode);
+  emit_insn (gen_udivsi3 (div, operands[1], operands[2]));
+
+  op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
+
+  /* This is a trick to get us to reuse the value that we're sure to
+     have already copied to the FP regs.  */
+  op1_di = gen_reg_rtx (DImode);
+  convert_move (op1_di, operands[1], 1);
+
+  emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
+			  gen_lowpart (SImode, op1_di)));
+  DONE;
+})
+
+(define_expand "divsi3_internal"
+  [(set (match_operand:RF 0 "fr_register_operand" "")
+        (float:RF (div:SI (match_operand:RF 1 "fr_register_operand" "")
+                          (match_operand:RF 2 "fr_register_operand" ""))))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx a         = operands[1];
+  rtx b         = operands[2];
+  rtx y         = gen_reg_rtx (RFmode);
+  rtx e         = gen_reg_rtx (RFmode);
+  rtx e1        = gen_reg_rtx (RFmode);
+  rtx q         = gen_reg_rtx (RFmode);
+  rtx q1        = gen_reg_rtx (RFmode);
+  rtx cond      = gen_reg_rtx (BImode);
+  rtx zero      = CONST0_RTX (RFmode);
+  rtx one       = CONST1_RTX (RFmode);
+  rtx status1   = CONST1_RTX (SImode);
+  rtx trunc_off = CONST2_RTX (SImode);
+  rtx twon34_exp = gen_reg_rtx (DImode);
+  rtx twon34    = gen_reg_rtx (RFmode);
+
+  /* Load cosntant 2**(-34) */
+  emit_move_insn (twon34_exp, GEN_INT (65501));
+  emit_insn (gen_setf_exp_rf (twon34, twon34_exp));
+
+  /* y  = 1 / b			*/
+  emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
+  /* e  = 1 - (b * y)		*/
+  emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
+  /* q  = a * y                 */
+  emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
+  /* q1 = q + (q * e)		*/
+  emit_insn (gen_m2addrf4_cond (q1, cond, q, q, e, zero, status1, trunc_off));
+  /* e1 = (2**-34) + (e * e)		*/
+  emit_insn (gen_m2addrf4_cond (e1, cond, twon34, e, e, zero, status1, trunc_off));
+  /* q2 = q1 + (e1 * q1)		*/
+  emit_insn (gen_m2addrf4_cond (operands[0], cond, q1, e1, q1, y, status1, trunc_off));
+  DONE;
+})
+
+(define_expand "divdi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(div:DI (match_operand:DI 1 "general_operand" "")
+		(match_operand:DI 2 "general_operand" "")))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx op1_rf, op2_rf, op0_rf;
+
+  op0_rf = gen_reg_rtx (RFmode);
+
+  if (! register_operand (operands[1], DImode))
+    operands[1] = force_reg (DImode, operands[1]);
+  op1_rf = gen_reg_rtx (RFmode);
+  expand_float (op1_rf, operands[1], 0);
+
+  if (! register_operand (operands[2], DImode))
+    operands[2] = force_reg (DImode, operands[2]);
+  op2_rf = gen_reg_rtx (RFmode);
+  expand_float (op2_rf, operands[2], 0);
+
+  emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
+                            CONST1_RTX (DImode)));
+
+  if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
+    emit_insn (gen_divdi3_internal_lat (op0_rf, op1_rf, op2_rf));
+  else
+    emit_insn (gen_divdi3_internal_thr (op0_rf, op1_rf, op2_rf));
+
+  emit_insn (gen_fix_truncrfdi2_alts (operands[0], op0_rf, const1_rtx));
+  DONE;
+})
+
+(define_expand "moddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(mod:SI (match_operand:DI 1 "general_operand" "")
+		(match_operand:DI 2 "general_operand" "")))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx op2_neg, div;
+
+  div = gen_reg_rtx (DImode);
+  emit_insn (gen_divdi3 (div, operands[1], operands[2]));
+
+  op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
+
+  emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
+  DONE;
+})
+
+(define_expand "udivdi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(udiv:DI (match_operand:DI 1 "general_operand" "")
+		 (match_operand:DI 2 "general_operand" "")))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx op1_rf, op2_rf, op0_rf;
+
+  op0_rf = gen_reg_rtx (RFmode);
+
+  if (! register_operand (operands[1], DImode))
+    operands[1] = force_reg (DImode, operands[1]);
+  op1_rf = gen_reg_rtx (RFmode);
+  expand_float (op1_rf, operands[1], 1);
+
+  if (! register_operand (operands[2], DImode))
+    operands[2] = force_reg (DImode, operands[2]);
+  op2_rf = gen_reg_rtx (RFmode);
+  expand_float (op2_rf, operands[2], 1);
+
+  emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
+                            CONST1_RTX (DImode)));
+
+  if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
+    emit_insn (gen_divdi3_internal_lat (op0_rf, op1_rf, op2_rf));
+  else
+    emit_insn (gen_divdi3_internal_thr (op0_rf, op1_rf, op2_rf));
+
+  emit_insn (gen_fixuns_truncrfdi2_alts (operands[0], op0_rf, const1_rtx));
+  DONE;
+})
+
+(define_expand "umoddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(umod:DI (match_operand:DI 1 "general_operand" "")
+		 (match_operand:DI 2 "general_operand" "")))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx op2_neg, div;
+
+  div = gen_reg_rtx (DImode);
+  emit_insn (gen_udivdi3 (div, operands[1], operands[2]));
+
+  op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
+
+  emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
+  DONE;
+})
+
+(define_expand "divdi3_internal_lat"
+  [(set (match_operand:RF 0 "fr_register_operand" "")
+        (float:RF (div:DI (match_operand:RF 1 "fr_register_operand" "")
+                          (match_operand:RF 2 "fr_register_operand" ""))))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx a         = operands[1];
+  rtx b         = operands[2];
+  rtx y         = gen_reg_rtx (RFmode);
+  rtx y1        = gen_reg_rtx (RFmode);
+  rtx y2        = gen_reg_rtx (RFmode);
+  rtx e         = gen_reg_rtx (RFmode);
+  rtx e1        = gen_reg_rtx (RFmode);
+  rtx q         = gen_reg_rtx (RFmode);
+  rtx q1        = gen_reg_rtx (RFmode);
+  rtx q2        = gen_reg_rtx (RFmode);
+  rtx r         = gen_reg_rtx (RFmode);
+  rtx cond      = gen_reg_rtx (BImode);
+  rtx zero      = CONST0_RTX (RFmode);
+  rtx one       = CONST1_RTX (RFmode);
+  rtx status1   = CONST1_RTX (SImode);
+  rtx trunc_off = CONST2_RTX (SImode);
+
+  /* y  = 1 / b			*/
+  emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
+  /* e  = 1 - (b * y)		*/
+  emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
+  /* q  = a * y                 */
+  emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
+  /* q1 = q + (q * e)		*/
+  emit_insn (gen_m2addrf4_cond (q1, cond, q, q, e, zero, status1, trunc_off));
+  /* e1 = e * e			*/
+  emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
+  /* q2 = q1 + (e1 * q1)	*/
+  emit_insn (gen_m2addrf4_cond (q2, cond, q1, e1, q1, zero, status1, trunc_off));
+  /* y1 = y + (y * e)		*/
+  emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
+  /* r  = a - (b * q2)		*/
+  emit_insn (gen_m2subrf4_cond (r, cond, a, b, q2, zero, status1, trunc_off));
+  /* y2 = y1 + (y1 * e1)	*/
+  emit_insn (gen_m2addrf4_cond (y2, cond, y1, y1, e1, zero, status1, trunc_off));
+  /* q3 = q2 + (r * y2)		*/
+  emit_insn (gen_m2addrf4_cond (operands[0], cond, q2, r, y2, y, status1, trunc_off));
+  DONE;
+})
+
+(define_expand "divdi3_internal_thr"
+  [(set (match_operand:RF 0 "fr_register_operand" "")
+        (float:RF (div:DI (match_operand:RF 1 "fr_register_operand" "")
+                          (match_operand:RF 2 "fr_register_operand" ""))))]
+  "TARGET_INLINE_INT_DIV"
+{
+  rtx a         = operands[1];
+  rtx b         = operands[2];
+  rtx y         = gen_reg_rtx (RFmode);
+  rtx y1        = gen_reg_rtx (RFmode);
+  rtx y2        = gen_reg_rtx (RFmode);
+  rtx e         = gen_reg_rtx (RFmode);
+  rtx e1        = gen_reg_rtx (RFmode);
+  rtx q2        = gen_reg_rtx (RFmode);
+  rtx r         = gen_reg_rtx (RFmode);
+  rtx cond      = gen_reg_rtx (BImode);
+  rtx zero      = CONST0_RTX (RFmode);
+  rtx one       = CONST1_RTX (RFmode);
+  rtx status1   = CONST1_RTX (SImode);
+  rtx trunc_off = CONST2_RTX (SImode);
+
+  /* y  = 1 / b			*/
+  emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
+  /* e  = 1 - (b * y)		*/
+  emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
+  /* y1 = y + (y * e)		*/
+  emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
+  /* e1 = e * e			*/
+  emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
+  /* y2 = y1 + (y1 * e1)	*/
+  emit_insn (gen_m2addrf4_cond (y2, cond, y1, y1, e1, zero, status1, trunc_off));
+  /* q2 = y2 * a		*/
+  emit_insn (gen_mulrf3_cond (q2, cond, y2, a, zero, status1, trunc_off));
+  /* r  = a - (b * q2)		*/
+  emit_insn (gen_m2subrf4_cond (r, cond, a, b, q2, zero, status1, trunc_off));
+  /* q3 = q2 + (r * y2)		*/
+  emit_insn (gen_m2addrf4_cond (operands[0], cond, q2, r, y2, y, status1, trunc_off));
+  DONE;
+})
+
 ;; SQRT operations
 
 
@@ -535,6 +928,20 @@ (define_insn "sqrt_approx_rf"
   [(set_attr "itanium_class" "fmisc")
    (set_attr "predicable" "no")])
 
+(define_expand "sqrtsf2"
+  [(set (match_operand:SF 0 "fr_register_operand" "=&f")
+	(sqrt:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
+  "TARGET_INLINE_SQRT"
+{
+  rtx insn;
+  if (TARGET_INLINE_SQRT == INL_MIN_LAT)
+    insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
+  else
+    insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
+  emit_insn (insn);
+  DONE;
+})
+
 (define_expand "sqrtsf2_internal_thr"
   [(set (match_operand:SF 0 "fr_register_operand" "")
         (sqrt:SF (match_operand:SF 1 "fr_register_operand" "")))]
@@ -662,6 +1069,22 @@ (define_expand "sqrtsf2_internal_lat"
   DONE;
 })
 
+(define_expand "sqrtdf2"
+  [(set (match_operand:DF 0 "fr_register_operand" "=&f")
+	(sqrt:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
+  "TARGET_INLINE_SQRT"
+{
+  rtx insn;
+#if 0
+  if (TARGET_INLINE_SQRT == INL_MIN_LAT)
+    insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
+  else
+#endif
+  insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
+  emit_insn (insn);
+  DONE;
+})
+
 (define_expand "sqrtdf2_internal_thr"
   [(set (match_operand:DF 0 "fr_register_operand" "")
         (sqrt:DF (match_operand:DF 1 "fr_register_operand" "")))]
@@ -727,7 +1150,7 @@ (define_expand "sqrtdf2_internal_thr"
   DONE;
 })
 
-(define_expand "sqrtxf2_internal"
+(define_expand "sqrtxf2"
   [(set (match_operand:XF 0 "fr_register_operand" "")
         (sqrt:XF (match_operand:XF 1 "fr_register_operand" "")))]
   "TARGET_INLINE_SQRT"



More information about the Gcc-patches mailing list