Hi All,<div><br></div><div>As Steve and Owen pointed out, FP_CONTRACT support is in the works. It might still be a little while though. In the mean time though it sounds like adding an "aggressive FMA formation" mode (#3 on Owen's list) would be immediately helpful to a lot of people. I'd be happy to implement that. My only question is, is everyone comfortable with aggressive FMA formation being allowed under the existing fast-math flag, or should we add a new option for this?</div>
<div><br></div><div>- Lang.</div><div><br></div><br><div class="gmail_quote">On Sat, Jun 2, 2012 at 12:15 PM, Owen Anderson <span dir="ltr"><<a href="mailto:resistor@mac.com" target="_blank">resistor@mac.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hal,<br>
<br>
I tend to view the world of FMA-optimization as falling into three categories:<br>
<br>
1) Strict mode: Never form an FMA unless it was explicitly written as fma() (or language-equivalent).  Useful to people who really care about numerics.<br>
<br>
2) "Normal" mode: Form FMA's when permitted by the language (FP_CONTRACT), or in cases where they don't (significantly?) change program semantics, similar to how we do slightly more FP constant folding even though it doesn't handle signaling NaNs correctly.  Additionally, never form a non-explicit FMA when it's not a performance win for the target.<br>

<br>
3) Relaxed mode, aka fast-math: Form FMA's aggressively, ignoring things like FP_CONTRACT and semantics preservation.  The only limiting factor is whether they're a performance win for the target.<br>
<br>
IMO, #2 should be the default.  The reason that I don't agree with conflating aggressive FMA formation with the excess-precision flag is that excess-precision is allowed by default (because of historical reasons involving 80-bit floating point on x86), but I think aggressive FMA formation should not the default.  Personally, I'd vote for having it under fast-math, but I'm married to that if people have other ideas.<br>

<span class="HOEnZb"><font color="#888888"><br>
--Owen<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Jun 2, 2012, at 12:04 PM, Hal Finkel wrote:<br>
<br>
> On Sat, 02 Jun 2012 11:44:01 -0700<br>
> Owen Anderson <<a href="mailto:resistor@mac.com">resistor@mac.com</a>> wrote:<br>
><br>
>> Elena,<br>
>><br>
>> It's entirely possible to want to target a processor with FMA3<br>
>> instructions, without wanting arbitrary fmul+fadd's to be turned into<br>
>> fma's.  The decision of when to form fma's from fmul+fadd involves a<br>
>> lot of factors, including: 1) language-specific restrictions like<br>
>> FP_CONTRACT, 2) appropriate fast-math flags, and 3) whether FMA is<br>
>> actually fast on the current subtarget (there are some ARM subtargets<br>
>> where it's not faster).<br>
>><br>
>> Consider these points:<br>
>> - FMA is not semantically equivalent to fmul+fadd<br>
>> - We may be allowed to relax fmul+fadd to FMA dependent on various<br>
>> factors<br>
>> - There are some users who care very strongly that we *don't* do so<br>
>> when told not to.<br>
>> - Other users (often the same as #3) want to be able to get FMA when<br>
>> they wrote it explicitly with calls to fma().<br>
>> - Said users will be very unhappy if they get a libcall rather than<br>
>> the fmadd instruction when they use +fma3, or when they get an fmadd<br>
>> when they wrote fmul+fadd.<br>
>><br>
>> The correct way to handle all of this is to write your patterns to<br>
>> match the FMA SDNode.  That way, users who explicitly wrote calls to<br>
>> fma() will get your instruction, as desired.  As I've pointed out<br>
>> earlier in this thread, there's already work going on on various<br>
>> fronts to turn fmul+fadd into the fma SDNode *when it is appropriate<br>
>> to do so*.  Part of that is honoring FP_CONTRACT, part of that may be<br>
>> adding DAGCombine's to apply the relaxation generally in fast-math<br>
>> (or excess-precision, or whatever) mode.<br>
><br>
> Owen,<br>
><br>
> Are these DAGCombine implementations going to be per-target or is there<br>
> going to be some general infrastructure? How is doing this in the DAG<br>
> combiner better than having patterns predicated on the appropriate<br>
> fast-math flag? On my end, I have some users who care a great deal<br>
> about strict correctness, but I also have a large population of users<br>
> who care about 'fast math' performance, and I don't want the 'fast<br>
> math' part of this to be given a lower priority than the rest.<br>
><br>
> Thanks again,<br>
> Hal<br>
><br>
>><br>
>> --Owen<br>
>><br>
>> On Jun 2, 2012, at 9:30 AM, Demikhovsky, Elena wrote:<br>
>><br>
>>> I don’t understand why. There is no automatic replacing fmul+fadd<br>
>>> with fma. You should explicitly specify “+fma3” for this. While<br>
>>> FP_CONTRACT is not ready, the  FMA3 auto-detection is disabled. As<br>
>>> far as intrinsics, they may be used without specifying “+fma3”.<br>
>>> - Elena<br>
>>> From: Craig Topper [mailto:<a href="mailto:craig.topper@gmail.com">craig.topper@gmail.com</a>]<br>
>>> Sent: Friday, June 01, 2012 09:06<br>
>>> To: Owen Anderson<br>
>>> Cc: Demikhovsky, Elena; <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
>>> Subject: Re: [llvm-commits] [llvm] r157737 - in /llvm/trunk:<br>
>>> lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp<br>
>>> lib/Target/X86/X86CodeEmitter.cpp lib/Target/X86/X86InstrFMA.td<br>
>>> lib/Target/X86/X86InstrInfo.cpp lib/Target/X86/X86InstrInfo.h<br>
>>> lib/Target/X86/X86Subta I'm going to remove the fmul(fadd) patterns<br>
>>> and enable automatic feature detection. We need to wait till<br>
>>> FP_CONTRACT is implemented before we can automatically generate<br>
>>> FMAs.<br>
>>><br>
>>> On Thu, May 31, 2012 at 10:13 PM, Craig Topper<br>
>>> <<a href="mailto:craig.topper@gmail.com">craig.topper@gmail.com</a>> wrote: The tablegen part of this patch is<br>
>>> full of 80 column violations. There also a lot of dangling spaces.<br>
>>> I'll go ahead and clean these up.<br>
>>><br>
>>> On Thu, May 31, 2012 at 9:46 AM, Owen Anderson <<a href="mailto:resistor@mac.com">resistor@mac.com</a>><br>
>>> wrote: I agree with Craig.  These should match fma @llvm.fma.  The<br>
>>> trick is that @llvm.fma should not (necessarily) be generated in<br>
>>> every where the user wrote fmul+fadd.  See Lang's thread yesterday<br>
>>> for a proposal for implement this correctly, respecting<br>
>>> FP_CONTRACT. --Owen On May 31, 2012, at 7:19 AM, Craig Topper<br>
>>> <<a href="mailto:craig.topper@gmail.com">craig.topper@gmail.com</a>> wrote:<br>
>>><br>
>>><br>
>>> Wouldn't it have been better to enable the intrinsics, but not<br>
>>> allow converting fmul(fadd) to FMA? That way people can still use<br>
>>> FMA if they explicitly request it through intrinsics?<br>
>>><br>
>>> On Thu, May 31, 2012 at 2:20 AM, Elena Demikhovsky<br>
>>> <<a href="mailto:elena.demikhovsky@intel.com">elena.demikhovsky@intel.com</a>> wrote: Author: delena<br>
>>> Date: Thu May 31 04:20:20 2012<br>
>>> New Revision: 157737<br>
>>><br>
>>> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=157737&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=157737&view=rev</a><br>
>>> Log:<br>
>>> Added FMA3 Intel instructions.<br>
>>> I disabled FMA3 autodetection, since the result may differ from<br>
>>> expected for some benchmarks. I added tests for GodeGen and<br>
>>> intrinsics. I did not change llvm.fma.f32/64 - it may be done later.<br>
>>><br>
>>><br>
>>> Added:<br>
>>>   llvm/trunk/test/CodeGen/X86/fma3-intrinsics.ll   (with props)<br>
>>>   llvm/trunk/test/CodeGen/X86/fma3.ll   (with props)<br>
>>> Modified:<br>
>>>   llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp<br>
>>>   llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp<br>
>>>   llvm/trunk/lib/Target/X86/X86InstrFMA.td<br>
>>>   llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>
>>>   llvm/trunk/lib/Target/X86/X86InstrInfo.h<br>
>>>   llvm/trunk/lib/Target/X86/X86Subtarget.cpp<br>
>>><br>
>>> Modified:<br>
>>> llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp?rev=157737&r1=157736&r2=157737&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp?rev=157737&r1=157736&r2=157737&view=diff</a><br>

>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp<br>
>>> (original) +++<br>
>>> llvm/trunk/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp Thu May<br>
>>> 31 04:20:20 2012 @@ -570,7 +570,11 @@ }<br>
>>><br>
>>>  // Classify VEX_B, VEX_4V, VEX_R, VEX_X<br>
>>> +  unsigned NumOps = Desc.getNumOperands();<br>
>>>  unsigned CurOp = 0;<br>
>>> +  if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) !=<br>
>>> -1)<br>
>>> +    ++CurOp;<br>
>>> +<br>
>>>  switch (TSFlags & X86II::FormMask) {<br>
>>>  case X86II::MRMInitReg: llvm_unreachable("FIXME: Remove this!");<br>
>>>  case X86II::MRMDestMem: {<br>
>>> @@ -603,11 +607,11 @@<br>
>>>    //  FMA4:<br>
>>>    //  dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(VEX_I8IMM)<br>
>>>    //  dst(ModR/M.reg), src1(VEX_4V), src2(VEX_I8IMM),<br>
>>> src3(ModR/M),<br>
>>> -    if (X86II::isX86_64ExtendedReg(MI.getOperand(0).getReg()))<br>
>>> +    if<br>
>>> (X86II::isX86_64ExtendedReg(MI.getOperand(CurOp++).getReg())) VEX_R<br>
>>> = 0x0;<br>
>>><br>
>>>    if (HasVEX_4V)<br>
>>> -      VEX_4V = getVEXRegisterEncoding(MI, 1);<br>
>>> +      VEX_4V = getVEXRegisterEncoding(MI, CurOp);<br>
>>><br>
>>>    if (X86II::isX86_64ExtendedReg(<br>
>>>               MI.getOperand(MemOperand+X86::AddrBaseReg).getReg()))<br>
>>><br>
>>> Modified: llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp?rev=157737&r1=157736&r2=157737&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp?rev=157737&r1=157736&r2=157737&view=diff</a><br>

>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp (original) +++<br>
>>> llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp Thu May 31 04:20:20<br>
>>> 2012 @@ -933,7 +933,10 @@ }<br>
>>><br>
>>>  // Classify VEX_B, VEX_4V, VEX_R, VEX_X<br>
>>> +  unsigned NumOps = Desc->getNumOperands();<br>
>>>  unsigned CurOp = 0;<br>
>>> +  if (NumOps > 1 && Desc->getOperandConstraint(1,<br>
>>> MCOI::TIED_TO) != -1)<br>
>>> +    ++CurOp;<br>
>>>  switch (TSFlags & X86II::FormMask) {<br>
>>>    case X86II::MRMInitReg:<br>
>>>      // Duplicate register.<br>
>>><br>
>>> Modified: llvm/trunk/lib/Target/X86/X86InstrFMA.td<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrFMA.td?rev=157737&r1=157736&r2=157737&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrFMA.td?rev=157737&r1=157736&r2=157737&view=diff</a><br>

>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Target/X86/X86InstrFMA.td (original) +++<br>
>>> llvm/trunk/lib/Target/X86/X86InstrFMA.td Thu May 31 04:20:20 2012<br>
>>> @@ -15,83 +15,358 @@ // FMA3 - Intel 3 operand Fused Multiply-Add<br>
>>> instructions //===----------------------------------------------------------------------===//<br>
>>><br>
>>> +let Constraints = "$src1 = $dst" in {<br>
>>> multiclass fma3p_rm<bits<8> opc, string OpcodeStr> {<br>
>>>  def r : FMA3<opc, MRMSrcReg, (outs VR128:$dst),<br>
>>> -           (ins VR128:$src1, VR128:$src2),<br>
>>> -           !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst,<br>
>>> $src1, $src2}"),<br>
>>> +           (ins VR128:$src1, VR128:$src2, VR128:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"), []>;<br>
>>> +  let mayLoad = 1 in<br>
>>>  def m : FMA3<opc, MRMSrcMem, (outs VR128:$dst),<br>
>>> -           (ins VR128:$src1, f128mem:$src2),<br>
>>> -           !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst,<br>
>>> $src1, $src2}"),<br>
>>> +           (ins VR128:$src1, VR128:$src2, f128mem:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"), []>;<br>
>>>  def rY : FMA3<opc, MRMSrcReg, (outs VR256:$dst),<br>
>>> -           (ins VR256:$src1, VR256:$src2),<br>
>>> -           !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst,<br>
>>> $src1, $src2}"),<br>
>>> +           (ins VR256:$src1, VR256:$src2, VR256:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"), []>;<br>
>>> +  let mayLoad = 1 in<br>
>>>  def mY : FMA3<opc, MRMSrcMem, (outs VR256:$dst),<br>
>>> -           (ins VR256:$src1, f256mem:$src2),<br>
>>> -           !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst,<br>
>>> $src1, $src2}"),<br>
>>> +           (ins VR256:$src1, VR256:$src2, f256mem:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"), []>;<br>
>>> }<br>
>>><br>
>>> +// Intrinsic for 132 pattern<br>
>>> +multiclass fma3p_rm_int<bits<8> opc, string OpcodeStr,<br>
>>> +                        PatFrag MemFrag128, PatFrag MemFrag256,<br>
>>> +                        Intrinsic Int128, Intrinsic Int256> {<br>
>>> +  def r_Int : FMA3<opc, MRMSrcReg, (outs VR128:$dst),<br>
>>> +           (ins VR128:$src1, VR128:$src2, VR128:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"),<br>
>>> +           [(set VR128:$dst, (Int128 VR128:$src1, VR128:$src3,<br>
>>> VR128:$src2))]>;<br>
>>> +  //let mayLoad = 1 in<br>
>>> +  def m_Int : FMA3<opc, MRMSrcMem, (outs VR128:$dst),<br>
>>> +           (ins VR128:$src1, VR128:$src2, f128mem:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"),<br>
>>> +           [(set VR128:$dst, (Int128 VR128:$src1, (MemFrag128<br>
>>> addr:$src3), VR128:$src2))]>;<br>
>>> +  def rY_Int : FMA3<opc, MRMSrcReg, (outs VR256:$dst),<br>
>>> +           (ins VR256:$src1, VR256:$src2, VR256:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"),<br>
>>> +           [(set VR256:$dst, (Int256 VR256:$src1, VR256:$src3,<br>
>>> VR256:$src2))]>;<br>
>>> +  //let mayLoad = 1 in<br>
>>> +  def mY_Int : FMA3<opc, MRMSrcMem, (outs VR256:$dst),<br>
>>> +           (ins VR256:$src1, VR256:$src2, f256mem:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"),<br>
>>> +           [(set VR256:$dst, (Int256 VR256:$src1, (MemFrag256<br>
>>> addr:$src3), VR256:$src2))]>; +}<br>
>>> +}<br>
>>> +<br>
>>> multiclass fma3p_forms<bits<8> opc132, bits<8> opc213, bits<8><br>
>>> opc231,<br>
>>> -                       string OpcodeStr, string PackTy> {<br>
>>> -  defm r132 :<br>
>>> fma3p_rm<opc132, !strconcat(OpcodeStr, !strconcat("132", PackTy))>;<br>
>>> -  defm r213 :<br>
>>> fma3p_rm<opc213, !strconcat(OpcodeStr, !strconcat("213", PackTy))>;<br>
>>> -  defm r231 :<br>
>>> fma3p_rm<opc231, !strconcat(OpcodeStr, !strconcat("231", PackTy))>;<br>
>>> +                       string OpcodeStr, string PackTy,<br>
>>> +                       PatFrag MemFrag128, PatFrag MemFrag256,<br>
>>> +                       Intrinsic Int128, Intrinsic Int256> {<br>
>>> +  defm r132 : fma3p_rm_int<br>
>>> <opc132, !strconcat(OpcodeStr, !strconcat("132", PackTy)),<br>
>>> +                              MemFrag128, MemFrag256, Int128,<br>
>>> Int256>;<br>
>>> +  defm r132 : fma3p_rm<br>
>>> <opc132, !strconcat(OpcodeStr, !strconcat("132", PackTy))>;<br>
>>> +  defm r213 : fma3p_rm<br>
>>> <opc213, !strconcat(OpcodeStr, !strconcat("213", PackTy))>;<br>
>>> +  defm r231 : fma3p_rm<br>
>>> <opc231, !strconcat(OpcodeStr, !strconcat("231", PackTy))>; }<br>
>>><br>
>>> // Fused Multiply-Add<br>
>>> let ExeDomain = SSEPackedSingle in {<br>
>>> -  defm VFMADDPS    : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "ps">;<br>
>>> -  defm VFMSUBPS    : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub", "ps">;<br>
>>> -  defm VFMADDSUBPS : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub",<br>
>>> "ps">;<br>
>>> -  defm VFMSUBADDPS : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd",<br>
>>> "ps">;<br>
>>> +  defm VFMADDPS    : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "ps",<br>
>>> memopv4f32, memopv8f32,<br>
>>> +    int_x86_fma4_vfmadd_ps, int_x86_fma4_vfmadd_ps_256>;<br>
>>> +  defm VFMSUBPS    : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub",<br>
>>> "ps",  memopv4f32, memopv8f32,<br>
>>> +    int_x86_fma4_vfmsub_ps, int_x86_fma4_vfmsub_ps_256>;<br>
>>> +  defm VFMADDSUBPS : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub",<br>
>>> "ps", memopv4f32, memopv8f32,<br>
>>> +    int_x86_fma4_vfmaddsub_ps, int_x86_fma4_vfmaddsub_ps_256>;<br>
>>> +  defm VFMSUBADDPS : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd",<br>
>>> "ps", memopv4f32, memopv8f32,<br>
>>> +    int_x86_fma4_vfmsubadd_ps, int_x86_fma4_vfmaddsub_ps_256>;<br>
>>> }<br>
>>><br>
>>> let ExeDomain = SSEPackedDouble in {<br>
>>> -  defm VFMADDPD    : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd",<br>
>>> "pd">, VEX_W;<br>
>>> -  defm VFMSUBPD    : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub",<br>
>>> "pd">, VEX_W;<br>
>>> -  defm VFMADDSUBPD : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub",<br>
>>> "pd">, VEX_W;<br>
>>> -  defm VFMSUBADDPD : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd",<br>
>>> "pd">, VEX_W;<br>
>>> +  defm VFMADDPD    : fma3p_forms<0x98, 0xA8, 0xB8, "vfmadd", "pd",<br>
>>> memopv2f64, memopv4f64,<br>
>>> +    int_x86_fma4_vfmadd_pd, int_x86_fma4_vfmadd_pd_256>, VEX_W;<br>
>>> +  defm VFMSUBPD    : fma3p_forms<0x9A, 0xAA, 0xBA, "vfmsub", "pd",<br>
>>> memopv2f64, memopv4f64,<br>
>>> +    int_x86_fma4_vfmsub_pd, int_x86_fma4_vfmsub_pd_256>, VEX_W;<br>
>>> +  defm VFMADDSUBPD : fma3p_forms<0x96, 0xA6, 0xB6, "vfmaddsub",<br>
>>> "pd", memopv2f64, memopv4f64,<br>
>>> +    int_x86_fma4_vfmaddsub_pd, int_x86_fma4_vfmaddsub_pd_256>,<br>
>>> VEX_W;<br>
>>> +  defm VFMSUBADDPD : fma3p_forms<0x97, 0xA7, 0xB7, "vfmsubadd",<br>
>>> "pd", memopv2f64, memopv4f64,<br>
>>> +    int_x86_fma4_vfmsubadd_pd, int_x86_fma4_vfmsubadd_pd_256>,<br>
>>> VEX_W; }<br>
>>><br>
>>> // Fused Negative Multiply-Add<br>
>>> let ExeDomain = SSEPackedSingle in {<br>
>>> -  defm VFNMADDPS : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "ps">;<br>
>>> -  defm VFNMSUBPS : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "ps">;<br>
>>> +  defm VFNMADDPS : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "ps",<br>
>>> memopv4f32, memopv8f32,<br>
>>> +    int_x86_fma4_vfnmadd_ps, int_x86_fma4_vfnmadd_ps_256>;<br>
>>> +  defm VFNMSUBPS : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "ps",<br>
>>> memopv4f32, memopv8f32,<br>
>>> +    int_x86_fma4_vfnmsub_ps, int_x86_fma4_vfnmsub_ps_256>;<br>
>>> }<br>
>>> let ExeDomain = SSEPackedDouble in {<br>
>>> -  defm VFNMADDPD : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "pd">,<br>
>>> VEX_W;<br>
>>> -  defm VFNMSUBPD : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "pd">,<br>
>>> VEX_W;<br>
>>> +  defm VFNMADDPD : fma3p_forms<0x9C, 0xAC, 0xBC, "vfnmadd", "pd",<br>
>>> memopv2f64, memopv4f64,<br>
>>> +    int_x86_fma4_vfnmadd_pd, int_x86_fma4_vfnmadd_pd_256>, VEX_W;<br>
>>> +  defm VFNMSUBPD : fma3p_forms<0x9E, 0xAE, 0xBE, "vfnmsub", "pd",<br>
>>> memopv2f64, memopv4f64,<br>
>>> +    int_x86_fma4_vfnmsub_pd, int_x86_fma4_vfnmsub_pd_256>, VEX_W;<br>
>>> }<br>
>>><br>
>>> -multiclass fma3s_rm<bits<8> opc, string OpcodeStr, X86MemOperand<br>
>>> x86memop> {<br>
>>> -  def r : FMA3<opc, MRMSrcReg, (outs VR128:$dst),<br>
>>> -           (ins VR128:$src1, VR128:$src2),<br>
>>> -           !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst,<br>
>>> $src1, $src2}"), +let Predicates = [HasFMA3], AddedComplexity = 20<br>
>>> in { +//------------<br>
>>> +// FP double precision ADD - 256<br>
>>> +//------------<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 + src1<br>
>>> +def : Pat<(v4f64 (fadd (fmul VR256:$src2, (memopv4f64<br>
>>> addr:$src3)), VR256:$src1)),<br>
>>> +        (VFMADDPDr231mY VR256:$src1, VR256:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 + src1<br>
>>> +def : Pat<(v4f64 (fadd (fmul VR256:$src2, VR256:$src3),<br>
>>> VR256:$src1)),<br>
>>> +        (VFMADDPDr231rY VR256:$src1, VR256:$src2, VR256:$src3)>;<br>
>>> +<br>
>>> +<br>
>>> +//------------<br>
>>> +// FP double precision ADD - 128<br>
>>> +//------------<br>
>>> +<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 + src1<br>
>>> +def : Pat<(v2f64 (fadd (fmul VR128:$src2, (memopv2f64<br>
>>> addr:$src3)), VR128:$src1)),<br>
>>> +            (VFMADDPDr231m VR128:$src1, VR128:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 + src1<br>
>>> +def : Pat<(v2f64 (fadd (fmul VR128:$src2, VR128:$src3),<br>
>>> VR128:$src1)),<br>
>>> +            (VFMADDPDr231r VR128:$src1, VR128:$src2, VR128:$src3)>;<br>
>>> +<br>
>>> +//------------<br>
>>> +// FP double precision SUB - 256<br>
>>> +//------------<br>
>>> +// FMA231: src1 = src2*src3 - src1<br>
>>> +def : Pat<(v4f64 (fsub (fmul VR256:$src2, (memopv4f64<br>
>>> addr:$src3)), VR256:$src1)),<br>
>>> +           (VFMSUBPDr231mY VR256:$src1, VR256:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 - src1<br>
>>> +def : Pat<(v4f64 (fsub (fmul VR256:$src2, VR256:$src3),<br>
>>> VR256:$src1)),<br>
>>> +            (VFMSUBPDr231rY VR256:$src1, VR256:$src2,<br>
>>> VR256:$src3)>; +<br>
>>> +<br>
>>> +//------------<br>
>>> +// FP double precision SUB - 128<br>
>>> +//------------<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 - src1<br>
>>> +def : Pat<(v2f64 (fsub (fmul VR128:$src2, (memopv2f64<br>
>>> addr:$src3)), VR128:$src1)),<br>
>>> +            (VFMSUBPDr231m VR128:$src1, VR128:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 - src1<br>
>>> +def : Pat<(v2f64 (fsub (fmul VR128:$src2, VR128:$src3),<br>
>>> VR128:$src1)),<br>
>>> +            (VFMSUBPDr231r VR128:$src1, VR128:$src2, VR128:$src3)>;<br>
>>> +<br>
>>> +//------------<br>
>>> +// FP double precision FNMADD - 256<br>
>>> +//------------<br>
>>> +// FMA231: src1 = - src2*src3 + src1<br>
>>> +def : Pat<(v4f64 (fsub VR256:$src1, (fmul VR256:$src2, (memopv4f64<br>
>>> addr:$src3)))),<br>
>>> +            (VFNMADDPDr231mY VR256:$src1, VR256:$src2,<br>
>>> addr:$src3)>; +<br>
>>> +// FMA231: src1 = - src2*src3 + src1<br>
>>> +def : Pat<(v4f64 (fsub VR256:$src1, (fmul VR256:$src2,<br>
>>> VR256:$src3))),<br>
>>> +            (VFNMADDPDr231rY VR256:$src1, VR256:$src2,<br>
>>> VR256:$src3)>; +<br>
>>> +//------------<br>
>>> +// FP double precision FNMADD - 128<br>
>>> +//------------<br>
>>> +<br>
>>> +// FMA231: src1 = - src2*src3 + src1<br>
>>> +def : Pat<(v2f64 (fsub VR128:$src1, (fmul VR128:$src2, (memopv2f64<br>
>>> addr:$src3)))),<br>
>>> +            (VFNMADDPDr231m VR128:$src1, VR128:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231: src1 = - src2*src3 + src1<br>
>>> +def : Pat<(v2f64 (fsub VR128:$src1, (fmul VR128:$src2,<br>
>>> VR128:$src3))),<br>
>>> +            (VFNMADDPDr231r VR128:$src1, VR128:$src2,<br>
>>> VR128:$src3)>; +<br>
>>> +//------------<br>
>>> +// FP single precision ADD - 256<br>
>>> +//------------<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 + src1<br>
>>> +def : Pat<(v8f32 (fadd (fmul VR256:$src2, VR256:$src3),<br>
>>> VR256:$src1)),<br>
>>> +            (VFMADDPSr231rY VR256:$src1, VR256:$src2,<br>
>>> VR256:$src3)>; +<br>
>>> +// FMA213 : src1 = src2*src1 + src3<br>
>>> +def : Pat<(v8f32 (fadd (fmul VR256:$src1, VR256:$src2),<br>
>>> (memopv8f32 addr:$src3))),<br>
>>> +            (VFMADDPSr213mY VR256:$src1, VR256:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 + src1<br>
>>> +def : Pat<(v8f32 (fadd (fmul (memopv8f32 addr:$src3),<br>
>>> VR256:$src2), VR256:$src1)),<br>
>>> +            (VFMADDPSr231mY VR256:$src1, VR256:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA213: src1 = src2*src1 + src3<br>
>>> +def : Pat<(v8f32 (fadd (fmul VR256:$src2, VR256:$src1),<br>
>>> VR256:$src3)),<br>
>>> +            (VFMADDPSr213rY VR256:$src1, VR256:$src2,<br>
>>> VR256:$src3)>; +<br>
>>> +//------------<br>
>>> +// FP single precision ADD - 128<br>
>>> +//------------<br>
>>> +<br>
>>> +// FMA231 : src1 = src2*src3 + src1<br>
>>> +def : Pat<(v4f32 (fadd (fmul VR128:$src2, (memopv4f32<br>
>>> addr:$src3)), VR128:$src1)),<br>
>>> +            (VFMADDPSr231m VR128:$src1, VR128:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231 : src1 = src2*src3 + src1<br>
>>> +def : Pat<(v4f32 (fadd (fmul VR128:$src2, VR128:$src3),<br>
>>> VR128:$src1)),<br>
>>> +        (VFMADDPSr231r VR128:$src1, VR128:$src2, VR128:$src3)>;<br>
>>> +<br>
>>> +//------------<br>
>>> +// FP single precision SUB - 256<br>
>>> +//------------<br>
>>> +// FMA231: src1 = src2*src3 - src1<br>
>>> +def : Pat<(v8f32 (fsub (fmul VR256:$src2, (memopv8f32<br>
>>> addr:$src3)), VR256:$src1)),<br>
>>> +            (VFMSUBPSr231mY VR256:$src1, VR256:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231: src1 = src2*src3 - src1<br>
>>> +def : Pat<(v8f32 (fsub (fmul VR256:$src2, VR256:$src3),<br>
>>> VR256:$src1)),<br>
>>> +            (VFMSUBPSr231rY VR256:$src1, VR256:$src2,<br>
>>> VR256:$src3)>; +<br>
>>> +//------------<br>
>>> +// FP single precision SUB - 128<br>
>>> +//------------<br>
>>> +// FMA231 : src1 = src2*src3 - src1<br>
>>> +def : Pat<(v4f32 (fsub (fmul VR128:$src2, (memopv4f32<br>
>>> addr:$src3)), VR128:$src1)),<br>
>>> +            (VFMSUBPSr231m VR128:$src1, VR128:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231 : src1 = src2*src3 - src1<br>
>>> +def : Pat<(v4f32 (fsub (fmul VR128:$src2, VR128:$src3),<br>
>>> VR128:$src1)),<br>
>>> +            (VFMSUBPSr231r VR128:$src1, VR128:$src2, VR128:$src3)>;<br>
>>> +<br>
>>> +//------------<br>
>>> +// FP single precision FNMADD - 256<br>
>>> +//------------<br>
>>> +// FMA231: src1 = - src2*src3 + src1<br>
>>> +def : Pat<(v8f32 (fsub VR256:$src1, (fmul VR256:$src2, (memopv8f32<br>
>>> addr:$src3)))),<br>
>>> +            (VFNMADDPSr231mY VR256:$src1, VR256:$src2,<br>
>>> addr:$src3)>; +<br>
>>> +// FMA231: src1 = - src2*src3 + src1<br>
>>> +def : Pat<(v8f32 (fsub VR256:$src1, (fmul VR256:$src2,<br>
>>> VR256:$src3))),<br>
>>> +            (VFNMADDPSr231rY VR256:$src1, VR256:$src2,<br>
>>> VR256:$src3)>; +<br>
>>> +//------------<br>
>>> +// FP single precision FNMADD - 128<br>
>>> +//------------<br>
>>> +<br>
>>> +// FMA231 : src1 = src2*src3 - src1<br>
>>> +def : Pat<(v4f32 (fsub VR128:$src1, (fmul VR128:$src2, (memopv4f32<br>
>>> addr:$src3)))),<br>
>>> +            (VFNMADDPSr231m VR128:$src1, VR128:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +// FMA231 : src1 = src2*src3 - src1<br>
>>> +def : Pat<(v4f32 (fsub VR128:$src1, (fmul VR128:$src2,<br>
>>> VR128:$src3))),<br>
>>> +            (VFNMADDPSr231r VR128:$src1, VR128:$src2,<br>
>>> VR128:$src3)>; +<br>
>>> +} // HasFMA3<br>
>>> +<br>
>>> +//------------------------------<br>
>>> +// SCALAR<br>
>>> +//------------------------------<br>
>>> +<br>
>>> +let Constraints = "$src1 = $dst" in {<br>
>>> +multiclass fma3s_rm<bits<8> opc, string OpcodeStr, X86MemOperand<br>
>>> x86memop, RegisterClass RC> {<br>
>>> +  def r : FMA3<opc, MRMSrcReg, (outs RC:$dst),<br>
>>> +           (ins RC:$src1, RC:$src2, RC:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"), []>;<br>
>>> -  def m : FMA3<opc, MRMSrcMem, (outs VR128:$dst),<br>
>>> -           (ins VR128:$src1, x86memop:$src2),<br>
>>> -           !strconcat(OpcodeStr, "\t{$src2, $src1, $dst|$dst,<br>
>>> $src1, $src2}"),<br>
>>> +  def m : FMA3<opc, MRMSrcMem, (outs RC:$dst),<br>
>>> +           (ins RC:$src1, RC:$src2, x86memop:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"), []>;<br>
>>> }<br>
>>><br>
>>> +multiclass fma3s_rm_int<bits<8> opc, string<br>
>>> OpcodeStr,X86MemOperand x86memop, RegisterClass RC,<br>
>>> +           Intrinsic IntId> {<br>
>>> +  def r_Int : FMA3<opc, MRMSrcReg, (outs RC:$dst),<br>
>>> +           (ins RC:$src1, RC:$src2, RC:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"),<br>
>>> +           [(set RC:$dst, (IntId RC:$src1, RC:$src3, RC:$src2))]>;<br>
>>> +  def m_Int : FMA3<opc, MRMSrcMem, (outs RC:$dst),<br>
>>> +           (ins RC:$src1, VR128:$src2, x86memop:$src3),<br>
>>> +           !strconcat(OpcodeStr, "\t{$src3, $src2, $dst|$dst,<br>
>>> $src2, $src3}"),<br>
>>> +           [(set RC:$dst, (IntId RC:$src1, (load addr:$src3),<br>
>>> RC:$src2))]>; +}<br>
>>> +}<br>
>>> +<br>
>>> multiclass fma3s_forms<bits<8> opc132, bits<8> opc213, bits<8><br>
>>> opc231,<br>
>>> -                       string OpcodeStr> {<br>
>>> -  defm SSr132 : fma3s_rm<opc132, !strconcat(OpcodeStr, "132ss"),<br>
>>> f32mem>;<br>
>>> -  defm SSr213 : fma3s_rm<opc213, !strconcat(OpcodeStr, "213ss"),<br>
>>> f32mem>;<br>
>>> -  defm SSr231 : fma3s_rm<opc231, !strconcat(OpcodeStr, "231ss"),<br>
>>> f32mem>;<br>
>>> -  defm SDr132 : fma3s_rm<opc132, !strconcat(OpcodeStr, "132sd"),<br>
>>> f64mem>, VEX_W;<br>
>>> -  defm SDr213 : fma3s_rm<opc213, !strconcat(OpcodeStr, "213sd"),<br>
>>> f64mem>, VEX_W;<br>
>>> -  defm SDr231 : fma3s_rm<opc231, !strconcat(OpcodeStr, "231sd"),<br>
>>> f64mem>, VEX_W;<br>
>>> +                       string OpcodeStr, string PackTy,<br>
>>> X86MemOperand MemOp,<br>
>>> +                       RegisterClass RC, Intrinsic IntId> {<br>
>>> +  defm r132    : fma3s_rm<br>
>>> <opc132, !strconcat(OpcodeStr, !strconcat("132", PackTy)), MemOp,<br>
>>> RC>;<br>
>>> +  defm r213    : fma3s_rm<br>
>>> <opc213, !strconcat(OpcodeStr, !strconcat("213", PackTy)), MemOp,<br>
>>> RC>;<br>
>>> +  defm r231    : fma3s_rm<br>
>>> <opc231, !strconcat(OpcodeStr, !strconcat("231", PackTy)), MemOp,<br>
>>> RC>;<br>
>>> +  defm r132_Int: fma3s_rm_int<br>
>>> <opc132, !strconcat(OpcodeStr, !strconcat("132", PackTy)), MemOp,<br>
>>> VR128, IntId>; }<br>
>>><br>
>>> -defm VFMADD : fma3s_forms<0x99, 0xA9, 0xB9, "vfmadd">, VEX_LIG;<br>
>>> -defm VFMSUB : fma3s_forms<0x9B, 0xAB, 0xBB, "vfmsub">, VEX_LIG;<br>
>>> +defm VFMADDSS : fma3s_forms<0x99, 0xA9, 0xB9, "vfmadd", "ss",<br>
>>> f32mem, FR32, int_x86_fma4_vfmadd_ss>, VEX_LIG; +defm VFMADDSD :<br>
>>> fma3s_forms<0x99, 0xA9, 0xB9, "vfmadd", "sd", f64mem, FR64,<br>
>>> int_x86_fma4_vfmadd_sd>, VEX_W, VEX_LIG; +defm VFMSUBSS :<br>
>>> fma3s_forms<0x9B, 0xAB, 0xBB, "vfmsub", "ss", f32mem, FR32,<br>
>>> int_x86_fma4_vfmsub_ss>, VEX_LIG; +defm VFMSUBSD :<br>
>>> fma3s_forms<0x9B, 0xAB, 0xBB, "vfmsub", "sd", f64mem, FR64,<br>
>>> int_x86_fma4_vfmsub_sd>, VEX_W, VEX_LIG; + +defm VFNMADDSS :<br>
>>> fma3s_forms<0x9D, 0xAD, 0xBD, "vfnmadd", "ss", f32mem, FR32,<br>
>>> int_x86_fma4_vfnmadd_ss>, VEX_LIG; +defm VFNMADDSD :<br>
>>> fma3s_forms<0x9D, 0xAD, 0xBD, "vfnmadd", "sd", f64mem, FR64,<br>
>>> int_x86_fma4_vfnmadd_sd>, VEX_W, VEX_LIG; +defm VFNMSUBSS :<br>
>>> fma3s_forms<0x9F, 0xAF, 0xBF, "vfnmsub", "ss", f32mem, FR32,<br>
>>> int_x86_fma4_vfnmsub_ss>, VEX_LIG; +defm VFNMSUBSD :<br>
>>> fma3s_forms<0x9F, 0xAF, 0xBF, "vfnmsub", "sd", f64mem, FR64,<br>
>>> int_x86_fma4_vfnmsub_sd>, VEX_W, VEX_LIG; + + +let Predicates =<br>
>>> [HasFMA3], AddedComplexity = 20 in { + +//------------ +// FP<br>
>>> scalar ADD +//------------<br>
>>><br>
>>> -defm VFNMADD : fma3s_forms<0x9D, 0xAD, 0xBD, "vfnmadd">, VEX_LIG;<br>
>>> -defm VFNMSUB : fma3s_forms<0x9F, 0xAF, 0xBF, "vfnmsub">, VEX_LIG;<br>
>>> +<br>
>>> +// FMADD231 : src1 = src2*src3 + src1<br>
>>> +def : Pat<(f32 (fadd (fmul FR32:$src2, FR32:$src3), FR32:$src1)),<br>
>>> +            (VFMADDSSr231r FR32:$src1, FR32:$src2, FR32:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f32 (fadd (fmul FR32:$src2, (loadf32 addr:$src3)),<br>
>>> FR32:$src1)),<br>
>>> +            (VFMADDSSr231m FR32:$src1, FR32:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f64 (fadd (fmul FR64:$src2, FR64:$src3), FR64:$src1)),<br>
>>> +            (VFMADDSDr231r FR64:$src1, FR64:$src2, FR64:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f64 (fadd (fmul FR64:$src2, (loadf64 addr:$src3)),<br>
>>> FR64:$src1)),<br>
>>> +            (VFMADDSDr231m FR64:$src1, FR64:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +<br>
>>> +<br>
>>> +//------------<br>
>>> +// FP  scalar SUB src2*src3 - src1<br>
>>> +//------------<br>
>>> +<br>
>>> +def : Pat<(f32 (fsub (fmul FR32:$src2, FR32:$src3), FR32:$src1)),<br>
>>> +            (VFMSUBSSr231r FR32:$src1, FR32:$src2, FR32:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f32 (fsub (fmul FR32:$src2, (loadf32 addr:$src3)),<br>
>>> FR32:$src1)),<br>
>>> +            (VFMSUBSSr231m FR32:$src1, FR32:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f64 (fsub (fmul FR64:$src2, FR64:$src3), FR64:$src1)),<br>
>>> +            (VFMSUBSDr231r FR64:$src1, FR64:$src2, FR64:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f64 (fsub (fmul FR64:$src2, (loadf64 addr:$src3)),<br>
>>> FR64:$src1)),<br>
>>> +            (VFMSUBSDr231m FR64:$src1, FR64:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +//------------<br>
>>> +// FP  scalar NADD src1 - src2*src3<br>
>>> +//------------<br>
>>> +<br>
>>> +def : Pat<(f32 (fsub FR32:$src1, (fmul FR32:$src2, FR32:$src3))),<br>
>>> +            (VFNMADDSSr231r FR32:$src1, FR32:$src2, FR32:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f32 (fsub FR32:$src1, (fmul FR32:$src2, (loadf32<br>
>>> addr:$src3)))),<br>
>>> +            (VFNMADDSSr231m FR32:$src1, FR32:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f64 (fsub FR64:$src1, (fmul FR64:$src2, FR64:$src3))),<br>
>>> +            (VFNMADDSDr231r FR64:$src1, FR64:$src2, FR64:$src3)>;<br>
>>> +<br>
>>> +def : Pat<(f64 (fsub FR64:$src1, (fmul FR64:$src2, (loadf64<br>
>>> addr:$src3)))),<br>
>>> +            (VFNMADDSDr231m FR64:$src1, FR64:$src2, addr:$src3)>;<br>
>>> +<br>
>>> +} // HasFMA3<br>
>>><br>
>>> //===----------------------------------------------------------------------===//<br>
>>> // FMA4 - AMD 4 operand Fused Multiply-Add instructions<br>
>>> @@ -178,6 +453,8 @@<br>
>>> } // isCodeGenOnly = 1<br>
>>> }<br>
>>><br>
>>> +let Predicates = [HasFMA4] in {<br>
>>> +<br>
>>> defm VFMADDSS4    : fma4s<0x6A, "vfmaddss", ssmem, sse_load_f32,<br>
>>>                          int_x86_fma4_vfmadd_ss>;<br>
>>> defm VFMADDSD4    : fma4s<0x6B, "vfmaddsd", sdmem, sse_load_f64,<br>
>>> @@ -218,3 +495,5 @@<br>
>>>                         int_x86_fma4_vfmsubadd_ps_256, memopv4f32,<br>
>>> memopv8f32>; defm VFMSUBADDPD4 : fma4p<0x5F, "vfmsubaddpd",<br>
>>> memopv8f32>int_x86_fma4_vfmsubadd_pd,<br>
>>>                         int_x86_fma4_vfmsubadd_pd_256, memopv2f64,<br>
>>> memopv4f64>; +} // HasFMA4<br>
>>> +<br>
>>><br>
>>> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=157737&r1=157736&r2=157737&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=157737&r1=157736&r2=157737&view=diff</a><br>

>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original) +++<br>
>>> llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Thu May 31 04:20:20 2012<br>
>>> @@ -58,6 +58,7 @@ TB_INDEX_0    = 0,<br>
>>>  TB_INDEX_1    = 1,<br>
>>>  TB_INDEX_2    = 2,<br>
>>> +  TB_INDEX_3    = 3,<br>
>>>  TB_INDEX_MASK = 0xff,<br>
>>><br>
>>>  // Minimum alignment required for load/store.<br>
>>> @@ -1122,6 +1123,75 @@<br>
>>>                  // Index 2, folded load<br>
>>>                  Flags | TB_INDEX_2 | TB_FOLDED_LOAD);<br>
>>>  }<br>
>>> +<br>
>>> +  static const X86OpTblEntry OpTbl3[] = {<br>
>>> +    // FMA foldable instructions<br>
>>> +    { X86::VFMADDSSr231r,     X86::VFMADDSSr231m,      0 },<br>
>>> +    { X86::VFMADDSDr231r,     X86::VFMADDSDr231m,      0 },<br>
>>> +    { X86::VFMADDSSr132r,     X86::VFMADDSSr132m,      0 },<br>
>>> +    { X86::VFMADDSDr132r,     X86::VFMADDSDr132m,      0 },<br>
>>> +<br>
>>> +    { X86::VFMADDPSr231r,     X86::VFMADDPSr231m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMADDPDr231r,     X86::VFMADDPDr231m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMADDPSr132r,     X86::VFMADDPSr132m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMADDPDr132r,     X86::VFMADDPDr132m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMADDPSr213r,     X86::VFMADDPSr213m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMADDPDr213r,     X86::VFMADDPDr213m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMADDPSr231rY,    X86::VFMADDPSr231mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMADDPDr231rY,    X86::VFMADDPDr231mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMADDPSr132rY,    X86::VFMADDPSr132mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMADDPDr132rY,    X86::VFMADDPDr132mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMADDPSr213rY,    X86::VFMADDPSr213mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMADDPDr213rY,    X86::VFMADDPDr213mY,<br>
>>> TB_ALIGN_32 }, +<br>
>>> +    { X86::VFNMADDSSr231r,    X86::VFNMADDSSr231m,     0 },<br>
>>> +    { X86::VFNMADDSDr231r,    X86::VFNMADDSDr231m,     0 },<br>
>>> +    { X86::VFNMADDSSr132r,    X86::VFNMADDSSr132m,     0 },<br>
>>> +    { X86::VFNMADDSDr132r,    X86::VFNMADDSDr132m,     0 },<br>
>>> +<br>
>>> +    { X86::VFNMADDPSr231r,    X86::VFNMADDPSr231m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFNMADDPDr231r,    X86::VFNMADDPDr231m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFNMADDPSr132r,    X86::VFNMADDPSr132m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFNMADDPDr132r,    X86::VFNMADDPDr132m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFNMADDPSr213r,    X86::VFNMADDPSr213m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFNMADDPDr213r,    X86::VFNMADDPDr213m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFNMADDPSr231rY,   X86::VFNMADDPSr231mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFNMADDPDr231rY,   X86::VFNMADDPDr231mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFNMADDPSr132rY,   X86::VFNMADDPSr132mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFNMADDPDr132rY,   X86::VFNMADDPDr132mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFNMADDPSr213rY,   X86::VFNMADDPSr213mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFNMADDPDr213rY,   X86::VFNMADDPDr213mY,<br>
>>> TB_ALIGN_32 }, +<br>
>>> +    { X86::VFMSUBSSr231r,     X86::VFMSUBSSr231m,      0 },<br>
>>> +    { X86::VFMSUBSDr231r,     X86::VFMSUBSDr231m,      0 },<br>
>>> +    { X86::VFMSUBSSr132r,     X86::VFMSUBSSr132m,      0 },<br>
>>> +    { X86::VFMSUBSDr132r,     X86::VFMSUBSDr132m,      0 },<br>
>>> +<br>
>>> +    { X86::VFMSUBPSr231r,     X86::VFMSUBPSr231m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMSUBPDr231r,     X86::VFMSUBPDr231m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMSUBPSr132r,     X86::VFMSUBPSr132m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMSUBPDr132r,     X86::VFMSUBPDr132m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMSUBPSr213r,     X86::VFMSUBPSr213m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMSUBPDr213r,     X86::VFMSUBPDr213m,<br>
>>> TB_ALIGN_16 },<br>
>>> +    { X86::VFMSUBPSr231rY,    X86::VFMSUBPSr231mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMSUBPDr231rY,    X86::VFMSUBPDr231mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMSUBPSr132rY,    X86::VFMSUBPSr132mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMSUBPDr132rY,    X86::VFMSUBPDr132mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMSUBPSr213rY,    X86::VFMSUBPSr213mY,<br>
>>> TB_ALIGN_32 },<br>
>>> +    { X86::VFMSUBPDr213rY,    X86::VFMSUBPDr213mY,<br>
>>> TB_ALIGN_32 }, +<br>
>>> +  };<br>
>>> +<br>
>>> +  for (unsigned i = 0, e = array_lengthof(OpTbl3); i != e; ++i) {<br>
>>> +    unsigned RegOp = OpTbl3[i].RegOp;<br>
>>> +    unsigned MemOp = OpTbl3[i].MemOp;<br>
>>> +    unsigned Flags = OpTbl3[i].Flags;<br>
>>> +    AddTableEntry(RegOp2MemOpTable3, MemOp2RegOpTable,<br>
>>> +                  RegOp, MemOp,<br>
>>> +                  // Index 3, folded load<br>
>>> +                  Flags | TB_INDEX_3 | TB_FOLDED_LOAD);<br>
>>> +  }<br>
>>> +<br>
>>> }<br>
>>><br>
>>> void<br>
>>><br>
>>> Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=157737&r1=157736&r2=157737&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=157737&r1=157736&r2=157737&view=diff</a><br>

>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original) +++<br>
>>> llvm/trunk/lib/Target/X86/X86InstrInfo.h Thu May 31 04:20:20 2012<br>
>>> @@ -128,7 +128,8 @@ X86TargetMachine &TM;<br>
>>>  const X86RegisterInfo RI;<br>
>>><br>
>>> -  /// RegOp2MemOpTable2Addr, RegOp2MemOpTable0, RegOp2MemOpTable1,<br>
>>> +  /// RegOp2MemOpTable3Addr, RegOp2MemOpTable2Addr,<br>
>>> +  /// RegOp2MemOpTable0, RegOp2MemOpTable1,<br>
>>>  /// RegOp2MemOpTable2 - Load / store folding opcode maps.<br>
>>>  ///<br>
>>>  typedef DenseMap<unsigned,<br>
>>> @@ -137,6 +138,7 @@<br>
>>>  RegOp2MemOpTableType RegOp2MemOpTable0;<br>
>>>  RegOp2MemOpTableType RegOp2MemOpTable1;<br>
>>>  RegOp2MemOpTableType RegOp2MemOpTable2;<br>
>>> +  RegOp2MemOpTableType RegOp2MemOpTable3;<br>
>>><br>
>>>  /// MemOp2RegOpTable - Load / store unfolding opcode map.<br>
>>>  ///<br>
>>><br>
>>> Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=157737&r1=157736&r2=157737&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=157737&r1=157736&r2=157737&view=diff</a><br>

>>> ==============================================================================<br>
>>> --- llvm/trunk/lib/Target/X86/X86Subtarget.cpp (original) +++<br>
>>> llvm/trunk/lib/Target/X86/X86Subtarget.cpp Thu May 31 04:20:20 2012<br>
>>> @@ -205,10 +205,12 @@ HasCLMUL = true;<br>
>>>    ToggleFeature(X86::FeatureCLMUL);<br>
>>>  }<br>
>>> -  if ((ECX >> 12) & 0x1) {<br>
>>> -    HasFMA3 = true;<br>
>>> -    ToggleFeature(X86::FeatureFMA3);<br>
>>> -  }<br>
>>> +  // FMA3 autodetection is switched off until we have a special<br>
>>> flag<br>
>>> +  // in code generator<br>
>>> +  //if ((ECX >> 12) & 0x1) {<br>
>>> +  //  HasFMA3 = true;<br>
>>> +  //  ToggleFeature(X86::FeatureFMA3);<br>
>>> +  //}<br>
>>>  if (IsIntel && ((ECX >> 22) & 0x1)) {<br>
>>>    HasMOVBE = true;<br>
>>>    ToggleFeature(X86::FeatureMOVBE);<br>
>>><br>
>>> Added: llvm/trunk/test/CodeGen/X86/fma3-intrinsics.ll<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fma3-intrinsics.ll?rev=157737&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fma3-intrinsics.ll?rev=157737&view=auto</a><br>

>>> ==============================================================================<br>
>>> --- llvm/trunk/test/CodeGen/X86/fma3-intrinsics.ll (added) +++<br>
>>> llvm/trunk/test/CodeGen/X86/fma3-intrinsics.ll Thu May 31 04:20:20<br>
>>> 2012 @@ -0,0 +1,132 @@ +; RUN: llc < %s -mtriple=x86_64-pc-win32<br>
>>> -mcpu=core-avx2 -mattr=avx2,+fma3 | FileCheck %s +<br>
>>> +define <4 x float> @test_x86_fmadd_ss(<4 x float> %a0, <4 x float><br>
>>> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fmadd132ss {{.*\(%r.*}}, %xmm<br>
>>> +  %res = call <4 x float> @llvm.x86.fma4.vfmadd.ss(<4 x float><br>
>>> %a0, <4 x float> %a1, <4 x float> %a2) nounwind<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +declare <4 x float> @llvm.x86.fma4.vfmadd.ss(<4 x float>, <4 x<br>
>>> float>, <4 x float>) nounwind readnone +<br>
>>> +define <4 x float> @test_x86_fmadd_ps(<4 x float> %a0, <4 x float><br>
>>> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fmadd132ps<br>
>>> +  %res = call <4 x float> @<a href="http://llvm.x86.fma4.vfmadd.ps" target="_blank">llvm.x86.fma4.vfmadd.ps</a>(<4 x float><br>
>>> %a0, <4 x float> %a1, <4 x float> %a2) nounwind<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +declare <4 x float> @<a href="http://llvm.x86.fma4.vfmadd.ps" target="_blank">llvm.x86.fma4.vfmadd.ps</a>(<4 x float>, <4 x<br>
>>> float>, <4 x float>) nounwind readnone +<br>
>>> +define <8 x float> @test_x86_fmadd_ps_y(<8 x float> %a0, <8 x<br>
>>> float> %a1, <8 x float> %a2) {<br>
>>> +  ; CHECK: fmadd132ps {{.*\(%r.*}}, %ymm<br>
>>> +  %res = call <8 x float> @llvm.x86.fma4.vfmadd.ps.256(<8 x float><br>
>>> %a0, <8 x float> %a1, <8 x float> %a2) nounwind<br>
>>> +  ret <8 x float> %res<br>
>>> +}<br>
>>> +declare <8 x float> @llvm.x86.fma4.vfmadd.ps.256(<8 x float>, <8 x<br>
>>> float>, <8 x float>) nounwind readnone +<br>
>>> +define <4 x float> @test_x86_fnmadd_ss(<4 x float> %a0, <4 x<br>
>>> float> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fnmadd132ss {{.*\(%r.*}}, %xmm<br>
>>> +  %res = call <4 x float> @llvm.x86.fma4.vfnmadd.ss(<4 x float><br>
>>> %a0, <4 x float> %a1, <4 x float> %a2) nounwind<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +declare <4 x float> @llvm.x86.fma4.vfnmadd.ss(<4 x float>, <4 x<br>
>>> float>, <4 x float>) nounwind readnone +<br>
>>> +define <4 x float> @test_x86_fnmadd_ps(<4 x float> %a0, <4 x<br>
>>> float> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fnmadd132ps<br>
>>> +  %res = call <4 x float> @<a href="http://llvm.x86.fma4.vfnmadd.ps" target="_blank">llvm.x86.fma4.vfnmadd.ps</a>(<4 x float><br>
>>> %a0, <4 x float> %a1, <4 x float> %a2) nounwind<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +declare <4 x float> @<a href="http://llvm.x86.fma4.vfnmadd.ps" target="_blank">llvm.x86.fma4.vfnmadd.ps</a>(<4 x float>, <4 x<br>
>>> float>, <4 x float>) nounwind readnone +<br>
>>> +define <8 x float> @test_x86_fnmadd_ps_y(<8 x float> %a0, <8 x<br>
>>> float> %a1, <8 x float> %a2) {<br>
>>> +  ; CHECK: fnmadd132ps {{.*\(%r.*}}, %ymm<br>
>>> +  %res = call <8 x float> @llvm.x86.fma4.vfnmadd.ps.256(<8 x<br>
>>> float> %a0, <8 x float> %a1, <8 x float> %a2) nounwind<br>
>>> +  ret <8 x float> %res<br>
>>> +}<br>
>>> +declare <8 x float> @llvm.x86.fma4.vfnmadd.ps.256(<8 x float>, <8<br>
>>> x float>, <8 x float>) nounwind readnone +<br>
>>> +<br>
>>> +define <4 x float> @test_x86_fmsub_ss(<4 x float> %a0, <4 x float><br>
>>> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fmsub132ss<br>
>>> +  %res = call <4 x float> @llvm.x86.fma4.vfmsub.ss(<4 x float><br>
>>> %a0, <4 x float> %a1, <4 x float> %a2) nounwind<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +declare <4 x float> @llvm.x86.fma4.vfmsub.ss(<4 x float>, <4 x<br>
>>> float>, <4 x float>) nounwind readnone +<br>
>>> +define <4 x float> @test_x86_fmsub_ps(<4 x float> %a0, <4 x float><br>
>>> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fmsub132ps<br>
>>> +  %res = call <4 x float> @<a href="http://llvm.x86.fma4.vfmsub.ps" target="_blank">llvm.x86.fma4.vfmsub.ps</a>(<4 x float><br>
>>> %a0, <4 x float> %a1, <4 x float> %a2) nounwind<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +declare <4 x float> @<a href="http://llvm.x86.fma4.vfmsub.ps" target="_blank">llvm.x86.fma4.vfmsub.ps</a>(<4 x float>, <4 x<br>
>>> float>, <4 x float>) nounwind readnone +<br>
>>> +define <4 x float> @test_x86_fnmsub_ss(<4 x float> %a0, <4 x<br>
>>> float> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fnmsub132ss<br>
>>> +  %res = call <4 x float> @llvm.x86.fma4.vfnmsub.ss(<4 x float><br>
>>> %a0, <4 x float> %a1, <4 x float> %a2) nounwind<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +declare <4 x float> @llvm.x86.fma4.vfnmsub.ss(<4 x float>, <4 x<br>
>>> float>, <4 x float>) nounwind readnone +<br>
>>> +define <4 x float> @test_x86_fnmsub_ps(<4 x float> %a0, <4 x<br>
>>> float> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fnmsub132ps<br>
>>> +  %res = call <4 x float> @<a href="http://llvm.x86.fma4.vfnmsub.ps" target="_blank">llvm.x86.fma4.vfnmsub.ps</a>(<4 x float><br>
>>> %a0, <4 x float> %a1, <4 x float> %a2) nounwind<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +declare <4 x float> @<a href="http://llvm.x86.fma4.vfnmsub.ps" target="_blank">llvm.x86.fma4.vfnmsub.ps</a>(<4 x float>, <4 x<br>
>>> float>, <4 x float>) nounwind readnone +<br>
>>> +;;;;<br>
>>> +<br>
>>> +define <2 x double> @test_x86_fmadd_sd(<2 x double> %a0, <2 x<br>
>>> double> %a1, <2 x double> %a2) {<br>
>>> +  ; CHECK: fmadd132sd<br>
>>> +  %res = call <2 x double> @<a href="http://llvm.x86.fma4.vfmadd.sd" target="_blank">llvm.x86.fma4.vfmadd.sd</a>(<2 x double><br>
>>> %a0, <2 x double> %a1, <2 x double> %a2) nounwind<br>
>>> +  ret <2 x double> %res<br>
>>> +}<br>
>>> +declare <2 x double> @<a href="http://llvm.x86.fma4.vfmadd.sd" target="_blank">llvm.x86.fma4.vfmadd.sd</a>(<2 x double>, <2 x<br>
>>> double>, <2 x double>) nounwind readnone +<br>
>>> +define <2 x double> @test_x86_fmadd_pd(<2 x double> %a0, <2 x<br>
>>> double> %a1, <2 x double> %a2) {<br>
>>> +  ; CHECK: fmadd132pd<br>
>>> +  %res = call <2 x double> @llvm.x86.fma4.vfmadd.pd(<2 x double><br>
>>> %a0, <2 x double> %a1, <2 x double> %a2) nounwind<br>
>>> +  ret <2 x double> %res<br>
>>> +}<br>
>>> +declare <2 x double> @llvm.x86.fma4.vfmadd.pd(<2 x double>, <2 x<br>
>>> double>, <2 x double>) nounwind readnone +<br>
>>> +define <2 x double> @test_x86_fnmadd_sd(<2 x double> %a0, <2 x<br>
>>> double> %a1, <2 x double> %a2) {<br>
>>> +  ; CHECK: fnmadd132sd<br>
>>> +  %res = call <2 x double> @<a href="http://llvm.x86.fma4.vfnmadd.sd" target="_blank">llvm.x86.fma4.vfnmadd.sd</a>(<2 x double><br>
>>> %a0, <2 x double> %a1, <2 x double> %a2) nounwind<br>
>>> +  ret <2 x double> %res<br>
>>> +}<br>
>>> +declare <2 x double> @<a href="http://llvm.x86.fma4.vfnmadd.sd" target="_blank">llvm.x86.fma4.vfnmadd.sd</a>(<2 x double>, <2 x<br>
>>> double>, <2 x double>) nounwind readnone +<br>
>>> +define <2 x double> @test_x86_fnmadd_pd(<2 x double> %a0, <2 x<br>
>>> double> %a1, <2 x double> %a2) {<br>
>>> +  ; CHECK: fnmadd132pd<br>
>>> +  %res = call <2 x double> @llvm.x86.fma4.vfnmadd.pd(<2 x double><br>
>>> %a0, <2 x double> %a1, <2 x double> %a2) nounwind<br>
>>> +  ret <2 x double> %res<br>
>>> +}<br>
>>> +declare <2 x double> @llvm.x86.fma4.vfnmadd.pd(<2 x double>, <2 x<br>
>>> double>, <2 x double>) nounwind readnone +<br>
>>> +<br>
>>> +<br>
>>> +define <2 x double> @test_x86_fmsub_sd(<2 x double> %a0, <2 x<br>
>>> double> %a1, <2 x double> %a2) {<br>
>>> +  ; CHECK: fmsub132sd<br>
>>> +  %res = call <2 x double> @<a href="http://llvm.x86.fma4.vfmsub.sd" target="_blank">llvm.x86.fma4.vfmsub.sd</a>(<2 x double><br>
>>> %a0, <2 x double> %a1, <2 x double> %a2) nounwind<br>
>>> +  ret <2 x double> %res<br>
>>> +}<br>
>>> +declare <2 x double> @<a href="http://llvm.x86.fma4.vfmsub.sd" target="_blank">llvm.x86.fma4.vfmsub.sd</a>(<2 x double>, <2 x<br>
>>> double>, <2 x double>) nounwind readnone +<br>
>>> +define <2 x double> @test_x86_fmsub_pd(<2 x double> %a0, <2 x<br>
>>> double> %a1, <2 x double> %a2) {<br>
>>> +  ; CHECK: fmsub132pd<br>
>>> +  %res = call <2 x double> @llvm.x86.fma4.vfmsub.pd(<2 x double><br>
>>> %a0, <2 x double> %a1, <2 x double> %a2) nounwind<br>
>>> +  ret <2 x double> %res<br>
>>> +}<br>
>>> +declare <2 x double> @llvm.x86.fma4.vfmsub.pd(<2 x double>, <2 x<br>
>>> double>, <2 x double>) nounwind readnone +<br>
>>> +define <2 x double> @test_x86_fnmsub_sd(<2 x double> %a0, <2 x<br>
>>> double> %a1, <2 x double> %a2) {<br>
>>> +  ; CHECK: fnmsub132sd<br>
>>> +  %res = call <2 x double> @<a href="http://llvm.x86.fma4.vfnmsub.sd" target="_blank">llvm.x86.fma4.vfnmsub.sd</a>(<2 x double><br>
>>> %a0, <2 x double> %a1, <2 x double> %a2) nounwind<br>
>>> +  ret <2 x double> %res<br>
>>> +}<br>
>>> +declare <2 x double> @<a href="http://llvm.x86.fma4.vfnmsub.sd" target="_blank">llvm.x86.fma4.vfnmsub.sd</a>(<2 x double>, <2 x<br>
>>> double>, <2 x double>) nounwind readnone +<br>
>>> +define <2 x double> @test_x86_fnmsub_pd(<2 x double> %a0, <2 x<br>
>>> double> %a1, <2 x double> %a2) {<br>
>>> +  ; CHECK: fnmsub132pd<br>
>>> +  %res = call <2 x double> @llvm.x86.fma4.vfnmsub.pd(<2 x double><br>
>>> %a0, <2 x double> %a1, <2 x double> %a2) nounwind<br>
>>> +  ret <2 x double> %res<br>
>>> +}<br>
>>> +declare <2 x double> @llvm.x86.fma4.vfnmsub.pd(<2 x double>, <2 x<br>
>>> double>, <2 x double>) nounwind readnone<br>
>>><br>
>>> Propchange: llvm/trunk/test/CodeGen/X86/fma3-intrinsics.ll<br>
>>> ------------------------------------------------------------------------------<br>
>>>   svn:executable = *<br>
>>><br>
>>> Added: llvm/trunk/test/CodeGen/X86/fma3.ll<br>
>>> URL:<br>
>>> <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fma3.ll?rev=157737&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fma3.ll?rev=157737&view=auto</a><br>

>>> ==============================================================================<br>
>>> --- llvm/trunk/test/CodeGen/X86/fma3.ll (added) +++<br>
>>> llvm/trunk/test/CodeGen/X86/fma3.ll Thu May 31 04:20:20 2012 @@<br>
>>> -0,0 +1,66 @@ +; RUN: llc < %s -mtriple=x86_64-pc-win32<br>
>>> -mcpu=core-avx2 -mattr=avx2,+fma3 | FileCheck %s +<br>
>>> +define <4 x float> @test_x86_fmadd_ps(<4 x float> %a0, <4 x float><br>
>>> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fmadd231ps {{.*\(%r.*}}, %xmm<br>
>>> +  %x = fmul <4 x float> %a0, %a1<br>
>>> +  %res = fadd <4 x float> %x, %a2<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +<br>
>>> +define <4 x float> @test_x86_fmsub_ps(<4 x float> %a0, <4 x float><br>
>>> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fmsub231ps {{.*\(%r.*}}, %xmm<br>
>>> +  %x = fmul <4 x float> %a0, %a1<br>
>>> +  %res = fsub <4 x float> %x, %a2<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +<br>
>>> +define <4 x float> @test_x86_fnmadd_ps(<4 x float> %a0, <4 x<br>
>>> float> %a1, <4 x float> %a2) {<br>
>>> +  ; CHECK: fnmadd231ps {{.*\(%r.*}}, %xmm<br>
>>> +  %x = fmul <4 x float> %a0, %a1<br>
>>> +  %res = fsub <4 x float> %a2, %x<br>
>>> +  ret <4 x float> %res<br>
>>> +}<br>
>>> +<br>
>>> +define <8 x float> @test_x86_fmadd_ps_y(<8 x float> %a0, <8 x<br>
>>> float> %a1, <8 x float> %a2) {<br>
>>> +  ; CHECK: vfmadd213ps {{.*\(%r.*}}, %ymm<br>
>>> +  %x = fmul <8 x float> %a0, %a1<br>
>>> +  %res = fadd <8 x float> %x, %a2<br>
>>> +  ret <8 x float> %res<br>
>>> +}<br>
>>> +<br>
>>> +define <4 x double> @test_x86_fmadd_pd_y(<4 x double> %a0, <4 x<br>
>>> double> %a1, <4 x double> %a2) {<br>
>>> +  ; CHECK: vfmadd231pd {{.*\(%r.*}}, %ymm<br>
>>> +  %x = fmul <4 x double> %a0, %a1<br>
>>> +  %res = fadd <4 x double> %x, %a2<br>
>>> +  ret <4 x double> %res<br>
>>> +}<br>
>>> +<br>
>>> +<br>
>>> +define <8 x float> @test_x86_fmsub_ps_y(<8 x float> %a0, <8 x<br>
>>> float> %a1, <8 x float> %a2) {<br>
>>> +  ; CHECK: fmsub231ps {{.*\(%r.*}}, %ymm<br>
>>> +  %x = fmul <8 x float> %a0, %a1<br>
>>> +  %res = fsub <8 x float> %x, %a2<br>
>>> +  ret <8 x float> %res<br>
>>> +}<br>
>>> +<br>
>>> +define <8 x float> @test_x86_fnmadd_ps_y(<8 x float> %a0, <8 x<br>
>>> float> %a1, <8 x float> %a2) {<br>
>>> +  ; CHECK: fnmadd231ps {{.*\(%r.*}}, %ymm<br>
>>> +  %x = fmul <8 x float> %a0, %a1<br>
>>> +  %res = fsub <8 x float> %a2, %x<br>
>>> +  ret <8 x float> %res<br>
>>> +}<br>
>>> +<br>
>>> +define float @test_x86_fnmadd_ss(float %a0, float %a1, float %a2) {<br>
>>> +  ; CHECK: vfnmadd231ss    %xmm1, %xmm0, %xmm2<br>
>>> +  %x = fmul float %a0, %a1<br>
>>> +  %res = fsub float %a2, %x<br>
>>> +  ret float %res<br>
>>> +}<br>
>>> +<br>
>>> +define double @test_x86_fnmadd_sd(double %a0, double %a1, double<br>
>>> %a2) {<br>
>>> +  ; CHECK: vfnmadd231sd    %xmm1, %xmm0, %xmm2<br>
>>> +  %x = fmul double %a0, %a1<br>
>>> +  %res = fsub double %a2, %x<br>
>>> +  ret double %res<br>
>>> +}<br>
>>> +<br>
>>><br>
>>> Propchange: llvm/trunk/test/CodeGen/X86/fma3.ll<br>
>>> ------------------------------------------------------------------------------<br>
>>>   svn:executable = *<br>
>>><br>
>>><br>
>>> _______________________________________________<br>
>>> llvm-commits mailing list<br>
>>> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
>>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
>>><br>
>>><br>
>>><br>
>>> --<br>
>>> ~Craig<br>
>>> _______________________________________________<br>
>>> llvm-commits mailing list<br>
>>> <a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
>>> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
>>><br>
>>><br>
>>><br>
>>> --<br>
>>> ~Craig<br>
>>><br>
>>><br>
>>><br>
>>> --<br>
>>> ~Craig<br>
>>> ---------------------------------------------------------------------<br>
>>> Intel Israel (74) Limited<br>
>>><br>
>>> This e-mail and any attachments may contain confidential material<br>
>>> for the sole use of the intended recipient(s). Any review or<br>
>>> distribution by others is strictly prohibited. If you are not the<br>
>>> intended recipient, please contact the sender and delete all copies.<br>
>><br>
><br>
><br>
><br>
> --<br>
> Hal Finkel<br>
> Postdoctoral Appointee<br>
> Leadership Computing Facility<br>
> Argonne National Laboratory<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br>