llvm.org GIT mirror llvm / 05ef777
Merging r310604: ------------------------------------------------------------------------ r310604 | niravd | 2017-08-10 08:12:32 -0700 (Thu, 10 Aug 2017) | 13 lines [X86] Keep dependencies when constructing loads in combineStore Summary: Preserve chain dependecies between old and new loads constructed to prevent loads from reordering below later stores. Fixes PR34088. Reviewers: craig.topper, spatel, RKSimon, efriedma Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D36528 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_50@310678 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 3 years ago
4 changed file(s) with 62 addition(s) and 12 deletion(s). Raw diff Collapse all Expand all
12191219 /// If an existing load has uses of its chain, create a token factor node with
12201220 /// that chain and the new memory node's chain and update users of the old
12211221 /// chain to the token factor. This ensures that the new memory node will have
1222 /// the same relative memory dependency position as the old load.
1223 void makeEquivalentMemoryOrdering(LoadSDNode *Old, SDValue New);
1222 /// the same relative memory dependency position as the old load. Returns the
1223 /// new merged load chain.
1224 SDValue makeEquivalentMemoryOrdering(LoadSDNode *Old, SDValue New);
12241225
12251226 /// Topological-sort the AllNodes list and a
12261227 /// assign a unique node id for each node in the DAG based on their
72617261 AddDbgValue(I, ToNode, false);
72627262 }
72637263
7264 void SelectionDAG::makeEquivalentMemoryOrdering(LoadSDNode *OldLoad,
7265 SDValue NewMemOp) {
7264 SDValue SelectionDAG::makeEquivalentMemoryOrdering(LoadSDNode *OldLoad,
7265 SDValue NewMemOp) {
72667266 assert(isa(NewMemOp.getNode()) && "Expected a memop node");
7267 if (!OldLoad->hasAnyUseOfValue(1))
7268 return;
7269
72707267 // The new memory operation must have the same position as the old load in
72717268 // terms of memory dependency. Create a TokenFactor for the old load and new
72727269 // memory operation and update uses of the old load's output chain to use that
72737270 // TokenFactor.
72747271 SDValue OldChain = SDValue(OldLoad, 1);
72757272 SDValue NewChain = SDValue(NewMemOp.getNode(), 1);
7273 if (!OldLoad->hasAnyUseOfValue(1))
7274 return NewChain;
7275
72767276 SDValue TokenFactor =
72777277 getNode(ISD::TokenFactor, SDLoc(OldLoad), MVT::Other, OldChain, NewChain);
72787278 ReplaceAllUsesOfValueWith(OldChain, TokenFactor);
72797279 UpdateNodeOperands(TokenFactor.getNode(), OldChain, NewChain);
7280 return TokenFactor;
72807281 }
72817282
72827283 //===----------------------------------------------------------------------===//
3338533385 SDValue NewLd = DAG.getLoad(LdVT, LdDL, Ld->getChain(), Ld->getBasePtr(),
3338633386 Ld->getPointerInfo(), Ld->getAlignment(),
3338733387 Ld->getMemOperand()->getFlags());
33388 SDValue NewChain = NewLd.getValue(1);
33388 // Make sure new load is placed in same chain order.
33389 SDValue NewChain = DAG.makeEquivalentMemoryOrdering(Ld, NewLd);
3338933390 if (TokenFactorIndex >= 0) {
3339033391 Ops.push_back(NewChain);
3339133392 NewChain = DAG.getNode(ISD::TokenFactor, LdDL, MVT::Other, Ops);
3340633407 Ld->getPointerInfo().getWithOffset(4),
3340733408 MinAlign(Ld->getAlignment(), 4),
3340833409 Ld->getMemOperand()->getFlags());
33409
33410 SDValue NewChain = LoLd.getValue(1);
33410 // Make sure new loads are placed in same chain order.
33411 SDValue NewChain = DAG.makeEquivalentMemoryOrdering(Ld, LoLd);
33412 NewChain = DAG.makeEquivalentMemoryOrdering(Ld, HiLd);
33413
3341133414 if (TokenFactorIndex >= 0) {
33412 Ops.push_back(LoLd);
33413 Ops.push_back(HiLd);
33415 Ops.push_back(NewChain);
3341433416 NewChain = DAG.getNode(ISD::TokenFactor, LdDL, MVT::Other, Ops);
3341533417 }
3341633418
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc < %s -mtriple=i686-unknown -mcpu=pentium4 | FileCheck %s
2
3 %struct.Foo = type { i32, %struct.Bar }
4 %struct.Bar = type { i32, %struct.Buffer, i32 }
5 %struct.Buffer = type { i8*, i32 }
6
7 ; This test checks that the load of store %2 is not dropped.
8 ;
9 define i32 @pr34088() local_unnamed_addr {
10 ; CHECK-LABEL: pr34088:
11 ; CHECK: # BB#0: # %entry
12 ; CHECK-NEXT: pushl %ebp
13 ; CHECK-NEXT: .Lcfi0:
14 ; CHECK-NEXT: .cfi_def_cfa_offset 8
15 ; CHECK-NEXT: .Lcfi1:
16 ; CHECK-NEXT: .cfi_offset %ebp, -8
17 ; CHECK-NEXT: movl %esp, %ebp
18 ; CHECK-NEXT: .Lcfi2:
19 ; CHECK-NEXT: .cfi_def_cfa_register %ebp
20 ; CHECK-NEXT: andl $-16, %esp
21 ; CHECK-NEXT: subl $32, %esp
22 ; CHECK-NEXT: xorps %xmm0, %xmm0
23 ; CHECK-NEXT: movaps {{.*#+}} xmm1 = [205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205]
24 ; CHECK-NEXT: xorl %eax, %eax
25 ; CHECK-NEXT: movaps %xmm0, (%esp)
26 ; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
27 ; CHECK-NEXT: movaps %xmm1, (%esp)
28 ; CHECK-NEXT: movl $-842150451, {{[0-9]+}}(%esp) # imm = 0xCDCDCDCD
29 ; CHECK-NEXT: movsd %xmm0, {{[0-9]+}}(%esp)
30 ; CHECK-NEXT: movl %ebp, %esp
31 ; CHECK-NEXT: popl %ebp
32 ; CHECK-NEXT: retl
33 entry:
34 %foo = alloca %struct.Foo, align 4
35 %0 = bitcast %struct.Foo* %foo to i8*
36 call void @llvm.memset.p0i8.i32(i8* nonnull %0, i8 0, i32 20, i32 4, i1 false)
37 %buffer1 = getelementptr inbounds %struct.Foo, %struct.Foo* %foo, i32 0, i32 1, i32 1
38 %1 = bitcast %struct.Buffer* %buffer1 to i64*
39 %2 = load i64, i64* %1, align 4
40 call void @llvm.memset.p0i8.i32(i8* nonnull %0, i8 -51, i32 20, i32 4, i1 false)
41 store i64 %2, i64* %1, align 4
42 ret i32 0
43 }
44
45 declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i32, i1)