1 //=======- CaptureTrackingTest.cpp - Unit test for the Capture Tracking ---===//
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
7 //===----------------------------------------------------------------------===//
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"
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)
27 define void @test_few_uses(i8* %arg) {
28 call void @doesnt_capture(i8* %arg, i8* %arg, i8* %arg, i8* %arg, i8* %arg)
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)
50 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
51 ASSERT_TRUE(M
) << "Bad assembly?";
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
));
62 BasicBlock
*EntryBB
= &F
->getEntryBlock();
65 Instruction
*Ret
= EntryBB
->getTerminator();
66 ASSERT_TRUE(isa
<ReturnInst
>(Ret
));
67 ASSERT_FALSE(PointerMayBeCapturedBefore(Arg
, true, true, Ret
, &DT
, false,
69 ASSERT_TRUE(PointerMayBeCapturedBefore(Arg
, true, true, Ret
, &DT
, false,
73 Test("test_few_uses", 6, 4);
74 Test("test_many_uses", 50, 30);
77 struct CollectingCaptureTracker
: public CaptureTracker
{
78 SmallVector
<const Use
*, 4> Captures
;
79 void tooManyUses() override
{ }
80 bool captured(const Use
*U
) override
{
81 Captures
.push_back(U
);
86 TEST(CaptureTracking
, MultipleUsesInSameInstruction
) {
87 StringRef Assembly
= R
"(
88 declare void @call(i8*, i8*, i8*)
90 define void @test(i8* %arg, i8** %ptr) {
91 call void @call(i8* %arg, i8* nocapture %arg, i8* %arg) [ "bundle
"(i8* %arg) ]
92 cmpxchg i8** %ptr, i8* %arg, i8* %arg acq_rel monotonic
93 icmp eq i8* %arg, %arg
100 auto M
= parseAssemblyString(Assembly
, Error
, Context
);
101 ASSERT_TRUE(M
) << "Bad assembly?";
103 Function
*F
= M
->getFunction("test");
104 Value
*Arg
= &*F
->arg_begin();
105 BasicBlock
*BB
= &F
->getEntryBlock();
106 Instruction
*Call
= &*BB
->begin();
107 Instruction
*CmpXChg
= Call
->getNextNode();
108 Instruction
*ICmp
= CmpXChg
->getNextNode();
110 CollectingCaptureTracker CT
;
111 PointerMayBeCaptured(Arg
, &CT
);
112 EXPECT_EQ(7u, CT
.Captures
.size());
114 EXPECT_EQ(Call
, CT
.Captures
[0]->getUser());
115 EXPECT_EQ(0u, CT
.Captures
[0]->getOperandNo());
117 EXPECT_EQ(Call
, CT
.Captures
[1]->getUser());
118 EXPECT_EQ(2u, CT
.Captures
[1]->getOperandNo());
119 // Operand bundle arg
120 EXPECT_EQ(Call
, CT
.Captures
[2]->getUser());
121 EXPECT_EQ(3u, CT
.Captures
[2]->getOperandNo());
122 // Cmpxchg compare operand
123 EXPECT_EQ(CmpXChg
, CT
.Captures
[3]->getUser());
124 EXPECT_EQ(1u, CT
.Captures
[3]->getOperandNo());
125 // Cmpxchg new value operand
126 EXPECT_EQ(CmpXChg
, CT
.Captures
[4]->getUser());
127 EXPECT_EQ(2u, CT
.Captures
[4]->getOperandNo());
128 // ICmp first operand
129 EXPECT_EQ(ICmp
, CT
.Captures
[5]->getUser());
130 EXPECT_EQ(0u, CT
.Captures
[5]->getOperandNo());
131 // ICmp second operand
132 EXPECT_EQ(ICmp
, CT
.Captures
[6]->getUser());
133 EXPECT_EQ(1u, CT
.Captures
[6]->getOperandNo());