diff mbox series

[1/6,ARC] Remove non standard funcions calls.

Message ID 20181010080016.12317-2-claziss@gmail.com
State New
Headers show
Series ARC updates | expand

Commit Message

Claudiu Zissulescu Ianculescu Oct. 10, 2018, 8 a.m. UTC
Replace all custom "library" calls with compiler known patterns.

gcc/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc.md (mulsi3): Remove call to mulsi_600_lib.
	(mulsi3_600_lib): Remove pattern.
	(umulsi3_highpart_600_lib_le): Likewise.
	(umulsi3_highpart): Remove call to umulsi3_highpart_600_lib_le.
	(umulsidi3): Remove call to umulsidi3_600_lib.
	(umulsidi3_600_lib): Remove pattern.
	(peephole2): Remove peephole using the above deprecated patterns.

testsuite/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* gcc.target/arc/mulsi3_highpart-2.c: Update test.

libgcc/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/lib1funcs.S (_muldi3): New function.
	* config/arc/t-arc (LIB1ASMFUNCS): Add _muldi3.
---
 gcc/config/arc/arc.md                         | 158 ++----------------
 .../gcc.target/arc/mulsi3_highpart-2.c        |   5 +-
 libgcc/config/arc/lib1funcs.S                 |  54 ++++++
 libgcc/config/arc/t-arc                       |   2 +-
 4 files changed, 67 insertions(+), 152 deletions(-)

Comments

Andrew Burgess Oct. 11, 2018, 10:11 a.m. UTC | #1
* Claudiu Zissulescu <claziss@gmail.com> [2018-10-10 11:00:11 +0300]:

> Replace all custom "library" calls with compiler known patterns.
> 
> gcc/
> xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>
> 
> 	* config/arc/arc.md (mulsi3): Remove call to mulsi_600_lib.
> 	(mulsi3_600_lib): Remove pattern.
> 	(umulsi3_highpart_600_lib_le): Likewise.
> 	(umulsi3_highpart): Remove call to umulsi3_highpart_600_lib_le.
> 	(umulsidi3): Remove call to umulsidi3_600_lib.
> 	(umulsidi3_600_lib): Remove pattern.
> 	(peephole2): Remove peephole using the above deprecated patterns.
> 
> testsuite/
> xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>
> 
> 	* gcc.target/arc/mulsi3_highpart-2.c: Update test.
> 
> libgcc/
> xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>
> 
> 	* config/arc/lib1funcs.S (_muldi3): New function.
> 	* config/arc/t-arc (LIB1ASMFUNCS): Add _muldi3.

This seems fine.

Thanks,
Andrew

> ---
>  gcc/config/arc/arc.md                         | 158 ++----------------
>  .../gcc.target/arc/mulsi3_highpart-2.c        |   5 +-
>  libgcc/config/arc/lib1funcs.S                 |  54 ++++++
>  libgcc/config/arc/t-arc                       |   2 +-
>  4 files changed, 67 insertions(+), 152 deletions(-)
> 
> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
> index 42ca820b91d..d73289a20c4 100644
> --- a/gcc/config/arc/arc.md
> +++ b/gcc/config/arc/arc.md
> @@ -2076,44 +2076,21 @@ archs4x, archs4xd, archs4xd_slow"
>  ;; SI <- SI * SI
>  
>  (define_expand "mulsi3"
> - [(set (match_operand:SI 0 "nonimmediate_operand"            "")
> + [(set (match_operand:SI 0 "register_operand"            "")
>  	(mult:SI (match_operand:SI 1 "register_operand"  "")
>  		 (match_operand:SI 2 "nonmemory_operand" "")))]
> -  ""
> +  "TARGET_ANY_MPY"
>  {
> -  if (TARGET_MPY)
> -    {
> -      if (!register_operand (operands[0], SImode))
> -	{
> -	  rtx result = gen_reg_rtx (SImode);
> -
> -	  emit_insn (gen_mulsi3 (result, operands[1], operands[2]));
> -	  emit_move_insn (operands[0], result);
> -	  DONE;
> -	}
> -    }
> -  else if (TARGET_MUL64_SET)
> +  if (TARGET_MUL64_SET)
>      {
> -     rtx tmp = gen_reg_rtx (SImode);
> -     emit_insn (gen_mulsi64 (tmp, operands[1], operands[2]));
> -     emit_move_insn (operands[0], tmp);
> +     emit_insn (gen_mulsi64 (operands[0], operands[1], operands[2]));
>       DONE;
>      }
>    else if (TARGET_MULMAC_32BY16_SET)
>      {
> -     rtx tmp = gen_reg_rtx (SImode);
> -     emit_insn (gen_mulsi32x16 (tmp, operands[1], operands[2]));
> -     emit_move_insn (operands[0], tmp);
> +     emit_insn (gen_mulsi32x16 (operands[0], operands[1], operands[2]));
>       DONE;
>      }
> -  else
> -    {
> -      emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
> -      emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
> -      emit_insn (gen_mulsi3_600_lib ());
> -      emit_move_insn (operands[0], gen_rtx_REG (SImode, R0_REG));
> -      DONE;
> -    }
>  })
>  
>  (define_insn_and_split "mulsi32x16"
> @@ -2229,27 +2206,6 @@ archs4x, archs4xd, archs4xd_slow"
>     (set_attr "predicable" "yes,yes,no,yes")
>     (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
>  
> -; If we compile without an mul option enabled, but link with libraries
> -; for a mul option, we'll see clobbers of multiplier output registers.
> -; There is also an implementation using norm that clobbers the loop registers.
> -(define_insn "mulsi3_600_lib"
> -  [(set (reg:SI R0_REG)
> -	(mult:SI (reg:SI R0_REG) (reg:SI R1_REG)))
> -   (clobber (reg:SI RETURN_ADDR_REGNUM))
> -   (clobber (reg:SI R1_REG))
> -   (clobber (reg:SI R2_REG))
> -   (clobber (reg:SI R3_REG))
> -   (clobber (reg:DI MUL64_OUT_REG))
> -   (clobber (reg:SI LP_COUNT))
> -   (clobber (reg:SI LP_START))
> -   (clobber (reg:SI LP_END))
> -   (clobber (reg:CC CC_REG))]
> -  "!TARGET_ANY_MPY
> -   && SFUNC_CHECK_PREDICABLE"
> -  "*return arc_output_libcall (\"__mulsi3\");"
> -  [(set_attr "is_sfunc" "yes")
> -   (set_attr "predicable" "yes")])
> -
>  (define_insn_and_split "mulsidi_600"
>    [(set (match_operand:DI 0 "register_operand"                               "=c, c,c,  c")
>  	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "%Rcq#q, c,c,  c"))
> @@ -2504,48 +2460,6 @@ archs4x, archs4xd, archs4xd_slow"
>     (set_attr "predicable" "yes,no,yes,no")
>     (set_attr "cond" "canuse,nocond,canuse,nocond")])
>  
> -; Implementations include additional labels for umulsidi3, so we got all
> -; the same clobbers - plus one for the result low part.  */
> -(define_insn "umulsi3_highpart_600_lib_le"
> -  [(set (reg:SI R1_REG)
> -	(truncate:SI
> -	 (lshiftrt:DI
> -	  (mult:DI (zero_extend:DI (reg:SI R0_REG))
> -		   (zero_extend:DI (reg:SI R1_REG)))
> -	  (const_int 32))))
> -   (clobber (reg:SI RETURN_ADDR_REGNUM))
> -   (clobber (reg:SI R0_REG))
> -   (clobber (reg:DI R2_REG))
> -   (clobber (reg:SI R12_REG))
> -   (clobber (reg:DI MUL64_OUT_REG))
> -   (clobber (reg:CC CC_REG))]
> -  "!TARGET_BIG_ENDIAN
> -   && !TARGET_ANY_MPY
> -   && SFUNC_CHECK_PREDICABLE"
> -  "*return arc_output_libcall (\"__umulsi3_highpart\");"
> -  [(set_attr "is_sfunc" "yes")
> -   (set_attr "predicable" "yes")])
> -
> -(define_insn "umulsi3_highpart_600_lib_be"
> -  [(set (reg:SI R0_REG)
> -	(truncate:SI
> -	 (lshiftrt:DI
> -	  (mult:DI (zero_extend:DI (reg:SI R0_REG))
> -		   (zero_extend:DI (reg:SI R1_REG)))
> -	  (const_int 32))))
> -   (clobber (reg:SI RETURN_ADDR_REGNUM))
> -   (clobber (reg:SI R1_REG))
> -   (clobber (reg:DI R2_REG))
> -   (clobber (reg:SI R12_REG))
> -   (clobber (reg:DI MUL64_OUT_REG))
> -   (clobber (reg:CC CC_REG))]
> -  "TARGET_BIG_ENDIAN
> -   && !TARGET_ANY_MPY
> -   && SFUNC_CHECK_PREDICABLE"
> -  "*return arc_output_libcall (\"__umulsi3_highpart\");"
> -  [(set_attr "is_sfunc" "yes")
> -   (set_attr "predicable" "yes")])
> -
>  ;; (zero_extend:DI (const_int)) leads to internal errors in combine, so we
>  ;; need a separate pattern for immediates
>  ;; ??? This is fine for combine, but not for reload.
> @@ -2572,23 +2486,11 @@ archs4x, archs4xd, archs4xd_slow"
>  	   (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
>  	   (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" "")))
>  	  (const_int 32))))]
> -  "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET"
> +  "TARGET_MPY"
>    "
>  {
>    rtx target = operands[0];
>  
> -  if (!TARGET_MPY)
> -    {
> -      emit_move_insn (gen_rtx_REG (SImode, 0), operands[1]);
> -      emit_move_insn (gen_rtx_REG (SImode, 1), operands[2]);
> -      if (TARGET_BIG_ENDIAN)
> -	emit_insn (gen_umulsi3_highpart_600_lib_be ());
> -      else
> -	emit_insn (gen_umulsi3_highpart_600_lib_le ());
> -      emit_move_insn (target, gen_rtx_REG (SImode, 0));
> -      DONE;
> -    }
> -
>    if (!register_operand (target, SImode))
>      target = gen_reg_rtx (SImode);
>  
> @@ -2607,7 +2509,7 @@ archs4x, archs4xd, archs4xd_slow"
>    [(set (match_operand:DI 0 "register_operand" "")
>  	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
>  		 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
> -  ""
> +  "TARGET_ANY_MPY"
>  {
>    if (TARGET_PLUS_MACD)
>      {
> @@ -2646,12 +2548,8 @@ archs4x, archs4xd, archs4xd_slow"
>        DONE;
>      }
>    else
> -    {
> -      emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
> -      emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
> -      emit_insn (gen_umulsidi3_600_lib ());
> -      emit_move_insn (operands[0], gen_rtx_REG (DImode, R0_REG));
> -      DONE;
> +  {
> +   gcc_unreachable ();
>      }
>  })
>  
> @@ -2729,7 +2627,7 @@ archs4x, archs4xd, archs4xd_slow"
>  		 (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
>    "TARGET_MPY && !TARGET_PLUS_MACD"
>    "#"
> -  "reload_completed"
> +  "TARGET_MPY && !TARGET_PLUS_MACD && reload_completed"
>    [(const_int 0)]
>  {
>    int hi = !TARGET_BIG_ENDIAN;
> @@ -2743,42 +2641,6 @@ archs4x, archs4xd, archs4xd_slow"
>    [(set_attr "type" "umulti")
>    (set_attr "length" "8")])
>  
> -(define_insn "umulsidi3_600_lib"
> -  [(set (reg:DI R0_REG)
> -	(mult:DI (zero_extend:DI (reg:SI R0_REG))
> -		 (zero_extend:DI (reg:SI R1_REG))))
> -   (clobber (reg:SI RETURN_ADDR_REGNUM))
> -   (clobber (reg:DI R2_REG))
> -   (clobber (reg:SI R12_REG))
> -   (clobber (reg:DI MUL64_OUT_REG))
> -   (clobber (reg:CC CC_REG))]
> -   "!TARGET_ANY_MPY
> -   && SFUNC_CHECK_PREDICABLE"
> -  "*return arc_output_libcall (\"__umulsidi3\");"
> -  [(set_attr "is_sfunc" "yes")
> -   (set_attr "predicable" "yes")])
> -
> -(define_peephole2
> -  [(parallel
> -     [(set (reg:DI R0_REG)
> -	   (mult:DI (zero_extend:DI (reg:SI R0_REG))
> -		    (zero_extend:DI (reg:SI R1_REG))))
> -      (clobber (reg:SI RETURN_ADDR_REGNUM))
> -      (clobber (reg:DI R2_REG))
> -      (clobber (reg:SI R12_REG))
> -      (clobber (reg:DI MUL64_OUT_REG))
> -      (clobber (reg:CC CC_REG))])]
> -  "!TARGET_ANY_MPY
> -   && peep2_regno_dead_p (1, TARGET_BIG_ENDIAN ? R1_REG : R0_REG)"
> -  [(pc)]
> -{
> -  if (TARGET_BIG_ENDIAN)
> -    emit_insn (gen_umulsi3_highpart_600_lib_be ());
> -  else
> -    emit_insn (gen_umulsi3_highpart_600_lib_le ());
> -  DONE;
> -})
> -
>  (define_expand "addsi3"
>    [(set (match_operand:SI 0 "dest_reg_operand" "")
>  	(plus:SI (match_operand:SI 1 "register_operand" "")
> diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
> index 4b54cbf6a52..22b28cf2507 100644
> --- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
> +++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
> @@ -1,7 +1,7 @@
>  /* { dg-do run } */
>  /* { dg-skip-if "ARC700 always has mpy option on" { arc700 } } */
>  /* { dg-skip-if "ARC600 doesn't have mpy instruction" { arc6xx } } */
> -/* { dg-options "-O2 -mmpy-option=0 -w" } */
> +/* { dg-options "-O2 -mmpy-option=0 -w -save-temps" } */
>  
>  #include <stdlib.h>
>  
> @@ -28,5 +28,4 @@ main (void)
>  }
>  
>  /* { dg-final { scan-assembler-not "mpyhu\[ \t\]" } } */
> -/* { dg-final { scan-assembler-not "@__muldi3" } } */
> -/* { dg-final { scan-assembler "@__umulsi3_highpart" } } */
> +/* { dg-final { scan-assembler "@__muldi3" } } */
> diff --git a/libgcc/config/arc/lib1funcs.S b/libgcc/config/arc/lib1funcs.S
> index 9a626022612..249dd7a7ff7 100644
> --- a/libgcc/config/arc/lib1funcs.S
> +++ b/libgcc/config/arc/lib1funcs.S
> @@ -232,6 +232,60 @@ SYM(__umulsi3_highpart):
>  #endif
>  #endif /* L_umulsidi3 */
>  
> +#ifdef L_muldi3
> +	.section .text
> +	.align 4
> +	.global SYM(__muldi3)
> +SYM(__muldi3):
> +#ifdef __LITTLE_ENDIAN__
> +        push_s blink
> +        mov_s r4,r3     ;4
> +        mov_s r5,r2     ;4
> +        mov_s r9,r0     ;4
> +        mov_s r8,r1     ;4
> +        bl.d @__umulsidi3
> +        mov_s r1,r2     ;4
> +        mov_s r6,r0     ;4
> +        mov_s r7,r1     ;4
> +        mov_s r0,r9     ;4
> +        bl.d @__mulsi3
> +        mov_s r1,r4     ;4
> +        mov_s r4,r0     ;4
> +        mov_s r1,r8     ;4
> +        bl.d @__mulsi3
> +        mov_s r0,r5     ;4
> +        pop_s blink
> +        add_s r0,r0,r4 ;2
> +        add r1,r0,r7
> +        j_s.d [blink]
> +        mov_s r0,r6     ;4
> +#else
> +	push_s  blink
> +	mov_s   r5,r3
> +	mov_s   r9,r2
> +	mov_s   r4,r1
> +	mov_s   r8,r0
> +	mov_s   r0,r1
> +	bl.d 	@__umulsidi3
> +	mov_s   r1,r3
> +	mov_s   r7,r0
> +	mov_s   r6,r1
> +	mov_s   r0,r4
> +	bl.d    @__mulsi3
> +	mov_s   r1,r9
> +	mov_s   r4,r0
> +	mov_s   r1,r8
> +	bl.d    @__mulsi3
> +	mov_s   r0,r5
> +	pop_s   blink
> +	add_s   r0,r0,r4
> +	add_s   r0,r0,r7
> +	j_s.d   [blink]
> +	mov_s   r1,r6
> +#endif /* __LITTLE_ENDIAN__ */
> +ENDFUNC(__muldi3)
> +#endif /* L_muldi3 */
> +
>  #ifdef  L_umulsi3_highpart
>  #include "ieee-754/arc-ieee-754.h"
>  /* For use without a barrel shifter, and for ARC700 / ARC_MUL64, the
> diff --git a/libgcc/config/arc/t-arc b/libgcc/config/arc/t-arc
> index ad30fdb1db7..c79bc1cfdc4 100644
> --- a/libgcc/config/arc/t-arc
> +++ b/libgcc/config/arc/t-arc
> @@ -21,7 +21,7 @@
>  
>  CROSS_LIBGCC1 = libgcc1-asm.a
>  LIB1ASMSRC = arc/lib1funcs.S
> -LIB1ASMFUNCS = _mulsi3 _umulsidi3  _umulsi3_highpart \
> +LIB1ASMFUNCS = _mulsi3 _umulsidi3  _umulsi3_highpart _muldi3 \
>    _udivsi3 _divsi3 _umodsi3 _modsi3 \
>    _divmod_tools _clzsi2 \
>    _millicodethunk_st _millicodethunk_ld _millicodethunk_ret \
> -- 
> 2.17.1
>
Claudiu Zissulescu Ianculescu Oct. 31, 2018, 11:30 a.m. UTC | #2
Thank you for your review. Patch pushed,
Claudiu
diff mbox series

Patch

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 42ca820b91d..d73289a20c4 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -2076,44 +2076,21 @@  archs4x, archs4xd, archs4xd_slow"
 ;; SI <- SI * SI
 
 (define_expand "mulsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand"            "")
+ [(set (match_operand:SI 0 "register_operand"            "")
 	(mult:SI (match_operand:SI 1 "register_operand"  "")
 		 (match_operand:SI 2 "nonmemory_operand" "")))]
-  ""
+  "TARGET_ANY_MPY"
 {
-  if (TARGET_MPY)
-    {
-      if (!register_operand (operands[0], SImode))
-	{
-	  rtx result = gen_reg_rtx (SImode);
-
-	  emit_insn (gen_mulsi3 (result, operands[1], operands[2]));
-	  emit_move_insn (operands[0], result);
-	  DONE;
-	}
-    }
-  else if (TARGET_MUL64_SET)
+  if (TARGET_MUL64_SET)
     {
-     rtx tmp = gen_reg_rtx (SImode);
-     emit_insn (gen_mulsi64 (tmp, operands[1], operands[2]));
-     emit_move_insn (operands[0], tmp);
+     emit_insn (gen_mulsi64 (operands[0], operands[1], operands[2]));
      DONE;
     }
   else if (TARGET_MULMAC_32BY16_SET)
     {
-     rtx tmp = gen_reg_rtx (SImode);
-     emit_insn (gen_mulsi32x16 (tmp, operands[1], operands[2]));
-     emit_move_insn (operands[0], tmp);
+     emit_insn (gen_mulsi32x16 (operands[0], operands[1], operands[2]));
      DONE;
     }
-  else
-    {
-      emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
-      emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
-      emit_insn (gen_mulsi3_600_lib ());
-      emit_move_insn (operands[0], gen_rtx_REG (SImode, R0_REG));
-      DONE;
-    }
 })
 
 (define_insn_and_split "mulsi32x16"
@@ -2229,27 +2206,6 @@  archs4x, archs4xd, archs4xd_slow"
    (set_attr "predicable" "yes,yes,no,yes")
    (set_attr "cond" "canuse,canuse,canuse_limm,canuse")])
 
-; If we compile without an mul option enabled, but link with libraries
-; for a mul option, we'll see clobbers of multiplier output registers.
-; There is also an implementation using norm that clobbers the loop registers.
-(define_insn "mulsi3_600_lib"
-  [(set (reg:SI R0_REG)
-	(mult:SI (reg:SI R0_REG) (reg:SI R1_REG)))
-   (clobber (reg:SI RETURN_ADDR_REGNUM))
-   (clobber (reg:SI R1_REG))
-   (clobber (reg:SI R2_REG))
-   (clobber (reg:SI R3_REG))
-   (clobber (reg:DI MUL64_OUT_REG))
-   (clobber (reg:SI LP_COUNT))
-   (clobber (reg:SI LP_START))
-   (clobber (reg:SI LP_END))
-   (clobber (reg:CC CC_REG))]
-  "!TARGET_ANY_MPY
-   && SFUNC_CHECK_PREDICABLE"
-  "*return arc_output_libcall (\"__mulsi3\");"
-  [(set_attr "is_sfunc" "yes")
-   (set_attr "predicable" "yes")])
-
 (define_insn_and_split "mulsidi_600"
   [(set (match_operand:DI 0 "register_operand"                               "=c, c,c,  c")
 	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"  "%Rcq#q, c,c,  c"))
@@ -2504,48 +2460,6 @@  archs4x, archs4xd, archs4xd_slow"
    (set_attr "predicable" "yes,no,yes,no")
    (set_attr "cond" "canuse,nocond,canuse,nocond")])
 
-; Implementations include additional labels for umulsidi3, so we got all
-; the same clobbers - plus one for the result low part.  */
-(define_insn "umulsi3_highpart_600_lib_le"
-  [(set (reg:SI R1_REG)
-	(truncate:SI
-	 (lshiftrt:DI
-	  (mult:DI (zero_extend:DI (reg:SI R0_REG))
-		   (zero_extend:DI (reg:SI R1_REG)))
-	  (const_int 32))))
-   (clobber (reg:SI RETURN_ADDR_REGNUM))
-   (clobber (reg:SI R0_REG))
-   (clobber (reg:DI R2_REG))
-   (clobber (reg:SI R12_REG))
-   (clobber (reg:DI MUL64_OUT_REG))
-   (clobber (reg:CC CC_REG))]
-  "!TARGET_BIG_ENDIAN
-   && !TARGET_ANY_MPY
-   && SFUNC_CHECK_PREDICABLE"
-  "*return arc_output_libcall (\"__umulsi3_highpart\");"
-  [(set_attr "is_sfunc" "yes")
-   (set_attr "predicable" "yes")])
-
-(define_insn "umulsi3_highpart_600_lib_be"
-  [(set (reg:SI R0_REG)
-	(truncate:SI
-	 (lshiftrt:DI
-	  (mult:DI (zero_extend:DI (reg:SI R0_REG))
-		   (zero_extend:DI (reg:SI R1_REG)))
-	  (const_int 32))))
-   (clobber (reg:SI RETURN_ADDR_REGNUM))
-   (clobber (reg:SI R1_REG))
-   (clobber (reg:DI R2_REG))
-   (clobber (reg:SI R12_REG))
-   (clobber (reg:DI MUL64_OUT_REG))
-   (clobber (reg:CC CC_REG))]
-  "TARGET_BIG_ENDIAN
-   && !TARGET_ANY_MPY
-   && SFUNC_CHECK_PREDICABLE"
-  "*return arc_output_libcall (\"__umulsi3_highpart\");"
-  [(set_attr "is_sfunc" "yes")
-   (set_attr "predicable" "yes")])
-
 ;; (zero_extend:DI (const_int)) leads to internal errors in combine, so we
 ;; need a separate pattern for immediates
 ;; ??? This is fine for combine, but not for reload.
@@ -2572,23 +2486,11 @@  archs4x, archs4xd, archs4xd_slow"
 	   (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
 	   (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" "")))
 	  (const_int 32))))]
-  "!TARGET_MUL64_SET && !TARGET_MULMAC_32BY16_SET"
+  "TARGET_MPY"
   "
 {
   rtx target = operands[0];
 
-  if (!TARGET_MPY)
-    {
-      emit_move_insn (gen_rtx_REG (SImode, 0), operands[1]);
-      emit_move_insn (gen_rtx_REG (SImode, 1), operands[2]);
-      if (TARGET_BIG_ENDIAN)
-	emit_insn (gen_umulsi3_highpart_600_lib_be ());
-      else
-	emit_insn (gen_umulsi3_highpart_600_lib_le ());
-      emit_move_insn (target, gen_rtx_REG (SImode, 0));
-      DONE;
-    }
-
   if (!register_operand (target, SImode))
     target = gen_reg_rtx (SImode);
 
@@ -2607,7 +2509,7 @@  archs4x, archs4xd, archs4xd_slow"
   [(set (match_operand:DI 0 "register_operand" "")
 	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" ""))
 		 (zero_extend:DI (match_operand:SI 2 "nonmemory_operand" ""))))]
-  ""
+  "TARGET_ANY_MPY"
 {
   if (TARGET_PLUS_MACD)
     {
@@ -2646,12 +2548,8 @@  archs4x, archs4xd, archs4xd_slow"
       DONE;
     }
   else
-    {
-      emit_move_insn (gen_rtx_REG (SImode, R0_REG), operands[1]);
-      emit_move_insn (gen_rtx_REG (SImode, R1_REG), operands[2]);
-      emit_insn (gen_umulsidi3_600_lib ());
-      emit_move_insn (operands[0], gen_rtx_REG (DImode, R0_REG));
-      DONE;
+  {
+   gcc_unreachable ();
     }
 })
 
@@ -2729,7 +2627,7 @@  archs4x, archs4xd, archs4xd_slow"
 		 (zero_extend:DI (match_operand:SI 2 "extend_operand" "cL"))))]
   "TARGET_MPY && !TARGET_PLUS_MACD"
   "#"
-  "reload_completed"
+  "TARGET_MPY && !TARGET_PLUS_MACD && reload_completed"
   [(const_int 0)]
 {
   int hi = !TARGET_BIG_ENDIAN;
@@ -2743,42 +2641,6 @@  archs4x, archs4xd, archs4xd_slow"
   [(set_attr "type" "umulti")
   (set_attr "length" "8")])
 
-(define_insn "umulsidi3_600_lib"
-  [(set (reg:DI R0_REG)
-	(mult:DI (zero_extend:DI (reg:SI R0_REG))
-		 (zero_extend:DI (reg:SI R1_REG))))
-   (clobber (reg:SI RETURN_ADDR_REGNUM))
-   (clobber (reg:DI R2_REG))
-   (clobber (reg:SI R12_REG))
-   (clobber (reg:DI MUL64_OUT_REG))
-   (clobber (reg:CC CC_REG))]
-   "!TARGET_ANY_MPY
-   && SFUNC_CHECK_PREDICABLE"
-  "*return arc_output_libcall (\"__umulsidi3\");"
-  [(set_attr "is_sfunc" "yes")
-   (set_attr "predicable" "yes")])
-
-(define_peephole2
-  [(parallel
-     [(set (reg:DI R0_REG)
-	   (mult:DI (zero_extend:DI (reg:SI R0_REG))
-		    (zero_extend:DI (reg:SI R1_REG))))
-      (clobber (reg:SI RETURN_ADDR_REGNUM))
-      (clobber (reg:DI R2_REG))
-      (clobber (reg:SI R12_REG))
-      (clobber (reg:DI MUL64_OUT_REG))
-      (clobber (reg:CC CC_REG))])]
-  "!TARGET_ANY_MPY
-   && peep2_regno_dead_p (1, TARGET_BIG_ENDIAN ? R1_REG : R0_REG)"
-  [(pc)]
-{
-  if (TARGET_BIG_ENDIAN)
-    emit_insn (gen_umulsi3_highpart_600_lib_be ());
-  else
-    emit_insn (gen_umulsi3_highpart_600_lib_le ());
-  DONE;
-})
-
 (define_expand "addsi3"
   [(set (match_operand:SI 0 "dest_reg_operand" "")
 	(plus:SI (match_operand:SI 1 "register_operand" "")
diff --git a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
index 4b54cbf6a52..22b28cf2507 100644
--- a/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
+++ b/gcc/testsuite/gcc.target/arc/mulsi3_highpart-2.c
@@ -1,7 +1,7 @@ 
 /* { dg-do run } */
 /* { dg-skip-if "ARC700 always has mpy option on" { arc700 } } */
 /* { dg-skip-if "ARC600 doesn't have mpy instruction" { arc6xx } } */
-/* { dg-options "-O2 -mmpy-option=0 -w" } */
+/* { dg-options "-O2 -mmpy-option=0 -w -save-temps" } */
 
 #include <stdlib.h>
 
@@ -28,5 +28,4 @@  main (void)
 }
 
 /* { dg-final { scan-assembler-not "mpyhu\[ \t\]" } } */
-/* { dg-final { scan-assembler-not "@__muldi3" } } */
-/* { dg-final { scan-assembler "@__umulsi3_highpart" } } */
+/* { dg-final { scan-assembler "@__muldi3" } } */
diff --git a/libgcc/config/arc/lib1funcs.S b/libgcc/config/arc/lib1funcs.S
index 9a626022612..249dd7a7ff7 100644
--- a/libgcc/config/arc/lib1funcs.S
+++ b/libgcc/config/arc/lib1funcs.S
@@ -232,6 +232,60 @@  SYM(__umulsi3_highpart):
 #endif
 #endif /* L_umulsidi3 */
 
+#ifdef L_muldi3
+	.section .text
+	.align 4
+	.global SYM(__muldi3)
+SYM(__muldi3):
+#ifdef __LITTLE_ENDIAN__
+        push_s blink
+        mov_s r4,r3     ;4
+        mov_s r5,r2     ;4
+        mov_s r9,r0     ;4
+        mov_s r8,r1     ;4
+        bl.d @__umulsidi3
+        mov_s r1,r2     ;4
+        mov_s r6,r0     ;4
+        mov_s r7,r1     ;4
+        mov_s r0,r9     ;4
+        bl.d @__mulsi3
+        mov_s r1,r4     ;4
+        mov_s r4,r0     ;4
+        mov_s r1,r8     ;4
+        bl.d @__mulsi3
+        mov_s r0,r5     ;4
+        pop_s blink
+        add_s r0,r0,r4 ;2
+        add r1,r0,r7
+        j_s.d [blink]
+        mov_s r0,r6     ;4
+#else
+	push_s  blink
+	mov_s   r5,r3
+	mov_s   r9,r2
+	mov_s   r4,r1
+	mov_s   r8,r0
+	mov_s   r0,r1
+	bl.d 	@__umulsidi3
+	mov_s   r1,r3
+	mov_s   r7,r0
+	mov_s   r6,r1
+	mov_s   r0,r4
+	bl.d    @__mulsi3
+	mov_s   r1,r9
+	mov_s   r4,r0
+	mov_s   r1,r8
+	bl.d    @__mulsi3
+	mov_s   r0,r5
+	pop_s   blink
+	add_s   r0,r0,r4
+	add_s   r0,r0,r7
+	j_s.d   [blink]
+	mov_s   r1,r6
+#endif /* __LITTLE_ENDIAN__ */
+ENDFUNC(__muldi3)
+#endif /* L_muldi3 */
+
 #ifdef  L_umulsi3_highpart
 #include "ieee-754/arc-ieee-754.h"
 /* For use without a barrel shifter, and for ARC700 / ARC_MUL64, the
diff --git a/libgcc/config/arc/t-arc b/libgcc/config/arc/t-arc
index ad30fdb1db7..c79bc1cfdc4 100644
--- a/libgcc/config/arc/t-arc
+++ b/libgcc/config/arc/t-arc
@@ -21,7 +21,7 @@ 
 
 CROSS_LIBGCC1 = libgcc1-asm.a
 LIB1ASMSRC = arc/lib1funcs.S
-LIB1ASMFUNCS = _mulsi3 _umulsidi3  _umulsi3_highpart \
+LIB1ASMFUNCS = _mulsi3 _umulsidi3  _umulsi3_highpart _muldi3 \
   _udivsi3 _divsi3 _umodsi3 _modsi3 \
   _divmod_tools _clzsi2 \
   _millicodethunk_st _millicodethunk_ld _millicodethunk_ret \