llvm.org GIT mirror llvm / 9e1154c
Reverted r152620 - DSE: Shorten memset when a later store overwrites the start of it. There were all sorts of buildbot issues git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151621 91177308-0d34-0410-b5e6-96231b3b80d8 Pete Cooper 7 years ago
2 changed file(s) with 2 addition(s) and 137 deletion(s). Raw diff Collapse all Expand all
258258 }
259259 }
260260
261
262 /// isMemset - Returns true if this instruction is an intrinsic memset
263 static bool isMemset(Instruction *I) {
264 IntrinsicInst *II = dyn_cast(I);
265 return II && II->getIntrinsicID() == Intrinsic::memset;
266 }
267
268261 /// getStoredPointerOperand - Return the pointer that is being written to.
269262 static Value *getStoredPointerOperand(Instruction *I) {
270263 if (StoreInst *SI = dyn_cast(I))
316309 {
317310 OverwriteComplete,
318311 OverwriteEnd,
319 OverwriteStart,
320312 OverwriteUnknown
321313 };
322314 }
323315
324316 /// isOverwrite - Return 'OverwriteComplete' if a store to the 'Later' location
325317 /// completely overwrites a store to the 'Earlier' location.
326 /// 'OverwriteEnd' if the end of the 'Earlier' location is completely
327 /// overwritten by 'Later', 'OverWriteStart' if the start of 'Earlier'
328 /// is completely overwritten by 'Later' or 'OverwriteUnknown' if nothing
329 /// can be determined
318 /// 'OverwriteEnd' if the end of the 'Earlier' location is completely
319 /// overwritten by 'Later', or 'OverwriteUnknown' if nothing can be determined
330320 static OverwriteResult isOverwrite(const AliasAnalysis::Location &Later,
331321 const AliasAnalysis::Location &Earlier,
332322 AliasAnalysis &AA,
427417 LaterOff < int64_t(EarlierOff + Earlier.Size) &&
428418 int64_t(LaterOff + Later.Size) >= int64_t(EarlierOff + Earlier.Size))
429419 return OverwriteEnd;
430
431 // The other interesting case is if the later store overwrites the end of
432 // the earlier store
433 //
434 // |--earlier--|
435 // |-- later --|
436 //
437 // In this case we may want to trim the size of earlier to avoid generating
438 // writes to addresses which will definitely be overwritten later
439 if (EarlierOff >= LaterOff &&
440 EarlierOff < int64_t(LaterOff + Later.Size) &&
441 int64_t(EarlierOff + Earlier.Size) >= int64_t(LaterOff + Later.Size)) {
442 LaterOff = LaterOff + Later.Size;
443 return OverwriteStart;
444 }
445420
446421 // Otherwise, they don't completely overlap.
447422 return OverwriteUnknown;
613588 DepIntrinsic->setLength(TrimmedLength);
614589 MadeChange = true;
615590 }
616 } else if (OR == OverwriteStart && isMemset(DepWrite)) {
617 // TODO: base this on the target vector size so that if the earlier
618 // store was too small to get vector writes anyway then its likely
619 // a good idea to shorten it
620 // Power of 2 vector writes are probably always a bad idea to optimize
621 // as any store/memset/memcpy is likely using vector instructions so
622 // shortening it to not vector size is likely to be slower
623 // TODO: shorten memcpy and memmove by offsetting the source address.
624 MemIntrinsic* DepIntrinsic = cast(DepWrite);
625 unsigned DepWriteAlign = DepIntrinsic->getAlignment();
626 if (llvm::isPowerOf2_64(InstWriteOffset) ||
627 ((DepWriteAlign != 0) && InstWriteOffset % DepWriteAlign == 0)) {
628
629 DEBUG(dbgs() << "DSE: Remove Dead Store:\n OW START: "
630 << *DepWrite << "\n KILLER (offset "
631 << InstWriteOffset << ", "
632 << DepWriteOffset << ", "
633 << DepLoc.Size << ")"
634 << *Inst << '\n');
635
636 Value* DepWriteLength = DepIntrinsic->getLength();
637 Value* TrimmedLength = ConstantInt::get(DepWriteLength->getType(),
638 DepLoc.Size -
639 (InstWriteOffset -
640 DepWriteOffset));
641 DepIntrinsic->setLength(TrimmedLength);
642 const TargetData *TD = AA->getTargetData();
643 Type *IntPtrTy = TD->getIntPtrType(BB.getContext());
644 Value* Offset = ConstantInt::get(IntPtrTy,
645 InstWriteOffset - DepWriteOffset);
646 // Offset the start of the memset with a GEP. As the memset type is
647 // i8* a GEP will do this without needing to use ptrtoint, etc.
648 Value *Dest = GetElementPtrInst::Create(DepIntrinsic->getRawDest(),
649 Offset,
650 "",
651 DepWrite);
652 DepIntrinsic->setDest(Dest);
653 MadeChange = true;
654 }
655591 }
656592 }
657593
+0
-71
test/Transforms/DeadStoreElimination/OverwriteStoreStart.ll less more
None ; RUN: opt < %s -basicaa -dse -S | FileCheck %s
1 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
2
3 %struct.vec2 = type { <4 x i32>, <4 x i32> }
4 %struct.vec2plusi = type { <4 x i32>, <4 x i32>, i32 }
5
6 @glob1 = global %struct.vec2 zeroinitializer, align 16
7 @glob2 = global %struct.vec2plusi zeroinitializer, align 16
8
9 define void @write4to8(i32* nocapture %p) nounwind uwtable ssp {
10 ; CHECK: @write4to8
11 entry:
12 %arrayidx0 = getelementptr inbounds i32* %p, i64 1
13 %p3 = bitcast i32* %arrayidx0 to i8*
14 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %{{[0-9]+}}, i8 0, i64 24, i32 4, i1 false)
15 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
16 %arrayidx1 = getelementptr inbounds i32* %p, i64 1
17 store i32 1, i32* %arrayidx1, align 4
18 ret void
19 }
20
21 define void @write4to12(i32* nocapture %p) nounwind uwtable ssp {
22 ; CHECK: @write4to12
23 entry:
24 %arrayidx0 = getelementptr inbounds i32* %p, i64 1
25 %p3 = bitcast i32* %arrayidx0 to i8*
26 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %{{[0-9]+}}, i8 0, i64 20, i32 4, i1 false)
27 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
28 %arrayidx1 = bitcast i32* %arrayidx0 to i64*
29 store i64 1, i64* %arrayidx1, align 4
30 ret void
31 }
32
33 define void @write4to8_2(i32* nocapture %p) nounwind uwtable ssp {
34 ; CHECK: @write4to8_2
35 entry:
36 %arrayidx0 = getelementptr inbounds i32* %p, i64 1
37 %p3 = bitcast i32* %arrayidx0 to i8*
38 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %{{[0-9]+}}, i8 0, i64 24, i32 4, i1 false)
39 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
40 %arrayidx1 = bitcast i32* %p to i64*
41 store i64 1, i64* %arrayidx1, align 4
42 ret void
43 }
44
45 define void @dontwrite4to6(i32* nocapture %p) nounwind uwtable ssp {
46 ; CHECK: @dontwrite4to6
47 entry:
48 %arrayidx0 = getelementptr inbounds i32* %p, i64 1
49 %p3 = bitcast i32* %arrayidx0 to i8*
50 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
51 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
52 %arrayidx1 = bitcast i32* %arrayidx0 to i16*
53 store i16 1, i16* %arrayidx1, align 4
54 ret void
55 }
56
57 define void @write4to8_neg_gep(i32* nocapture %p) nounwind uwtable ssp {
58 ; CHECK: @write4to8_neg_gep
59 entry:
60 %arrayidx0 = getelementptr inbounds i32* %p, i64 -1
61 %p3 = bitcast i32* %arrayidx0 to i8*
62 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %{{[0-9]+}}, i8 0, i64 24, i32 4, i1 false)
63 call void @llvm.memset.p0i8.i64(i8* %p3, i8 0, i64 28, i32 4, i1 false)
64 %neg2 = getelementptr inbounds i32* %p, i64 -2
65 %arrayidx1 = bitcast i32* %neg2 to i64*
66 store i64 1, i64* %arrayidx1, align 4
67 ret void
68 }
69
70 declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind