-(define_insn "sse_cvtss2siq"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (unspec:DI
- [(vec_select:SF
- (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
- (parallel [(const_int 0)]))]
- UNSPEC_FIX_NOTRUNC))]
- "TARGET_SSE && TARGET_64BIT"
- "cvtss2siq\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "double,vector")
- (set_attr "prefix_rep" "1")
- (set_attr "mode" "DI")])
-
-(define_insn "sse_cvtss2siq_2"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (unspec:DI [(match_operand:SF 1 "nonimmediate_operand" "x,m")]
- UNSPEC_FIX_NOTRUNC))]
- "TARGET_SSE && TARGET_64BIT"
- "cvtss2siq\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "double,vector")
- (set_attr "amdfam10_decode" "double,double")
- (set_attr "prefix_rep" "1")
- (set_attr "mode" "DI")])
-
-(define_insn "sse_cvttss2si"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (fix:SI
- (vec_select:SF
- (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE"
- "cvttss2si\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "double,vector")
- (set_attr "amdfam10_decode" "double,double")
- (set_attr "prefix_rep" "1")
- (set_attr "mode" "SI")])
-
-(define_insn "sse_cvttss2siq"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (fix:DI
- (vec_select:SF
- (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
- (parallel [(const_int 0)]))))]
- "TARGET_SSE && TARGET_64BIT"
- "cvttss2siq\t{%1, %0|%0, %1}"
- [(set_attr "type" "sseicvt")
- (set_attr "athlon_decode" "double,vector")
- (set_attr "amdfam10_decode" "double,double")
- (set_attr "prefix_rep" "1")
- (set_attr "mode" "DI")])
-
-(define_insn "sse2_cvtdq2ps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (float:V4SF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "cvtdq2ps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse2_cvtps2dq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
- UNSPEC_FIX_NOTRUNC))]
- "TARGET_SSE2"
- "cvtps2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "prefix_data16" "1")
- (set_attr "mode" "TI")])
-
-(define_insn "sse2_cvttps2dq"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
- "TARGET_SSE2"
- "cvttps2dq\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "prefix_rep" "1")
- (set_attr "mode" "TI")])
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Parallel single-precision floating point element swizzling
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(define_insn "sse_movhlps"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
- (vec_select:V4SF
- (vec_concat:V8SF
- (match_operand:V4SF 1 "nonimmediate_operand" " 0,0,0")
- (match_operand:V4SF 2 "nonimmediate_operand" " x,o,x"))
- (parallel [(const_int 6)
- (const_int 7)
- (const_int 2)
- (const_int 3)])))]
- "TARGET_SSE && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
- "@
- movhlps\t{%2, %0|%0, %2}
- movlps\t{%H2, %0|%0, %H2}
- movhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V4SF,V2SF,V2SF")])
-
-(define_insn "sse_movlhps"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,o")
- (vec_select:V4SF
- (vec_concat:V8SF
- (match_operand:V4SF 1 "nonimmediate_operand" " 0,0,0")
- (match_operand:V4SF 2 "nonimmediate_operand" " x,m,x"))
- (parallel [(const_int 0)
- (const_int 1)
- (const_int 4)
- (const_int 5)])))]
- "TARGET_SSE && ix86_binary_operator_ok (UNKNOWN, V4SFmode, operands)"
- "@
- movlhps\t{%2, %0|%0, %2}
- movhps\t{%2, %0|%0, %2}
- movlps\t{%2, %H0|%H0, %2}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V4SF,V2SF,V2SF")])
-
-(define_insn "sse_unpckhps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_select:V4SF
- (vec_concat:V8SF
- (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (parallel [(const_int 2) (const_int 6)
- (const_int 3) (const_int 7)])))]
- "TARGET_SSE"
- "unpckhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse_unpcklps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_select:V4SF
- (vec_concat:V8SF
- (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (parallel [(const_int 0) (const_int 4)
- (const_int 1) (const_int 5)])))]
- "TARGET_SSE"
- "unpcklps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog")
- (set_attr "mode" "V4SF")])
-
-;; These are modeled with the same vec_concat as the others so that we
-;; capture users of shufps that can use the new instructions
-(define_insn "sse3_movshdup"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_select:V4SF
- (vec_concat:V8SF
- (match_operand:V4SF 1 "nonimmediate_operand" "xm")
- (match_dup 1))
- (parallel [(const_int 1)
- (const_int 1)
- (const_int 7)
- (const_int 7)])))]
- "TARGET_SSE3"
- "movshdup\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "prefix_rep" "1")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse3_movsldup"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_select:V4SF
- (vec_concat:V8SF
- (match_operand:V4SF 1 "nonimmediate_operand" "xm")
- (match_dup 1))
- (parallel [(const_int 0)
- (const_int 0)
- (const_int 6)
- (const_int 6)])))]
- "TARGET_SSE3"
- "movsldup\t{%1, %0|%0, %1}"
- [(set_attr "type" "sse")
- (set_attr "prefix_rep" "1")
- (set_attr "mode" "V4SF")])
-
-(define_expand "sse_shufps"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V4SF 1 "register_operand" "")
- (match_operand:V4SF 2 "nonimmediate_operand" "")
- (match_operand:SI 3 "const_int_operand" "")]
- "TARGET_SSE"
-{
- int mask = INTVAL (operands[3]);
- emit_insn (gen_sse_shufps_1 (operands[0], operands[1], operands[2],
- GEN_INT ((mask >> 0) & 3),
- GEN_INT ((mask >> 2) & 3),
- GEN_INT (((mask >> 4) & 3) + 4),
- GEN_INT (((mask >> 6) & 3) + 4)));
- DONE;
-})
-
-(define_insn "sse_shufps_1"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_select:V4SF
- (vec_concat:V8SF
- (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
- (parallel [(match_operand 3 "const_0_to_3_operand" "")
- (match_operand 4 "const_0_to_3_operand" "")
- (match_operand 5 "const_4_to_7_operand" "")
- (match_operand 6 "const_4_to_7_operand" "")])))]
- "TARGET_SSE"
-{
- int mask = 0;
- mask |= INTVAL (operands[3]) << 0;
- mask |= INTVAL (operands[4]) << 2;
- mask |= (INTVAL (operands[5]) - 4) << 4;
- mask |= (INTVAL (operands[6]) - 4) << 6;
- operands[3] = GEN_INT (mask);
-
- return "shufps\t{%3, %2, %0|%0, %2, %3}";
-}
- [(set_attr "type" "sselog")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse_storehps"
- [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,x,x")
- (vec_select:V2SF
- (match_operand:V4SF 1 "nonimmediate_operand" "x,x,o")
- (parallel [(const_int 2) (const_int 3)])))]
- "TARGET_SSE"
- "@
- movhps\t{%1, %0|%0, %1}
- movhlps\t{%1, %0|%0, %1}
- movlps\t{%H1, %0|%0, %H1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V2SF,V4SF,V2SF")])
-
-(define_insn "sse_loadhps"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,o")
- (vec_concat:V4SF
- (vec_select:V2SF
- (match_operand:V4SF 1 "nonimmediate_operand" "0,0,0")
- (parallel [(const_int 0) (const_int 1)]))
- (match_operand:V2SF 2 "nonimmediate_operand" "m,x,x")))]
- "TARGET_SSE"
- "@
- movhps\t{%2, %0|%0, %2}
- movlhps\t{%2, %0|%0, %2}
- movlps\t{%2, %H0|%H0, %2}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V2SF,V4SF,V2SF")])
-
-(define_insn "sse_storelps"
- [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,x,x")
- (vec_select:V2SF
- (match_operand:V4SF 1 "nonimmediate_operand" "x,x,m")
- (parallel [(const_int 0) (const_int 1)])))]
- "TARGET_SSE"
- "@
- movlps\t{%1, %0|%0, %1}
- movaps\t{%1, %0|%0, %1}
- movlps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V2SF,V4SF,V2SF")])
-
-(define_insn "sse_loadlps"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
- (vec_concat:V4SF
- (match_operand:V2SF 2 "nonimmediate_operand" "0,m,x")
- (vec_select:V2SF
- (match_operand:V4SF 1 "nonimmediate_operand" "x,0,0")
- (parallel [(const_int 2) (const_int 3)]))))]
- "TARGET_SSE"
- "@
- shufps\t{$0xe4, %1, %0|%0, %1, 0xe4}
- movlps\t{%2, %0|%0, %2}
- movlps\t{%2, %0|%0, %2}"
- [(set_attr "type" "sselog,ssemov,ssemov")
- (set_attr "mode" "V4SF,V2SF,V2SF")])
-
-(define_insn "sse_movss"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (match_operand:V4SF 2 "register_operand" "x")
- (match_operand:V4SF 1 "register_operand" "0")
- (const_int 1)))]
- "TARGET_SSE"
- "movss\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "SF")])
-
-(define_insn "*vec_dupv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_duplicate:V4SF
- (match_operand:SF 1 "register_operand" "0")))]
- "TARGET_SSE"
- "shufps\t{$0, %0, %0|%0, %0, 0}"
- [(set_attr "type" "sselog1")
- (set_attr "mode" "V4SF")])
-
-;; ??? In theory we can match memory for the MMX alternative, but allowing
-;; nonimmediate_operand for operand 2 and *not* allowing memory for the SSE
-;; alternatives pretty much forces the MMX alternative to be chosen.
-(define_insn "*sse_concatv2sf"
- [(set (match_operand:V2SF 0 "register_operand" "=x,x,*y,*y")
- (vec_concat:V2SF
- (match_operand:SF 1 "nonimmediate_operand" " 0,m, 0, m")
- (match_operand:SF 2 "reg_or_0_operand" " x,C,*y, C")))]
- "TARGET_SSE"
- "@
- unpcklps\t{%2, %0|%0, %2}
- movss\t{%1, %0|%0, %1}
- punpckldq\t{%2, %0|%0, %2}
- movd\t{%1, %0|%0, %1}"
- [(set_attr "type" "sselog,ssemov,mmxcvt,mmxmov")
- (set_attr "mode" "V4SF,SF,DI,DI")])
-
-(define_insn "*sse_concatv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=x,x")
- (vec_concat:V4SF
- (match_operand:V2SF 1 "register_operand" " 0,0")
- (match_operand:V2SF 2 "nonimmediate_operand" " x,m")))]
- "TARGET_SSE"
- "@
- movlhps\t{%2, %0|%0, %2}
- movhps\t{%2, %0|%0, %2}"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "V4SF,V2SF")])
-
-(define_expand "vec_initv4sf"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand 1 "" "")]
- "TARGET_SSE"
-{
- ix86_expand_vector_init (false, operands[0], operands[1]);
- DONE;
-})
-
-(define_insn "vec_setv4sf_0"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,Y2,m")
- (vec_merge:V4SF
- (vec_duplicate:V4SF
- (match_operand:SF 2 "general_operand" " x,m,*r,x*rfF"))
- (match_operand:V4SF 1 "vector_move_operand" " 0,C,C ,0")
- (const_int 1)))]
- "TARGET_SSE"
- "@
- movss\t{%2, %0|%0, %2}
- movss\t{%2, %0|%0, %2}
- movd\t{%2, %0|%0, %2}
- #"
- [(set_attr "type" "ssemov")
- (set_attr "mode" "SF")])
-
-;; A subset is vec_setv4sf.
-(define_insn "*vec_setv4sf_sse4_1"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_merge:V4SF
- (vec_duplicate:V4SF
- (match_operand:SF 2 "nonimmediate_operand" "xm"))
- (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:SI 3 "const_pow2_1_to_8_operand" "n")))]
- "TARGET_SSE4_1"
-{
- operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])) << 4);
- return "insertps\t{%3, %2, %0|%0, %2, %3}";
-}
- [(set_attr "type" "sselog")
- (set_attr "prefix_extra" "1")
- (set_attr "mode" "V4SF")])
-
-(define_insn "sse4_1_insertps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (unspec:V4SF [(match_operand:V4SF 2 "register_operand" "x")
- (match_operand:V4SF 1 "register_operand" "0")
- (match_operand:SI 3 "const_0_to_255_operand" "n")]
- UNSPEC_INSERTPS))]
- "TARGET_SSE4_1"
- "insertps\t{%3, %2, %0|%0, %2, %3}";
- [(set_attr "type" "sselog")
- (set_attr "prefix_extra" "1")
- (set_attr "mode" "V4SF")])
-
-(define_split
- [(set (match_operand:V4SF 0 "memory_operand" "")
- (vec_merge:V4SF
- (vec_duplicate:V4SF
- (match_operand:SF 1 "nonmemory_operand" ""))
- (match_dup 0)
- (const_int 1)))]
- "TARGET_SSE && reload_completed"
- [(const_int 0)]
-{
- emit_move_insn (adjust_address (operands[0], SFmode, 0), operands[1]);
- DONE;
-})
-
-(define_expand "vec_setv4sf"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:SF 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_SSE"
-{
- ix86_expand_vector_set (false, operands[0], operands[1],
- INTVAL (operands[2]));
- DONE;
-})
-
-(define_insn_and_split "*vec_extractv4sf_0"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=x,m,fr")
- (vec_select:SF
- (match_operand:V4SF 1 "nonimmediate_operand" "xm,x,m")
- (parallel [(const_int 0)])))]
- "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- rtx op1 = operands[1];
- if (REG_P (op1))
- op1 = gen_rtx_REG (SFmode, REGNO (op1));
- else
- op1 = gen_lowpart (SFmode, op1);
- emit_move_insn (operands[0], op1);
- DONE;
-})
-
-(define_insn "*sse4_1_extractps"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=rm")
- (vec_select:SF
- (match_operand:V4SF 1 "register_operand" "x")
- (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n")])))]
- "TARGET_SSE4_1"
- "extractps\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "sselog")
- (set_attr "prefix_extra" "1")
- (set_attr "mode" "V4SF")])
-
-(define_insn_and_split "*vec_extract_v4sf_mem"
- [(set (match_operand:SF 0 "register_operand" "=x*rf")
- (vec_select:SF
- (match_operand:V4SF 1 "memory_operand" "o")
- (parallel [(match_operand 2 "const_0_to_3_operand" "n")])))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
-{
- int i = INTVAL (operands[2]);
-
- emit_move_insn (operands[0], adjust_address (operands[1], SFmode, i*4));
- DONE;
-})
-
-(define_expand "vec_extractv4sf"
- [(match_operand:SF 0 "register_operand" "")
- (match_operand:V4SF 1 "register_operand" "")
- (match_operand 2 "const_int_operand" "")]
- "TARGET_SSE"
-{
- ix86_expand_vector_extract (false, operands[0], operands[1],
- INTVAL (operands[2]));
- DONE;
-})
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; SSE5 floating point multiply/accumulate instructions This includes the
-;; scalar version of the instructions as well as the vector
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;; In order to match (*a * *b) + *c, particularly when vectorizing, allow
-;; combine to generate a multiply/add with two memory references. We then
-;; split this insn, into loading up the destination register with one of the
-;; memory operations. If we don't manage to split the insn, reload will
-;; generate the appropriate moves. The reason this is needed, is that combine
-;; has already folded one of the memory references into both the multiply and
-;; add insns, and it can't generate a new pseudo. I.e.:
-;; (set (reg1) (mem (addr1)))
-;; (set (reg2) (mult (reg1) (mem (addr2))))
-;; (set (reg3) (plus (reg2) (mem (addr3))))
-
-(define_insn "sse5_fmadd<mode>4"
- [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
- (plus:SSEMODEF4
- (mult:SSEMODEF4
- (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
- (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))
- (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")))]
- "TARGET_SSE5 && TARGET_FUSED_MADD
- && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
- "fmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "type" "ssemuladd")
- (set_attr "mode" "<MODE>")])
-
-;; Split fmadd with two memory operands into a load and the fmadd.
-(define_split
- [(set (match_operand:SSEMODEF4 0 "register_operand" "")
- (plus:SSEMODEF4
- (mult:SSEMODEF4
- (match_operand:SSEMODEF4 1 "nonimmediate_operand" "")
- (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))
- (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")))]
- "TARGET_SSE5
- && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
- && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
- && !reg_mentioned_p (operands[0], operands[1])
- && !reg_mentioned_p (operands[0], operands[2])
- && !reg_mentioned_p (operands[0], operands[3])"
- [(const_int 0)]
-{
- ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
- emit_insn (gen_sse5_fmadd<mode>4 (operands[0], operands[1],
- operands[2], operands[3]));
- DONE;
-})
-
-;; For the scalar operations, use operand1 for the upper words that aren't
-;; modified, so restrict the forms that are generated.
-;; Scalar version of fmadd
-(define_insn "sse5_vmfmadd<mode>4"
- [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
- (vec_merge:SSEMODEF2P
- (plus:SSEMODEF2P
- (mult:SSEMODEF2P
- (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
- (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
- (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE5 && TARGET_FUSED_MADD
- && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
- "fmadd<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "type" "ssemuladd")
- (set_attr "mode" "<MODE>")])
-
-;; Floating multiply and subtract
-;; Allow two memory operands the same as fmadd
-(define_insn "sse5_fmsub<mode>4"
- [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
- (minus:SSEMODEF4
- (mult:SSEMODEF4
- (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
- (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))
- (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")))]
- "TARGET_SSE5 && TARGET_FUSED_MADD
- && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
- "fmsub<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "type" "ssemuladd")
- (set_attr "mode" "<MODE>")])
-
-;; Split fmsub with two memory operands into a load and the fmsub.
-(define_split
- [(set (match_operand:SSEMODEF4 0 "register_operand" "")
- (minus:SSEMODEF4
- (mult:SSEMODEF4
- (match_operand:SSEMODEF4 1 "nonimmediate_operand" "")
- (match_operand:SSEMODEF4 2 "nonimmediate_operand" ""))
- (match_operand:SSEMODEF4 3 "nonimmediate_operand" "")))]
- "TARGET_SSE5
- && !ix86_sse5_valid_op_p (operands, insn, 4, true, 1)
- && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)
- && !reg_mentioned_p (operands[0], operands[1])
- && !reg_mentioned_p (operands[0], operands[2])
- && !reg_mentioned_p (operands[0], operands[3])"
- [(const_int 0)]
-{
- ix86_expand_sse5_multiple_memory (operands, 4, <MODE>mode);
- emit_insn (gen_sse5_fmsub<mode>4 (operands[0], operands[1],
- operands[2], operands[3]));
- DONE;
-})
-
-;; For the scalar operations, use operand1 for the upper words that aren't
-;; modified, so restrict the forms that are generated.
-;; Scalar version of fmsub
-(define_insn "sse5_vmfmsub<mode>4"
- [(set (match_operand:SSEMODEF2P 0 "register_operand" "=x,x")
- (vec_merge:SSEMODEF2P
- (minus:SSEMODEF2P
- (mult:SSEMODEF2P
- (match_operand:SSEMODEF2P 1 "nonimmediate_operand" "0,0")
- (match_operand:SSEMODEF2P 2 "nonimmediate_operand" "x,xm"))
- (match_operand:SSEMODEF2P 3 "nonimmediate_operand" "xm,x"))
- (match_dup 1)
- (const_int 1)))]
- "TARGET_SSE5 && TARGET_FUSED_MADD
- && ix86_sse5_valid_op_p (operands, insn, 4, true, 1)"
- "fmsub<ssemodesuffixf2s>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "type" "ssemuladd")
- (set_attr "mode" "<MODE>")])
-
-;; Floating point negative multiply and add
-;; Rewrite (- (a * b) + c) into the canonical form: c - (a * b)
-;; Note operands are out of order to simplify call to ix86_sse5_valid_p
-;; Allow two memory operands to help in optimizing.
-(define_insn "sse5_fnmadd<mode>4"
- [(set (match_operand:SSEMODEF4 0 "register_operand" "=x,x,x,x")
- (minus:SSEMODEF4
- (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x,0,0")
- (mult:SSEMODEF4
- (match_operand:SSEMODEF4 1 "nonimmediate_operand" "%0,0,x,xm")
- (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm,xm,x"))))]
- "TARGET_SSE5 && TARGET_FUSED_MADD
- && ix86_sse5_valid_op_p (operands, insn, 4, true, 2)"
- "fnmadd<ssemodesuffixf4>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
- [(set_attr "type" "ssemuladd")
- (set_attr "mode" "<MODE>")])