[llvm-commits] [llvm] r169791 - in /llvm/trunk: include/llvm/Target/ lib/CodeGen/SelectionDAG/ lib/Target/ARM/ lib/Target/Mips/ lib/Target/X86/ test/CodeGen/ARM/ test/CodeGen/X86/

Evan Cheng evan.cheng at apple.com
Wed Dec 12 12:44:33 PST 2012


r170018

Evan

On Dec 12, 2012, at 12:04 PM, Evan Cheng <evan.cheng at apple.com> wrote:

> I'm taking a look.
> 
> Evan
> 
> On Dec 12, 2012, at 11:58 AM, Akira Hatanaka <ahatanak at gmail.com> wrote:
> 
>> Evan,
>> 
>> I am seeing an assert when I compile a program with llc (the test program, strcat.llvm.mips64el.ll is attached to this email):
>> 
>> $ llc -march=mips64el -mcpu=mips64r2 -mattr=n64   -disable-mips-delay-filler -filetype=asm -relocation-model=pic    -asm-verbose=false -O3  Output/strcat.llvm.mips64el.ll -o Output/strcat.llc.mips64r2.s
>> 
>> llc: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:3588: llvm::SDValue getMemcpyLoadsAndStores(llvm::SelectionDAG&, llvm::DebugLoc, llvm::SDValue, llvm::SDValue, llvm::SDValue, uint64_t, unsigned int, bool, bool, llvm::MachinePointerInfo, llvm::MachinePointerInfo): Assertion `i == NumMemOps-1 && i != 0' failed.
>> 
>> The memcpy instruction which is causing assert copies an array of 7 chars to an i8 address.
>> 
>> (gdb) p I.dump()
>>   tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %endptr, i8* getelementptr inbounds ([7 x i8]* @.str2, i64 0, i64 0), i64 7, i32 1, i1 false)
>> 
>> I am not familiar with the pieces you touched in this commit, but llc terminates normally if I force the code to execute the else clause here by setting Flag=0 inside MipsTargetLowering::allowsUnalignedMemoryAccesses:
>> 
>> SelectionDAG.cpp:3510
>> 
>> +      // If the new VT cannot cover all of the remaining bits, then consider
>> +      // issuing a (or a pair of) unaligned and overlapping load / store.
>> +      // FIXME: Only does this for 64-bit or more since we don't have proper
>> +      // cost model for unaligned load / store.
>> +      bool Fast;
>> +      if (AllowOverlap && VTSize >= 8 && NewVTSize < Size &&
>> +          TLI.allowsUnalignedMemoryAccesses(VT, &Fast) && Fast)
>> +        VTSize = Size;
>> +      else {
>> +        VT = NewVT;
>> +        VTSize = NewVTSize;       
>> 
>> I think overlapping shouldn't be allowed here when the the source size (7B) is smaller than the load size (8B). 
>> 
>> Do you have any idea how this can be fixed?
>> 
>> On Mon, Dec 10, 2012 at 3:21 PM, Evan Cheng <evan.cheng at apple.com> wrote:
>> Author: evancheng
>> Date: Mon Dec 10 17:21:26 2012
>> New Revision: 169791
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=169791&view=rev
>> Log:
>> Some enhancements for memcpy / memset inline expansion.
>> 1. Teach it to use overlapping unaligned load / store to copy / set the trailing
>>    bytes. e.g. On 86, use two pairs of movups / movaps for 17 - 31 byte copies.
>> 2. Use f64 for memcpy / memset on targets where i64 is not legal but f64 is. e.g.
>>    x86 and ARM.
>> 3. When memcpy from a constant string, do *not* replace the load with a constant
>>    if it's not possible to materialize an integer immediate with a single
>>    instruction (required a new target hook: TLI.isIntImmLegal()).
>> 4. Use unaligned load / stores more aggressively if target hooks indicates they
>>    are "fast".
>> 5. Update ARM target hooks to use unaligned load / stores. e.g. vld1.8 / vst1.8.
>>    Also increase the threshold to something reasonable (8 for memset, 4 pairs
>>    for memcpy).
>> 
>> This significantly improves Dhrystone, up to 50% on ARM iOS devices.
>> 
>> rdar://12760078
>> 
>> Added:
>>     llvm/trunk/test/CodeGen/ARM/memset-inline.ll
>> Removed:
>>     llvm/trunk/test/CodeGen/ARM/reg_asc_order.ll
>> Modified:
>>     llvm/trunk/include/llvm/Target/TargetLowering.h
>>     llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
>>     llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>>     llvm/trunk/lib/Target/ARM/ARMISelLowering.h
>>     llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
>>     llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
>>     llvm/trunk/lib/Target/Mips/MipsISelLowering.h
>>     llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>>     llvm/trunk/lib/Target/X86/X86ISelLowering.h
>>     llvm/trunk/test/CodeGen/ARM/2011-10-26-memset-with-neon.ll
>>     llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll
>>     llvm/trunk/test/CodeGen/X86/2009-11-16-UnfoldMemOpBug.ll
>>     llvm/trunk/test/CodeGen/X86/memcpy-2.ll
>> 
>> Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
>> +++ llvm/trunk/include/llvm/Target/TargetLowering.h Mon Dec 10 17:21:26 2012
>> @@ -371,6 +371,16 @@
>>      return false;
>>    }
>> 
>> +  /// isIntImmLegal - Returns true if the target can instruction select the
>> +  /// specified integer immediate natively (that is, it's materialized with one
>> +  /// instruction). The current *assumption* in isel is all of integer
>> +  /// immediates are "legal" and only the memcpy / memset expansion code is
>> +  /// making use of this. The rest of isel doesn't have proper cost model for
>> +  /// immediate materialization.
>> +  virtual bool isIntImmLegal(const APInt &/*Imm*/, EVT /*VT*/) const {
>> +    return true;
>> +  }
>> +
>>    /// isShuffleMaskLegal - Targets can use this to indicate that they only
>>    /// support *some* VECTOR_SHUFFLE operations, those with specific masks.
>>    /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values
>> @@ -678,12 +688,14 @@
>>    }
>> 
>>    /// This function returns true if the target allows unaligned memory accesses.
>> -  /// of the specified type. This is used, for example, in situations where an
>> -  /// array copy/move/set is  converted to a sequence of store operations. It's
>> -  /// use helps to ensure that such replacements don't generate code that causes
>> -  /// an alignment error  (trap) on the target machine.
>> +  /// of the specified type. If true, it also returns whether the unaligned
>> +  /// memory access is "fast" in the second argument by reference. This is used,
>> +  /// for example, in situations where an array copy/move/set is  converted to a
>> +  /// sequence of store operations. It's use helps to ensure that such
>> +  /// replacements don't generate code that causes an alignment error  (trap) on
>> +  /// the target machine.
>>    /// @brief Determine if the target supports unaligned memory accesses.
>> -  virtual bool allowsUnalignedMemoryAccesses(EVT) const {
>> +  virtual bool allowsUnalignedMemoryAccesses(EVT, bool *Fast = 0) const {
>>      return false;
>>    }
>> 
>> 
>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Dec 10 17:21:26 2012
>> @@ -3373,7 +3373,7 @@
>>    unsigned NumVTBytes = VT.getSizeInBits() / 8;
>>    unsigned NumBytes = std::min(NumVTBytes, unsigned(Str.size()));
>> 
>> -  uint64_t Val = 0;
>> +  APInt Val(NumBytes*8, 0);
>>    if (TLI.isLittleEndian()) {
>>      for (unsigned i = 0; i != NumBytes; ++i)
>>        Val |= (uint64_t)(unsigned char)Str[i] << i*8;
>> @@ -3382,7 +3382,9 @@
>>        Val |= (uint64_t)(unsigned char)Str[i] << (NumVTBytes-i-1)*8;
>>    }
>> 
>> -  return DAG.getConstant(Val, VT);
>> +  if (TLI.isIntImmLegal(Val, VT))
>> +    return DAG.getConstant(Val, VT);
>> +  return SDValue(0, 0);
>>  }
>> 
>>  /// getMemBasePlusOffset - Returns base and offset node for the
>> @@ -3422,6 +3424,7 @@
>>                                       unsigned DstAlign, unsigned SrcAlign,
>>                                       bool IsZeroVal,
>>                                       bool MemcpyStrSrc,
>> +                                     bool AllowOverlap,
>>                                       SelectionDAG &DAG,
>>                                       const TargetLowering &TLI) {
>>    assert((SrcAlign == 0 || SrcAlign >= DstAlign) &&
>> @@ -3461,24 +3464,47 @@
>> 
>>    unsigned NumMemOps = 0;
>>    while (Size != 0) {
>> +    if (++NumMemOps > Limit)
>> +      return false;
>> +
>>      unsigned VTSize = VT.getSizeInBits() / 8;
>>      while (VTSize > Size) {
>>        // For now, only use non-vector load / store's for the left-over pieces.
>> +      EVT NewVT;
>> +      unsigned NewVTSize;
>>        if (VT.isVector() || VT.isFloatingPoint()) {
>> -        VT = MVT::i64;
>> -        while (!TLI.isTypeLegal(VT))
>> -          VT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1);
>> -        VTSize = VT.getSizeInBits() / 8;
>> +        NewVT = (VT.getSizeInBits() > 64) ? MVT::i64 : MVT::i32;
>> +        while (!TLI.isOperationLegalOrCustom(ISD::STORE, NewVT)) {
>> +          if (NewVT == MVT::i64 &&
>> +              TLI.isOperationLegalOrCustom(ISD::STORE, MVT::f64)) {
>> +            // i64 is usually not legal on 32-bit targets, but f64 may be.
>> +            NewVT = MVT::f64;
>> +            break;
>> +          }
>> +          NewVT = (MVT::SimpleValueType)(NewVT.getSimpleVT().SimpleTy - 1);
>> +        }
>> +        NewVTSize = NewVT.getSizeInBits() / 8;
>>        } else {
>>          // This can result in a type that is not legal on the target, e.g.
>>          // 1 or 2 bytes on PPC.
>> -        VT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1);
>> -        VTSize >>= 1;
>> +        NewVT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1);
>> +        NewVTSize = VTSize >> 1;
>> +      }
>> +
>> +      // If the new VT cannot cover all of the remaining bits, then consider
>> +      // issuing a (or a pair of) unaligned and overlapping load / store.
>> +      // FIXME: Only does this for 64-bit or more since we don't have proper
>> +      // cost model for unaligned load / store.
>> +      bool Fast;
>> +      if (AllowOverlap && VTSize >= 8 && NewVTSize < Size &&
>> +          TLI.allowsUnalignedMemoryAccesses(VT, &Fast) && Fast)
>> +        VTSize = Size;
>> +      else {
>> +        VT = NewVT;
>> +        VTSize = NewVTSize;
>>        }
>>      }
>> 
>> -    if (++NumMemOps > Limit)
>> -      return false;
>>      MemOps.push_back(VT);
>>      Size -= VTSize;
>>    }
>> @@ -3523,7 +3549,7 @@
>>    if (!FindOptimalMemOpLowering(MemOps, Limit, Size,
>>                                  (DstAlignCanChange ? 0 : Align),
>>                                  (isZeroStr ? 0 : SrcAlign),
>> -                                true, CopyFromStr, DAG, TLI))
>> +                                true, CopyFromStr, true, DAG, TLI))
>>      return SDValue();
>> 
>>    if (DstAlignCanChange) {
>> @@ -3545,6 +3571,14 @@
>>      unsigned VTSize = VT.getSizeInBits() / 8;
>>      SDValue Value, Store;
>> 
>> +    if (VTSize > Size) {
>> +      // Issuing an unaligned load / store pair  that overlaps with the previous
>> +      // pair. Adjust the offset accordingly.
>> +      assert(i == NumMemOps-1 && i != 0);
>> +      SrcOff -= VTSize - Size;
>> +      DstOff -= VTSize - Size;
>> +    }
>> +
>>      if (CopyFromStr &&
>>          (isZeroStr || (VT.isInteger() && !VT.isVector()))) {
>>        // It's unlikely a store of a vector immediate can be done in a single
>> @@ -3553,11 +3587,14 @@
>>        // FIXME: Handle other cases where store of vector immediate is done in
>>        // a single instruction.
>>        Value = getMemsetStringVal(VT, dl, DAG, TLI, Str.substr(SrcOff));
>> -      Store = DAG.getStore(Chain, dl, Value,
>> -                           getMemBasePlusOffset(Dst, DstOff, DAG),
>> -                           DstPtrInfo.getWithOffset(DstOff), isVol,
>> -                           false, Align);
>> -    } else {
>> +      if (Value.getNode())
>> +        Store = DAG.getStore(Chain, dl, Value,
>> +                             getMemBasePlusOffset(Dst, DstOff, DAG),
>> +                             DstPtrInfo.getWithOffset(DstOff), isVol,
>> +                             false, Align);
>> +    }
>> +
>> +    if (!Store.getNode()) {
>>        // The type might not be legal for the target.  This should only happen
>>        // if the type is smaller than a legal type, as on PPC, so the right
>>        // thing to do is generate a LoadExt/StoreTrunc pair.  These simplify
>> @@ -3577,6 +3614,7 @@
>>      OutChains.push_back(Store);
>>      SrcOff += VTSize;
>>      DstOff += VTSize;
>> +    Size -= VTSize;
>>    }
>> 
>>    return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
>> @@ -3613,7 +3651,7 @@
>> 
>>    if (!FindOptimalMemOpLowering(MemOps, Limit, Size,
>>                                  (DstAlignCanChange ? 0 : Align),
>> -                                SrcAlign, true, false, DAG, TLI))
>> +                                SrcAlign, true, false, false, DAG, TLI))
>>      return SDValue();
>> 
>>    if (DstAlignCanChange) {
>> @@ -3689,7 +3727,7 @@
>>      isa<ConstantSDNode>(Src) && cast<ConstantSDNode>(Src)->isNullValue();
>>    if (!FindOptimalMemOpLowering(MemOps, TLI.getMaxStoresPerMemset(OptSize),
>>                                  Size, (DstAlignCanChange ? 0 : Align), 0,
>> -                                IsZeroVal, false, DAG, TLI))
>> +                                IsZeroVal, false, true, DAG, TLI))
>>      return SDValue();
>> 
>>    if (DstAlignCanChange) {
>> @@ -3716,6 +3754,13 @@
>> 
>>    for (unsigned i = 0; i < NumMemOps; i++) {
>>      EVT VT = MemOps[i];
>> +    unsigned VTSize = VT.getSizeInBits() / 8;
>> +    if (VTSize > Size) {
>> +      // Issuing an unaligned load / store pair  that overlaps with the previous
>> +      // pair. Adjust the offset accordingly.
>> +      assert(i == NumMemOps-1 && i != 0);
>> +      DstOff -= VTSize - Size;
>> +    }
>> 
>>      // If this store is smaller than the largest store see whether we can get
>>      // the smaller value for free with a truncate.
>> @@ -3734,6 +3779,7 @@
>>                                   isVol, false, Align);
>>      OutChains.push_back(Store);
>>      DstOff += VT.getSizeInBits() / 8;
>> +    Size -= VTSize;
>>    }
>> 
>>    return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
>> 
>> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
>> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Dec 10 17:21:26 2012
>> @@ -833,9 +833,12 @@
>>      setSchedulingPreference(Sched::Hybrid);
>> 
>>    //// temporary - rewrite interface to use type
>> -  maxStoresPerMemcpy = maxStoresPerMemcpyOptSize = 1;
>> -  maxStoresPerMemset = 16;
>> +  maxStoresPerMemset = 8;
>>    maxStoresPerMemsetOptSize = Subtarget->isTargetDarwin() ? 8 : 4;
>> +  maxStoresPerMemcpy = 4; // For @llvm.memcpy -> sequence of stores
>> +  maxStoresPerMemcpyOptSize = Subtarget->isTargetDarwin() ? 4 : 2;
>> +  maxStoresPerMemmove = 4; // For @llvm.memmove -> sequence of stores
>> +  maxStoresPerMemmoveOptSize = Subtarget->isTargetDarwin() ? 4 : 2;
>> 
>>    // On ARM arguments smaller than 4 bytes are extended, so all arguments
>>    // are at least 4 bytes aligned.
>> @@ -9406,7 +9409,7 @@
>>    return (VT == MVT::f32) && (Opc == ISD::LOAD || Opc == ISD::STORE);
>>  }
>> 
>> -bool ARMTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const {
>> +bool ARMTargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const {
>>    // The AllowsUnaliged flag models the SCTLR.A setting in ARM cpus
>>    bool AllowsUnaligned = Subtarget->allowsUnalignedMem();
>> 
>> @@ -9415,15 +9418,27 @@
>>      return false;
>>    case MVT::i8:
>>    case MVT::i16:
>> -  case MVT::i32:
>> +  case MVT::i32: {
>>      // Unaligned access can use (for example) LRDB, LRDH, LDR
>> -    return AllowsUnaligned;
>> +    if (AllowsUnaligned) {
>> +      if (Fast)
>> +        *Fast = Subtarget->hasV7Ops();
>> +      return true;
>> +    }
>> +    return false;
>> +  }
>>    case MVT::f64:
>> -  case MVT::v2f64:
>> +  case MVT::v2f64: {
>>      // For any little-endian targets with neon, we can support unaligned ld/st
>>      // of D and Q (e.g. {D0,D1}) registers by using vld1.i8/vst1.i8.
>>      // A big-endian target may also explictly support unaligned accesses
>> -    return Subtarget->hasNEON() && (AllowsUnaligned || isLittleEndian());
>> +    if (Subtarget->hasNEON() && (AllowsUnaligned || isLittleEndian())) {
>> +      if (Fast)
>> +        *Fast = true;
>> +      return true;
>> +    }
>> +    return false;
>> +  }
>>    }
>>  }
>> 
>> @@ -9442,12 +9457,17 @@
>> 
>>    // See if we can use NEON instructions for this...
>>    if (IsZeroVal &&
>> -      !F->getFnAttributes().hasAttribute(Attributes::NoImplicitFloat) &&
>> -      Subtarget->hasNEON()) {
>> -    if (memOpAlign(SrcAlign, DstAlign, 16) && Size >= 16) {
>> -      return MVT::v4i32;
>> -    } else if (memOpAlign(SrcAlign, DstAlign, 8) && Size >= 8) {
>> -      return MVT::v2i32;
>> +      Subtarget->hasNEON() &&
>> +      !F->getFnAttributes().hasAttribute(Attributes::NoImplicitFloat)) {
>> +    bool Fast;
>> +    if (Size >= 16 && (memOpAlign(SrcAlign, DstAlign, 16) ||
>> +                       (allowsUnalignedMemoryAccesses(MVT::v2f64, &Fast) &&
>> +                        Fast))) {
>> +      return MVT::v2f64;
>> +    } else if (Size >= 8 && (memOpAlign(SrcAlign, DstAlign, 8) ||
>> +                             (allowsUnalignedMemoryAccesses(MVT::f64, &Fast) &&
>> +                              Fast))) {
>> +      return MVT::f64;
>>      }
>>    }
>> 
>> @@ -10241,6 +10261,24 @@
>>    return false;
>>  }
>> 
>> +bool ARMTargetLowering::isIntImmLegal(const APInt &Imm, EVT VT) const {
>> +  if (VT.getSizeInBits() > 32)
>> +    return false;
>> +
>> +  int32_t ImmVal = Imm.getSExtValue();
>> +  if (!Subtarget->isThumb()) {
>> +    return (ImmVal >= 0 && ImmVal < 65536) ||
>> +      (ARM_AM::getSOImmVal(ImmVal) != -1) ||
>> +      (ARM_AM::getSOImmVal(~ImmVal) != -1);
>> +  } else if (Subtarget->isThumb2()) {
>> +    return (ImmVal >= 0 && ImmVal < 65536) ||
>> +      (ARM_AM::getT2SOImmVal(ImmVal) != -1) ||
>> +      (ARM_AM::getT2SOImmVal(~ImmVal) != -1);
>> +  } else /*Thumb1*/ {
>> +    return (ImmVal >= 0 && ImmVal < 256);
>> +  }
>> +}
>> +
>>  /// getTgtMemIntrinsic - Represent NEON load and store intrinsics as
>>  /// MemIntrinsicNodes.  The associated MachineMemOperands record the alignment
>>  /// specified in the intrinsic calls.
>> 
>> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
>> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Mon Dec 10 17:21:26 2012
>> @@ -285,8 +285,9 @@
>>      bool isDesirableToTransformToIntegerOp(unsigned Opc, EVT VT) const;
>> 
>>      /// allowsUnalignedMemoryAccesses - Returns true if the target allows
>> -    /// unaligned memory accesses. of the specified type.
>> -    virtual bool allowsUnalignedMemoryAccesses(EVT VT) const;
>> +    /// unaligned memory accesses of the specified type. Returns whether it
>> +    /// is "fast" by reference in the second argument.
>> +    virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const;
>> 
>>      virtual EVT getOptimalMemOpType(uint64_t Size,
>>                                      unsigned DstAlign, unsigned SrcAlign,
>> @@ -386,6 +387,8 @@
>>      /// materialize the FP immediate as a load from a constant pool.
>>      virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const;
>> 
>> +    virtual bool isIntImmLegal(const APInt &Imm, EVT VT) const;
>> +
>>      virtual bool getTgtMemIntrinsic(IntrinsicInfo &Info,
>>                                      const CallInst &I,
>>                                      unsigned Intrinsic) const;
>> 
>> Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
>> +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Dec 10 17:21:26 2012
>> @@ -2315,13 +2315,15 @@
>>  /// changed to modify CPSR.
>>  multiclass T2I_un_irs<bits<4> opcod, string opc,
>>                       InstrItinClass iii, InstrItinClass iir, InstrItinClass iis,
>> -                      PatFrag opnode, bit Cheap = 0, bit ReMat = 0> {
>> +                      PatFrag opnode,
>> +                      bit Cheap = 0, bit ReMat = 0, bit MoveImm = 0> {
>>     // shifted imm
>>     def i : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), iii,
>>                  opc, "\t$Rd, $imm",
>>                  [(set rGPR:$Rd, (opnode t2_so_imm:$imm))]> {
>>       let isAsCheapAsAMove = Cheap;
>>       let isReMaterializable = ReMat;
>> +     let isMoveImm = MoveImm;
>>       let Inst{31-27} = 0b11110;
>>       let Inst{25} = 0;
>>       let Inst{24-21} = opcod;
>> @@ -2355,7 +2357,7 @@
>>  let AddedComplexity = 1 in
>>  defm t2MVN  : T2I_un_irs <0b0011, "mvn",
>>                            IIC_iMVNi, IIC_iMVNr, IIC_iMVNsi,
>> -                          UnOpFrag<(not node:$Src)>, 1, 1>;
>> +                          UnOpFrag<(not node:$Src)>, 1, 1, 1>;
>> 
>>  let AddedComplexity = 1 in
>>  def : T2Pat<(and     rGPR:$src, t2_so_imm_not:$imm),
>> 
>> Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp (original)
>> +++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp Mon Dec 10 17:21:26 2012
>> @@ -457,7 +457,8 @@
>>    maxStoresPerMemcpy = 16;
>>  }
>> 
>> -bool MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const {
>> +bool
>> +MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const {
>>    MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy;
>> 
>>    if (Subtarget->inMips16Mode())
>> @@ -466,6 +467,8 @@
>>    switch (SVT) {
>>    case MVT::i64:
>>    case MVT::i32:
>> +    if (Fast)
>> +      *Fast = true;
>>      return true;
>>    default:
>>      return false;
>> 
>> Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.h?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/Mips/MipsISelLowering.h (original)
>> +++ llvm/trunk/lib/Target/Mips/MipsISelLowering.h Mon Dec 10 17:21:26 2012
>> @@ -149,7 +149,7 @@
>> 
>>      virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
>> 
>> -    virtual bool allowsUnalignedMemoryAccesses (EVT VT) const;
>> +    virtual bool allowsUnalignedMemoryAccesses (EVT VT, bool *Fast) const;
>> 
>>      virtual void LowerOperationWrapper(SDNode *N,
>>                                         SmallVectorImpl<SDValue> &Results,
>> 
>> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
>> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Dec 10 17:21:26 2012
>> @@ -1412,6 +1412,13 @@
>>    return MVT::i32;
>>  }
>> 
>> +bool
>> +X86TargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const {
>> +  if (Fast)
>> +    *Fast = Subtarget->isUnalignedMemAccessFast();
>> +  return true;
>> +}
>> +
>>  /// getJumpTableEncoding - Return the entry encoding for a jump table in the
>>  /// current function.  The returned value is a member of the
>>  /// MachineJumpTableInfo::JTEntryKind enum.
>> 
>> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
>> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Mon Dec 10 17:21:26 2012
>> @@ -507,10 +507,9 @@
>>                          MachineFunction &MF) const;
>> 
>>      /// allowsUnalignedMemoryAccesses - Returns true if the target allows
>> -    /// unaligned memory accesses. of the specified type.
>> -    virtual bool allowsUnalignedMemoryAccesses(EVT VT) const {
>> -      return true;
>> -    }
>> +    /// unaligned memory accesses. of the specified type. Returns whether it
>> +    /// is "fast" by reference in the second argument.
>> +    virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const;
>> 
>>      /// LowerOperation - Provide custom lowering hooks for some operations.
>>      ///
>> 
>> Modified: llvm/trunk/test/CodeGen/ARM/2011-10-26-memset-with-neon.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2011-10-26-memset-with-neon.ll?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/ARM/2011-10-26-memset-with-neon.ll (original)
>> +++ llvm/trunk/test/CodeGen/ARM/2011-10-26-memset-with-neon.ll Mon Dec 10 17:21:26 2012
>> @@ -1,13 +1,5 @@
>>  ; RUN: llc -march=arm -mcpu=cortex-a8 < %s | FileCheck %s
>> 
>> -; Should trigger a NEON store.
>> -; CHECK: vstr
>> -define void @f_0_12(i8* nocapture %c) nounwind optsize {
>> -entry:
>> -  call void @llvm.memset.p0i8.i64(i8* %c, i8 0, i64 12, i32 8, i1 false)
>> -  ret void
>> -}
>> -
>>  ; Trigger multiple NEON stores.
>>  ; CHECK:      vst1.64
>>  ; CHECK-NEXT: vst1.64
>> 
>> Modified: llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll (original)
>> +++ llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll Mon Dec 10 17:21:26 2012
>> @@ -1,18 +1,115 @@
>> -; RUN: llc < %s -mtriple=thumbv7-apple-darwin -disable-post-ra | FileCheck %s
>> -
>> -; CHECK: ldrd
>> -; CHECK: strd
>> -; CHECK: ldrb
>> +; RUN: llc < %s -mtriple=thumbv7-apple-ios -mcpu=cortex-a8 -pre-RA-sched=source -disable-post-ra | FileCheck %s
>> 
>>  %struct.x = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 }
>> 
>>  @src = external global %struct.x
>>  @dst = external global %struct.x
>> 
>> -define i32 @t() {
>> + at .str1 = private unnamed_addr constant [31 x i8] c"DHRYSTONE PROGRAM, SOME STRING\00", align 1
>> + at .str2 = private unnamed_addr constant [36 x i8] c"DHRYSTONE PROGRAM, SOME STRING BLAH\00", align 1
>> + at .str3 = private unnamed_addr constant [24 x i8] c"DHRYSTONE PROGRAM, SOME\00", align 1
>> + at .str4 = private unnamed_addr constant [18 x i8] c"DHRYSTONE PROGR  \00", align 1
>> + at .str5 = private unnamed_addr constant [7 x i8] c"DHRYST\00", align 1
>> + at .str6 = private unnamed_addr constant [14 x i8] c"/tmp/rmXXXXXX\00", align 1
>> + at spool.splbuf = internal global [512 x i8] zeroinitializer, align 16
>> +
>> +define i32 @t0() {
>>  entry:
>> +; CHECK: t0:
>> +; CHECK: vldr [[REG1:d[0-9]+]],
>> +; CHECK: vstr [[REG1]],
>>    call void @llvm.memcpy.p0i8.p0i8.i32(i8* getelementptr inbounds (%struct.x* @dst, i32 0, i32 0), i8* getelementptr inbounds (%struct.x* @src, i32 0, i32 0), i32 11, i32 8, i1 false)
>>    ret i32 0
>>  }
>> 
>> +define void @t1(i8* nocapture %C) nounwind {
>> +entry:
>> +; CHECK: t1:
>> +; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
>> +; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
>> +; CHECK: adds r0, #15
>> +; CHECK: adds r1, #15
>> +; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
>> +; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
>> +  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %C, i8* getelementptr inbounds ([31 x i8]* @.str1, i64 0, i64 0), i64 31, i32 1, i1 false)
>> +  ret void
>> +}
>> +
>> +define void @t2(i8* nocapture %C) nounwind {
>> +entry:
>> +; CHECK: t2:
>> +; CHECK: ldr [[REG2:r[0-9]+]], [r1, #32]
>> +; CHECK: str [[REG2]], [r0, #32]
>> +; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
>> +; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
>> +; CHECK: adds r0, #16
>> +; CHECK: adds r1, #16
>> +; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
>> +; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
>> +  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %C, i8* getelementptr inbounds ([36 x i8]* @.str2, i64 0, i64 0), i64 36, i32 1, i1 false)
>> +  ret void
>> +}
>> +
>> +define void @t3(i8* nocapture %C) nounwind {
>> +entry:
>> +; CHECK: t3:
>> +; CHECK: vld1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
>> +; CHECK: vst1.8 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
>> +; CHECK: adds r0, #16
>> +; CHECK: adds r1, #16
>> +; CHECK: vld1.8 {d{{[0-9]+}}}, [r1]
>> +; CHECK: vst1.8 {d{{[0-9]+}}}, [r0]
>> +  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %C, i8* getelementptr inbounds ([24 x i8]* @.str3, i64 0, i64 0), i64 24, i32 1, i1 false)
>> +  ret void
>> +}
>> +
>> +define void @t4(i8* nocapture %C) nounwind {
>> +entry:
>> +; CHECK: t4:
>> +; CHECK: vld1.8 {[[REG3:d[0-9]+]], [[REG4:d[0-9]+]]}, [r1]
>> +; CHECK: vst1.8 {[[REG3]], [[REG4]]}, [r0]
>> +  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %C, i8* getelementptr inbounds ([18 x i8]* @.str4, i64 0, i64 0), i64 18, i32 1, i1 false)
>> +  ret void
>> +}
>> +
>> +define void @t5(i8* nocapture %C) nounwind {
>> +entry:
>> +; CHECK: t5:
>> +; CHECK: movs [[REG5:r[0-9]+]], #0
>> +; CHECK: strb [[REG5]], [r0, #6]
>> +; CHECK: movw [[REG6:r[0-9]+]], #21587
>> +; CHECK: strh [[REG6]], [r0, #4]
>> +; CHECK: ldr [[REG7:r[0-9]+]],
>> +; CHECK: str [[REG7]]
>> +  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %C, i8* getelementptr inbounds ([7 x i8]* @.str5, i64 0, i64 0), i64 7, i32 1, i1 false)
>> +  ret void
>> +}
>> +
>> +define void @t6() nounwind {
>> +entry:
>> +; CHECK: t6:
>> +; CHECK: vld1.8 {[[REG8:d[0-9]+]]}, [r0]
>> +; CHECK: vstr [[REG8]], [r1]
>> +; CHECK: adds r1, #6
>> +; CHECK: adds r0, #6
>> +; CHECK: vld1.8
>> +; CHECK: vst1.16
>> +  call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds ([512 x i8]* @spool.splbuf, i64 0, i64 0), i8* getelementptr inbounds ([14 x i8]* @.str6, i64 0, i64 0), i64 14, i32 1, i1 false)
>> +  ret void
>> +}
>> +
>> +%struct.Foo = type { i32, i32, i32, i32 }
>> +
>> +define void @t7(%struct.Foo* nocapture %a, %struct.Foo* nocapture %b) nounwind {
>> +entry:
>> +; CHECK: t7
>> +; CHECK: vld1.32
>> +; CHECK: vst1.32
>> +  %0 = bitcast %struct.Foo* %a to i8*
>> +  %1 = bitcast %struct.Foo* %b to i8*
>> +  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 16, i32 4, i1 false)
>> +  ret void
>> +}
>> +
>>  declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
>> +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind
>> 
>> Added: llvm/trunk/test/CodeGen/ARM/memset-inline.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/memset-inline.ll?rev=169791&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/ARM/memset-inline.ll (added)
>> +++ llvm/trunk/test/CodeGen/ARM/memset-inline.ll Mon Dec 10 17:21:26 2012
>> @@ -0,0 +1,30 @@
>> +; RUN: llc < %s -mtriple=thumbv7-apple-ios -mcpu=cortex-a8 -pre-RA-sched=source -disable-post-ra | FileCheck %s
>> +
>> +define void @t1(i8* nocapture %c) nounwind optsize {
>> +entry:
>> +; CHECK: t1:
>> +; CHECK: movs r1, #0
>> +; CHECK: str r1, [r0]
>> +; CHECK: str r1, [r0, #4]
>> +; CHECK: str r1, [r0, #8]
>> +  call void @llvm.memset.p0i8.i64(i8* %c, i8 0, i64 12, i32 8, i1 false)
>> +  ret void
>> +}
>> +
>> +define void @t2() nounwind ssp {
>> +entry:
>> +; CHECK: t2:
>> +; CHECK: add.w r1, r0, #10
>> +; CHECK: vmov.i32 {{q[0-9]+}}, #0x0
>> +; CHECK: vst1.16 {d{{[0-9]+}}, d{{[0-9]+}}}, [r1]
>> +; CHECK: vst1.32 {d{{[0-9]+}}, d{{[0-9]+}}}, [r0]
>> +  %buf = alloca [26 x i8], align 1
>> +  %0 = getelementptr inbounds [26 x i8]* %buf, i32 0, i32 0
>> +  call void @llvm.memset.p0i8.i32(i8* %0, i8 0, i32 26, i32 1, i1 false)
>> +  call void @something(i8* %0) nounwind
>> +  ret void
>> +}
>> +
>> +declare void @something(i8*) nounwind
>> +declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind
>> +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
>> 
>> Removed: llvm/trunk/test/CodeGen/ARM/reg_asc_order.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/reg_asc_order.ll?rev=169790&view=auto
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/ARM/reg_asc_order.ll (original)
>> +++ llvm/trunk/test/CodeGen/ARM/reg_asc_order.ll (removed)
>> @@ -1,16 +0,0 @@
>> -; RUN: llc < %s -march=arm -mcpu=cortex-a8 | FileCheck %s
>> -; Check that memcpy gets lowered to ldm/stm, at least in this very smple case.
>> -
>> -%struct.Foo = type { i32, i32, i32, i32 }
>> -
>> -define void @_Z10CopyStructP3FooS0_(%struct.Foo* nocapture %a, %struct.Foo* nocapture %b) nounwind {
>> -entry:
>> -;CHECK: ldm
>> -;CHECK: stm
>> -  %0 = bitcast %struct.Foo* %a to i8*
>> -  %1 = bitcast %struct.Foo* %b to i8*
>> -  tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 16, i32 4, i1 false)
>> -  ret void
>> -}
>> -
>> -declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
>> 
>> Modified: llvm/trunk/test/CodeGen/X86/2009-11-16-UnfoldMemOpBug.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-11-16-UnfoldMemOpBug.ll?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/2009-11-16-UnfoldMemOpBug.ll (original)
>> +++ llvm/trunk/test/CodeGen/X86/2009-11-16-UnfoldMemOpBug.ll Mon Dec 10 17:21:26 2012
>> @@ -6,15 +6,16 @@
>>  define void @t(i32 %count) ssp nounwind {
>>  entry:
>>  ; CHECK: t:
>> -; CHECK: movq ___stack_chk_guard at GOTPCREL(%rip)
>> -; CHECK: movups L_str(%rip), %xmm0
>> +; CHECK: movups L_str+12(%rip), %xmm0
>> +; CHECK: movups L_str(%rip), %xmm1
>>    %tmp0 = alloca [60 x i8], align 1
>>    %tmp1 = getelementptr inbounds [60 x i8]* %tmp0, i64 0, i64 0
>>    br label %bb1
>> 
>>  bb1:
>>  ; CHECK: LBB0_1:
>> -; CHECK: movaps %xmm0, (%rsp)
>> +; CHECK: movups %xmm0, 12(%rsp)
>> +; CHECK: movaps %xmm1, (%rsp)
>>    %tmp2 = phi i32 [ %tmp3, %bb1 ], [ 0, %entry ]
>>    call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp1, i8* getelementptr inbounds ([28 x i8]* @str, i64 0, i64 0), i64 28, i32 1, i1 false)
>>    %tmp3 = add i32 %tmp2, 1
>> 
>> Modified: llvm/trunk/test/CodeGen/X86/memcpy-2.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/memcpy-2.ll?rev=169791&r1=169790&r2=169791&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/X86/memcpy-2.ll (original)
>> +++ llvm/trunk/test/CodeGen/X86/memcpy-2.ll Mon Dec 10 17:21:26 2012
>> @@ -10,18 +10,18 @@
>>  define void @t1(i32 %argc, i8** %argv) nounwind  {
>>  entry:
>>  ; SSE2: t1:
>> +; SSE2: movsd _.str+16, %xmm0
>> +; SSE2: movsd %xmm0, 16(%esp)
>>  ; SSE2: movaps _.str, %xmm0
>>  ; SSE2: movaps %xmm0
>> -; SSE2: movb $0
>> -; SSE2: movl $0
>> -; SSE2: movl $0
>> +; SSE2: movb $0, 24(%esp)
>> 
>>  ; SSE1: t1:
>> +; SSE1: fldl _.str+16
>> +; SSE1: fstpl 16(%esp)
>>  ; SSE1: movaps _.str, %xmm0
>>  ; SSE1: movaps %xmm0
>> -; SSE1: movb $0
>> -; SSE1: movl $0
>> -; SSE1: movl $0
>> +; SSE1: movb $0, 24(%esp)
>> 
>>  ; NOSSE: t1:
>>  ; NOSSE: movb $0
>> 
>> 
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>> 
>> <strcat.llvm.mips64el.ll>
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121212/22d29d4f/attachment.html>


More information about the llvm-commits mailing list