xref: /llvm-project/llvm/unittests/Analysis/CaptureTrackingTest.cpp (revision 0c2b09a9b6246aebd301ad75b5d78ac1e7daa9c4)
1 //=======- CaptureTrackingTest.cpp - Unit test for the Capture Tracking ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Analysis/CaptureTracking.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/Dominators.h"
12 #include "llvm/IR/Instructions.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "gtest/gtest.h"
17 
18 using namespace llvm;
19 
20 TEST(CaptureTracking, MaxUsesToExplore) {
21   StringRef Assembly = R"(
22     ; Function Attrs: nounwind ssp uwtable
23     declare void @doesnt_capture(i8* nocapture, i8* nocapture, i8* nocapture,
24                                  i8* nocapture, i8* nocapture)
25 
26     ; %arg has 5 uses
27     define void @test_few_uses(i8* %arg) {
28       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
29       ret void
30     }
31 
32     ; %arg has 50 uses
33     define void @test_many_uses(i8* %arg) {
34       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
35       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
36       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
37       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
38       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
39       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
40       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
41       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
42       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
43       call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
44       ret void
45     }
46   )";
47 
48   LLVMContext Context;
49   SMDiagnostic Error;
50   auto M = parseAssemblyString(Assembly, Error, Context);
51   ASSERT_TRUE(M) << "Bad assembly?";
52 
53   auto Test = [&M](const char *FName, unsigned FalseMaxUsesLimit,
54                    unsigned TrueMaxUsesLimit) {
55     Function *F = M->getFunction(FName);
56     ASSERT_NE(F, nullptr);
57     Value *Arg = &*F->arg_begin();
58     ASSERT_NE(Arg, nullptr);
59     ASSERT_FALSE(PointerMayBeCaptured(Arg, true, true, FalseMaxUsesLimit));
60     ASSERT_TRUE(PointerMayBeCaptured(Arg, true, true, TrueMaxUsesLimit));
61 
62     BasicBlock *EntryBB = &F->getEntryBlock();
63     DominatorTree DT(*F);
64 
65     Instruction *Ret = EntryBB->getTerminator();
66     ASSERT_TRUE(isa<ReturnInst>(Ret));
67     ASSERT_FALSE(PointerMayBeCapturedBefore(Arg, true, true, Ret, &DT, false,
68                                             FalseMaxUsesLimit));
69     ASSERT_TRUE(PointerMayBeCapturedBefore(Arg, true, true, Ret, &DT, false,
70                                            TrueMaxUsesLimit));
71   };
72 
73   Test("test_few_uses", 6, 4);
74   Test("test_many_uses", 50, 30);
75 }
76