Commit 8ffd9c51 by Richard Kenner

(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
parent 1052937b
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment