1 //===- DDGTest.cpp - DDGAnalysis unit tests -------------------------------===//
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/DDG.h"
10 #include "llvm/Analysis/AliasAnalysis.h"
11 #include "llvm/Analysis/AssumptionCache.h"
12 #include "llvm/Analysis/BasicAliasAnalysis.h"
13 #include "llvm/Analysis/LoopInfo.h"
14 #include "llvm/Analysis/ScalarEvolution.h"
15 #include "llvm/Analysis/TargetLibraryInfo.h"
16 #include "llvm/AsmParser/Parser.h"
17 #include "llvm/IR/Dominators.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "gtest/gtest.h"
20
21 using namespace llvm;
22
23 /// Build the DDG analysis for a loop and run the given test \p Test.
runTest(Module & M,StringRef FuncName,function_ref<void (Function & F,LoopInfo & LI,DependenceInfo & DI,ScalarEvolution & SE)> Test)24 static void runTest(Module &M, StringRef FuncName,
25 function_ref<void(Function &F, LoopInfo &LI,
26 DependenceInfo &DI, ScalarEvolution &SE)>
27 Test) {
28 auto *F = M.getFunction(FuncName);
29 ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
30
31 TargetLibraryInfoImpl TLII;
32 TargetLibraryInfo TLI(TLII);
33 AssumptionCache AC(*F);
34 DominatorTree DT(*F);
35 LoopInfo LI(DT);
36 ScalarEvolution SE(*F, TLI, AC, DT, LI);
37 AAResults AA(TLI);
38 DependenceInfo DI(F, &AA, &SE, &LI);
39 Test(*F, LI, DI, SE);
40 }
41
makeLLVMModule(LLVMContext & Context,const char * ModuleStr)42 static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
43 const char *ModuleStr) {
44 SMDiagnostic Err;
45 return parseAssemblyString(ModuleStr, Err, Context);
46 }
47
TEST(DDGTest,getDependencies)48 TEST(DDGTest, getDependencies) {
49 const char *ModuleStr =
50 "target datalayout = \"e-m:e-i64:64-n32:64\"\n"
51 "target triple = \"powerpc64le-unknown-linux-gnu\"\n"
52 "\n"
53 "define dso_local void @foo(i32 signext %n, i32* noalias %A, i32* "
54 "noalias %B) {\n"
55 "entry:\n"
56 " %cmp1 = icmp sgt i32 %n, 0\n"
57 " br i1 %cmp1, label %for.body.preheader, label %for.end\n"
58 "\n"
59 "for.body.preheader:\n"
60 " %wide.trip.count = zext i32 %n to i64\n"
61 " br label %for.body\n"
62 " \n"
63 " for.body:\n"
64 " %indvars.iv = phi i64 [ 0, %for.body.preheader ], [ "
65 "%indvars.iv.next, %for.body ]\n"
66 " %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n"
67 " %0 = trunc i64 %indvars.iv to i32\n"
68 " store i32 %0, i32* %arrayidx, align 4\n"
69 " %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
70 " %arrayidx2 = getelementptr inbounds i32, i32* %A, i64 "
71 "%indvars.iv.next\n"
72 " %1 = load i32, i32* %arrayidx2, align 4\n"
73 " %add3 = add nsw i32 %1, 1\n"
74 " %arrayidx5 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv\n"
75 " store i32 %add3, i32* %arrayidx5, align 4\n"
76 " %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count\n"
77 " br i1 %exitcond, label %for.body, label %for.end.loopexit\n"
78 "\n"
79 "for.end.loopexit:\n"
80 " br label %for.end\n"
81 "\n"
82 "for.end:\n"
83 " ret void\n"
84 "}\n";
85
86 LLVMContext Context;
87 std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
88
89 runTest(
90 *M, "foo",
91 [&](Function &F, LoopInfo &LI, DependenceInfo &DI, ScalarEvolution &SE) {
92 Loop *L = *LI.begin();
93 assert(L && "expected the loop to be identified.");
94
95 DataDependenceGraph DDG(*L, LI, DI);
96
97 // Collect all the nodes that have an outgoing memory edge
98 // while collecting all memory edges as well. There should
99 // only be one node with an outgoing memory edge and there
100 // should only be one memory edge in the entire graph.
101 std::vector<DDGNode *> DependenceSourceNodes;
102 std::vector<DDGEdge *> MemoryEdges;
103 for (DDGNode *N : DDG) {
104 for (DDGEdge *E : *N) {
105 bool SourceAdded = false;
106 if (E->isMemoryDependence()) {
107 MemoryEdges.push_back(E);
108 if (!SourceAdded) {
109 DependenceSourceNodes.push_back(N);
110 SourceAdded = true;
111 }
112 }
113 }
114 }
115
116 EXPECT_EQ(DependenceSourceNodes.size(), 1ull);
117 EXPECT_EQ(MemoryEdges.size(), 1ull);
118
119 DataDependenceGraph::DependenceList DL;
120 DDG.getDependencies(*DependenceSourceNodes.back(),
121 MemoryEdges.back()->getTargetNode(), DL);
122
123 EXPECT_EQ(DL.size(), 1ull);
124 EXPECT_TRUE(DL.back()->isAnti());
125 EXPECT_EQ(DL.back()->getLevels(), 1u);
126 EXPECT_NE(DL.back()->getDistance(1), nullptr);
127 EXPECT_EQ(DL.back()->getDistance(1),
128 SE.getOne(DL.back()->getDistance(1)->getType()));
129 });
130 }
131