Index: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h @@ -1016,6 +1016,12 @@ ArrayRef Ops, EVT MemVT, MachineMemOperand *MMO); + /// Creates a LifetimeSDNode that starts (`IsStart==true`) or ends + /// (`IsStart==false`) the lifetime of the portion of `FrameIndex` between + /// offsets `Offset` and `Offset + Size`. + SDValue getLifetimeNode(bool IsStart, const SDLoc &dl, SDValue Chain, + int FrameIndex, int64_t Size, int64_t Offset = -1); + /// Create a MERGE_VALUES node from the given operands. SDValue getMergeValues(ArrayRef Ops, const SDLoc &dl); Index: llvm/trunk/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGAddressAnalysis.h @@ -48,14 +48,30 @@ SDValue getIndex() { return Index; } SDValue getIndex() const { return Index; } + // Returns true if `Other` and `*this` are both some offset from the same base + // pointer. In that case, `Off` is set to the offset between `*this` and + // `Other` (negative if `Other` is before `*this`). + bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, + int64_t &Off) const; + bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG) const { int64_t Off; return equalBaseIndex(Other, DAG, Off); } - bool equalBaseIndex(const BaseIndexOffset &Other, const SelectionDAG &DAG, - int64_t &Off) const; + // Returns true if `Other` (with size `OtherSize`) can be proven to be fully + // contained in `*this` (with size `Size`). + bool contains(int64_t Size, const BaseIndexOffset &Other, int64_t OtherSize, + const SelectionDAG &DAG) const; + + // Returns true `BasePtr0` and `BasePtr1` can be proven to alias/not alias, in + // which case `IsAlias` is set to true/false. + static bool computeAliasing(const BaseIndexOffset &BasePtr0, + const int64_t NumBytes0, + const BaseIndexOffset &BasePtr1, + const int64_t NumBytes1, const SelectionDAG &DAG, + bool &IsAlias); /// Parses tree in Ptr for base, index, offset addresses. static BaseIndexOffset match(const LSBaseSDNode *N, const SelectionDAG &DAG); Index: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1692,6 +1692,37 @@ } }; +/// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate +/// the offet and size that are started/ended in the underlying FrameIndex. +class LifetimeSDNode : public SDNode { + int64_t Size; + int64_t Offset; // -1 if offset is unknown. +public: + LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl, + SDVTList VTs, int64_t Size, int64_t Offset) + : SDNode(Opcode, Order, dl, VTs), Size(Size), Offset(Offset) {} + + int64_t getFrameIndex() const { + return cast(getOperand(1))->getIndex(); + } + + bool hasOffset() const { return Offset >= 0; } + int64_t getOffset() const { + assert(hasOffset() && "offset is unknown"); + return Offset; + } + int64_t getSize() const { + assert(hasOffset() && "offset is unknown"); + return Size; + } + + // Methods to support isa and dyn_cast + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::LIFETIME_START || + N->getOpcode() == ISD::LIFETIME_END; + } +}; + class JumpTableSDNode : public SDNode { friend class SelectionDAG; Index: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -385,6 +385,7 @@ SDValue replaceStoreOfFPConstant(StoreSDNode *ST); SDValue visitSTORE(SDNode *N); + SDValue visitLIFETIME_END(SDNode *N); SDValue visitINSERT_VECTOR_ELT(SDNode *N); SDValue visitEXTRACT_VECTOR_ELT(SDNode *N); SDValue visitBUILD_VECTOR(SDNode *N); @@ -1589,6 +1590,7 @@ case ISD::MLOAD: return visitMLOAD(N); case ISD::MSCATTER: return visitMSCATTER(N); case ISD::MSTORE: return visitMSTORE(N); + case ISD::LIFETIME_END: return visitLIFETIME_END(N); case ISD::FP_TO_FP16: return visitFP_TO_FP16(N); case ISD::FP16_TO_FP: return visitFP16_TO_FP(N); } @@ -15484,6 +15486,66 @@ return ReduceLoadOpStoreWidth(N); } +SDValue DAGCombiner::visitLIFETIME_END(SDNode *N) { + const auto *LifetimeEnd = cast(N); + if (!LifetimeEnd->hasOffset()) + return SDValue(); + + const BaseIndexOffset LifetimeEndBase(N->getOperand(1), SDValue(), + LifetimeEnd->getOffset(), false); + + // We walk up the chains to find stores. + SmallVector Chains = {N->getOperand(0)}; + while (!Chains.empty()) { + SDValue Chain = Chains.back(); + Chains.pop_back(); + switch (Chain.getOpcode()) { + case ISD::TokenFactor: + for (unsigned Nops = Chain.getNumOperands(); Nops;) + Chains.push_back(Chain.getOperand(--Nops)); + break; + case ISD::LIFETIME_START: + case ISD::LIFETIME_END: { + // We can forward past any lifetime start/end that can be proven not to + // alias the node. + const auto *LifetimeStart = cast(Chain); + if (!LifetimeStart->hasOffset()) + break; // Be conservative if we don't know the extents of the object. + + const BaseIndexOffset LifetimeStartBase( + LifetimeStart->getOperand(1), SDValue(), LifetimeStart->getOffset(), + false); + bool IsAlias; + if (BaseIndexOffset::computeAliasing( + LifetimeEndBase, LifetimeEnd->getSize(), LifetimeStartBase, + LifetimeStart->getSize(), DAG, IsAlias) && + !IsAlias) { + Chains.push_back(Chain.getOperand(0)); + } + break; + } + + case ISD::STORE: { + StoreSDNode *ST = dyn_cast(Chain); + if (ST->isVolatile() || !ST->hasOneUse() || ST->isIndexed()) + continue; + const BaseIndexOffset StoreBase = BaseIndexOffset::match(ST, DAG); + // If we store purely within object bounds just before its lifetime ends, + // we can remove the store. + if (LifetimeEndBase.contains(LifetimeEnd->getSize(), StoreBase, + ST->getMemoryVT().getStoreSize(), DAG)) { + LLVM_DEBUG(dbgs() << "\nRemoving store:"; StoreBase.dump(); + dbgs() << "\nwithin LIFETIME_END of : "; + LifetimeEndBase.dump(); dbgs() << "\n"); + CombineTo(ST, ST->getChain()); + return SDValue(N, 0); + } + } + } + } + return SDValue(); +} + /// For the instruction sequence of store below, F and I values /// are bundled together as an i64 value before being stored into memory. /// Sometimes it is more efficent to generate separate stores for F and I, @@ -19235,41 +19297,11 @@ unsigned NumBytes1 = Op1->getMemoryVT().getStoreSize(); // Check for BaseIndexOffset matching. - BaseIndexOffset BasePtr0 = BaseIndexOffset::match(Op0, DAG); - BaseIndexOffset BasePtr1 = BaseIndexOffset::match(Op1, DAG); - int64_t PtrDiff; - if (BasePtr0.getBase().getNode() && BasePtr1.getBase().getNode()) { - if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) - return !((NumBytes0 <= PtrDiff) || (PtrDiff + NumBytes1 <= 0)); - - // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be - // able to calculate their relative offset if at least one arises - // from an alloca. However, these allocas cannot overlap and we - // can infer there is no alias. - if (auto *A = dyn_cast(BasePtr0.getBase())) - if (auto *B = dyn_cast(BasePtr1.getBase())) { - MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); - // If the base are the same frame index but the we couldn't find a - // constant offset, (indices are different) be conservative. - if (A != B && (!MFI.isFixedObjectIndex(A->getIndex()) || - !MFI.isFixedObjectIndex(B->getIndex()))) - return false; - } - - bool IsFI0 = isa(BasePtr0.getBase()); - bool IsFI1 = isa(BasePtr1.getBase()); - bool IsGV0 = isa(BasePtr0.getBase()); - bool IsGV1 = isa(BasePtr1.getBase()); - bool IsCV0 = isa(BasePtr0.getBase()); - bool IsCV1 = isa(BasePtr1.getBase()); - - // If of mismatched base types or checkable indices we can check - // they do not alias. - if ((BasePtr0.getIndex() == BasePtr1.getIndex() || (IsFI0 != IsFI1) || - (IsGV0 != IsGV1) || (IsCV0 != IsCV1)) && - (IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) - return false; - } + bool IsAlias; + if (BaseIndexOffset::computeAliasing( + BaseIndexOffset::match(Op0, DAG), NumBytes0, + BaseIndexOffset::match(Op1, DAG), NumBytes1, DAG, IsAlias)) + return IsAlias; // If we know required SrcValue1 and SrcValue2 have relatively large // alignment compared to the size and offset of the access, we may be able @@ -19328,6 +19360,8 @@ // Get alias information for node. bool IsLoad = isa(N) && !N->isVolatile(); + const BaseIndexOffset LSBasePtr = BaseIndexOffset::match(N, DAG); + const unsigned LSNumBytes = N->getMemoryVT().getStoreSize(); // Starting off. Chains.push_back(OriginalChain); @@ -19398,6 +19432,27 @@ ++Depth; break; + case ISD::LIFETIME_START: + case ISD::LIFETIME_END: { + // We can forward past any lifetime start/end that can be proven not to + // alias the memory access. + const auto *Lifetime = cast(Chain); + if (!Lifetime->hasOffset()) + break; // Be conservative if we don't know the extents of the object. + + const BaseIndexOffset LifetimePtr(Lifetime->getOperand(1), SDValue(), + Lifetime->getOffset(), false); + bool IsAlias; + if (BaseIndexOffset::computeAliasing(LifetimePtr, Lifetime->getSize(), + LSBasePtr, LSNumBytes, DAG, + IsAlias) && + !IsAlias) { + Chains.push_back(Chain.getOperand(0)); + ++Depth; + } + break; + } + default: // For all other instructions we will just have to take what we can get. Aliases.push_back(Chain); Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -6502,6 +6502,36 @@ return SDValue(N, 0); } +SDValue SelectionDAG::getLifetimeNode(bool IsStart, const SDLoc &dl, + SDValue Chain, int FrameIndex, + int64_t Size, int64_t Offset) { + const unsigned Opcode = IsStart ? ISD::LIFETIME_START : ISD::LIFETIME_END; + const auto VTs = getVTList(MVT::Other); + SDValue Ops[2] = { + Chain, + getFrameIndex(FrameIndex, + getTargetLoweringInfo().getFrameIndexTy(getDataLayout()), + true)}; + + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTs, Ops); + ID.AddInteger(FrameIndex); + ID.AddInteger(Size); + ID.AddInteger(Offset); + void *IP = nullptr; + if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) + return SDValue(E, 0); + + LifetimeSDNode *N = newSDNode( + Opcode, dl.getIROrder(), dl.getDebugLoc(), VTs, Size, Offset); + createOperands(N, Ops); + CSEMap.InsertNode(N, IP); + InsertNode(N); + SDValue V(N, 0); + NewSDValueDbgMsg(V, "Creating new node: ", this); + return V; +} + /// InferPointerInfo - If the specified ptr/offset is a frame index, infer a /// MachinePointerInfo record from it. This is particularly useful because the /// code generator has many cases where it doesn't bother passing in a Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGAddressAnalysis.cpp @@ -79,6 +79,81 @@ return false; } +bool BaseIndexOffset::computeAliasing(const BaseIndexOffset &BasePtr0, + const int64_t NumBytes0, + const BaseIndexOffset &BasePtr1, + const int64_t NumBytes1, + const SelectionDAG &DAG, bool &IsAlias) { + if (!(BasePtr0.getBase().getNode() && BasePtr1.getBase().getNode())) + return false; + int64_t PtrDiff; + if (BasePtr0.equalBaseIndex(BasePtr1, DAG, PtrDiff)) { + // BasePtr1 is PtrDiff away from BasePtr0. They alias if none of the + // following situations arise: + IsAlias = !( + // [----BasePtr0----] + // [---BasePtr1--] + // ========PtrDiff========> + (NumBytes0 <= PtrDiff) || + // [----BasePtr0----] + // [---BasePtr1--] + // =====(-PtrDiff)====> + (PtrDiff + NumBytes1 <= 0)); // i.e. NumBytes1 < -PtrDiff. + return true; + } + // If both BasePtr0 and BasePtr1 are FrameIndexes, we will not be + // able to calculate their relative offset if at least one arises + // from an alloca. However, these allocas cannot overlap and we + // can infer there is no alias. + if (auto *A = dyn_cast(BasePtr0.getBase())) + if (auto *B = dyn_cast(BasePtr1.getBase())) { + MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); + // If the base are the same frame index but the we couldn't find a + // constant offset, (indices are different) be conservative. + if (A != B && (!MFI.isFixedObjectIndex(A->getIndex()) || + !MFI.isFixedObjectIndex(B->getIndex()))) { + IsAlias = false; + return true; + } + } + + bool IsFI0 = isa(BasePtr0.getBase()); + bool IsFI1 = isa(BasePtr1.getBase()); + bool IsGV0 = isa(BasePtr0.getBase()); + bool IsGV1 = isa(BasePtr1.getBase()); + bool IsCV0 = isa(BasePtr0.getBase()); + bool IsCV1 = isa(BasePtr1.getBase()); + + // If of mismatched base types or checkable indices we can check + // they do not alias. + if ((BasePtr0.getIndex() == BasePtr1.getIndex() || (IsFI0 != IsFI1) || + (IsGV0 != IsGV1) || (IsCV0 != IsCV1)) && + (IsFI0 || IsGV0 || IsCV0) && (IsFI1 || IsGV1 || IsCV1)) { + IsAlias = false; + return true; + } + return false; // Cannot determine whether the pointers alias. +} + +bool BaseIndexOffset::contains(int64_t Size, const BaseIndexOffset &Other, + int64_t OtherSize, + const SelectionDAG &DAG) const { + int64_t Offset; + if (!equalBaseIndex(Other, DAG, Offset)) + return false; + if (Offset >= 0) { + // Other is after *this: + // [-------*this---------] + // [---Other--] + // ==Offset==> + return Offset + OtherSize <= Size; + } + // Other starts strictly before *this, it cannot be fully contained. + // [-------*this---------] + // [--Other--] + return false; +} + /// Parses tree in Ptr for base, index, offset addresses. BaseIndexOffset BaseIndexOffset::match(const LSBaseSDNode *N, const SelectionDAG &DAG) { Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6373,8 +6373,11 @@ if (TM.getOptLevel() == CodeGenOpt::None) return nullptr; + const int64_t ObjectSize = + cast(I.getArgOperand(0))->getSExtValue(); + Value *const ObjectPtr = I.getArgOperand(1); SmallVector Allocas; - GetUnderlyingObjects(I.getArgOperand(1), Allocas, *DL); + GetUnderlyingObjects(ObjectPtr, Allocas, *DL); for (SmallVectorImpl::iterator Object = Allocas.begin(), E = Allocas.end(); Object != E; ++Object) { @@ -6390,15 +6393,13 @@ if (SI == FuncInfo.StaticAllocaMap.end()) return nullptr; - int FI = SI->second; - - SDValue Ops[2]; - Ops[0] = getRoot(); - Ops[1] = - DAG.getFrameIndex(FI, TLI.getFrameIndexTy(DAG.getDataLayout()), true); - unsigned Opcode = (IsStart ? ISD::LIFETIME_START : ISD::LIFETIME_END); - - Res = DAG.getNode(Opcode, sdl, MVT::Other, Ops); + const int FrameIndex = SI->second; + int64_t Offset; + if (GetPointerBaseWithConstantOffset( + ObjectPtr, Offset, DAG.getDataLayout()) != LifetimeObject) + Offset = -1; // Cannot determine offset from alloca to lifetime object. + Res = DAG.getLifetimeNode(IsStart, sdl, getRoot(), FrameIndex, ObjectSize, + Offset); DAG.setRoot(Res); } return nullptr; Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -709,6 +709,9 @@ << " -> " << ASC->getDestAddressSpace() << ']'; + } else if (const LifetimeSDNode *LN = dyn_cast(this)) { + if (LN->hasOffset()) + OS << "<" << LN->getOffset() << " to " << LN->getOffset() + LN->getSize() << ">"; } if (VerboseDAGDumping) { Index: llvm/trunk/test/CodeGen/BPF/remove_truncate_5.ll =================================================================== --- llvm/trunk/test/CodeGen/BPF/remove_truncate_5.ll +++ llvm/trunk/test/CodeGen/BPF/remove_truncate_5.ll @@ -25,12 +25,12 @@ call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %2) #3 call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 %2, i8* align 4 bitcast (%struct.test_t* @test.t to i8*), i64 16, i1 false) ; CHECK: r1 = 0 -; CHECK: r1 <<= 32 -; CHECK: r2 = r1 -; CHECK: r2 |= 0 -; CHECK: *(u64 *)(r10 - 8) = r2 -; CHECK: r1 |= 5 -; CHECK: *(u64 *)(r10 - 16) = r1 +; CHECK-NEXT: r1 <<= 32 +; CHECK-NEXT: r2 = r1 +; CHECK: [[SECOND:r[12]]] |= 5 +; CHECK-NEXT: *(u64 *)(r10 - 16) = [[SECOND]] +; CHECK: [[FIRST:r[12]]] |= 0 +; CHECK-NEXT: *(u64 *)(r10 - 8) = [[FIRST]] call void @foo(i8* nonnull %2) #3 ; CHECK: call foo call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %2) #3 Index: llvm/trunk/test/CodeGen/X86/swap.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/swap.ll +++ llvm/trunk/test/CodeGen/X86/swap.ll @@ -22,7 +22,6 @@ ; AA-LABEL: _Z4SwapP1SS0_: ; AA: # %bb.0: # %entry ; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: vmovups (%rsi), %xmm1 ; AA-NEXT: vmovups %xmm1, (%rdi) ; AA-NEXT: vmovups %xmm0, (%rsi) @@ -43,18 +42,10 @@ define dso_local void @onealloc_noreadback(i8* nocapture %a, i8* nocapture %b) local_unnamed_addr { ; NOAA-LABEL: onealloc_noreadback: ; NOAA: # %bb.0: # %entry -; NOAA-NEXT: vmovups (%rdi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; NOAA-NEXT: vmovups (%rsi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; NOAA-NEXT: retq ; ; AA-LABEL: onealloc_noreadback: ; AA: # %bb.0: # %entry -; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovups (%rsi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: retq entry: %alloc = alloca [16 x i8], i8 2, align 1 @@ -73,18 +64,10 @@ define dso_local void @twoallocs_trivial(i8* nocapture %a, i8* nocapture %b) local_unnamed_addr { ; NOAA-LABEL: twoallocs_trivial: ; NOAA: # %bb.0: # %entry -; NOAA-NEXT: vmovups (%rdi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; NOAA-NEXT: vmovups (%rsi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; NOAA-NEXT: retq ; ; AA-LABEL: twoallocs_trivial: ; AA: # %bb.0: # %entry -; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovups (%rsi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: retq entry: %alloc1 = alloca [16 x i8], align 1 @@ -104,16 +87,12 @@ ; NOAA-LABEL: twoallocs: ; NOAA: # %bb.0: # %entry ; NOAA-NEXT: vmovups (%rdi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; NOAA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; NOAA-NEXT: vmovups %xmm0, (%rsi) ; NOAA-NEXT: retq ; ; AA-LABEL: twoallocs: ; AA: # %bb.0: # %entry ; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; AA-NEXT: vmovups %xmm0, (%rsi) ; AA-NEXT: retq entry: @@ -137,18 +116,12 @@ ; NOAA-NEXT: vmovups (%rdi), %xmm0 ; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; NOAA-NEXT: vmovups (%rsi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; NOAA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; NOAA-NEXT: vmovups %xmm0, (%rdi) ; NOAA-NEXT: retq ; ; AA-LABEL: onealloc_readback_1: ; AA: # %bb.0: # %entry -; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: vmovups (%rsi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; AA-NEXT: vmovups %xmm0, (%rdi) ; AA-NEXT: retq entry: @@ -171,18 +144,12 @@ ; NOAA-NEXT: vmovups (%rdi), %xmm0 ; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; NOAA-NEXT: vmovups (%rsi), %xmm0 -; NOAA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; NOAA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; NOAA-NEXT: vmovups %xmm0, (%rdi) ; NOAA-NEXT: retq ; ; AA-LABEL: onealloc_readback_2: ; AA: # %bb.0: # %entry -; AA-NEXT: vmovups (%rdi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) ; AA-NEXT: vmovups (%rsi), %xmm0 -; AA-NEXT: vmovaps %xmm0, -{{[0-9]+}}(%rsp) -; AA-NEXT: vmovaps -{{[0-9]+}}(%rsp), %xmm0 ; AA-NEXT: vmovups %xmm0, (%rdi) ; AA-NEXT: retq entry: Index: llvm/trunk/test/DebugInfo/COFF/inlining.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/inlining.ll +++ llvm/trunk/test/DebugInfo/COFF/inlining.ll @@ -29,7 +29,6 @@ ; ASM: .cv_loc 1 1 9 5 # t.cpp:9:5 ; ASM: addl $4, "?x@@3HC" ; ASM: .cv_inline_site_id 2 within 1 inlined_at 1 10 3 -; ASM: .cv_loc 2 1 3 7 # t.cpp:3:7 ; ASM: .cv_loc 2 1 4 5 # t.cpp:4:5 ; ASM: addl {{.*}}, "?x@@3HC" ; ASM: .cv_loc 2 1 5 5 # t.cpp:5:5 @@ -172,7 +171,7 @@ ; OBJ: PtrParent: 0x0 ; OBJ: PtrEnd: 0x0 ; OBJ: PtrNext: 0x0 -; OBJ: CodeSize: 0x3C +; OBJ: CodeSize: 0x35 ; OBJ: DbgStart: 0x0 ; OBJ: DbgEnd: 0x0 ; OBJ: FunctionType: baz (0x1004) @@ -189,9 +188,9 @@ ; OBJ: Inlinee: bar (0x1002) ; OBJ: BinaryAnnotations [ ; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x8, LineOffset: 1} -; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x7, LineOffset: 1} +; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x9, LineOffset: 1} ; OBJ-NEXT: ChangeLineOffset: 1 -; OBJ-NEXT: ChangeCodeOffset: 0x1D +; OBJ-NEXT: ChangeCodeOffset: 0x14 ; OBJ-NEXT: ChangeCodeLength: 0x7 ; OBJ: ] ; OBJ: } @@ -200,8 +199,8 @@ ; OBJ: PtrEnd: 0x0 ; OBJ: Inlinee: foo (0x1003) ; OBJ: BinaryAnnotations [ -; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xF, LineOffset: 1} -; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x9, LineOffset: 1} +; OBJ-NEXT: ChangeLineOffset: 2 +; OBJ-NEXT: ChangeCodeOffset: 0x11 ; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x6, LineOffset: 1} ; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x7, LineOffset: 1} ; OBJ-NEXT: ChangeCodeLength: 0x7 Index: llvm/trunk/test/DebugInfo/COFF/lexicalblock.ll =================================================================== --- llvm/trunk/test/DebugInfo/COFF/lexicalblock.ll +++ llvm/trunk/test/DebugInfo/COFF/lexicalblock.ll @@ -70,9 +70,6 @@ ; CHECK: Kind: S_BLOCK32 {{.*}} ; CHECK: BlockName: ; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localC -; CHECK: } ; CHECK: ScopeEndSym { ; CHECK: Kind: S_END {{.*}} ; CHECK: } @@ -80,9 +77,6 @@ ; CHECK: Kind: S_BLOCK32 {{.*}} ; CHECK: BlockName: ; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localD -; CHECK: } ; CHECK: ScopeEndSym { ; CHECK: Kind: S_END {{.*}} ; CHECK: } @@ -90,38 +84,12 @@ ; CHECK: Kind: S_BLOCK32 {{.*}} ; CHECK: BlockName: ; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localE -; CHECK: } -; CHECK: ScopeEndSym { -; CHECK: } -; CHECK: BlockSym { -; CHECK: Kind: S_BLOCK32 {{.*}} -; CHECK: BlockName: -; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localF -; CHECK: } -; CHECK: BlockSym { -; CHECK: Kind: S_BLOCK32 {{.*}} -; CHECK: BlockName: -; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localG -; CHECK: } ; CHECK: ScopeEndSym { -; CHECK: Kind: S_END {{.*}} -; CHECK: } -; CHECK: ScopeEndSym { -; CHECK: Kind: S_END {{.*}} ; CHECK: } ; CHECK: BlockSym { ; CHECK: Kind: S_BLOCK32 {{.*}} ; CHECK: BlockName: ; CHECK: } -; CHECK: LocalSym { -; CHECK: VarName: localH -; CHECK: } ; CHECK: ScopeEndSym { ; CHECK: Kind: S_END {{.*}} ; CHECK: }