[llvm] r248832 - HHVM calling conventions.

Maksim Panchenko via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 15:09:17 PDT 2015


Author: maks
Date: Tue Sep 29 17:09:16 2015
New Revision: 248832

URL: http://llvm.org/viewvc/llvm-project?rev=248832&view=rev
Log:
HHVM calling conventions.

HHVM calling convention, hhvmcc, is used by HHVM JIT for
functions in translated cache. We currently support LLVM back end to
generate code for X86-64 and may support other architectures in the
future.

In HHVM calling convention any GP register could be used to pass and
return values, with the exception of R12 which is reserved for
thread-local area and is callee-saved. Other than R12, we always
pass RBX and RBP as args, which are our virtual machine's stack pointer
and frame pointer respectively.

When we enter translation cache via hhvmcc function, we expect
the stack to be aligned at 16 bytes, i.e. skewed by 8 bytes as opposed
to standard ABI alignment. This affects stack object alignment and stack
adjustments for function calls.

One extra calling convention, hhvm_ccc, is used to call C++ helpers from
HHVM's translation cache. It is almost identical to standard C calling
convention with an exception of first argument which is passed in RBP
(before we use RDI, RSI, etc.)

Differential Revision: http://reviews.llvm.org/D12681

Added:
    llvm/trunk/test/CodeGen/X86/hhvm-cc.ll
Modified:
    llvm/trunk/include/llvm/IR/CallingConv.h
    llvm/trunk/include/llvm/Support/MathExtras.h
    llvm/trunk/include/llvm/Target/TargetFrameLowering.h
    llvm/trunk/lib/AsmParser/LLLexer.cpp
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLToken.h
    llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp
    llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp
    llvm/trunk/lib/IR/AsmWriter.cpp
    llvm/trunk/lib/Target/X86/X86CallingConv.td
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp
    llvm/trunk/test/Feature/callingconventions.ll
    llvm/trunk/unittests/Support/MathExtrasTest.cpp
    llvm/trunk/utils/vim/syntax/llvm.vim

Modified: llvm/trunk/include/llvm/IR/CallingConv.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/CallingConv.h?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/CallingConv.h (original)
+++ llvm/trunk/include/llvm/IR/CallingConv.h Tue Sep 29 17:09:16 2015
@@ -147,7 +147,16 @@ namespace CallingConv {
 
     /// \brief MSVC calling convention that passes vectors and vector aggregates
     /// in SSE registers.
-    X86_VectorCall = 80
+    X86_VectorCall = 80,
+
+    /// \brief Calling convention used by HipHop Virtual Machine (HHVM) to
+    /// perform calls to and from translation cache, and for calling PHP
+    /// functions.
+    /// HHVM calling convention supports tail/sibling call elimination.
+    HHVM = 81,
+
+    /// \brief HHVM calling convention for invoking C/C++ helpers.
+    HHVM_C = 82
   };
 } // End CallingConv namespace
 

Modified: llvm/trunk/include/llvm/Support/MathExtras.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MathExtras.h?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/MathExtras.h (original)
+++ llvm/trunk/include/llvm/Support/MathExtras.h Tue Sep 29 17:09:16 2015
@@ -599,15 +599,27 @@ inline uint64_t PowerOf2Floor(uint64_t A
 /// Returns the next integer (mod 2**64) that is greater than or equal to
 /// \p Value and is a multiple of \p Align. \p Align must be non-zero.
 ///
+/// If non-zero \p Skew is specified, the return value will be a minimal
+/// integer that is greater than or equal to \p Value and equal to
+/// \p Align * N + \p Skew for some integer N. If \p Skew is larger than
+/// \p Align, its value is adjusted to '\p Skew mod \p Align'.
+///
 /// Examples:
 /// \code
 ///   RoundUpToAlignment(5, 8) = 8
 ///   RoundUpToAlignment(17, 8) = 24
 ///   RoundUpToAlignment(~0LL, 8) = 0
 ///   RoundUpToAlignment(321, 255) = 510
+///
+///   RoundUpToAlignment(5, 8, 7) = 7
+///   RoundUpToAlignment(17, 8, 1) = 17
+///   RoundUpToAlignment(~0LL, 8, 3) = 3
+///   RoundUpToAlignment(321, 255, 42) = 552
 /// \endcode
-inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align) {
-  return (Value + Align - 1) / Align * Align;
+inline uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align,
+                                   uint64_t Skew = 0) {
+  Skew %= Align;
+  return (Value + Align - 1 - Skew) / Align * Align + Skew;
 }
 
 /// Returns the offset to the next integer (mod 2**64) that is greater than

Modified: llvm/trunk/include/llvm/Target/TargetFrameLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetFrameLowering.h?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetFrameLowering.h (original)
+++ llvm/trunk/include/llvm/Target/TargetFrameLowering.h Tue Sep 29 17:09:16 2015
@@ -96,6 +96,11 @@ public:
     return StackRealignable;
   }
 
+  /// Return the skew that has to be applied to stack alignment under
+  /// certain conditions (e.g. stack was adjusted before function \p MF
+  /// was called).
+  virtual unsigned getStackAlignmentSkew(const MachineFunction &MF) const;
+
   /// getOffsetOfLocalArea - This method returns the offset of the local area
   /// from the stack pointer on entrance to a function.
   ///

Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Tue Sep 29 17:09:16 2015
@@ -587,6 +587,8 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(preserve_mostcc);
   KEYWORD(preserve_allcc);
   KEYWORD(ghccc);
+  KEYWORD(hhvmcc);
+  KEYWORD(hhvm_ccc);
 
   KEYWORD(cc);
   KEYWORD(c);

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Tue Sep 29 17:09:16 2015
@@ -1532,6 +1532,8 @@ bool LLParser::ParseOptionalDLLStorageCl
 ///   ::= 'preserve_mostcc'
 ///   ::= 'preserve_allcc'
 ///   ::= 'ghccc'
+///   ::= 'hhvmcc'
+///   ::= 'hhvm_ccc'
 ///   ::= 'cc' UINT
 ///
 bool LLParser::ParseOptionalCallingConv(unsigned &CC) {
@@ -1560,6 +1562,8 @@ bool LLParser::ParseOptionalCallingConv(
   case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break;
   case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break;
   case lltok::kw_ghccc:          CC = CallingConv::GHC; break;
+  case lltok::kw_hhvmcc:         CC = CallingConv::HHVM; break;
+  case lltok::kw_hhvm_ccc:       CC = CallingConv::HHVM_C; break;
   case lltok::kw_cc: {
       Lex.Lex();
       return ParseUInt32(CC);

Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Tue Sep 29 17:09:16 2015
@@ -97,6 +97,7 @@ namespace lltok {
     kw_webkit_jscc, kw_anyregcc,
     kw_preserve_mostcc, kw_preserve_allcc,
     kw_ghccc,
+    kw_hhvmcc, kw_hhvm_ccc,
 
     // Attributes:
     kw_attributes,

Modified: llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp (original)
+++ llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp Tue Sep 29 17:09:16 2015
@@ -500,7 +500,7 @@ void PEI::insertCSRSpillsAndRestores(Mac
 static inline void
 AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx,
                   bool StackGrowsDown, int64_t &Offset,
-                  unsigned &MaxAlign) {
+                  unsigned &MaxAlign, unsigned Skew) {
   // If the stack grows down, add the object size to find the lowest address.
   if (StackGrowsDown)
     Offset += MFI->getObjectSize(FrameIdx);
@@ -512,7 +512,7 @@ AdjustStackOffset(MachineFrameInfo *MFI,
   MaxAlign = std::max(MaxAlign, Align);
 
   // Adjust to alignment boundary.
-  Offset = RoundUpToAlignment(Offset, Align);
+  Offset = RoundUpToAlignment(Offset, Align, Skew);
 
   if (StackGrowsDown) {
     DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n");
@@ -530,12 +530,12 @@ static void
 AssignProtectedObjSet(const StackObjSet &UnassignedObjs,
                       SmallSet<int, 16> &ProtectedObjs,
                       MachineFrameInfo *MFI, bool StackGrowsDown,
-                      int64_t &Offset, unsigned &MaxAlign) {
+                      int64_t &Offset, unsigned &MaxAlign, unsigned Skew) {
 
   for (StackObjSet::const_iterator I = UnassignedObjs.begin(),
         E = UnassignedObjs.end(); I != E; ++I) {
     int i = *I;
-    AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
+    AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew);
     ProtectedObjs.insert(i);
   }
 }
@@ -563,6 +563,9 @@ void PEI::calculateFrameObjectOffsets(Ma
          && "Local area offset should be in direction of stack growth");
   int64_t Offset = LocalAreaOffset;
 
+  // Skew to be applied to alignment.
+  unsigned Skew = TFI.getStackAlignmentSkew(Fn);
+
   // If there are fixed sized objects that are preallocated in the local area,
   // non-fixed objects can't be allocated right at the start of local area.
   // We currently don't support filling in holes in between fixed sized
@@ -593,7 +596,7 @@ void PEI::calculateFrameObjectOffsets(Ma
 
       unsigned Align = MFI->getObjectAlignment(i);
       // Adjust to alignment boundary
-      Offset = RoundUpToAlignment(Offset, Align);
+      Offset = RoundUpToAlignment(Offset, Align, Skew);
 
       MFI->setObjectOffset(i, -Offset);        // Set the computed offset
     }
@@ -602,7 +605,7 @@ void PEI::calculateFrameObjectOffsets(Ma
     for (int i = MaxCSFI; i >= MinCSFI ; --i) {
       unsigned Align = MFI->getObjectAlignment(i);
       // Adjust to alignment boundary
-      Offset = RoundUpToAlignment(Offset, Align);
+      Offset = RoundUpToAlignment(Offset, Align, Skew);
 
       MFI->setObjectOffset(i, Offset);
       Offset += MFI->getObjectSize(i);
@@ -624,7 +627,7 @@ void PEI::calculateFrameObjectOffsets(Ma
     RS->getScavengingFrameIndices(SFIs);
     for (SmallVectorImpl<int>::iterator I = SFIs.begin(),
            IE = SFIs.end(); I != IE; ++I)
-      AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign);
+      AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew);
   }
 
   // FIXME: Once this is working, then enable flag will change to a target
@@ -635,7 +638,7 @@ void PEI::calculateFrameObjectOffsets(Ma
     unsigned Align = MFI->getLocalFrameMaxAlign();
 
     // Adjust to alignment boundary.
-    Offset = RoundUpToAlignment(Offset, Align);
+    Offset = RoundUpToAlignment(Offset, Align, Skew);
 
     DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n");
 
@@ -662,7 +665,7 @@ void PEI::calculateFrameObjectOffsets(Ma
     StackObjSet AddrOfObjs;
 
     AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), StackGrowsDown,
-                      Offset, MaxAlign);
+                      Offset, MaxAlign, Skew);
 
     // Assign large stack objects first.
     for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) {
@@ -695,11 +698,11 @@ void PEI::calculateFrameObjectOffsets(Ma
     }
 
     AssignProtectedObjSet(LargeArrayObjs, ProtectedObjs, MFI, StackGrowsDown,
-                          Offset, MaxAlign);
+                          Offset, MaxAlign, Skew);
     AssignProtectedObjSet(SmallArrayObjs, ProtectedObjs, MFI, StackGrowsDown,
-                          Offset, MaxAlign);
+                          Offset, MaxAlign, Skew);
     AssignProtectedObjSet(AddrOfObjs, ProtectedObjs, MFI, StackGrowsDown,
-                          Offset, MaxAlign);
+                          Offset, MaxAlign, Skew);
   }
 
   // Then assign frame offsets to stack objects that are not used to spill
@@ -719,7 +722,7 @@ void PEI::calculateFrameObjectOffsets(Ma
     if (ProtectedObjs.count(i))
       continue;
 
-    AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign);
+    AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew);
   }
 
   // Make sure the special register scavenging spill slot is closest to the
@@ -729,7 +732,7 @@ void PEI::calculateFrameObjectOffsets(Ma
     RS->getScavengingFrameIndices(SFIs);
     for (SmallVectorImpl<int>::iterator I = SFIs.begin(),
            IE = SFIs.end(); I != IE; ++I)
-      AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign);
+      AdjustStackOffset(MFI, *I, StackGrowsDown, Offset, MaxAlign, Skew);
   }
 
   if (!TFI.targetHandlesStackFrameRounding()) {
@@ -754,7 +757,7 @@ void PEI::calculateFrameObjectOffsets(Ma
     // If the frame pointer is eliminated, all frame offsets will be relative to
     // SP not FP. Align to MaxAlign so this works.
     StackAlign = std::max(StackAlign, MaxAlign);
-    Offset = RoundUpToAlignment(Offset, StackAlign);
+    Offset = RoundUpToAlignment(Offset, StackAlign, Skew);
   }
 
   // Update frame info to pretend that this is part of the stack...

Modified: llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetFrameLoweringImpl.cpp Tue Sep 29 17:09:16 2015
@@ -17,6 +17,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/CallingConv.h"
 #include "llvm/IR/Function.h"
 #include "llvm/Target/TargetRegisterInfo.h"
 #include "llvm/Target/TargetSubtargetInfo.h"
@@ -81,3 +82,13 @@ void TargetFrameLowering::determineCalle
       SavedRegs.set(Reg);
   }
 }
+
+unsigned TargetFrameLowering::getStackAlignmentSkew(
+    const MachineFunction &MF) const {
+  // When HHVM function is called, the stack is skewed as the return address
+  // is removed from the stack before we enter the function.
+  if (LLVM_UNLIKELY(MF.getFunction()->getCallingConv() == CallingConv::HHVM))
+    return MF.getTarget().getPointerSize();
+
+  return 0;
+}

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Tue Sep 29 17:09:16 2015
@@ -319,6 +319,8 @@ static void PrintCallingConv(unsigned cc
   case CallingConv::X86_64_Win64:  Out << "x86_64_win64cc"; break;
   case CallingConv::SPIR_FUNC:     Out << "spir_func"; break;
   case CallingConv::SPIR_KERNEL:   Out << "spir_kernel"; break;
+  case CallingConv::HHVM:          Out << "hhvmcc"; break;
+  case CallingConv::HHVM_C:        Out << "hhvm_ccc"; break;
   }
 }
 

Modified: llvm/trunk/lib/Target/X86/X86CallingConv.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CallingConv.td?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86CallingConv.td (original)
+++ llvm/trunk/lib/Target/X86/X86CallingConv.td Tue Sep 29 17:09:16 2015
@@ -202,6 +202,16 @@ def RetCC_X86_64_AnyReg : CallingConv<[
   CCCustom<"CC_X86_AnyReg_Error">
 ]>;
 
+// X86-64 HHVM return-value convention.
+def RetCC_X86_64_HHVM: CallingConv<[
+  // Promote all types to i64
+  CCIfType<[i8, i16, i32], CCPromoteToType<i64>>,
+
+  // Return: could return in any GP register save RSP and R12.
+  CCIfType<[i64], CCAssignToReg<[RBX, RBP, RDI, RSI, RDX, RCX, R8, R9,
+                                 RAX, R10, R11, R13, R14, R15]>>
+]>;
+
 // This is the root return-value convention for the X86-32 backend.
 def RetCC_X86_32 : CallingConv<[
   // If FastCC, use RetCC_X86_32_Fast.
@@ -227,6 +237,9 @@ def RetCC_X86_64 : CallingConv<[
   CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo<RetCC_X86_Win64_C>>,
   CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo<RetCC_X86_64_C>>,
 
+  // Handle HHVM calls.
+  CCIfCC<"CallingConv::HHVM", CCDelegateTo<RetCC_X86_64_HHVM>>,
+
   // Mingw64 and native Win64 use Win64 CC
   CCIfSubtarget<"isTargetWin64()", CCDelegateTo<RetCC_X86_Win64_C>>,
 
@@ -319,6 +332,23 @@ def CC_X86_64_C : CallingConv<[
            CCAssignToStack<64, 64>>
 ]>;
 
+// Calling convention for X86-64 HHVM.
+def CC_X86_64_HHVM : CallingConv<[
+  // Use all/any GP registers for args, except RSP.
+  CCIfType<[i64], CCAssignToReg<[RBX, R12, RBP, R15,
+                                 RDI, RSI, RDX, RCX, R8, R9,
+                                 RAX, R10, R11, R13, R14]>>
+]>;
+
+// Calling convention for helper functions in HHVM.
+def CC_X86_64_HHVM_C : CallingConv<[
+  // Pass the first argument in RBP.
+  CCIfType<[i64], CCAssignToReg<[RBP]>>,
+
+  // Otherwise it's the same as the regular C calling convention.
+  CCDelegateTo<CC_X86_64_C>
+]>;
+
 // Calling convention used on Win64
 def CC_X86_Win64_C : CallingConv<[
   // FIXME: Handle byval stuff.
@@ -734,6 +764,8 @@ def CC_X86_64 : CallingConv<[
   CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo<CC_X86_Win64_C>>,
   CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo<CC_X86_64_C>>,
   CCIfCC<"CallingConv::X86_VectorCall", CCDelegateTo<CC_X86_Win64_VectorCall>>,
+  CCIfCC<"CallingConv::HHVM", CCDelegateTo<CC_X86_64_HHVM>>,
+  CCIfCC<"CallingConv::HHVM_C", CCDelegateTo<CC_X86_64_HHVM_C>>,
 
   // Mingw64 and native Win64 use Win64 CC
   CCIfSubtarget<"isTargetWin64()", CCDelegateTo<CC_X86_Win64_C>>,
@@ -804,3 +836,6 @@ def CSR_64_Intel_OCL_BI_AVX    : CalleeS
 def CSR_64_Intel_OCL_BI_AVX512 : CalleeSavedRegs<(add RBX, RDI, RSI, R14, R15,
                                                   (sequence "ZMM%u", 16, 31),
                                                   K4, K5, K6, K7)>;
+
+// Only R12 is preserved for PHP calls in HHVM.
+def CSR_64_HHVM : CalleeSavedRegs<(add R12)>;

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Sep 29 17:09:16 2015
@@ -2426,7 +2426,7 @@ CreateCopyOfByValArgument(SDValue Src, S
 /// supports tail call optimization.
 static bool IsTailCallConvention(CallingConv::ID CC) {
   return (CC == CallingConv::Fast || CC == CallingConv::GHC ||
-          CC == CallingConv::HiPE);
+          CC == CallingConv::HiPE || CC == CallingConv::HHVM);
 }
 
 /// \brief Return true if the calling convention is a C calling convention.
@@ -3900,6 +3900,10 @@ bool X86::isOffsetSuitableForCodeModel(i
 /// Callee pop is necessary to support tail calls.
 bool X86::isCalleePop(CallingConv::ID CallingConv,
                       bool is64Bit, bool IsVarArg, bool TailCallOpt) {
+
+  if (IsTailCallConvention(CallingConv))
+    return IsVarArg ? false : TailCallOpt;
+
   switch (CallingConv) {
   default:
     return false;
@@ -3907,12 +3911,6 @@ bool X86::isCalleePop(CallingConv::ID Ca
   case CallingConv::X86_FastCall:
   case CallingConv::X86_ThisCall:
     return !is64Bit;
-  case CallingConv::Fast:
-  case CallingConv::GHC:
-  case CallingConv::HiPE:
-    if (IsVarArg)
-      return false;
-    return TailCallOpt;
   }
 }
 

Modified: llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp Tue Sep 29 17:09:16 2015
@@ -256,6 +256,8 @@ X86RegisterInfo::getCalleeSavedRegs(cons
       return CSR_64_Intel_OCL_BI_SaveList;
     break;
   }
+  case CallingConv::HHVM:
+    return CSR_64_HHVM_SaveList;
   case CallingConv::Cold:
     if (Is64Bit)
       return CSR_64_MostRegs_SaveList;
@@ -316,6 +318,8 @@ X86RegisterInfo::getCallPreservedMask(co
       return CSR_64_Intel_OCL_BI_RegMask;
     break;
   }
+  case CallingConv::HHVM:
+    return CSR_64_HHVM_RegMask;
   case CallingConv::Cold:
     if (Is64Bit)
       return CSR_64_MostRegs_RegMask;

Added: llvm/trunk/test/CodeGen/X86/hhvm-cc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/hhvm-cc.ll?rev=248832&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/hhvm-cc.ll (added)
+++ llvm/trunk/test/CodeGen/X86/hhvm-cc.ll Tue Sep 29 17:09:16 2015
@@ -0,0 +1,241 @@
+; RUN: llc < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare hhvmcc i64 @bar(i64, i64, i64) nounwind
+
+; Simply check we can modify %rbx and %rbp before returning via call to bar.
+define hhvmcc i64 @foo(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  foo:
+; CHECK-DAG:    movl $1, %ebx
+; CHECK-DAG:    movl $3, %ebp
+; CHECK:        jmp bar
+  %ret = musttail call hhvmcc i64 @bar(i64 1, i64 %b, i64 3)
+  ret i64 %ret
+}
+
+; Check that we can read and modify %rbx returned from PHP function.
+define hhvmcc i64 @mod_return(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  mod_return:
+; CHECK-NEXT:   {{^#.*}}
+; CHECK-NEXT:   callq bar
+; CHECK-NEXT:   incq %rbx
+  %tmp = call hhvmcc i64 @bar(i64 %a, i64 %b, i64 %c)
+  %retval = add i64 %tmp, 1
+  ret i64 %retval
+}
+
+%rettype = type { i64, i64, i64, i64, i64, i64, i64,
+                  i64, i64, i64, i64, i64, i64, i64
+}
+
+; Check that we can return up to 14 64-bit args in registers.
+define hhvmcc %rettype @return_all(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  return_all:
+; CHECK-DAG:    movl $1, %ebx
+; CHECK-DAG:    movl $2, %ebp
+; CHECK-DAG:    movl $3, %edi
+; CHECK-DAG:    movl $4, %esi
+; CHECK-DAG:    movl $5, %edx
+; CHECK-DAG:    movl $6, %ecx
+; CHECK-DAG:    movl $7, %r8
+; CHECK-DAG:    movl $8, %r9
+; CHECK-DAG:    movl $9, %eax
+; CHECK-DAG:    movl $10, %r10
+; CHECK-DAG:    movl $11, %r11
+; CHECK-DAG:    movl $12, %r13
+; CHECK-DAG:    movl $13, %r14
+; CHECK-DAG:    movl $14, %r15
+; CHECK:        retq
+  %r1 = insertvalue %rettype zeroinitializer, i64 1, 0
+  %r2 = insertvalue %rettype %r1, i64 2, 1
+  %r3 = insertvalue %rettype %r2, i64 3, 2
+  %r4 = insertvalue %rettype %r3, i64 4, 3
+  %r5 = insertvalue %rettype %r4, i64 5, 4
+  %r6 = insertvalue %rettype %r5, i64 6, 5
+  %r7 = insertvalue %rettype %r6, i64 7, 6
+  %r8 = insertvalue %rettype %r7, i64 8, 7
+  %r9 = insertvalue %rettype %r8, i64 9, 8
+  %r10 = insertvalue %rettype %r9, i64 10, 9
+  %r11 = insertvalue %rettype %r10, i64 11, 10
+  %r12 = insertvalue %rettype %r11, i64 12, 11
+  %r13 = insertvalue %rettype %r12, i64 13, 12
+  %r14 = insertvalue %rettype %r13, i64 14, 13
+  ret %rettype %r14
+}
+
+declare hhvmcc void @return_all_tc(i64, i64, i64, i64, i64, i64, i64, i64,
+                                 i64, i64, i64, i64, i64, i64, i64)
+
+; Check that we can return up to 14 64-bit args in registers via tail call.
+define hhvmcc void @test_return_all_tc(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  test_return_all_tc:
+; CHECK-NEXT:   {{^#.*}}
+; CHECK-DAG:    movl $1, %ebx
+; CHECK-DAG:    movl $3, %ebp
+; CHECK-DAG:    movl $4, %r15
+; CHECK-DAG:    movl $5, %edi
+; CHECK-DAG:    movl $6, %esi
+; CHECK-DAG:    movl $7, %edx
+; CHECK-DAG:    movl $8, %ecx
+; CHECK-DAG:    movl $9, %r8
+; CHECK-DAG:    movl $10, %r9
+; CHECK-DAG:    movl $11, %eax
+; CHECK-DAG:    movl $12, %r10
+; CHECK-DAG:    movl $13, %r11
+; CHECK-DAG:    movl $14, %r13
+; CHECK-DAG:    movl $15, %r14
+; CHECK:        jmp  return_all_tc
+  tail call hhvmcc void @return_all_tc(
+    i64 1, i64 %b, i64 3, i64 4, i64 5, i64 6, i64 7,
+    i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15)
+  ret void
+}
+
+declare hhvmcc {i64, i64} @php_short(i64, i64, i64, i64)
+
+define hhvmcc i64 @test_php_short(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  test_php_short:
+; CHECK-NEXT:   {{^#.*}}
+; CHECK-NEXT:   movl $42, %r15
+; CHECK-NEXT:   callq php_short
+; CHECK-NEXT:   leaq (%rbp,%r12), %rbx
+; CHECK-NEXT:   retq
+  %pair = call hhvmcc {i64, i64} @php_short(i64 %a, i64 %b, i64 %c, i64 42)
+  %fp = extractvalue {i64, i64} %pair, 1
+  %rv = add i64 %fp, %b
+  ret i64 %rv
+}
+
+declare hhvmcc %rettype @php_all(i64, i64, i64, i64, i64, i64, i64,
+                                 i64, i64, i64, i64, i64, i64, i64, i64)
+
+; Check that we can pass 15 arguments in registers.
+; Also check that %r12 (2nd arg) is not spilled.
+define hhvmcc i64 @test_php_all(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  test_php_all:
+; CHECK-NEXT:   {{^#.*}}
+; CHECK-NOT:    sub
+; CHECK-NOT:    sub
+; CHECK-DAG:    movl $1, %ebx
+; CHECK-DAG:    movl $3, %ebp
+; CHECK-DAG:    movl $4, %r15
+; CHECK-DAG:    movl $5, %edi
+; CHECK-DAG:    movl $6, %esi
+; CHECK-DAG:    movl $7, %edx
+; CHECK-DAG:    movl $8, %ecx
+; CHECK-DAG:    movl $9, %r8
+; CHECK-DAG:    movl $10, %r9
+; CHECK-DAG:    movl $11, %eax
+; CHECK-DAG:    movl $12, %r10
+; CHECK-DAG:    movl $13, %r11
+; CHECK-DAG:    movl $14, %r13
+; CHECK-DAG:    movl $15, %r14
+; CHECK:        callq php_all
+  %pair = call hhvmcc %rettype @php_all(
+    i64 1, i64 %b, i64 3, i64 4, i64 5, i64 6, i64 7,
+    i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15)
+  %fp = extractvalue %rettype %pair, 1
+  %rv = add i64 %fp, %b
+  ret i64 %rv
+}
+
+declare hhvmcc void @svcreq(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64,
+                             i64, i64)
+
+define hhvmcc void @test_svcreq(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  test_svcreq:
+; CHECK-DAG:    movl $42, %r10
+; CHECK-DAG:    movl $1, %edi
+; CHECK-DAG:    movl $2, %esi
+; CHECK-DAG:    movl $3, %edx
+; CHECK-DAG:    movl $4, %ecx
+; CHECK-DAG:    movl $5, %r8
+; CHECK-DAG:    movl $6, %r9
+; CHECK:        jmp svcreq
+  tail call hhvmcc void @svcreq(i64 %a, i64 %b, i64 %c, i64 undef, i64 1,
+                                i64 2, i64 3, i64 4, i64 5, i64 6, i64 undef,
+                                i64 42)
+  ret void
+}
+
+declare hhvm_ccc void @helper_short(i64, i64, i64, i64, i64, i64, i64)
+
+; Pass all arguments in registers and check that we don't adjust stack
+; for the call.
+define hhvmcc void @test_helper_short(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  test_helper_short:
+; CHECK-NOT:    push
+; CHECK-NOT:    sub
+; CHECK-DAG:    movl $1, %edi
+; CHECK-DAG:    movl $2, %esi
+; CHECK-DAG:    movl $3, %edx
+; CHECK-DAG:    movl $4, %ecx
+; CHECK-DAG:    movl $5, %r8
+; CHECK-DAG:    movl $6, %r9
+; CHECK:        callq helper_short
+  call hhvm_ccc void @helper_short(i64 %c, i64 1, i64 2, i64 3, i64 4,
+                                   i64 5, i64 6)
+  ret void
+}
+
+declare hhvm_ccc void @helper(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64)
+
+define hhvmcc void @test_helper(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  test_helper:
+; CHECK-DAG:    movl $1, %edi
+; CHECK-DAG:    movl $2, %esi
+; CHECK-DAG:    movl $3, %edx
+; CHECK-DAG:    movl $4, %ecx
+; CHECK-DAG:    movl $5, %r8
+; CHECK-DAG:    movl $6, %r9
+; CHECK:        callq helper
+  call hhvm_ccc void @helper(i64 %c, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6,
+                             i64 7, i64 8, i64 9)
+  ret void
+}
+
+; When we enter function with HHVM calling convention, the stack is aligned
+; at 16 bytes. This means we align objects on the stack differently and
+; adjust the stack differently for calls.
+declare hhvm_ccc void @stack_helper(i64, i64, i64)
+declare hhvm_ccc void @stack_helper2(<2 x double>, i64)
+
+define hhvmcc void @test_stack_helper(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  test_stack_helper:
+; CHECK-NOT:    push
+; CHECK:        subq $32, %rsp
+; CHECK:        movaps  16(%rsp), %xmm0
+; CHECK:        callq stack_helper2
+  %t1 = alloca <2 x double>, align 16
+  %t2 = alloca i64, align 8
+  %t3 = alloca i64, align 8
+  %load3 = load i64, i64 *%t3
+  call hhvm_ccc void @stack_helper(i64 %c, i64 %load3, i64 42)
+  %load = load <2 x double>, <2 x double> *%t1
+  %load2 = load i64, i64 *%t2
+  call hhvm_ccc void @stack_helper2(<2 x double> %load, i64 %load2)
+  ret void
+}
+
+; Check that we are not adjusting the stack before calling the helper.
+define hhvmcc void @test_stack_helper2(i64 %a, i64 %b, i64 %c) nounwind {
+entry:
+; CHECK-LABEL:  test_stack_helper2:
+; CHECK-NOT:    push
+; CHECK-NOT:    subq
+  call hhvm_ccc void @stack_helper(i64 %c, i64 7, i64 42)
+  ret void
+}
+

Modified: llvm/trunk/test/Feature/callingconventions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/callingconventions.ll?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/test/Feature/callingconventions.ll (original)
+++ llvm/trunk/test/Feature/callingconventions.ll Tue Sep 29 17:09:16 2015
@@ -59,4 +59,11 @@ define void @ghc_caller() {
   ret void
 }
 
+declare hhvm_ccc void @hhvm_c_callee()
+
+define hhvmcc void @hhvm_caller() {
+  call hhvm_ccc void @hhvm_c_callee()
+  ret void
+}
+
 declare i32 @__gxx_personality_v0(...)

Modified: llvm/trunk/unittests/Support/MathExtrasTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/MathExtrasTest.cpp?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/MathExtrasTest.cpp (original)
+++ llvm/trunk/unittests/Support/MathExtrasTest.cpp Tue Sep 29 17:09:16 2015
@@ -183,6 +183,11 @@ TEST(MathExtras, RoundUpToAlignment) {
   EXPECT_EQ(8u, RoundUpToAlignment(5, 8));
   EXPECT_EQ(24u, RoundUpToAlignment(17, 8));
   EXPECT_EQ(0u, RoundUpToAlignment(~0LL, 8));
+
+  EXPECT_EQ(7u, RoundUpToAlignment(5, 8, 7));
+  EXPECT_EQ(17u, RoundUpToAlignment(17, 8, 1));
+  EXPECT_EQ(3u, RoundUpToAlignment(~0LL, 8, 3));
+  EXPECT_EQ(552u, RoundUpToAlignment(321, 255, 42));
 }
 
 }

Modified: llvm/trunk/utils/vim/syntax/llvm.vim
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/vim/syntax/llvm.vim?rev=248832&r1=248831&r2=248832&view=diff
==============================================================================
--- llvm/trunk/utils/vim/syntax/llvm.vim (original)
+++ llvm/trunk/utils/vim/syntax/llvm.vim Tue Sep 29 17:09:16 2015
@@ -42,10 +42,11 @@ syn keyword llvmKeyword arm_aapcscc arm_
 syn keyword llvmKeyword blockaddress byval c catch cc ccc cleanup coldcc common
 syn keyword llvmKeyword constant datalayout declare default define deplibs
 syn keyword llvmKeyword distinct dllexport dllimport except extern_weak external
-syn keyword llvmKeyword externally_initialized fastcc filter gc global hidden
-syn keyword llvmKeyword initialexec inlinehint inreg intel_ocl_bicc inteldialect
-syn keyword llvmKeyword internal linkonce linkonce_odr localdynamic localexec
-syn keyword llvmKeyword minsize module monotonic msp430_intrcc naked nest
+syn keyword llvmKeyword externally_initialized fastcc filter gc global hhvmcc
+syn keyword llvmKeyword hhvm_ccc hidden initialexec inlinehint inreg
+syn keyword llvmKeyword intel_ocl_bicc inteldialect internal linkonce
+syn keyword llvmKeyword linkonce_odr localdynamic localexec minsize module
+syn keyword llvmKeyword monotonic msp430_intrcc musttail naked nest
 syn keyword llvmKeyword noalias nocapture noimplicitfloat noinline nonlazybind
 syn keyword llvmKeyword noredzone noreturn nounwind optnone optsize personality
 syn keyword llvmKeyword private protected ptx_device ptx_kernel readnone




More information about the llvm-commits mailing list