llvm.org GIT mirror llvm / 8bf245f
[MemCpyOpt] Update to new API for memory intrinsic alignment Summary: This change is part of step five in the series of changes to remove alignment argument from memcpy/memmove/memset in favour of alignment attributes. In particular, this changes the MemCpyOpt pass to cease using: 1) The old getAlignment() API of MemoryIntrinsic in favour of getting source & dest specific alignments through the new API. 2) The old IRBuilder CreateMemCpy/CreateMemMove single-alignment APIs in favour of the new API that allows setting source and destination alignments independently. We also add a few tests to fill gaps in the testing of this pass. Steps: Step 1) Remove alignment parameter and create alignment parameter attributes for memcpy/memmove/memset. ( rL322965, rC322964, rL322963 ) Step 2) Expand the IRBuilder API to allow creation of memcpy/memmove with differing source and dest alignments. ( rL323597 ) Step 3) Update Clang to use the new IRBuilder API. ( rC323617 ) Step 4) Update Polly to use the new IRBuilder API. ( rL323618 ) Step 5) Update LLVM passes that create memcpy/memmove calls to use the new IRBuilder API, and those that use use MemIntrinsicInst::[get|set]Alignment() to use [get|set]DestAlignment() and [get|set]SourceAlignment() instead. ( rL323886, rL323891, rL324148, rL324273, rL324278, rL324384, rL324395, rL324402, rL324626, rL324642, rL324653, rL324654, rL324773, rL324774, rL324781, rL324784, rL324955, rL324960, rL325816, rL327398, rL327421 ) Step 6) Remove the single-alignment IRBuilder API for memcpy/memmove, and the MemIntrinsicInst::[get|set]Alignment() methods. Reference http://lists.llvm.org/pipermail/llvm-dev/2015-August/089384.html http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20151109/312083.html git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328097 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Neilson 1 year, 7 months ago
3 changed file(s) with 78 addition(s) and 26 deletion(s). Raw diff Collapse all Expand all
262262
263263 void addMemSet(int64_t OffsetFromFirst, MemSetInst *MSI) {
264264 int64_t Size = cast(MSI->getLength())->getZExtValue();
265 addRange(OffsetFromFirst, Size, MSI->getDest(), MSI->getAlignment(), MSI);
265 addRange(OffsetFromFirst, Size, MSI->getDest(), MSI->getDestAlignment(), MSI);
266266 }
267267
268268 void addRange(int64_t Start, int64_t Size, Value *Ptr,
497497 return AMemSet;
498498 }
499499
500 static unsigned findCommonAlignment(const DataLayout &DL, const StoreInst *SI,
501 const LoadInst *LI) {
500 static unsigned findStoreAlignment(const DataLayout &DL, const StoreInst *SI) {
502501 unsigned StoreAlign = SI->getAlignment();
503502 if (!StoreAlign)
504503 StoreAlign = DL.getABITypeAlignment(SI->getOperand(0)->getType());
504 return StoreAlign;
505 }
506
507 static unsigned findLoadAlignment(const DataLayout &DL, const LoadInst *LI) {
505508 unsigned LoadAlign = LI->getAlignment();
506509 if (!LoadAlign)
507510 LoadAlign = DL.getABITypeAlignment(LI->getType());
508
509 return std::min(StoreAlign, LoadAlign);
511 return LoadAlign;
512 }
513
514 static unsigned findCommonAlignment(const DataLayout &DL, const StoreInst *SI,
515 const LoadInst *LI) {
516 unsigned StoreAlign = findStoreAlignment(DL, SI);
517 unsigned LoadAlign = findLoadAlignment(DL, LI);
518 return MinAlign(StoreAlign, LoadAlign);
510519 }
511520
512521 // This method try to lift a store instruction before position P.
655664 if (!AA.isNoAlias(MemoryLocation::get(SI), LoadLoc))
656665 UseMemMove = true;
657666
658 unsigned Align = findCommonAlignment(DL, SI, LI);
659667 uint64_t Size = DL.getTypeStoreSize(T);
660668
661669 IRBuilder<> Builder(P);
662670 Instruction *M;
663671 if (UseMemMove)
664 M = Builder.CreateMemMove(SI->getPointerOperand(),
665 LI->getPointerOperand(), Size,
666 Align, SI->isVolatile());
672 M = Builder.CreateMemMove(
673 SI->getPointerOperand(), findStoreAlignment(DL, SI),
674 LI->getPointerOperand(), findLoadAlignment(DL, LI), Size,
675 SI->isVolatile());
667676 else
668 M = Builder.CreateMemCpy(SI->getPointerOperand(),
669 LI->getPointerOperand(), Size,
670 Align, SI->isVolatile());
677 M = Builder.CreateMemCpy(
678 SI->getPointerOperand(), findStoreAlignment(DL, SI),
679 LI->getPointerOperand(), findLoadAlignment(DL, LI), Size,
680 SI->isVolatile());
671681
672682 DEBUG(dbgs() << "Promoting " << *LI << " to " << *SI
673683 << " => " << *M << "\n");
10461056
10471057 // If all checks passed, then we can transform M.
10481058
1049 // Make sure to use the lesser of the alignment of the source and the dest
1050 // since we're changing where we're reading from, but don't want to increase
1051 // the alignment past what can be read from or written to.
10521059 // TODO: Is this worth it if we're creating a less aligned memcpy? For
10531060 // example we could be moving from movaps -> movq on x86.
1054 unsigned Align = std::min(MDep->getAlignment(), M->getAlignment());
1055
10561061 IRBuilder<> Builder(M);
10571062 if (UseMemMove)
1058 Builder.CreateMemMove(M->getRawDest(), MDep->getRawSource(), M->getLength(),
1059 Align, M->isVolatile());
1063 Builder.CreateMemMove(M->getRawDest(), M->getDestAlignment(),
1064 MDep->getRawSource(), MDep->getSourceAlignment(),
1065 M->getLength(), M->isVolatile());
10601066 else
1061 Builder.CreateMemCpy(M->getRawDest(), MDep->getRawSource(), M->getLength(),
1062 Align, M->isVolatile());
1067 Builder.CreateMemCpy(M->getRawDest(), M->getDestAlignment(),
1068 MDep->getRawSource(), MDep->getSourceAlignment(),
1069 M->getLength(), M->isVolatile());
10631070
10641071 // Remove the instruction we're replacing.
10651072 MD->removeInstruction(M);
11051112 // If Dest is aligned, and SrcSize is constant, use the minimum alignment
11061113 // of the sum.
11071114 const unsigned DestAlign =
1108 std::max(MemSet->getAlignment(), MemCpy->getAlignment());
1115 std::max(MemSet->getDestAlignment(), MemCpy->getDestAlignment());
11091116 if (DestAlign > 1)
11101117 if (ConstantInt *SrcSizeC = dyn_cast(SrcSize))
11111118 Align = MinAlign(SrcSizeC->getZExtValue(), DestAlign);
11651172
11661173 IRBuilder<> Builder(MemCpy);
11671174 Builder.CreateMemSet(MemCpy->getRawDest(), MemSet->getOperand(1),
1168 CopySize, MemCpy->getAlignment());
1175 CopySize, MemCpy->getDestAlignment());
11691176 return true;
11701177 }
11711178
11911198 if (Value *ByteVal = isBytewiseValue(GV->getInitializer())) {
11921199 IRBuilder<> Builder(M);
11931200 Builder.CreateMemSet(M->getRawDest(), ByteVal, M->getLength(),
1194 M->getAlignment(), false);
1201 M->getDestAlignment(), false);
11951202 MD->removeInstruction(M);
11961203 M->eraseFromParent();
11971204 ++NumCpyToSet;
12201227 // d) memcpy from a just-memset'd source can be turned into memset.
12211228 if (DepInfo.isClobber()) {
12221229 if (CallInst *C = dyn_cast(DepInfo.getInst())) {
1230 // FIXME: Can we pass in either of dest/src alignment here instead
1231 // of conservatively taking the minimum?
1232 unsigned Align = MinAlign(M->getDestAlignment(), M->getSourceAlignment());
12231233 if (performCallSlotOptzn(M, M->getDest(), M->getSource(),
1224 CopySize->getZExtValue(), M->getAlignment(),
1234 CopySize->getZExtValue(), Align,
12251235 C)) {
12261236 MD->removeInstruction(M);
12271237 M->eraseFromParent();
13361346 // source of the memcpy to the alignment we need. If we fail, we bail out.
13371347 AssumptionCache &AC = LookupAssumptionCache();
13381348 DominatorTree &DT = LookupDomTree();
1339 if (MDep->getAlignment() < ByValAlign &&
1349 if (MDep->getSourceAlignment() < ByValAlign &&
13401350 getOrEnforceKnownAlignment(MDep->getSource(), ByValAlign, DL,
13411351 CS.getInstruction(), &AC, &DT) < ByValAlign)
13421352 return false;
11 ; RUN: opt -basicaa -scoped-noalias -memcpyopt -S %s | FileCheck %s
22
33 %T = type { i8, i32 }
4
5 ; Ensure load-store forwarding of an aggregate is interpreted as
6 ; a memmove when the source and dest may alias
7 define void @test_memmove(%T* align 8 %a, %T* align 16 %b) {
8 ; CHECK-LABEL: @test_memmove(
9 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast %T* [[B:%.*]] to i8*
10 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast %T* [[A:%.*]] to i8*
11 ; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 16 [[TMP1]], i8* align 8 [[TMP2]], i64 8, i1 false)
12 ; CHECK-NEXT: ret void
13 ;
14 %val = load %T, %T* %a, align 8
15 store %T %val, %T* %b, align 16
16 ret void
17 }
18
19 ; Ensure load-store forwarding of an aggregate is interpreted as
20 ; a memcpy when the source and dest do not alias
21 define void @test_memcpy(%T* noalias align 8 %a, %T* noalias align 16 %b) {
22 ; CHECK-LABEL: @test_memcpy(
23 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast %T* [[B:%.*]] to i8*
24 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast %T* [[A:%.*]] to i8*
25 ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 [[TMP1]], i8* align 8 [[TMP2]], i64 8, i1 false)
26 ; CHECK-NEXT: ret void
27 ;
28 %val = load %T, %T* %a, align 8
29 store %T %val, %T* %b, align 16
30 ret void
31 }
432
533 ; memcpy(%d, %a) should not be generated since store2 may-aliases load %a.
634 define void @f(%T* %a, %T* %b, %T* %c, %T* %d) {
4242
4343 ; CHECK-LABEL: @test2(
4444 ; CHECK-NEXT: call void @llvm.memmove{{.*}}(i8* align 16 %Q, i8* align 16 %P
45 ; CHECK-NEXT: ret void
46 }
47
48 ; The intermediate alloca and one of the memcpy's should be eliminated, the
49 ; other should be related with a memcpy.
50 define void @test2_memcpy(i8* noalias %P, i8* noalias %Q) nounwind {
51 %memtmp = alloca %0, align 16
52 %R = bitcast %0* %memtmp to i8*
53 call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %R, i8* align 16 %P, i32 32, i1 false)
54 call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %Q, i8* align 16 %R, i32 32, i1 false)
55 ret void
56
57 ; CHECK-LABEL: @test2_memcpy(
58 ; CHECK-NEXT: call void @llvm.memcpy{{.*}}(i8* align 16 %Q, i8* align 16 %P
4559 ; CHECK-NEXT: ret void
4660 }
4761