From: Richard Kenner Date: Fri, 18 Mar 1994 22:52:27 +0000 (-0500) Subject: (divmodsi4, udivsi3, divsi3, udivmodsi4): Add AIX common-mode cases. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8ffd9c51e4d97ff8a7fb9a282a7cb535c51d82f1;p=platform%2Fupstream%2Fgcc.git (divmodsi4, udivsi3, divsi3, udivmodsi4): Add AIX common-mode cases. (mulh_call, mull_call, divss_call, divus_call, quoss_call, quous_call): AIX common-mode call patterns. (ashlsi3): More TARGET_POWERPC to ! TARGET_POWER changes. (addsf3, subsf3, mulsf3, divsf3, etc.): Change TARGET_POWER to ! TARGET_POWERPC. (fix_truncdfsi2): Use POWER/2 and PowerPC FP convert instruction. (fpcvtsi): New pattern. (mulsidi3): Add AIX common-mode case, add imul attribute to POWER pattern, add PowerPC pattern, flag input operands as commutative. (smulsi3_highpart): Add AIX common-mode case. (movsi matcher): Add mtjmpr attribute to ! TARGET_POWER case. (movsf): Clean up load from memory or integer register test. (movdi matcher): Add FP register support. (smulsi3_highpart): New patterns. (umulsi3_highpart_power): New pattern. From-SVN: r6816 --- diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index aa55d33..316c7be 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -715,7 +715,26 @@ ;; 0 and remainder to operand 3. ;; ??? At some point, see what, if anything, we can do about if (x % y == 0). -(define_insn "divmodsi4" +(define_expand "divmodsi4" + [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") + (div:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "gpc_reg_operand" ""))) + (set (match_operand:SI 3 "gpc_reg_operand" "") + (mod:SI (match_dup 1) (match_dup 2)))])] + "TARGET_POWER || (! TARGET_POWER && ! TARGET_POWERPC)" + " +{ + if (! TARGET_POWER && ! TARGET_POWERPC) + { + emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]); + emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]); + emit_insn (gen_divss_call ()); + emit_move_insn (operands[0], gen_rtx (REG, SImode, 3)); + emit_move_insn (operands[3], gen_rtx (REG, SImode, 4)); + DONE; + } +}") +(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (div:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "gpc_reg_operand" "r"))) @@ -733,7 +752,23 @@ "divw %0, %1, %2" [(set_attr "type" "idiv")]) -(define_insn "udivsi3" +(define_expand "udivsi3" + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (udiv:SI (match_operand:SI 1 "gpc_reg_operand" "") + (match_operand:SI 2 "gpc_reg_operand" "")))] + "TARGET_POWERPC || (! TARGET_POWER && ! TARGET_POWERPC)" + " +{ + if (! TARGET_POWER && ! TARGET_POWERPC) + { + emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]); + emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]); + emit_insn (gen_quous_call ()); + emit_move_insn (operands[0], gen_rtx (REG, SImode, 3)); + DONE; + } +}") +(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (udiv:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "gpc_reg_operand" "r")))] @@ -743,7 +778,8 @@ ;; For powers of two we can do srai/aze for divide and then adjust for ;; modulus. If it isn't a power of two, FAIL on POWER so divmodsi4 will be -;; used; for PowerPC, force operands into register and do a normal divide. +;; used; for PowerPC, force operands into register and do a normal divide; +;; for AIX common-mode, use quoss call on register operands. (define_expand "divsi3" [(set (match_operand:SI 0 "gpc_reg_operand" "") (div:SI (match_operand:SI 1 "gpc_reg_operand" "") @@ -754,10 +790,18 @@ if (GET_CODE (operands[2]) == CONST_INT && exact_log2 (INTVAL (operands[2])) >= 0) ; - else if (! TARGET_POWERPC) + else if (TARGET_POWER && ! TARGET_POWERPC) FAIL; else operands[2] = force_reg (SImode, operands[2]); + if (! TARGET_POWER && ! TARGET_POWERPC) + { + emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]); + emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]); + emit_insn (gen_quoss_call ()); + emit_move_insn (operands[0], gen_rtx (REG, SImode, 3)); + DONE; + } }") (define_expand "modsi3" @@ -781,7 +825,6 @@ emit_insn (gen_ashlsi3 (temp2, temp1, GEN_INT (i))); emit_insn (gen_subsi3 (operands[0], operands[1], temp2)); DONE; - }") (define_insn "" @@ -877,11 +920,23 @@ (match_operand:SI 2 "reg_or_cint_operand" ""))) (set (match_operand:SI 3 "gpc_reg_operand" "") (umod:SI (match_dup 1) (match_dup 2)))])] - "TARGET_POWER" + "" " { rtx label = 0; + if (! TARGET_POWER) + if (! TARGET_POWERPC) + { + emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]); + emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]); + emit_insn (gen_divus_call ()); + emit_move_insn (operands[0], gen_rtx (REG, SImode, 3)); + emit_move_insn (operands[3], gen_rtx (REG, SImode, 4)); + DONE; + } + else + FAIL; if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 0) { operands[2] = force_reg (SImode, operands[2]); @@ -899,7 +954,60 @@ DONE; }") - +;; AIX architecture-independent common-mode multiply (DImode), +;; divide/modulus, and quotient subroutine calls. Input operands in R3 and +;; R4; results in R3 and somtimes R4; link register always clobbered by bla +;; instruction; R0 sometimes clobbered; also, MQ sometimes clobbered but +;; assumed unused if generating common-mode, so ignore. +(define_insn "mulh_call" + [(set (reg:SI 3) + (truncate:SI + (lshiftrt:DI (mult:DI (sign_extend:DI (reg:SI 3)) + (sign_extend:DI (reg:SI 4))) + (const_int 32)))) + (clobber (match_scratch:SI 0 "=l"))] + "! TARGET_POWER && ! TARGET_POWERPC" + "bla __mulh") +(define_insn "mull_call" + [(set (reg:DI 3) + (mult:DI (sign_extend:DI (reg:SI 3)) + (sign_extend:DI (reg:SI 4)))) + (clobber (match_scratch:SI 0 "=l")) + (clobber (reg:SI 0))] + "! TARGET_POWER && ! TARGET_POWERPC" + "bla __mull") +(define_insn "divss_call" + [(set (reg:SI 3) + (div:SI (reg:SI 3) (reg:SI 4))) + (set (reg:SI 4) + (mod:SI (reg:SI 3) (reg:SI 4))) + (clobber (match_scratch:SI 0 "=l")) + (clobber (reg:SI 0))] + "! TARGET_POWER && ! TARGET_POWERPC" + "bla __divss") +(define_insn "divus_call" + [(set (reg:SI 3) + (udiv:SI (reg:SI 3) (reg:SI 4))) + (set (reg:SI 4) + (umod:SI (reg:SI 3) (reg:SI 4))) + (clobber (match_scratch:SI 0 "=l")) + (clobber (reg:SI 0))] + "! TARGET_POWER && ! TARGET_POWERPC" + "bla __divus") +(define_insn "quoss_call" + [(set (reg:SI 3) + (div:SI (reg:SI 3) (reg:SI 4))) + (clobber (match_scratch:SI 0 "=l"))] + "! TARGET_POWER && ! TARGET_POWERPC" + "bla __quoss") +(define_insn "quous_call" + [(set (reg:SI 3) + (udiv:SI (reg:SI 3) (reg:SI 4))) + (clobber (match_scratch:SI 0 "=l")) + (clobber (reg:SI 0))] + "! TARGET_POWER && ! TARGET_POWERPC" + "bla __quous") + (define_insn "andsi3" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r") (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r") @@ -1603,7 +1711,7 @@ (match_operand:SI 2 "reg_or_cint_operand" "ri")) (const_int 0))) (clobber (match_scratch:SI 3 "=r"))] - "TARGET_POWERPC" + "! TARGET_POWER" "slw%I2. %3,%1,%2" [(set_attr "type" "delayed_compare")]) @@ -1628,7 +1736,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r") (ashift:SI (match_dup 1) (match_dup 2)))] - "TARGET_POWERPC" + "! TARGET_POWER" "slw%I2. %0,%1,%2" [(set_attr "type" "delayed_compare")]) @@ -2114,7 +2222,7 @@ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (plus:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_POWER" + "! TARGET_POWERPC" "{fa|fadd} %0,%1,%2" [(set_attr "type" "fp")]) @@ -2137,7 +2245,7 @@ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (match_operand:SF 1 "gpc_reg_operand" "f") (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_POWER" + "! TARGET_POWERPC" "{fs|fsub} %0,%1,%2" [(set_attr "type" "fp")]) @@ -2160,7 +2268,7 @@ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_POWER" + "! TARGET_POWERPC" "{fm|fmul} %0,%1,%2" [(set_attr "type" "fp")]) @@ -2183,7 +2291,7 @@ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (div:SF (match_operand:SF 1 "gpc_reg_operand" "f") (match_operand:SF 2 "gpc_reg_operand" "f")))] - "TARGET_POWER" + "! TARGET_POWERPC" "{fd|fdiv} %0,%1,%2" [(set_attr "type" "sdiv")]) @@ -2201,7 +2309,7 @@ (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) (match_operand:SF 3 "gpc_reg_operand" "f")))] - "TARGET_POWER" + "! TARGET_POWERPC" "{fma|fmadd} %0,%1,%2,%3" [(set_attr "type" "fp")]) @@ -2219,7 +2327,7 @@ (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) (match_operand:SF 3 "gpc_reg_operand" "f")))] - "TARGET_POWER" + "! TARGET_POWERPC" "{fms|fmsub} %0,%1,%2,%3" [(set_attr "type" "fp")]) @@ -2237,7 +2345,7 @@ (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) (match_operand:SF 3 "gpc_reg_operand" "f"))))] - "TARGET_POWER" + "! TARGET_POWERPC" "{fnma|fnmadd} %0,%1,%2,%3" [(set_attr "type" "fp")]) @@ -2255,7 +2363,7 @@ (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) (match_operand:SF 3 "gpc_reg_operand" "f"))))] - "TARGET_POWER" + "! TARGET_POWERPC" "{fnms|fnmsub} %0,%1,%2,%3" [(set_attr "type" "fp")]) @@ -2638,15 +2746,36 @@ "" " { - emit_insn (gen_trunc_call (operands[0], operands[1], - gen_rtx (SYMBOL_REF, Pmode, RS6000_ITRUNC))); - DONE; + if (TARGET_POWER2 || TARGET_POWERPC) + { + rtx stack_slot, temp = gen_reg_rtx (DImode); + emit_insn (gen_fpcvtsi (temp, operands[1])); + stack_slot = gen_rtx (MEM, DImode, + plus_constant (stack_pointer_rtx, 8)); + emit_move_insn (stack_slot, temp); + emit_move_insn (operands[0], + operand_subword (stack_slot, 1, 0, DImode)); + DONE; + } + else + { + emit_insn (gen_trunc_call (operands[0], operands[1], + gen_rtx (SYMBOL_REF, Pmode, RS6000_ITRUNC))); + DONE; + } }") +(define_insn "fpcvtsi" + [(set (match_operand:DI 0 "gpc_reg_operand" "=f") + (sign_extend:DI + (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))))] + "TARGET_POWER2 || TARGET_POWERPC" + "{fcirz|fctiwz} %0,%1" + [(set_attr "type" "fp")]) (define_expand "fixuns_truncdfsi2" [(set (match_operand:SI 0 "gpc_reg_operand" "") (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))] - "" + "! TARGET_POWER2 && ! TARGET_POWERPC" " { emit_insn (gen_trunc_call (operands[0], operands[1], @@ -2763,14 +2892,106 @@ "{sfi|subfic} %L0,%L1,0\;{sfze|subfze} %0,%1" [(set_attr "length" "8")]) -(define_insn "mulsidi3" +(define_expand "mulsidi3" + [(set (match_operand:DI 0 "gpc_reg_operand" "") + (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")) + (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" ""))))] + "" + " +{ + if (! TARGET_POWER && ! TARGET_POWERPC) + { + emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]); + emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]); + emit_insn (gen_mull_call ()); + emit_move_insn (operand_subword (operands[0], 0, 0, DImode), + gen_rtx (REG, SImode, 3)); + emit_move_insn (operand_subword (operands[0], 1, 0, DImode), + gen_rtx (REG, SImode, 4)); + DONE; + } + else if (TARGET_POWER) + { + emit_insn (gen_mulsidi3_mq (operands[0], operands[1], operands[2])); + DONE; + } +}") +(define_insn "mulsidi3_mq" [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r")) + (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r")) (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r")))) (clobber (match_scratch:SI 3 "=q"))] "TARGET_POWER" "mul %0,%1,%2\;mfmq %L0" - [(set_attr "length" "8")]) + [(set_attr "type" "imul") + (set_attr "length" "8")]) +(define_insn "" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r")) + (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))] + "TARGET_POWERPC" + "mulhw %0,%1,%2\;mullw %L0,%1,%2" + [(set_attr "type" "imul") + (set_attr "length" "8")]) +(define_expand "smulsi3_highpart" + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (truncate:SI + (lshiftrt:DI (mult:DI (sign_extend:DI + (match_operand:SI 1 "gpc_reg_operand" "%r")) + (sign_extend:DI + (match_operand:SI 2 "gpc_reg_operand" "r"))) + (const_int 32))))] + "" + " +{ + if (! TARGET_POWER && ! TARGET_POWERPC) + { + emit_move_insn (gen_rtx (REG, SImode, 3), operands[1]); + emit_move_insn (gen_rtx (REG, SImode, 4), operands[2]); + emit_insn (gen_mulh_call ()); + emit_move_insn (operands[0], gen_rtx (REG, SImode, 3)); + DONE; + } + else if (TARGET_POWER) + { + emit_insn (gen_smulsi3_highpart_mq (operands[0], operands[1], operands[2])); + DONE; + } +}") +(define_insn "smulsi3_highpart_mq" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (truncate:SI + (lshiftrt:DI (mult:DI (sign_extend:DI + (match_operand:SI 1 "gpc_reg_operand" "%r")) + (sign_extend:DI + (match_operand:SI 2 "gpc_reg_operand" "r"))) + (const_int 32)))) + (clobber (match_scratch:SI 3 "=q"))] + "TARGET_POWER" + "mul %0,%1,%2" + [(set_attr "type" "imul")]) +(define_insn "" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (truncate:SI + (lshiftrt:DI (mult:DI (sign_extend:DI + (match_operand:SI 1 "gpc_reg_operand" "%r")) + (sign_extend:DI + (match_operand:SI 2 "gpc_reg_operand" "r"))) + (const_int 32))))] + "TARGET_POWERPC" + "mulhw %0,%1,%2" + [(set_attr "type" "imul")]) +(define_insn "umulsi3_highpart" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (truncate:SI + (lshiftrt:DI (mult:DI (zero_extend:DI + (match_operand:SI 1 "gpc_reg_operand" "%r")) + (zero_extend:DI + (match_operand:SI 2 "gpc_reg_operand" "r"))) + (const_int 32))))] + "TARGET_POWERPC" + "mulhwu %0,%1,%2" + [(set_attr "type" "imul")]) ;; If operands 0 and 2 are in the same register, we have a problem. But ;; operands 0 and 1 (the usual case) can be in the same register. That's @@ -2914,7 +3135,7 @@ lis %0,%u1 mf%1 %0 mt%0 %1" - [(set_attr "type" "*,load,*,*,*,*,*")]) + [(set_attr "type" "*,load,*,*,*,*,mtjmpr")]) ;; Split a load of a large constant into the appropriate two-insn ;; sequence. @@ -3125,9 +3346,10 @@ #if HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT && ! defined(REAL_IS_NOT_DOUBLE) || GET_CODE (operands[1]) == CONST_DOUBLE #endif - || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 32) - || (reload_in_progress && GET_CODE (operands[1]) == REG - && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)) + || (GET_CODE (operands[1]) == REG + && (REGNO (operands[1]) < 32 + || (reload_in_progress + && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)))) { emit_move_insn (operand_subword (operands[0], 0, 0, SFmode), operand_subword (operands[1], 0, 0, SFmode)); @@ -3286,8 +3508,8 @@ }") (define_insn "" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m") - (match_operand:DI 1 "input_operand" "r,m,r"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m") + (match_operand:DI 1 "input_operand" "r,m,r,f,m,f"))] "gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode)" "* @@ -3314,10 +3536,16 @@ return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\"; case 2: return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; + case 3: + return \"fmr %0,%1\"; + case 4: + return \"lfd%U1%X1 %0,%1\"; + case 5: + return \"stfd%U0%X0 %1,%0\"; } }" - [(set_attr "type" "*,load,*") - (set_attr "length" "8")]) + [(set_attr "type" "*,load,*,fp,fpload,*") + (set_attr "length" "8,8,8,*,*,*")]) ;; TImode is similar, except that we usually want to compute the address into ;; a register and use lsi/stsi (the exception is during reload). MQ is also