llvm.org GIT mirror llvm / 0edfaf6
[CodeExtractor] Fix sinking of allocas with multiple bitcast uses (PR42451) An alloca which can be sunk into the extraction region may have more than one bitcast use. Move these uses along with the alloca to prevent use-before-def. Testing: check-llvm, stage2 build of clang Fixes llvm.org/PR42451. Differential Revision: https://reviews.llvm.org/D64463 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365660 91177308-0d34-0410-b5e6-96231b3b80d8 Vedant Kumar 2 months ago
3 changed file(s) with 104 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
518518 if (Bitcasts.empty())
519519 continue;
520520
521 Instruction *BitcastAddr = Bitcasts.back();
522 const LifetimeMarkerInfo &LMI = BitcastLifetimeInfo.back();
523 assert(LMI.LifeStart &&
524 "Unsafe to sink bitcast without lifetime markers");
525 moveOrIgnoreLifetimeMarkers(LMI);
526 if (!definedInRegion(Blocks, BitcastAddr)) {
527 LLVM_DEBUG(dbgs() << "Sinking bitcast-of-alloca: " << *BitcastAddr
528 << "\n");
529 SinkCands.insert(BitcastAddr);
530 }
531521 LLVM_DEBUG(dbgs() << "Sinking alloca (via bitcast): " << *AI << "\n");
532522 SinkCands.insert(AI);
523 for (unsigned I = 0, E = Bitcasts.size(); I != E; ++I) {
524 Instruction *BitcastAddr = Bitcasts[I];
525 const LifetimeMarkerInfo &LMI = BitcastLifetimeInfo[I];
526 assert(LMI.LifeStart &&
527 "Unsafe to sink bitcast without lifetime markers");
528 moveOrIgnoreLifetimeMarkers(LMI);
529 if (!definedInRegion(Blocks, BitcastAddr)) {
530 LLVM_DEBUG(dbgs() << "Sinking bitcast-of-alloca: " << *BitcastAddr
531 << "\n");
532 SinkCands.insert(BitcastAddr);
533 }
534 }
533535 }
534536 }
535537 }
14301432 findInputsOutputs(inputs, outputs, SinkingCands);
14311433
14321434 // Now sink all instructions which only have non-phi uses inside the region.
1433 for (auto *II : SinkingCands)
1434 cast(II)->moveBefore(*newFuncRoot,
1435 newFuncRoot->getFirstInsertionPt());
1435 // Group the allocas at the start of the block, so that any bitcast uses of
1436 // the allocas are well-defined.
1437 AllocaInst *FirstSunkAlloca = nullptr;
1438 for (auto *II : SinkingCands) {
1439 if (auto *AI = dyn_cast(II)) {
1440 AI->moveBefore(*newFuncRoot, newFuncRoot->getFirstInsertionPt());
1441 if (!FirstSunkAlloca)
1442 FirstSunkAlloca = AI;
1443 }
1444 }
1445 assert((SinkingCands.empty() || FirstSunkAlloca) &&
1446 "Did not expect a sink candidate without any allocas");
1447 for (auto *II : SinkingCands) {
1448 if (!isa(II)) {
1449 cast(II)->moveAfter(FirstSunkAlloca);
1450 }
1451 }
14361452
14371453 if (!HoistingCands.empty()) {
14381454 auto *HoistToBlock = findOrCreateBlockForHoisting(CommonExit);
4444 ; CHECK-LABEL: define internal void @_Z3foov.1.
4545 ; CHECK: newFuncRoot:
4646 ; CHECK-NEXT: alloca
47 ; CHECK-NEXT: alloca
4748 ; CHECK-NEXT: bitcast
4849 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8
49 ; CHECK-NEXT: alloca
5050 ; CHECK-NEXT: bitcast
5151 ; CHECK-NEXT: call void @llvm.lifetime.start.p0i8
5252 ; CHECK: call void @llvm.lifetime.end.p0i8
0 ; RUN: opt -hotcoldsplit -hotcoldsplit-threshold=-1 -S < %s | FileCheck %s
1
2 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-apple-macosx10.14.0"
4
5 @c = common global i32 0, align 4
6 @h = common global i32 0, align 4
7
8 declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
9
10 declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
11
12 declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #1
13
14 declare i32* @m()
15
16 ; CHECK-LABEL: define void @main()
17 ; CHECK-NEXT: %.sroa.4.i = alloca [20 x i8], align 2
18 ; CHECK-NEXT: %.sroa.5.i = alloca [6 x i8], align 8
19 ; CHECK-NEXT: %1 = bitcast [6 x i8]* %.sroa.5.i to i8*
20
21 define void @main() #0 {
22 %.sroa.4.i = alloca [20 x i8], align 2
23 %.sroa.5.i = alloca [6 x i8], align 8
24 %1 = bitcast [6 x i8]* %.sroa.5.i to i8*
25 %2 = load i32, i32* @h, align 4, !tbaa !4
26 %3 = icmp ne i32 %2, 0
27 br i1 %3, label %12, label %4
28
29 4: ; preds = %0
30 %5 = call i32* @m() #3
31 %.sroa.4.0..sroa_idx21.i = getelementptr inbounds [20 x i8], [20 x i8]* %.sroa.4.i, i64 0, i64 0
32 call void @llvm.lifetime.start.p0i8(i64 20, i8* %.sroa.4.0..sroa_idx21.i) #3
33 %.sroa.5.0..sroa_idx16.i = getelementptr inbounds [6 x i8], [6 x i8]* %.sroa.5.i, i64 0, i64 0
34 call void @llvm.lifetime.start.p0i8(i64 6, i8* %.sroa.5.0..sroa_idx16.i) #3
35 call void @llvm.memset.p0i8.i64(i8* align 2 %.sroa.4.0..sroa_idx21.i, i8 0, i64 20, i1 false) #3
36 call void @llvm.memset.p0i8.i64(i8* align 8 %.sroa.5.0..sroa_idx16.i, i8 0, i64 6, i1 false) #3
37 %6 = load i32, i32* @c, align 4, !tbaa !4
38 %7 = trunc i32 %6 to i16
39 call void @llvm.lifetime.end.p0i8(i64 20, i8* %.sroa.4.0..sroa_idx21.i) #3
40 call void @llvm.lifetime.end.p0i8(i64 6, i8* %.sroa.5.0..sroa_idx16.i) #3
41 call void @llvm.lifetime.start.p0i8(i64 6, i8* %1) #3
42 call void @llvm.memset.p0i8.i64(i8* align 1 %1, i8 3, i64 6, i1 false)
43 br label %8
44
45 8: ; preds = %8, %4
46 %.0.i = phi i32 [ 0, %4 ], [ %10, %8 ]
47 %9 = sext i32 %.0.i to i64
48 %10 = add nsw i32 %.0.i, 1
49 %11 = icmp slt i32 %10, 6
50 br i1 %11, label %8, label %l.exit
51
52 l.exit: ; preds = %8
53 call void @llvm.lifetime.end.p0i8(i64 6, i8* %1) #3
54 br label %12
55
56 12: ; preds = %l.exit, %0
57 %13 = phi i1 [ true, %0 ], [ true, %l.exit ]
58 ret void
59 }
60
61 attributes #0 = { cold }
62
63 !llvm.module.flags = !{!0, !1, !2}
64 !llvm.ident = !{!3}
65
66 !0 = !{i32 2, !"SDK Version", [2 x i32] [i32 10, i32 14]}
67 !1 = !{i32 1, !"wchar_size", i32 4}
68 !2 = !{i32 7, !"PIC Level", i32 2}
69 !3 = !{!"Apple clang version 11.0.0 (clang-1100.0.20.17)"}
70 !4 = !{!5, !5, i64 0}
71 !5 = !{!"int", !6, i64 0}
72 !6 = !{!"omnipotent char", !7, i64 0}
73 !7 = !{!"Simple C/C++ TBAA"}