<HTML><HEAD>
<META content="text/html; charset=utf-8" http-equiv=Content-Type></HEAD>
<BODY>
<DIV>
<DIV style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif">If I recall correctly from the code review, he has a test which does that as well. The debug-only test is just extra goodness that checks whats going on under the hood.<BR><BR>James</DIV></DIV>
<DIV dir=ltr>
<HR>
<SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif; FONT-WEIGHT: bold">From: </SPAN><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif"><A href="mailto:echristo@gmail.com">Eric Christopher</A></SPAN><BR><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif; FONT-WEIGHT: bold">Sent: </SPAN><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif">‎09/‎05/‎2014 21:12</SPAN><BR><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif; FONT-WEIGHT: bold">To: </SPAN><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif"><A href="mailto:dblaikie@gmail.com">David Blaikie</A></SPAN><BR><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif; FONT-WEIGHT: bold">Cc: </SPAN><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif"><A href="mailto:james@jamesmolloy.co.uk">James Molloy</A>; <A href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits</A></SPAN><BR><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif; FONT-WEIGHT: bold">Subject: </SPAN><SPAN style="FONT-SIZE: 11pt; FONT-FAMILY: Calibri,sans-serif">Re: [llvm] r208413 - ARM: HFAs must be passed in consecutiveregisters</SPAN><BR><BR></DIV>On Fri, May 9, 2014 at 10:25 AM, David Blaikie <dblaikie@gmail.com> wrote:<BR>> On Fri, May 9, 2014 at 9:29 AM, James Molloy <james@jamesmolloy.co.uk> wrote:<BR>>> Hi,<BR>>><BR>>> I've fixed the test to only run with an asserts build - builds should now be<BR>>> green again.<BR>><BR>> Why does this test require asserts?<BR>><BR><BR>He's checking debug output in the build.<BR><BR>I don't think this is the right test though. Better would be to check<BR>the actual allocation that goes on.<BR><BR>-eric<BR><BR>>><BR>>> Cheers,<BR>>><BR>>> James<BR>>><BR>>><BR>>> On 9 May 2014 17:12, Alexander Kornienko <alexfh@google.com> wrote:<BR>>>><BR>>>> This breaks our builds as well. Please fix or revert.<BR>>>><BR>>>><BR>>>><BR>>>> On Fri, May 9, 2014 at 6:05 PM, Aaron Ballman <aaron@aaronballman.com><BR>>>> wrote:<BR>>>>><BR>>>>> FYI: This appears to have broken at least one of the bots:<BR>>>>><BR>>>>> http://bb.pgr.jp/builders/cmake-llvm-x86_64-linux/builds/12820<BR>>>>><BR>>>>> ~Aaron<BR>>>>><BR>>>>> On Fri, May 9, 2014 at 10:01 AM, Oliver Stannard<BR>>>>> <oliver.stannard@arm.com> wrote:<BR>>>>> > Author: olista01<BR>>>>> > Date: Fri May  9 09:01:47 2014<BR>>>>> > New Revision: 208413<BR>>>>> ><BR>>>>> > URL: http://llvm.org/viewvc/llvm-project?rev=208413&view=rev<BR>>>>> > Log:<BR>>>>> > ARM: HFAs must be passed in consecutive registers<BR>>>>> ><BR>>>>> > When using the ARM AAPCS, HFAs (Homogeneous Floating-point Aggregates)<BR>>>>> > must<BR>>>>> > be passed in a block of consecutive floating-point registers, or on the<BR>>>>> > stack.<BR>>>>> > This means that unused floating-point registers cannot be back-filled<BR>>>>> > with<BR>>>>> > part of an HFA, however this can currently happen. This patch, along<BR>>>>> > with the<BR>>>>> > corresponding clang patch (http://reviews.llvm.org/D3083) prevents<BR>>>>> > this.<BR>>>>> ><BR>>>>> ><BR>>>>> > Added:<BR>>>>> >     llvm/trunk/test/CodeGen/ARM/aapcs-hfa.ll<BR>>>>> >     llvm/trunk/test/CodeGen/ARM/hfa-in-contiguous-registers.ll<BR>>>>> > Modified:<BR>>>>> >     llvm/trunk/include/llvm/CodeGen/CallingConvLower.h<BR>>>>> >     llvm/trunk/include/llvm/Target/TargetCallingConv.h<BR>>>>> >     llvm/trunk/include/llvm/Target/TargetCallingConv.td<BR>>>>> >     llvm/trunk/include/llvm/Target/TargetLowering.h<BR>>>>> >     llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<BR>>>>> >     llvm/trunk/lib/Target/ARM/ARMCallingConv.h<BR>>>>> >     llvm/trunk/lib/Target/ARM/ARMCallingConv.td<BR>>>>> >     llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp<BR>>>>> >     llvm/trunk/lib/Target/ARM/ARMISelLowering.h<BR>>>>> ><BR>>>>> > Modified: llvm/trunk/include/llvm/CodeGen/CallingConvLower.h<BR>>>>> > URL:<BR>>>>> > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CallingConvLower.h?rev=208413&r1=208412&r2=208413&view=diff<BR>>>>> ><BR>>>>> > ==============================================================================<BR>>>>> > --- llvm/trunk/include/llvm/CodeGen/CallingConvLower.h (original)<BR>>>>> > +++ llvm/trunk/include/llvm/CodeGen/CallingConvLower.h Fri May  9<BR>>>>> > 09:01:47 2014<BR>>>>> > @@ -112,6 +112,23 @@ public:<BR>>>>> >      return Ret;<BR>>>>> >    }<BR>>>>> ><BR>>>>> > +  // There is no need to differentiate between a pending CCValAssign<BR>>>>> > and other<BR>>>>> > +  // kinds, as they are stored in a different list.<BR>>>>> > +  static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT,<BR>>>>> > +                                LocInfo HTP) {<BR>>>>> > +    return getReg(ValNo, ValVT, 0, LocVT, HTP);<BR>>>>> > +  }<BR>>>>> > +<BR>>>>> > +  void convertToReg(unsigned RegNo) {<BR>>>>> > +    Loc = RegNo;<BR>>>>> > +    isMem = false;<BR>>>>> > +  }<BR>>>>> > +<BR>>>>> > +  void convertToMem(unsigned Offset) {<BR>>>>> > +    Loc = Offset;<BR>>>>> > +    isMem = true;<BR>>>>> > +  }<BR>>>>> > +<BR>>>>> >    unsigned getValNo() const { return ValNo; }<BR>>>>> >    MVT getValVT() const { return ValVT; }<BR>>>>> ><BR>>>>> > @@ -164,6 +181,7 @@ private:<BR>>>>> ><BR>>>>> >    unsigned StackOffset;<BR>>>>> >    SmallVector<uint32_t, 16> UsedRegs;<BR>>>>> > +  SmallVector<CCValAssign, 4> PendingLocs;<BR>>>>> ><BR>>>>> >    // ByValInfo and SmallVector<ByValInfo, 4> ByValRegs:<BR>>>>> >    //<BR>>>>> > @@ -317,6 +335,31 @@ public:<BR>>>>> >      return Reg;<BR>>>>> >    }<BR>>>>> ><BR>>>>> > +  /// AllocateRegBlock - Attempt to allocate a block of RegsRequired<BR>>>>> > consecutive<BR>>>>> > +  /// registers. If this is not possible, return zero. Otherwise,<BR>>>>> > return the first<BR>>>>> > +  /// register of the block that were allocated, marking the entire<BR>>>>> > block as allocated.<BR>>>>> > +  unsigned AllocateRegBlock(const uint16_t *Regs, unsigned NumRegs,<BR>>>>> > unsigned RegsRequired) {<BR>>>>> > +    for (unsigned StartIdx = 0; StartIdx <= NumRegs - RegsRequired;<BR>>>>> > ++StartIdx) {<BR>>>>> > +      bool BlockAvailable = true;<BR>>>>> > +      // Check for already-allocated regs in this block<BR>>>>> > +      for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx)<BR>>>>> > {<BR>>>>> > +        if (isAllocated(Regs[StartIdx + BlockIdx])) {<BR>>>>> > +          BlockAvailable = false;<BR>>>>> > +          break;<BR>>>>> > +        }<BR>>>>> > +      }<BR>>>>> > +      if (BlockAvailable) {<BR>>>>> > +        // Mark the entire block as allocated<BR>>>>> > +        for (unsigned BlockIdx = 0; BlockIdx < RegsRequired;<BR>>>>> > ++BlockIdx) {<BR>>>>> > +          MarkAllocated(Regs[StartIdx + BlockIdx]);<BR>>>>> > +        }<BR>>>>> > +        return Regs[StartIdx];<BR>>>>> > +      }<BR>>>>> > +    }<BR>>>>> > +    // No block was available<BR>>>>> > +    return 0;<BR>>>>> > +  }<BR>>>>> > +<BR>>>>> >    /// Version of AllocateReg with list of registers to be shadowed.<BR>>>>> >    unsigned AllocateReg(const MCPhysReg *Regs, const MCPhysReg<BR>>>>> > *ShadowRegs,<BR>>>>> >                         unsigned NumRegs) {<BR>>>>> > @@ -411,6 +454,11 @@ public:<BR>>>>> ><BR>>>>> >    ParmContext getCallOrPrologue() const { return CallOrPrologue; }<BR>>>>> ><BR>>>>> > +  // Get list of pending assignments<BR>>>>> > +  SmallVectorImpl<llvm::CCValAssign> &getPendingLocs() {<BR>>>>> > +    return PendingLocs;<BR>>>>> > +  }<BR>>>>> > +<BR>>>>> >  private:<BR>>>>> >    /// MarkAllocated - Mark a register and all of its aliases as<BR>>>>> > allocated.<BR>>>>> >    void MarkAllocated(unsigned Reg);<BR>>>>> ><BR>>>>> > Modified: llvm/trunk/include/llvm/Target/TargetCallingConv.h<BR>>>>> > URL:<BR>>>>> > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetCallingConv.h?rev=208413&r1=208412&r2=208413&view=diff<BR>>>>> ><BR>>>>> > ==============================================================================<BR>>>>> > --- llvm/trunk/include/llvm/Target/TargetCallingConv.h (original)<BR>>>>> > +++ llvm/trunk/include/llvm/Target/TargetCallingConv.h Fri May  9<BR>>>>> > 09:01:47 2014<BR>>>>> > @@ -47,8 +47,12 @@ namespace ISD {<BR>>>>> >      static const uint64_t InAllocaOffs   = 12;<BR>>>>> >      static const uint64_t OrigAlign      = 0x1FULL<<27;<BR>>>>> >      static const uint64_t OrigAlignOffs  = 27;<BR>>>>> > -    static const uint64_t ByValSize      = 0xffffffffULL<<32; ///<<BR>>>>> > Struct size<BR>>>>> > +    static const uint64_t ByValSize      = 0x3fffffffULL<<32; ///<<BR>>>>> > Struct size<BR>>>>> >      static const uint64_t ByValSizeOffs  = 32;<BR>>>>> > +    static const uint64_t InConsecutiveRegsLast      = 0x1ULL<<62;<BR>>>>> > ///< Struct size<BR>>>>> > +    static const uint64_t InConsecutiveRegsLastOffs  = 62;<BR>>>>> > +    static const uint64_t InConsecutiveRegs      = 0x1ULL<<63; ///<<BR>>>>> > Struct size<BR>>>>> > +    static const uint64_t InConsecutiveRegsOffs  = 63;<BR>>>>> ><BR>>>>> >      static const uint64_t One            = 1ULL; ///< 1 of this type,<BR>>>>> > for shifts<BR>>>>> ><BR>>>>> > @@ -80,6 +84,12 @@ namespace ISD {<BR>>>>> >      bool isReturned()  const { return Flags & Returned; }<BR>>>>> >      void setReturned() { Flags |= One << ReturnedOffs; }<BR>>>>> ><BR>>>>> > +    bool isInConsecutiveRegs()  const { return Flags &<BR>>>>> > InConsecutiveRegs; }<BR>>>>> > +    void setInConsecutiveRegs() { Flags |= One <<<BR>>>>> > InConsecutiveRegsOffs; }<BR>>>>> > +<BR>>>>> > +    bool isInConsecutiveRegsLast()  const { return Flags &<BR>>>>> > InConsecutiveRegsLast; }<BR>>>>> > +    void setInConsecutiveRegsLast() { Flags |= One <<<BR>>>>> > InConsecutiveRegsLastOffs; }<BR>>>>> > +<BR>>>>> >      unsigned getByValAlign() const {<BR>>>>> >        return (unsigned)<BR>>>>> >          ((One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2);<BR>>>>> ><BR>>>>> > Modified: llvm/trunk/include/llvm/Target/TargetCallingConv.td<BR>>>>> > URL:<BR>>>>> > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetCallingConv.td?rev=208413&r1=208412&r2=208413&view=diff<BR>>>>> ><BR>>>>> > ==============================================================================<BR>>>>> > --- llvm/trunk/include/llvm/Target/TargetCallingConv.td (original)<BR>>>>> > +++ llvm/trunk/include/llvm/Target/TargetCallingConv.td Fri May  9<BR>>>>> > 09:01:47 2014<BR>>>>> > @@ -42,6 +42,11 @@ class CCIf<string predicate, CCAction A><BR>>>>> >  class CCIfByVal<CCAction A> : CCIf<"ArgFlags.isByVal()", A> {<BR>>>>> >  }<BR>>>>> ><BR>>>>> > +/// CCIfConsecutiveRegs - If the current argument has<BR>>>>> > InConsecutiveRegs<BR>>>>> > +/// parameter attribute, apply Action A.<BR>>>>> > +class CCIfConsecutiveRegs<CCAction A> :<BR>>>>> > CCIf<"ArgFlags.isInConsecutiveRegs()", A> {<BR>>>>> > +}<BR>>>>> > +<BR>>>>> >  /// CCIfCC - Match if the current calling convention is 'CC'.<BR>>>>> >  class CCIfCC<string CC, CCAction A><BR>>>>> >    : CCIf<!strconcat("State.getCallingConv() == ", CC), A> {}<BR>>>>> ><BR>>>>> > Modified: llvm/trunk/include/llvm/Target/TargetLowering.h<BR>>>>> > URL:<BR>>>>> > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=208413&r1=208412&r2=208413&view=diff<BR>>>>> ><BR>>>>> > ==============================================================================<BR>>>>> > --- llvm/trunk/include/llvm/Target/TargetLowering.h (original)<BR>>>>> > +++ llvm/trunk/include/llvm/Target/TargetLowering.h Fri May  9 09:01:47<BR>>>>> > 2014<BR>>>>> > @@ -2233,6 +2233,15 @@ public:<BR>>>>> >      return VT.bitsLT(MinVT) ? MinVT : VT;<BR>>>>> >    }<BR>>>>> ><BR>>>>> > +  /// For some targets, an LLVM struct type must be broken down into<BR>>>>> > multiple<BR>>>>> > +  /// simple types, but the calling convention specifies that the<BR>>>>> > entire struct<BR>>>>> > +  /// must be passed in a block of consecutive registers.<BR>>>>> > +  virtual bool<BR>>>>> > +  functionArgumentNeedsConsecutiveRegisters(Type *Ty, CallingConv::ID<BR>>>>> > CallConv,<BR>>>>> > +                                            bool isVarArg) const {<BR>>>>> > +    return false;<BR>>>>> > +  }<BR>>>>> > +<BR>>>>> >    /// Returns a 0 terminated array of registers that can be safely<BR>>>>> > used as<BR>>>>> >    /// scratch registers.<BR>>>>> >    virtual const MCPhysReg *getScratchRegisters(CallingConv::ID CC)<BR>>>>> > const {<BR>>>>> ><BR>>>>> > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<BR>>>>> > URL:<BR>>>>> > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=208413&r1=208412&r2=208413&view=diff<BR>>>>> ><BR>>>>> > ==============================================================================<BR>>>>> > --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<BR>>>>> > (original)<BR>>>>> > +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Fri May<BR>>>>> > 9 09:01:47 2014<BR>>>>> > @@ -7128,8 +7128,13 @@ TargetLowering::LowerCallTo(TargetLoweri<BR>>>>> >    for (unsigned i = 0, e = Args.size(); i != e; ++i) {<BR>>>>> >      SmallVector<EVT, 4> ValueVTs;<BR>>>>> >      ComputeValueVTs(*this, Args[i].Ty, ValueVTs);<BR>>>>> > -    for (unsigned Value = 0, NumValues = ValueVTs.size();<BR>>>>> > -         Value != NumValues; ++Value) {<BR>>>>> > +    Type *FinalType = Args[i].Ty;<BR>>>>> > +    if (Args[i].isByVal)<BR>>>>> > +      FinalType = cast<PointerType>(Args[i].Ty)->getElementType();<BR>>>>> > +    bool NeedsRegBlock = functionArgumentNeedsConsecutiveRegisters(<BR>>>>> > +        FinalType, CLI.CallConv, CLI.IsVarArg);<BR>>>>> > +    for (unsigned Value = 0, NumValues = ValueVTs.size(); Value !=<BR>>>>> > NumValues;<BR>>>>> > +         ++Value) {<BR>>>>> >        EVT VT = ValueVTs[Value];<BR>>>>> >        Type *ArgTy = VT.getTypeForEVT(CLI.RetTy->getContext());<BR>>>>> >        SDValue Op = SDValue(Args[i].Node.getNode(),<BR>>>>> > @@ -7171,6 +7176,11 @@ TargetLowering::LowerCallTo(TargetLoweri<BR>>>>> >        }<BR>>>>> >        if (Args[i].isNest)<BR>>>>> >          Flags.setNest();<BR>>>>> > +      if (NeedsRegBlock) {<BR>>>>> > +        Flags.setInConsecutiveRegs();<BR>>>>> > +        if (Value == NumValues - 1)<BR>>>>> > +          Flags.setInConsecutiveRegsLast();<BR>>>>> > +      }<BR>>>>> >        Flags.setOrigAlign(OriginalAlignment);<BR>>>>> ><BR>>>>> >        MVT PartVT = getRegisterType(CLI.RetTy->getContext(), VT);<BR>>>>> > @@ -7356,6 +7366,11 @@ void SelectionDAGISel::LowerArguments(co<BR>>>>> >      ComputeValueVTs(*TLI, I->getType(), ValueVTs);<BR>>>>> >      bool isArgValueUsed = !I->use_empty();<BR>>>>> >      unsigned PartBase = 0;<BR>>>>> > +    Type *FinalType = I->getType();<BR>>>>> > +    if (F.getAttributes().hasAttribute(Idx, Attribute::ByVal))<BR>>>>> > +      FinalType = cast<PointerType>(FinalType)->getElementType();<BR>>>>> > +    bool NeedsRegBlock =<BR>>>>> > TLI->functionArgumentNeedsConsecutiveRegisters(<BR>>>>> > +        FinalType, F.getCallingConv(), F.isVarArg());<BR>>>>> >      for (unsigned Value = 0, NumValues = ValueVTs.size();<BR>>>>> >           Value != NumValues; ++Value) {<BR>>>>> >        EVT VT = ValueVTs[Value];<BR>>>>> > @@ -7397,6 +7412,11 @@ void SelectionDAGISel::LowerArguments(co<BR>>>>> >        }<BR>>>>> >        if (F.getAttributes().hasAttribute(Idx, Attribute::Nest))<BR>>>>> >          Flags.setNest();<BR>>>>> > +      if (NeedsRegBlock) {<BR>>>>> > +        Flags.setInConsecutiveRegs();<BR>>>>> > +        if (Value == NumValues - 1)<BR>>>>> > +          Flags.setInConsecutiveRegsLast();<BR>>>>> > +      }<BR>>>>> >        Flags.setOrigAlign(OriginalAlignment);<BR>>>>> ><BR>>>>> >        MVT RegisterVT = TLI->getRegisterType(*CurDAG->getContext(),<BR>>>>> > VT);<BR>>>>> ><BR>>>>> > Modified: llvm/trunk/lib/Target/ARM/ARMCallingConv.h<BR>>>>> > URL:<BR>>>>> > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCallingConv.h?rev=208413&r1=208412&r2=208413&view=diff<BR>>>>> ><BR>>>>> > ==============================================================================<BR>>>>> > --- llvm/trunk/lib/Target/ARM/ARMCallingConv.h (original)<BR>>>>> > +++ llvm/trunk/lib/Target/ARM/ARMCallingConv.h Fri May  9 09:01:47 2014<BR>>>>> > @@ -160,6 +160,96 @@ static bool RetCC_ARM_AAPCS_Custom_f64(u<BR>>>>> >                                     State);<BR>>>>> >  }<BR>>>>> ><BR>>>>> > +static const uint16_t SRegList[] = { ARM::S0,  ARM::S1,  ARM::S2,<BR>>>>> > ARM::S3,<BR>>>>> > +                                     ARM::S4,  ARM::S5,  ARM::S6,<BR>>>>> > ARM::S7,<BR>>>>> > +                                     ARM::S8,  ARM::S9,  ARM::S10,<BR>>>>> > ARM::S11,<BR>>>>> > +                                     ARM::S12, ARM::S13, ARM::S14,<BR>>>>> > ARM::S15 };<BR>>>>> > +static const uint16_t DRegList[] = { ARM::D0, ARM::D1, ARM::D2,<BR>>>>> > ARM::D3,<BR>>>>> > +                                     ARM::D4, ARM::D5, ARM::D6,<BR>>>>> > ARM::D7 };<BR>>>>> > +static const uint16_t QRegList[] = { ARM::Q0, ARM::Q1, ARM::Q2,<BR>>>>> > ARM::Q3 };<BR>>>>> > +<BR>>>>> > +// Allocate part of an AAPCS HFA or HVA. We assume that each member of<BR>>>>> > the HA<BR>>>>> > +// has InConsecutiveRegs set, and that the last member also has<BR>>>>> > +// InConsecutiveRegsLast set. We must process all members of the HA<BR>>>>> > before<BR>>>>> > +// we can allocate it, as we need to know the total number of<BR>>>>> > registers that<BR>>>>> > +// will be needed in order to (attempt to) allocate a contiguous<BR>>>>> > block.<BR>>>>> > +static bool CC_ARM_AAPCS_Custom_HA(unsigned &ValNo, MVT &ValVT, MVT<BR>>>>> > &LocVT,<BR>>>>> > +                                   CCValAssign::LocInfo &LocInfo,<BR>>>>> > +                                   ISD::ArgFlagsTy &ArgFlags, CCState<BR>>>>> > &State) {<BR>>>>> > +  SmallVectorImpl<CCValAssign> &PendingHAMembers =<BR>>>>> > State.getPendingLocs();<BR>>>>> > +<BR>>>>> > +  // AAPCS HFAs must have 1-4 elements, all of the same type<BR>>>>> > +  assert(PendingHAMembers.size() < 4);<BR>>>>> > +  if (PendingHAMembers.size() > 0)<BR>>>>> > +    assert(PendingHAMembers[0].getLocVT() == LocVT);<BR>>>>> > +<BR>>>>> > +  // Add the argument to the list to be allocated once we know the<BR>>>>> > size of the<BR>>>>> > +  // HA<BR>>>>> > +  PendingHAMembers.push_back(<BR>>>>> > +      CCValAssign::getPending(ValNo, ValVT, LocVT, LocInfo));<BR>>>>> > +<BR>>>>> > +  if (ArgFlags.isInConsecutiveRegsLast()) {<BR>>>>> > +    assert(PendingHAMembers.size() > 0 && PendingHAMembers.size() <= 4<BR>>>>> > &&<BR>>>>> > +           "Homogeneous aggregates must have between 1 and 4<BR>>>>> > members");<BR>>>>> > +<BR>>>>> > +    // Try to allocate a contiguous block of registers, each of the<BR>>>>> > correct<BR>>>>> > +    // size to hold one member.<BR>>>>> > +    const uint16_t *RegList;<BR>>>>> > +    unsigned NumRegs;<BR>>>>> > +    switch (LocVT.SimpleTy) {<BR>>>>> > +    case MVT::f32:<BR>>>>> > +      RegList = SRegList;<BR>>>>> > +      NumRegs = 16;<BR>>>>> > +      break;<BR>>>>> > +    case MVT::f64:<BR>>>>> > +      RegList = DRegList;<BR>>>>> > +      NumRegs = 8;<BR>>>>> > +      break;<BR>>>>> > +    case MVT::v2f64:<BR>>>>> > +      RegList = QRegList;<BR>>>>> > +      NumRegs = 4;<BR>>>>> > +      break;<BR>>>>> > +    default:<BR>>>>> > +      llvm_unreachable("Unexpected member type for HA");<BR>>>>> > +      break;<BR>>>>> > +    }<BR>>>>> > +<BR>>>>> > +    unsigned RegResult =<BR>>>>> > +        State.AllocateRegBlock(RegList, NumRegs,<BR>>>>> > PendingHAMembers.size());<BR>>>>> > +<BR>>>>> > +    if (RegResult) {<BR>>>>> > +      for (SmallVectorImpl<CCValAssign>::iterator It =<BR>>>>> > PendingHAMembers.begin();<BR>>>>> > +           It != PendingHAMembers.end(); ++It) {<BR>>>>> > +        It->convertToReg(RegResult);<BR>>>>> > +        State.addLoc(*It);<BR>>>>> > +        ++RegResult;<BR>>>>> > +      }<BR>>>>> > +      PendingHAMembers.clear();<BR>>>>> > +      return true;<BR>>>>> > +    }<BR>>>>> > +<BR>>>>> > +    // Register allocation failed, fall back to the stack<BR>>>>> > +<BR>>>>> > +    // Mark all VFP regs as unavailable (AAPCS rule C.2.vfp)<BR>>>>> > +    for (unsigned regNo = 0; regNo < 16; ++regNo)<BR>>>>> > +      State.AllocateReg(SRegList[regNo]);<BR>>>>> > +<BR>>>>> > +    unsigned Size = LocVT.getSizeInBits() / 8;<BR>>>>> > +    unsigned Align = LocVT.SimpleTy == MVT::v2f64 ? 8 : Size;<BR>>>>> > +<BR>>>>> > +    for (auto It : PendingHAMembers) {<BR>>>>> > +      It.convertToMem(State.AllocateStack(Size, Align));<BR>>>>> > +      State.addLoc(It);<BR>>>>> > +    }<BR>>>>> > +<BR>>>>> > +    // All pending members have now been allocated<BR>>>>> > +    PendingHAMembers.clear();<BR>>>>> > +  }<BR>>>>> > +<BR>>>>> > +  // This will be allocated by the last member of the HA<BR>>>>> > +  return true;<BR>>>>> > +}<BR>>>>> > +<BR>>>>> >  } // End llvm namespace<BR>>>>> ><BR>>>>> >  #endif<BR>>>>> ><BR>>>>> > Modified: llvm/trunk/lib/Target/ARM/ARMCallingConv.td<BR>>>>> > URL:<BR>>>>> > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCallingConv.td?rev=208413&r1=208412&r2=208413&view=diff<BR>>>>> ><BR>>>>> > ==============================================================================<BR>>>>> > --- llvm/trunk/lib/Target/ARM/ARMCallingConv.td (original)<BR>>>>> > +++ llvm/trunk/lib/Target/ARM/ARMCallingConv.td Fri May  9 09:01:47<BR>>>>> > 2014<BR>>>>> > @@ -174,6 +174,9 @@ def CC_ARM_AAPCS_VFP : CallingConv<[<BR>>>>> >    CCIfType<[v1i64, v2i32, v4i16, v8i8, v2f32],<BR>>>>> > CCBitConvertToType<f64>>,<BR>>>>> >    CCIfType<[v2i64, v4i32, v8i16, v16i8, v4f32],<BR>>>>> > CCBitConvertToType<v2f64>>,<BR>>>>> ><BR>>>>> > +  // HFAs are passed in a contiguous block of registers, or on the<BR>>>>> > stack<BR>>>>> > +  CCIfConsecutiveRegs<CCCustom<"CC_ARM_AAPCS_Custom_HA">>,<BR>>>>> > +<BR>>>>> >    CCIfType<[v2f64], CCAssignToReg<[Q0, Q1, Q2, Q3]>>,<BR>>>>> >    CCIfType<[f64], CCAssignToReg<[D0, D1, D2, D3, D4, D5, D6, D7]>>,<BR>>>>> >    CCIfType<[f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7, S8,<BR>>>>> ><BR>>>>> > Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp<BR>>>>> > URL:<BR>>>>> > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=208413&r1=208412&r2=208413&view=diff<BR>>>>> ><BR>>>>> > ==============================================================================<BR>>>>> > --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)<BR>>>>> > +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri May  9 09:01:47<BR>>>>> > 2014<BR>>>>> > @@ -43,6 +43,7 @@<BR>>>>> >  #include "llvm/IR/Type.h"<BR>>>>> >  #include "llvm/MC/MCSectionMachO.h"<BR>>>>> >  #include "llvm/Support/<BR><BR>
<DIV>[The entire original message is not included.]</DIV></BODY></HTML>