<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:Tahoma;
        panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
        {mso-style-priority:99;
        mso-style-link:"Balloon Text Char";
        margin:0cm;
        margin-bottom:.0001pt;
        font-size:8.0pt;
        font-family:"Tahoma","sans-serif";}
span.EmailStyle17
        {mso-style-type:personal;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Calibri","sans-serif";
        color:#1F497D;}
span.BalloonTextChar
        {mso-style-name:"Balloon Text Char";
        mso-style-priority:99;
        mso-style-link:"Balloon Text";
        font-family:"Tahoma","sans-serif";}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Argh.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Apparently, the way X86FrameLowering::emitPrologue() tries to find the right place to insert the stack allocation for locals is by skipping *<b>all</b>* register
 push instructions from the start of the entry block, because it imagines all of them are pushes of callee-save registers.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">This happens to be false when the first instruction following these spills is a push of an argument that goes another call, and this argument just happens to
 live in-register.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><a name="_MailEndCompose"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">I’ll fix that, commit the fix, reapply r240257, and then add a test for the fix (because I don’t see how it can be tested without
 r240257 being in).<o:p></o:p></span></a></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Michael<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif""> Kuperstein, Michael M
<br>
<b>Sent:</b> Thursday, July 16, 2015 08:34<br>
<b>To:</b> 'Reid Kleckner'<br>
<b>Cc:</b> llvm-commits<br>
<b>Subject:</b> RE: [llvm] r240257 - [X86] Allow more call sequences to use push instructions for argument passing<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Wow, really, only one?! :-)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Thanks for the test-case, I’ll look into it ASAP.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Out of curiosity, how big was the size win?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Michael<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"><o:p> </o:p></span></p>
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">From:</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif""> Reid Kleckner [<a href="mailto:rnk@google.com">mailto:rnk@google.com</a>]
<br>
<b>Sent:</b> Thursday, July 16, 2015 04:11<br>
<b>To:</b> Kuperstein, Michael M<br>
<b>Cc:</b> llvm-commits<br>
<b>Subject:</b> Re: [llvm] r240257 - [X86] Allow more call sequences to use push instructions for argument passing<o:p></o:p></span></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<p class="MsoNormal" style="line-height:115%">The size win from this is pretty exciting, but it's miscompiling a function in Chromium:<o:p></o:p></p>
<div>
<p class="MsoNormal" style="line-height:115%"><a href="https://urldefense.proofpoint.com/v2/url?u=https-3A__code.google.com_p_chromium_codesearch-23chromium_src_third-5Fparty_libjingle_source_talk_session_media_mediasession.cc-26l-3D606&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=OYUMfyJifi3hCVZRJpa7hPGsih26TcOSlreroSSiCbQ&s=1UG4rH_ZnuXjmnnbQorLOxsDxwcXDKhABtZ0xo18QkU&e=">https://code.google.com/p/chromium/codesearch#chromium/src/third_party/libjingle/source/talk/session/media/mediasession.cc&l=606</a><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">On the bright side, it's only one!<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">We end up with a fastcc function (taking parameters in ecx / edx) calling a thiscall function in the entry block, and somehow the stack adjustment ends up in the wrong place:<o:p></o:p></p>
</div>
<div>
<div>
<p class="MsoNormal" style="line-height:115%">        pushl   %ebp<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">        movl    %esp, %ebp<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">        pushl   %ebx<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">        pushl   %edi<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">        pushl   %esi  <---- end pushing non-volatile regs<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">        pushl   %edx <----- set up second argument to GetContentByName, ecx is already arranged<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">        subl    $48, %esp <---- BUG: stack allocation here!?<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">        calll   "?GetContentByName@SessionDescription@cricket@@QAEPAUContentInfo@2@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z"<o:p></o:p></p>
</div>
</div>
<div>
<p class="MsoNormal" style="line-height:115%"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%">I've attached the extracted function and you can see the bug by inspection with llc.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="line-height:115%"><o:p> </o:p></p>
</div>
<div>
<div>
<p class="MsoNormal" style="line-height:115%">I'm going to flip the sense of the call frame optimization command line flag so that it's off by default for now. Feel free to flip it back when you sort this out.<o:p></o:p></p>
</div>
</div>
</div>
<div>
<p class="MsoNormal" style="line-height:115%"><o:p> </o:p></p>
<div>
<p class="MsoNormal" style="line-height:115%">On Mon, Jun 22, 2015 at 1:31 AM, Michael Kuperstein <<a href="mailto:michael.m.kuperstein@intel.com" target="_blank">michael.m.kuperstein@intel.com</a>> wrote:<o:p></o:p></p>
<p class="MsoNormal" style="line-height:115%">Author: mkuper<br>
Date: Mon Jun 22 03:31:22 2015<br>
New Revision: 240257<br>
<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D240257-26view-3Drev&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=OYUMfyJifi3hCVZRJpa7hPGsih26TcOSlreroSSiCbQ&s=1OPIA9Jy3g_SjV1gPWgBQsu4E2Ada8HrW2vPNItMGcs&e=" target="_blank">
http://llvm.org/viewvc/llvm-project?rev=240257&view=rev</a><br>
Log:<br>
[X86] Allow more call sequences to use push instructions for argument passing<br>
<br>
This allows more call sequences to use pushes instead of movs when optimizing for size.<br>
In particular, calling conventions that pass some parameters in registers (e.g. thiscall) are now supported.<br>
<br>
Differential Revision: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__reviews.llvm.org_D10500&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=OYUMfyJifi3hCVZRJpa7hPGsih26TcOSlreroSSiCbQ&s=9Gu3fOap9_jRPvre3FmcXENrgk06NrzwyemstgJPK2w&e=" target="_blank">http://reviews.llvm.org/D10500</a><br>
<br>
Modified:<br>
    llvm/trunk/lib/Target/X86/X86CallFrameOptimization.cpp<br>
    llvm/trunk/test/CodeGen/X86/movtopush.ll<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86CallFrameOptimization.cpp<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_lib_Target_X86_X86CallFrameOptimization.cpp-3Frev-3D240257-26r1-3D240256-26r2-3D240257-26view-3Ddiff&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=OYUMfyJifi3hCVZRJpa7hPGsih26TcOSlreroSSiCbQ&s=kwM2hAJ5xEbMEyye_kIZ7n_eFY4KNQAc_cvJ_ITfrPA&e=" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CallFrameOptimization.cpp?rev=240257&r1=240256&r2=240257&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86CallFrameOptimization.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86CallFrameOptimization.cpp Mon Jun 22 03:31:22 2015<br>
@@ -78,7 +78,7 @@ private:<br>
   typedef DenseMap<MachineInstr *, CallContext> ContextMap;<br>
<br>
   bool isLegal(MachineFunction &MF);<br>
-<br>
+<br>
   bool isProfitable(MachineFunction &MF, ContextMap &CallSeqMap);<br>
<br>
   void collectCallInfo(MachineFunction &MF, MachineBasicBlock &MBB,<br>
@@ -90,6 +90,13 @@ private:<br>
   MachineInstr *canFoldIntoRegPush(MachineBasicBlock::iterator FrameSetup,<br>
                                    unsigned Reg);<br>
<br>
+  enum InstClassification { Convert, Skip, Exit };<br>
+<br>
+  InstClassification classifyInstruction(MachineBasicBlock &MBB,<br>
+                                         MachineBasicBlock::iterator MI,<br>
+                                         const X86RegisterInfo &RegInfo,<br>
+                                         DenseSet<unsigned int> &UsedRegs);<br>
+<br>
   const char *getPassName() const override { return "X86 Optimize Call Frame"; }<br>
<br>
   const TargetInstrInfo *TII;<br>
@@ -105,7 +112,7 @@ FunctionPass *llvm::createX86CallFrameOp<br>
   return new X86CallFrameOptimization();<br>
 }<br>
<br>
-// This checks whether the transformation is legal.<br>
+// This checks whether the transformation is legal.<br>
 // Also returns false in cases where it's potentially legal, but<br>
 // we don't even want to try.<br>
 bool X86CallFrameOptimization::isLegal(MachineFunction &MF) {<br>
@@ -170,9 +177,8 @@ bool X86CallFrameOptimization::isProfita<br>
   if (!OptForSize)<br>
     return false;<br>
<br>
-<br>
   unsigned StackAlign = TFL->getStackAlignment();<br>
-<br>
+<br>
   int64_t Advantage = 0;<br>
   for (auto CC : CallSeqMap) {<br>
     // Call sites where no parameters are passed on the stack<br>
@@ -205,7 +211,6 @@ bool X86CallFrameOptimization::isProfita<br>
   return (Advantage >= 0);<br>
 }<br>
<br>
-<br>
 bool X86CallFrameOptimization::runOnMachineFunction(MachineFunction &MF) {<br>
   TII = MF.getSubtarget().getInstrInfo();<br>
   TFL = MF.getSubtarget().getFrameLowering();<br>
@@ -237,6 +242,64 @@ bool X86CallFrameOptimization::runOnMach<br>
   return Changed;<br>
 }<br>
<br>
+X86CallFrameOptimization::InstClassification<br>
+X86CallFrameOptimization::classifyInstruction(<br>
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,<br>
+    const X86RegisterInfo &RegInfo, DenseSet<unsigned int> &UsedRegs) {<br>
+  if (MI == MBB.end())<br>
+    return Exit;<br>
+<br>
+  // The instructions we actually care about are movs onto the stack<br>
+  int Opcode = MI->getOpcode();<br>
+  if (Opcode == X86::MOV32mi || Opcode == X86::MOV32mr)<br>
+    return Convert;<br>
+<br>
+  // Not all calling conventions have only stack MOVs between the stack<br>
+  // adjust and the call.<br>
+<br>
+  // We want to tolerate other instructions, to cover more cases.<br>
+  // In particular:<br>
+  // a) PCrel calls, where we expect an additional COPY of the basereg.<br>
+  // b) Passing frame-index addresses.<br>
+  // c) Calling conventions that have inreg parameters. These generate<br>
+  //    both copies and movs into registers.<br>
+  // To avoid creating lots of special cases, allow any instruction<br>
+  // that does not write into memory, does not def or use the stack<br>
+  // pointer, and does not def any register that was used by a preceding<br>
+  // push.<br>
+  // (Reading from memory is allowed, even if referenced through a<br>
+  // frame index, since these will get adjusted properly in PEI)<br>
+<br>
+  // The reason for the last condition is that the pushes can't replace<br>
+  // the movs in place, because the order must be reversed.<br>
+  // So if we have a MOV32mr that uses EDX, then an instruction that defs<br>
+  // EDX, and then the call, after the transformation the push will use<br>
+  // the modified version of EDX, and not the original one.<br>
+  // Since we are still in SSA form at this point, we only need to<br>
+  // make sure we don't clobber any *physical* registers that were<br>
+  // used by an earlier mov that will become a push.<br>
+<br>
+  if (MI->isCall() || MI->mayStore())<br>
+    return Exit;<br>
+<br>
+  for (const MachineOperand &MO : MI->operands()) {<br>
+    if (!MO.isReg())<br>
+      continue;<br>
+    unsigned int Reg = MO.getReg();<br>
+    if (!RegInfo.isPhysicalRegister(Reg))<br>
+      continue;<br>
+    if (RegInfo.regsOverlap(Reg, RegInfo.getStackRegister()))<br>
+      return Exit;<br>
+    if (MO.isDef()) {<br>
+      for (unsigned int U : UsedRegs)<br>
+        if (RegInfo.regsOverlap(Reg, U))<br>
+          return Exit;<br>
+    }<br>
+  }<br>
+<br>
+  return Skip;<br>
+}<br>
+<br>
 void X86CallFrameOptimization::collectCallInfo(MachineFunction &MF,<br>
                                                MachineBasicBlock &MBB,<br>
                                                MachineBasicBlock::iterator I,<br>
@@ -254,8 +317,8 @@ void X86CallFrameOptimization::collectCa<br>
<br>
   // How much do we adjust the stack? This puts an upper bound on<br>
   // the number of parameters actually passed on it.<br>
-  unsigned int MaxAdjust = FrameSetup->getOperand(0).getImm() / 4;<br>
-<br>
+  unsigned int MaxAdjust = FrameSetup->getOperand(0).getImm() / 4;<br>
+<br>
   // A zero adjustment means no stack parameters<br>
   if (!MaxAdjust) {<br>
     Context.NoStackParams = true;<br>
@@ -284,11 +347,17 @@ void X86CallFrameOptimization::collectCa<br>
   if (MaxAdjust > 4)<br>
     Context.MovVector.resize(MaxAdjust, nullptr);<br>
<br>
-  do {<br>
-    int Opcode = I->getOpcode();<br>
-    if (Opcode != X86::MOV32mi && Opcode != X86::MOV32mr)<br>
-      break;<br>
+  InstClassification Classification;<br>
+  DenseSet<unsigned int> UsedRegs;<br>
<br>
+  while ((Classification = classifyInstruction(MBB, I, RegInfo, UsedRegs)) !=<br>
+         Exit) {<br>
+    if (Classification == Skip) {<br>
+      ++I;<br>
+      continue;<br>
+    }<br>
+<br>
+    // We know the instruction is a MOV32mi/MOV32mr.<br>
     // We only want movs of the form:<br>
     // movl imm/r32, k(%esp)<br>
     // If we run into something else, bail.<br>
@@ -323,24 +392,20 @@ void X86CallFrameOptimization::collectCa<br>
       return;<br>
     Context.MovVector[StackDisp] = I;<br>
<br>
-    ++I;<br>
-  } while (I != MBB.end());<br>
-<br>
-  // We now expect the end of the sequence - a call and a stack adjust.<br>
-  if (I == MBB.end())<br>
-    return;<br>
+    for (const MachineOperand &MO : I->uses()) {<br>
+      if (!MO.isReg())<br>
+        continue;<br>
+      unsigned int Reg = MO.getReg();<br>
+      if (RegInfo.isPhysicalRegister(Reg))<br>
+        UsedRegs.insert(Reg);<br>
+    }<br>
<br>
-  // For PCrel calls, we expect an additional COPY of the basereg.<br>
-  // If we find one, skip it.<br>
-  if (I->isCopy()) {<br>
-    if (I->getOperand(1).getReg() ==<br>
-        MF.getInfo<X86MachineFunctionInfo>()->getGlobalBaseReg())<br>
-      ++I;<br>
-    else<br>
-      return;<br>
+    ++I;<br>
   }<br>
<br>
-  if (!I->isCall())<br>
+  // We now expect the end of the sequence. If we stopped early,<br>
+  // or reached the end of the block without finding a call, bail.<br>
+  if (I == MBB.end() || !I->isCall())<br>
     return;<br>
<br>
   Context.Call = I;<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/movtopush.ll<br>
URL: <a href="https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_llvm_trunk_test_CodeGen_X86_movtopush.ll-3Frev-3D240257-26r1-3D240256-26r2-3D240257-26view-3Ddiff&d=AwMGaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=OYUMfyJifi3hCVZRJpa7hPGsih26TcOSlreroSSiCbQ&s=6muMs4mmOgDdQA3g7W4ueLLIhAL5FidEnqpErTDCH3M&e=" target="_blank">
http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/movtopush.ll?rev=240257&r1=240256&r2=240257&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/movtopush.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/movtopush.ll Mon Jun 22 03:31:22 2015<br>
@@ -2,11 +2,15 @@<br>
 ; RUN: llc < %s -mtriple=x86_64-windows | FileCheck %s -check-prefix=X64<br>
 ; RUN: llc < %s -mtriple=i686-windows -force-align-stack -stack-alignment=32 | FileCheck %s -check-prefix=ALIGNED<br>
<br>
+%class.Class = type { i32 }<br>
+%struct.s = type { i64 }<br>
+<br>
 declare void @good(i32 %a, i32 %b, i32 %c, i32 %d)<br>
 declare void @inreg(i32 %a, i32 inreg %b, i32 %c, i32 %d)<br>
+declare x86_thiscallcc void @thiscall(%class.Class* %class, i32 %a, i32 %b, i32 %c, i32 %d)<br>
 declare void @oneparam(i32 %a)<br>
 declare void @eightparams(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h)<br>
-<br>
+declare void @struct(%struct.s* byval %a, i32 %b, i32 %c, i32 %d)<br>
<br>
 ; Here, we should have a reserved frame, so we don't expect pushes<br>
 ; NORMAL-LABEL: test1:<br>
@@ -108,13 +112,12 @@ entry:<br>
   ret void<br>
 }<br>
<br>
-; We don't support weird calling conventions<br>
+; We support weird calling conventions<br>
 ; NORMAL-LABEL: test4:<br>
-; NORMAL: subl    $12, %esp<br>
-; NORMAL-NEXT: movl    $4, 8(%esp)<br>
-; NORMAL-NEXT: movl    $3, 4(%esp)<br>
-; NORMAL-NEXT: movl    $1, (%esp)<br>
-; NORMAL-NEXT: movl    $2, %eax<br>
+; NORMAL: movl    $2, %eax<br>
+; NORMAL-NEXT: pushl   $4<br>
+; NORMAL-NEXT: pushl   $3<br>
+; NORMAL-NEXT: pushl   $1<br>
 ; NORMAL-NEXT: call<br>
 ; NORMAL-NEXT: addl $12, %esp<br>
 define void @test4() optsize {<br>
@@ -123,6 +126,20 @@ entry:<br>
   ret void<br>
 }<br>
<br>
+; NORMAL-LABEL: test4b:<br>
+; NORMAL: movl 4(%esp), %ecx<br>
+; NORMAL-NEXT: pushl   $4<br>
+; NORMAL-NEXT: pushl   $3<br>
+; NORMAL-NEXT: pushl   $2<br>
+; NORMAL-NEXT: pushl   $1<br>
+; NORMAL-NEXT: call<br>
+; NORMAL-NEXT: ret<br>
+define void @test4b(%class.Class* %f) optsize {<br>
+entry:<br>
+  call x86_thiscallcc void @thiscall(%class.Class* %f, i32 1, i32 2, i32 3, i32 4)<br>
+  ret void<br>
+}<br>
+<br>
 ; When there is no reserved call frame, check that additional alignment<br>
 ; is added when the pushes don't add up to the required alignment.<br>
 ; ALIGNED-LABEL: test5:<br>
@@ -229,20 +246,27 @@ entry:<br>
 ; NORMAL-NEXT: pushl $1<br>
 ; NORMAL-NEXT: call<br>
 ; NORMAL-NEXT: addl $16, %esp<br>
-; NORMAL-NEXT: subl $16, %esp<br>
-; NORMAL-NEXT: leal 16(%esp), [[EAX:%e..]]<br>
-; NORMAL-NEXT: movl    [[EAX]], 12(%esp)<br>
-; NORMAL-NEXT: movl    $7, 8(%esp)<br>
-; NORMAL-NEXT: movl    $6, 4(%esp)<br>
-; NORMAL-NEXT: movl    $5, (%esp)<br>
+; NORMAL-NEXT: subl $20, %esp<br>
+; NORMAL-NEXT: movl 20(%esp), [[E1:%e..]]<br>
+; NORMAL-NEXT: movl 24(%esp), [[E2:%e..]]<br>
+; NORMAL-NEXT: movl    [[E2]], 4(%esp)<br>
+; NORMAL-NEXT: movl    [[E1]], (%esp)<br>
+; NORMAL-NEXT: leal 32(%esp), [[E3:%e..]]<br>
+; NORMAL-NEXT: movl    [[E3]], 16(%esp)<br>
+; NORMAL-NEXT: leal 28(%esp), [[E4:%e..]]<br>
+; NORMAL-NEXT: movl    [[E4]], 12(%esp)<br>
+; NORMAL-NEXT: movl    $6, 8(%esp)<br>
 ; NORMAL-NEXT: call<br>
-; NORMAL-NEXT: addl $16, %esp<br>
+; NORMAL-NEXT: addl $20, %esp<br>
 define void @test9() optsize {<br>
 entry:<br>
   %p = alloca i32, align 4<br>
+  %q = alloca i32, align 4<br>
+  %s = alloca %struct.s, align 4<br>
   call void @good(i32 1, i32 2, i32 3, i32 4)<br>
-  %0 = ptrtoint i32* %p to i32<br>
-  call void @good(i32 5, i32 6, i32 7, i32 %0)<br>
+  %pv = ptrtoint i32* %p to i32<br>
+  %qv = ptrtoint i32* %q to i32<br>
+  call void @struct(%struct.s* byval %s, i32 6, i32 %qv, i32 %pv)<br>
   ret void<br>
 }<br>
<br>
@@ -291,28 +315,17 @@ define void @test11() optsize {<br>
 ; Converting one mov into a push isn't worth it when<br>
 ; doing so forces too much overhead for other calls.<br>
 ; NORMAL-LABEL: test12:<br>
-; NORMAL: subl    $16, %esp<br>
-; NORMAL-NEXT: movl    $4, 8(%esp)<br>
-; NORMAL-NEXT: movl    $3, 4(%esp)<br>
-; NORMAL-NEXT: movl    $1, (%esp)<br>
-; NORMAL-NEXT: movl    $2, %eax<br>
-; NORMAL-NEXT: calll _inreg<br>
-; NORMAL-NEXT: movl    $8, 12(%esp)<br>
+; NORMAL: movl    $8, 12(%esp)<br>
 ; NORMAL-NEXT: movl    $7, 8(%esp)<br>
 ; NORMAL-NEXT: movl    $6, 4(%esp)<br>
 ; NORMAL-NEXT: movl    $5, (%esp)<br>
 ; NORMAL-NEXT: calll _good<br>
-; NORMAL-NEXT: movl    $12, 8(%esp)<br>
-; NORMAL-NEXT: movl    $11, 4(%esp)<br>
-; NORMAL-NEXT: movl    $9, (%esp)<br>
-; NORMAL-NEXT: movl    $10, %eax<br>
-; NORMAL-NEXT: calll _inreg<br>
-; NORMAL-NEXT: addl $16, %esp<br>
 define void @test12() optsize {<br>
 entry:<br>
-  call void @inreg(i32 1, i32 2, i32 3, i32 4)<br>
+  %s = alloca %struct.s, align 4<br>
+  call void @struct(%struct.s* %s, i32 2, i32 3, i32 4)<br>
   call void @good(i32 5, i32 6, i32 7, i32 8)<br>
-  call void @inreg(i32 9, i32 10, i32 11, i32 12)<br>
+  call void @struct(%struct.s* %s, i32 10, i32 11, i32 12)<br>
   ret void<br>
 }<br>
<br>
@@ -324,13 +337,12 @@ entry:<br>
 ; NORMAL-NEXT: pushl    $1<br>
 ; NORMAL-NEXT: calll _good<br>
 ; NORMAL-NEXT: addl    $16, %esp<br>
-; NORMAL-NEXT: subl    $12, %esp<br>
-; NORMAL-NEXT: movl    $8, 8(%esp)<br>
-; NORMAL-NEXT: movl    $7, 4(%esp)<br>
-; NORMAL-NEXT: movl    $5, (%esp)<br>
-; NORMAL-NEXT: movl    $6, %eax<br>
-; NORMAL-NEXT: calll _inreg<br>
-; NORMAL-NEXT: addl    $12, %esp<br>
+; NORMAL-NEXT: subl    $20, %esp<br>
+; NORMAL: movl    $8, 16(%esp)<br>
+; NORMAL-NEXT: movl    $7, 12(%esp)<br>
+; NORMAL-NEXT: movl    $6, 8(%esp)<br>
+; NORMAL-NEXT: calll _struct<br>
+; NORMAL-NEXT: addl    $20, %esp<br>
 ; NORMAL-NEXT: pushl    $12<br>
 ; NORMAL-NEXT: pushl    $11<br>
 ; NORMAL-NEXT: pushl    $10<br>
@@ -339,8 +351,9 @@ entry:<br>
 ; NORMAL-NEXT: addl $16, %esp<br>
 define void @test12b() optsize {<br>
 entry:<br>
-  call void @good(i32 1, i32 2, i32 3, i32 4)<br>
-  call void @inreg(i32 5, i32 6, i32 7, i32 8)<br>
+  %s = alloca %struct.s, align 4<br>
+  call void @good(i32 1, i32 2, i32 3, i32 4)<br>
+  call void @struct(%struct.s* %s, i32 6, i32 7, i32 8)<br>
   call void @good(i32 9, i32 10, i32 11, i32 12)<br>
   ret void<br>
 }<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><o:p></o:p></p>
</div>
<p class="MsoNormal" style="line-height:115%"><o:p> </o:p></p>
</div>
</div>
<p>---------------------------------------------------------------------<br>
Intel Israel (74) Limited</p>

<p>This e-mail and any attachments may contain confidential material for<br>
the sole use of the intended recipient(s). Any review or distribution<br>
by others is strictly prohibited. If you are not the intended<br>
recipient, please contact the sender and delete all copies.</p></body>
</html>