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] Use FPU for integer division on Alpha


Richard Henderson <rth@redhat.com> writes:

> On Thu, Mar 17, 2005 at 12:50:17PM +0100, Falk Hueffner wrote:
>> problem. The Java frontend (and presumably other frontends where
>> division by zero is not undefined) checks for 0 before doing the
>> division.
>
> I'm not quite sure why libjava isn't using 
>
>         DIVIDESPEC=-fno-use-divide-subroutine
>
> on Alpha.  Perhaps we missed some little bit?
>
> Anyway, the imprecise traps thing would be solvable by noting that
> DIVC can trap, and doing the "&" thing when precise traps are 
> enabled.  That should get a trapb insn added appropriately.  And
> it'll work for Java, because we enable -mieee there.

But that'd also add lots of trapbs when compiling C with -mieee. Is
there some way to make this Java specific? Since Java currently uses
the divide subroutine anyway, I'd prefer to postpone this...

> And I'm not 100% convinced we shouldn't add an option to disable
> this change.

I couldn't find any software that would need that from a quick search.
But I don't have a strong opinion there, if anybody thinks this should
be optional, I can add that.

> Raw creation of subregs is wrong.  You bork endianness.

OK, I changed it. I also simplified the modulo patterns a bit by
having them call the division patterns.

-- 
	Falk


2005-03-19  Falk Hueffner  <falk@debian.org>

	* config/alpha/alpha.md (UNSPEC_DIVC): New constant.
	(divsi3_fp, divsi3, udivsi3_fp, udivsi3, modsi3_fp, modsi3,
	umodsi3_fp, umodsi3): New pattern.
	(divsi3_libcall, udivsi3_libcall, modsi3_libcall,
	umodsi3_libcall): Rename from divsi3, udivsi3, modsi3.
	(divc): New pattern.

Index: gcc/config/alpha/alpha.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.md,v
retrieving revision 1.237
diff -u -p -r1.237 alpha.md
--- gcc/config/alpha/alpha.md	17 Mar 2005 10:43:19 -0000	1.237
+++ gcc/config/alpha/alpha.md	19 Mar 2005 18:40:55 -0000
@@ -26,6 +26,7 @@
 
 (define_constants
   [(UNSPEC_ARG_HOME	0)
+   (UNSPEC_DIVC		1)
    (UNSPEC_INSXH	2)
    (UNSPEC_MSKXH	3)
    (UNSPEC_CVTQL	4)
@@ -779,6 +780,33 @@
   [(set_attr "type" "imul")
    (set_attr "opsize" "udi")])
 
+(define_expand "divsi3_fp"
+  [(set (match_dup 3)
+	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
+   (set (match_dup 4)
+	(sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "")))
+   (set (match_dup 5)
+	(float:DF (match_dup 3)))
+   (set (match_dup 6)
+	(float:DF (match_dup 4)))
+   (set (match_dup 7)
+	(unspec:DF [(match_dup 5)
+	       	    (match_dup 6)] UNSPEC_DIVC))
+   (set (match_dup 8)
+	(fix:DI (match_dup 7)))
+   (set (match_operand:SI 0 "nonimmediate_operand" "")
+	(match_dup 9))]
+  "TARGET_FP"
+{
+  operands[3] = gen_reg_rtx (DImode);
+  operands[4] = gen_reg_rtx (DImode);
+  operands[5] = gen_reg_rtx (DFmode);
+  operands[6] = gen_reg_rtx (DFmode);
+  operands[7] = gen_reg_rtx (DFmode);
+  operands[8] = gen_reg_rtx (DImode);
+  operands[9] = lowpart_subreg (SImode, operands[8], DImode);
+})
+
 ;; The divide and remainder operations take their inputs from r24 and
 ;; r25, put their output in r27, and clobber r23 and r28 on all
 ;; systems except Unicos/Mk. On Unicos, the standard library provides
@@ -791,7 +819,7 @@
 ;; problem.  Is it worth the complication here to eliminate the sign
 ;; extension?
 
-(define_expand "divsi3"
+(define_expand "divsi3_libcall"
   [(set (match_dup 3)
 	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
    (set (match_dup 4)
@@ -809,7 +837,49 @@
   operands[5] = gen_reg_rtx (DImode);
 })
 
-(define_expand "udivsi3"
+(define_expand "divsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(div:SI (match_operand:SI 1 "register_operand" "")
+		(match_operand:SI 2 "register_operand" "")))]
+  ""
+{
+  if (TARGET_FP && optimize && !optimize_size)
+    emit_insn (gen_divsi3_fp (operands[0], operands[1], operands[2]));
+  else if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK)
+    emit_insn (gen_divsi3_libcall (operands[0], operands[1], operands[2]));
+  else
+    FAIL;
+  DONE;
+})
+
+(define_expand "udivsi3_fp"
+  [(set (match_dup 3)
+	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
+   (set (match_dup 4)
+	(zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "")))
+   (set (match_dup 5)
+	(float:DF (match_dup 3)))
+   (set (match_dup 6)
+	(float:DF (match_dup 4)))
+   (set (match_dup 7)
+	(unspec:DF [(match_dup 5)
+	       	    (match_dup 6)] UNSPEC_DIVC))
+   (set (match_dup 8)
+	(fix:DI (match_dup 7)))
+   (set (match_operand:SI 0 "nonimmediate_operand" "")
+	(match_dup 9))]
+  "TARGET_FP"
+{
+  operands[3] = gen_reg_rtx (DImode);
+  operands[4] = gen_reg_rtx (DImode);
+  operands[5] = gen_reg_rtx (DFmode);
+  operands[6] = gen_reg_rtx (DFmode);
+  operands[7] = gen_reg_rtx (DFmode);
+  operands[8] = gen_reg_rtx (DImode);
+  operands[9] = lowpart_subreg (SImode, operands[8], DImode);
+})
+
+(define_expand "udivsi3_libcall"
   [(set (match_dup 3)
 	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
    (set (match_dup 4)
@@ -827,7 +897,36 @@
   operands[5] = gen_reg_rtx (DImode);
 })
 
-(define_expand "modsi3"
+(define_expand "udivsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(udiv:SI (match_operand:SI 1 "register_operand" "")
+		(match_operand:SI 2 "register_operand" "")))]
+  ""
+{
+  if (TARGET_FP && optimize && !optimize_size)
+    emit_insn (gen_udivsi3_fp (operands[0], operands[1], operands[2]));
+  else if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK)
+    emit_insn (gen_udivsi3_libcall (operands[0], operands[1], operands[2]));
+  else
+    FAIL;
+  DONE;
+})
+
+(define_expand "modsi3_fp"
+  [(set (match_dup 4)
+	(mult:SI (match_dup 3)
+		 (match_operand:SI 2 "nonimmediate_operand" "")))
+   (set (match_operand:SI 0 "nonimmediate_operand" "")
+	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
+		  (match_dup 4)))]
+  "TARGET_FP"
+{
+  operands[3] = gen_reg_rtx (SImode);
+  operands[4] = gen_reg_rtx (SImode);
+  emit_insn (gen_divsi3_fp (operands[3], operands[1], operands[2]));
+})
+
+(define_expand "modsi3_libcall"
   [(set (match_dup 3)
 	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
    (set (match_dup 4)
@@ -845,7 +944,36 @@
   operands[5] = gen_reg_rtx (DImode);
 })
 
-(define_expand "umodsi3"
+(define_expand "modsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(mod:SI (match_operand:SI 1 "register_operand" "")
+		(match_operand:SI 2 "register_operand" "")))]
+  ""
+{
+  if (TARGET_FP && optimize && !optimize_size)
+    emit_insn (gen_modsi3_fp (operands[0], operands[1], operands[2]));
+  else if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK)
+    emit_insn (gen_modsi3_libcall (operands[0], operands[1], operands[2]));
+  else
+    FAIL;
+  DONE;
+})
+
+(define_expand "umodsi3_fp"
+  [(set (match_dup 4)
+	(mult:SI (match_dup 3)
+		 (match_operand:SI 2 "nonimmediate_operand" "")))
+   (set (match_operand:SI 0 "nonimmediate_operand" "")
+	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
+		  (match_dup 4)))]
+  "TARGET_FP"
+{
+  operands[3] = gen_reg_rtx (SImode);
+  operands[4] = gen_reg_rtx (SImode);
+  emit_insn (gen_udivsi3_fp (operands[3], operands[1], operands[2]));
+})
+
+(define_expand "umodsi3_libcall"
   [(set (match_dup 3)
 	(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))
    (set (match_dup 4)
@@ -863,6 +991,21 @@
   operands[5] = gen_reg_rtx (DImode);
 })
 
+(define_expand "umodsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(umod:SI (match_operand:SI 1 "register_operand" "")
+		(match_operand:SI 2 "register_operand" "")))]
+  ""
+{
+  if (TARGET_FP && optimize && !optimize_size)
+    emit_insn (gen_umodsi3_fp (operands[0], operands[1], operands[2]));
+  else if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK)
+    emit_insn (gen_umodsi3_libcall (operands[0], operands[1], operands[2]));
+  else
+    FAIL;
+  DONE;
+})
+
 (define_expand "divdi3"
   [(parallel [(set (match_operand:DI 0 "register_operand" "")
 		   (div:DI (match_operand:DI 1 "register_operand" "")
@@ -2783,6 +2926,18 @@
    (set_attr "round_suffix" "normal")
    (set_attr "trap_suffix" "u_su_sui")])
 
+;; This is only used for integer division, and can only trap for division by
+;; zero, which is undefined, so we don't bother to avoid imprecise traps and
+;; claim it cannot trap.
+(define_insn "divc"
+  [(set (match_operand:DF 0 "register_operand" "=f")
+	(unspec:DF [(match_operand:DF 1 "reg_or_0_operand" "fG")
+		    (match_operand:DF 2 "reg_or_0_operand" "fG")] UNSPEC_DIVC))]
+  "TARGET_FP"
+  "div%-%/ %R1,%R2,%0"
+  [(set_attr "type" "fdiv")
+   (set_attr "round_suffix" "c")])
+
 (define_insn "*divdf_ext1"
   [(set (match_operand:DF 0 "register_operand" "=f")
 	(div:DF (float_extend:DF (match_operand:SF 1 "reg_or_0_operand" "fG"))


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