mips16: div/mod by zero patch

Gavin Koch gavin@cygnus.com
Thu Jan 15 16:30:00 GMT 1998


In the mips backend, for non-optimized -mips16 code, for a div
or mod by the constant zero (or something that folds to the
constant zero), the compiler is generating something like

    div $0,$4,0

which is not a valid mips16 instruction, and you get assembler
errors.  

(Of course div or mod by zero will fail, but it should not
do so until runtime, if the expression is exectuted.  Ironically
this does not fail for other constants, because the compiler
generally generates a sequence of shifts and adds for the division.)

This patch fixes this by changing the non-optimized div and mod
insns to force the last arg into a register if -mips16.

	mips/mips.md (divsi3,divdi3,modsi3,moddi3,udivsi3,udivdi3,
	umodsi3,umoddi3): Handle mips16 div/mod by a constant.

Index: mips.md
===================================================================
***************
*** 2246,2252 ****
     (set_attr "mode"	"DI")
     (set_attr "length"	"8")])		;; various tests for dividing by 0 and such
  
! (define_insn "divsi3"
    [(set (match_operand:SI 0 "register_operand" "=d")
  	(div:SI (match_operand:SI 1 "register_operand" "d")
  		(match_operand:SI 2 "nonmemory_operand" "di")))
--- 2246,2252 ----
     (set_attr "mode"	"DI")
     (set_attr "length"	"8")])		;; various tests for dividing by 0 and such
  
! (define_expand "divsi3"
    [(set (match_operand:SI 0 "register_operand" "=d")
  	(div:SI (match_operand:SI 1 "register_operand" "d")
  		(match_operand:SI 2 "nonmemory_operand" "di")))
***************
*** 2254,2265 ****
     (clobber (match_scratch:SI 4 "=h"))
     (clobber (match_scratch:SI 6 "=a"))]
    "!optimize"
    "div\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"SI")
!    (set_attr "length"	"13")])		;; various tests for dividing by 0 and such
  
! (define_insn "divdi3"
    [(set (match_operand:DI 0 "register_operand" "=d")
  	(div:DI (match_operand:DI 1 "se_register_operand" "d")
  		(match_operand:DI 2 "se_nonmemory_operand" "di")))
--- 2254,2277 ----
     (clobber (match_scratch:SI 4 "=h"))
     (clobber (match_scratch:SI 6 "=a"))]
    "!optimize"
+   "
+ {
+   /* MIPS16 needs div/rem ops in registers. */
+   if (TARGET_MIPS16)
+     operands[2] = force_reg (SImode, operands[2]);
+ }")
+ 
+ (define_insn "divsi3_internal"
+   [(set (match_operand:SI 0 "register_operand" "=d")
+ 	(div:SI (match_operand:SI 1 "register_operand" "d")
+ 		(match_operand:SI 2 "nonmemory_operand" "di")))]
+   "!optimize"
    "div\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"SI")
!    (set_attr "length"	"13")])	;; various tests for dividing by 0 and such
  
! (define_expand "divdi3"
    [(set (match_operand:DI 0 "register_operand" "=d")
  	(div:DI (match_operand:DI 1 "se_register_operand" "d")
  		(match_operand:DI 2 "se_nonmemory_operand" "di")))
***************
*** 2267,2278 ****
     (clobber (match_scratch:DI 4 "=h"))
     (clobber (match_scratch:DI 6 "=a"))]
    "TARGET_64BIT && !optimize"
    "ddiv\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"DI")
!    (set_attr "length"	"14")])		;; various tests for dividing by 0 and such
  
! (define_insn "modsi3"
    [(set (match_operand:SI 0 "register_operand" "=d")
  	(mod:SI (match_operand:SI 1 "register_operand" "d")
  		(match_operand:SI 2 "nonmemory_operand" "di")))
--- 2279,2302 ----
     (clobber (match_scratch:DI 4 "=h"))
     (clobber (match_scratch:DI 6 "=a"))]
    "TARGET_64BIT && !optimize"
+   "
+ {
+   /* MIPS16 needs div/rem ops in registers. */
+   if (TARGET_MIPS16)
+     operands[2] = force_reg (DImode, operands[2]);
+ }")
+ 
+ (define_insn "divdi3_internal"
+   [(set (match_operand:DI 0 "register_operand" "=d")
+ 	(div:DI (match_operand:DI 1 "se_register_operand" "d")
+ 		(match_operand:DI 2 "se_nonmemory_operand" "di")))]
+   "TARGET_64BIT && !optimize"
    "ddiv\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"DI")
!    (set_attr "length"	"14")])	;; various tests for dividing by 0 and such
  
! (define_expand "modsi3"
    [(set (match_operand:SI 0 "register_operand" "=d")
  	(mod:SI (match_operand:SI 1 "register_operand" "d")
  		(match_operand:SI 2 "nonmemory_operand" "di")))
***************
*** 2280,2291 ****
     (clobber (match_scratch:SI 4 "=h"))
     (clobber (match_scratch:SI 6 "=a"))]
    "!optimize"
    "rem\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"SI")
!    (set_attr "length"	"13")])		;; various tests for dividing by 0 and such
  
! (define_insn "moddi3"
    [(set (match_operand:DI 0 "register_operand" "=d")
  	(mod:DI (match_operand:DI 1 "se_register_operand" "d")
  		(match_operand:DI 2 "se_nonmemory_operand" "di")))
--- 2304,2327 ----
     (clobber (match_scratch:SI 4 "=h"))
     (clobber (match_scratch:SI 6 "=a"))]
    "!optimize"
+   "
+ {
+   /* MIPS16 needs div/rem ops in registers. */
+   if (TARGET_MIPS16)
+     operands[2] = force_reg (SImode, operands[2]);
+ }")
+ 
+ (define_insn "modsi3_internal"
+   [(set (match_operand:SI 0 "register_operand" "=d")
+ 	(mod:SI (match_operand:SI 1 "register_operand" "d")
+ 		(match_operand:SI 2 "nonmemory_operand" "di")))]
+   "!optimize"
    "rem\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"SI")
!    (set_attr "length"	"13")])	;; various tests for dividing by 0 and such
  
! (define_expand "moddi3"
    [(set (match_operand:DI 0 "register_operand" "=d")
  	(mod:DI (match_operand:DI 1 "se_register_operand" "d")
  		(match_operand:DI 2 "se_nonmemory_operand" "di")))
***************
*** 2293,2304 ****
     (clobber (match_scratch:DI 4 "=h"))
     (clobber (match_scratch:DI 6 "=a"))]
    "TARGET_64BIT && !optimize"
    "drem\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"DI")
!    (set_attr "length"	"14")])		;; various tests for dividing by 0 and such
  
! (define_insn "udivsi3"
    [(set (match_operand:SI 0 "register_operand" "=d")
  	(udiv:SI (match_operand:SI 1 "register_operand" "d")
  		 (match_operand:SI 2 "nonmemory_operand" "di")))
--- 2329,2352 ----
     (clobber (match_scratch:DI 4 "=h"))
     (clobber (match_scratch:DI 6 "=a"))]
    "TARGET_64BIT && !optimize"
+   "
+ {
+   /* MIPS16 needs div/rem ops in registers. */
+   if (TARGET_MIPS16)
+     operands[2] = force_reg (DImode, operands[2]);
+ }")
+ 
+ (define_insn "moddi3_internal"
+   [(set (match_operand:DI 0 "register_operand" "=d")
+ 	(mod:DI (match_operand:DI 1 "se_register_operand" "d")
+ 		(match_operand:DI 2 "se_nonmemory_operand" "di")))]
+   "TARGET_64BIT && !optimize"
    "drem\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"DI")
!    (set_attr "length"	"14")])	;; various tests for dividing by 0 and such
  
! (define_expand "udivsi3"
    [(set (match_operand:SI 0 "register_operand" "=d")
  	(udiv:SI (match_operand:SI 1 "register_operand" "d")
  		 (match_operand:SI 2 "nonmemory_operand" "di")))
***************
*** 2306,2317 ****
     (clobber (match_scratch:SI 4 "=h"))
     (clobber (match_scratch:SI 6 "=a"))]
    "!optimize"
    "divu\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"SI")
!    (set_attr "length"	"7")])		;; various tests for dividing by 0 and such
  
! (define_insn "udivdi3"
    [(set (match_operand:DI 0 "register_operand" "=d")
  	(udiv:DI (match_operand:DI 1 "se_register_operand" "d")
  		 (match_operand:DI 2 "se_nonmemory_operand" "di")))
--- 2354,2377 ----
     (clobber (match_scratch:SI 4 "=h"))
     (clobber (match_scratch:SI 6 "=a"))]
    "!optimize"
+   "
+ {
+   /* MIPS16 needs div/rem ops in registers. */
+   if (TARGET_MIPS16)
+     operands[2] = force_reg (SImode, operands[2]);
+ }")
+ 
+ (define_insn "udivsi3_internal"
+   [(set (match_operand:SI 0 "register_operand" "=d")
+ 	(udiv:SI (match_operand:SI 1 "register_operand" "d")
+ 		 (match_operand:SI 2 "nonmemory_operand" "di")))]
+   "!optimize"
    "divu\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"SI")
!    (set_attr "length"	"7")])	;; various tests for dividing by 0 and such
  
! (define_expand "udivdi3"
    [(set (match_operand:DI 0 "register_operand" "=d")
  	(udiv:DI (match_operand:DI 1 "se_register_operand" "d")
  		 (match_operand:DI 2 "se_nonmemory_operand" "di")))
***************
*** 2319,2330 ****
     (clobber (match_scratch:DI 4 "=h"))
     (clobber (match_scratch:DI 6 "=a"))]
    "TARGET_64BIT && !optimize"
    "ddivu\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"DI")
!    (set_attr "length"	"7")])		;; various tests for dividing by 0 and such
  
! (define_insn "umodsi3"
    [(set (match_operand:SI 0 "register_operand" "=d")
  	(umod:SI (match_operand:SI 1 "register_operand" "d")
  		 (match_operand:SI 2 "nonmemory_operand" "di")))
--- 2379,2402 ----
     (clobber (match_scratch:DI 4 "=h"))
     (clobber (match_scratch:DI 6 "=a"))]
    "TARGET_64BIT && !optimize"
+   "
+ {
+   /* MIPS16 needs div/rem ops in registers. */
+   if (TARGET_MIPS16)
+     operands[2] = force_reg (DImode, operands[2]);
+ }")
+ 
+ (define_insn "udivdi3_internal"
+   [(set (match_operand:DI 0 "register_operand" "=d")
+ 	(udiv:DI (match_operand:DI 1 "se_register_operand" "d")
+ 		 (match_operand:DI 2 "se_nonmemory_operand" "di")))]
+   "TARGET_64BIT && !optimize"
    "ddivu\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"DI")
!    (set_attr "length"	"7")])	;; various tests for dividing by 0 and such
  
! (define_expand "umodsi3"
    [(set (match_operand:SI 0 "register_operand" "=d")
  	(umod:SI (match_operand:SI 1 "register_operand" "d")
  		 (match_operand:SI 2 "nonmemory_operand" "di")))
***************
*** 2332,2343 ****
     (clobber (match_scratch:SI 4 "=h"))
     (clobber (match_scratch:SI 6 "=a"))]
    "!optimize"
    "remu\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"SI")
!    (set_attr "length"	"7")])		;; various tests for dividing by 0 and such
  
! (define_insn "umoddi3"
    [(set (match_operand:DI 0 "register_operand" "=d")
  	(umod:DI (match_operand:DI 1 "se_register_operand" "d")
  		 (match_operand:DI 2 "se_nonmemory_operand" "di")))
--- 2404,2427 ----
     (clobber (match_scratch:SI 4 "=h"))
     (clobber (match_scratch:SI 6 "=a"))]
    "!optimize"
+   "
+ {
+   /* MIPS16 needs div/rem ops in registers. */
+   if (TARGET_MIPS16)
+     operands[2] = force_reg (SImode, operands[2]);
+ }")
+ 
+ (define_insn "umodsi3_internal"
+   [(set (match_operand:SI 0 "register_operand" "=d")
+ 	(umod:SI (match_operand:SI 1 "register_operand" "d")
+ 		 (match_operand:SI 2 "nonmemory_operand" "di")))]
+   "!optimize"
    "remu\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"SI")
!    (set_attr "length"	"7")])	;; various tests for dividing by 0 and such
  
! (define_expand "umoddi3"
    [(set (match_operand:DI 0 "register_operand" "=d")
  	(umod:DI (match_operand:DI 1 "se_register_operand" "d")
  		 (match_operand:DI 2 "se_nonmemory_operand" "di")))
***************
*** 2345,2354 ****
     (clobber (match_scratch:DI 4 "=h"))
     (clobber (match_scratch:DI 6 "=a"))]
    "TARGET_64BIT && !optimize"
    "dremu\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"DI")
!    (set_attr "length"	"7")])		;; various tests for dividing by 0 and such
  
  
  ;;
--- 2429,2450 ----
     (clobber (match_scratch:DI 4 "=h"))
     (clobber (match_scratch:DI 6 "=a"))]
    "TARGET_64BIT && !optimize"
+   "
+ {
+   /* MIPS16 needs div/rem ops in registers. */
+   if (TARGET_MIPS16)
+     operands[2] = force_reg (DImode, operands[2]);
+ }")
+ 
+ (define_insn "umoddi3_internal"
+   [(set (match_operand:DI 0 "register_operand" "=d")
+ 	(umod:DI (match_operand:DI 1 "se_register_operand" "d")
+ 		 (match_operand:DI 2 "se_nonmemory_operand" "di")))]
+   "TARGET_64BIT && !optimize"
    "dremu\\t%0,%1,%2"
    [(set_attr "type"	"idiv")
     (set_attr "mode"	"DI")
!    (set_attr "length"	"7")])	;; various tests for dividing by 0 and such
  
  
  ;;




More information about the Gcc mailing list