blob: ab601222ae875230c523bff6b0d1678576defaac [file] [log] [blame]
Nick Lewyckyc8a15692011-02-20 08:38:20 +00001//===- Local.cpp - Unit tests for Local -----------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chandler Carruth130cec22012-12-04 10:23:08 +000010#include "llvm/Transforms/Utils/Local.h"
Reid Kleckner0fe506b2017-09-21 19:52:03 +000011#include "llvm/AsmParser/Parser.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000012#include "llvm/IR/BasicBlock.h"
Reid Kleckner0fe506b2017-09-21 19:52:03 +000013#include "llvm/IR/DIBuilder.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000014#include "llvm/IR/IRBuilder.h"
15#include "llvm/IR/Instructions.h"
Reid Kleckner0fe506b2017-09-21 19:52:03 +000016#include "llvm/IR/IntrinsicInst.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000017#include "llvm/IR/LLVMContext.h"
Reid Kleckner0fe506b2017-09-21 19:52:03 +000018#include "llvm/Support/SourceMgr.h"
Chandler Carruthaafe0912012-06-29 12:38:19 +000019#include "gtest/gtest.h"
20
Nick Lewyckyc8a15692011-02-20 08:38:20 +000021using namespace llvm;
22
23TEST(Local, RecursivelyDeleteDeadPHINodes) {
Mehdi Amini03b42e42016-04-14 21:59:01 +000024 LLVMContext C;
Nick Lewyckyc8a15692011-02-20 08:38:20 +000025
26 IRBuilder<> builder(C);
27
28 // Make blocks
29 BasicBlock *bb0 = BasicBlock::Create(C);
30 BasicBlock *bb1 = BasicBlock::Create(C);
31
32 builder.SetInsertPoint(bb0);
Jay Foad52131342011-03-30 11:28:46 +000033 PHINode *phi = builder.CreatePHI(Type::getInt32Ty(C), 2);
Nick Lewyckyc8a15692011-02-20 08:38:20 +000034 BranchInst *br0 = builder.CreateCondBr(builder.getTrue(), bb0, bb1);
35
36 builder.SetInsertPoint(bb1);
37 BranchInst *br1 = builder.CreateBr(bb0);
38
39 phi->addIncoming(phi, bb0);
40 phi->addIncoming(phi, bb1);
41
42 // The PHI will be removed
43 EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
44
45 // Make sure the blocks only contain the branches
46 EXPECT_EQ(&bb0->front(), br0);
47 EXPECT_EQ(&bb1->front(), br1);
48
Nick Lewycky183c24c2011-02-20 18:05:56 +000049 builder.SetInsertPoint(bb0);
Jay Foad52131342011-03-30 11:28:46 +000050 phi = builder.CreatePHI(Type::getInt32Ty(C), 0);
Nick Lewycky183c24c2011-02-20 18:05:56 +000051
52 EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
53
Duncan Sands6dcd49b2011-02-21 16:27:36 +000054 builder.SetInsertPoint(bb0);
Jay Foad52131342011-03-30 11:28:46 +000055 phi = builder.CreatePHI(Type::getInt32Ty(C), 0);
Duncan Sands6dcd49b2011-02-21 16:27:36 +000056 builder.CreateAdd(phi, phi);
57
58 EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
59
Nick Lewyckyc8a15692011-02-20 08:38:20 +000060 bb0->dropAllReferences();
61 bb1->dropAllReferences();
62 delete bb0;
63 delete bb1;
64}
Benjamin Kramerf175e042015-09-02 19:52:23 +000065
66TEST(Local, RemoveDuplicatePHINodes) {
Mehdi Amini03b42e42016-04-14 21:59:01 +000067 LLVMContext C;
Benjamin Kramerf175e042015-09-02 19:52:23 +000068 IRBuilder<> B(C);
69
70 std::unique_ptr<Function> F(
71 Function::Create(FunctionType::get(B.getVoidTy(), false),
72 GlobalValue::ExternalLinkage, "F"));
73 BasicBlock *Entry(BasicBlock::Create(C, "", F.get()));
74 BasicBlock *BB(BasicBlock::Create(C, "", F.get()));
75 BranchInst::Create(BB, Entry);
76
77 B.SetInsertPoint(BB);
78
79 AssertingVH<PHINode> P1 = B.CreatePHI(Type::getInt32Ty(C), 2);
80 P1->addIncoming(B.getInt32(42), Entry);
81
82 PHINode *P2 = B.CreatePHI(Type::getInt32Ty(C), 2);
83 P2->addIncoming(B.getInt32(42), Entry);
84
85 AssertingVH<PHINode> P3 = B.CreatePHI(Type::getInt32Ty(C), 2);
86 P3->addIncoming(B.getInt32(42), Entry);
87 P3->addIncoming(B.getInt32(23), BB);
88
89 PHINode *P4 = B.CreatePHI(Type::getInt32Ty(C), 2);
90 P4->addIncoming(B.getInt32(42), Entry);
91 P4->addIncoming(B.getInt32(23), BB);
92
93 P1->addIncoming(P3, BB);
94 P2->addIncoming(P4, BB);
95 BranchInst::Create(BB, BB);
96
97 // Verify that we can eliminate PHIs that become duplicates after chaning PHIs
98 // downstream.
99 EXPECT_TRUE(EliminateDuplicatePHINodes(BB));
100 EXPECT_EQ(3U, BB->size());
101}
Reid Kleckner0fe506b2017-09-21 19:52:03 +0000102
103std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
104 SMDiagnostic Err;
105 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
106 if (!Mod)
107 Err.print("UtilsTests", errs());
108 return Mod;
109}
110
111TEST(Local, ReplaceDbgDeclare) {
112 LLVMContext C;
113
114 // Original C source to get debug info for a local variable:
115 // void f() { int x; }
116 std::unique_ptr<Module> M = parseIR(
117 C,
118 "define void @f() !dbg !8 {\n"
119 "entry:\n"
120 " %x = alloca i32, align 4\n"
121 " call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata "
122 "!DIExpression()), !dbg !13\n"
123 " call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata "
124 "!DIExpression()), !dbg !13\n"
125 " ret void, !dbg !14\n"
126 "}\n"
127 "declare void @llvm.dbg.declare(metadata, metadata, metadata)\n"
128 "!llvm.dbg.cu = !{!0}\n"
129 "!llvm.module.flags = !{!3, !4}\n"
130 "!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "
131 "\"clang version 6.0.0 \", isOptimized: false, runtimeVersion: 0, "
132 "emissionKind: FullDebug, enums: !2)\n"
133 "!1 = !DIFile(filename: \"t2.c\", directory: \"foo\")\n"
134 "!2 = !{}\n"
135 "!3 = !{i32 2, !\"Dwarf Version\", i32 4}\n"
136 "!4 = !{i32 2, !\"Debug Info Version\", i32 3}\n"
137 "!8 = distinct !DISubprogram(name: \"f\", scope: !1, file: !1, line: 1, "
138 "type: !9, isLocal: false, isDefinition: true, scopeLine: 1, "
139 "isOptimized: false, unit: !0, variables: !2)\n"
140 "!9 = !DISubroutineType(types: !10)\n"
141 "!10 = !{null}\n"
142 "!11 = !DILocalVariable(name: \"x\", scope: !8, file: !1, line: 2, type: "
143 "!12)\n"
144 "!12 = !DIBasicType(name: \"int\", size: 32, encoding: DW_ATE_signed)\n"
145 "!13 = !DILocation(line: 2, column: 7, scope: !8)\n"
146 "!14 = !DILocation(line: 3, column: 1, scope: !8)\n");
147 auto *GV = M->getNamedValue("f");
148 ASSERT_TRUE(GV);
149 auto *F = dyn_cast<Function>(GV);
150 ASSERT_TRUE(F);
151 Instruction *Inst = &F->front().front();
152 auto *AI = dyn_cast<AllocaInst>(Inst);
153 ASSERT_TRUE(AI);
154 Inst = Inst->getNextNode()->getNextNode();
155 ASSERT_TRUE(Inst);
156 auto *DII = dyn_cast<DbgDeclareInst>(Inst);
157 ASSERT_TRUE(DII);
158 Value *NewBase = Constant::getNullValue(Type::getInt32PtrTy(C));
159 DIBuilder DIB(*M);
Adrian Prantld1317012017-12-08 21:58:18 +0000160 replaceDbgDeclare(AI, NewBase, DII, DIB, DIExpression::NoDeref, 0,
161 DIExpression::NoDeref);
Reid Kleckner0fe506b2017-09-21 19:52:03 +0000162
163 // There should be exactly two dbg.declares.
164 int Declares = 0;
165 for (const Instruction &I : F->front())
166 if (isa<DbgDeclareInst>(I))
167 Declares++;
168 EXPECT_EQ(2, Declares);
169}
Balaram Makam9ee942f2017-10-26 15:04:53 +0000170
171/// Build the dominator tree for the function and run the Test.
172static void runWithDomTree(
173 Module &M, StringRef FuncName,
174 function_ref<void(Function &F, DominatorTree *DT)> Test) {
175 auto *F = M.getFunction(FuncName);
176 ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
177 // Compute the dominator tree for the function.
178 DominatorTree DT(*F);
179 Test(*F, &DT);
180}
181
182TEST(Local, MergeBasicBlockIntoOnlyPred) {
183 LLVMContext C;
184
185 std::unique_ptr<Module> M = parseIR(
186 C,
187 "define i32 @f(i8* %str) {\n"
188 "entry:\n"
189 " br label %bb2.i\n"
190 "bb2.i: ; preds = %bb4.i, %entry\n"
191 " br i1 false, label %bb4.i, label %base2flt.exit204\n"
192 "bb4.i: ; preds = %bb2.i\n"
193 " br i1 false, label %base2flt.exit204, label %bb2.i\n"
194 "bb10.i196.bb7.i197_crit_edge: ; No predecessors!\n"
195 " br label %bb7.i197\n"
196 "bb7.i197: ; preds = %bb10.i196.bb7.i197_crit_edge\n"
197 " %.reg2mem.0 = phi i32 [ %.reg2mem.0, %bb10.i196.bb7.i197_crit_edge ]\n"
198 " br i1 undef, label %base2flt.exit204, label %base2flt.exit204\n"
199 "base2flt.exit204: ; preds = %bb7.i197, %bb7.i197, %bb2.i, %bb4.i\n"
200 " ret i32 0\n"
201 "}\n");
202 runWithDomTree(
203 *M, "f", [&](Function &F, DominatorTree *DT) {
204 for (Function::iterator I = F.begin(), E = F.end(); I != E;) {
205 BasicBlock *BB = &*I++;
206 BasicBlock *SinglePred = BB->getSinglePredecessor();
207 if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) continue;
208 BranchInst *Term = dyn_cast<BranchInst>(SinglePred->getTerminator());
209 if (Term && !Term->isConditional())
210 MergeBasicBlockIntoOnlyPred(BB, DT);
211 }
212 EXPECT_TRUE(DT->verify());
213 });
214}
Matt Arsenault0cfebd92018-01-17 16:27:17 +0000215
216TEST(Local, ConstantFoldTerminator) {
217 LLVMContext C;
218
219 std::unique_ptr<Module> M = parseIR(
220 C,
221 "define void @br_same_dest() {\n"
222 "entry:\n"
223 " br i1 false, label %bb0, label %bb0\n"
224 "bb0:\n"
225 " ret void\n"
226 "}\n"
227 "\n"
228 "define void @br_different_dest() {\n"
229 "entry:\n"
230 " br i1 true, label %bb0, label %bb1\n"
231 "bb0:\n"
232 " br label %exit\n"
233 "bb1:\n"
234 " br label %exit\n"
235 "exit:\n"
236 " ret void\n"
237 "}\n"
238 "\n"
239 "define void @switch_2_different_dest() {\n"
240 "entry:\n"
241 " switch i32 0, label %default [ i32 0, label %bb0 ]\n"
242 "default:\n"
243 " ret void\n"
244 "bb0:\n"
245 " ret void\n"
246 "}\n"
247 "define void @switch_2_different_dest_default() {\n"
248 "entry:\n"
249 " switch i32 1, label %default [ i32 0, label %bb0 ]\n"
250 "default:\n"
251 " ret void\n"
252 "bb0:\n"
253 " ret void\n"
254 "}\n"
255 "define void @switch_3_different_dest() {\n"
256 "entry:\n"
257 " switch i32 0, label %default [ i32 0, label %bb0\n"
258 " i32 1, label %bb1 ]\n"
259 "default:\n"
260 " ret void\n"
261 "bb0:\n"
262 " ret void\n"
263 "bb1:\n"
264 " ret void\n"
265 "}\n"
266 "\n"
267 "define void @switch_variable_2_default_dest(i32 %arg) {\n"
268 "entry:\n"
269 " switch i32 %arg, label %default [ i32 0, label %default ]\n"
270 "default:\n"
271 " ret void\n"
272 "}\n"
273 "\n"
274 "define void @switch_constant_2_default_dest() {\n"
275 "entry:\n"
276 " switch i32 1, label %default [ i32 0, label %default ]\n"
277 "default:\n"
278 " ret void\n"
279 "}\n"
280 "\n"
281 "define void @switch_constant_3_repeated_dest() {\n"
282 "entry:\n"
283 " switch i32 0, label %default [ i32 0, label %bb0\n"
284 " i32 1, label %bb0 ]\n"
285 " bb0:\n"
286 " ret void\n"
287 "default:\n"
288 " ret void\n"
289 "}\n"
290 "\n"
291 "define void @indirectbr() {\n"
292 "entry:\n"
293 " indirectbr i8* blockaddress(@indirectbr, %bb0), [label %bb0, label %bb1]\n"
294 "bb0:\n"
295 " ret void\n"
296 "bb1:\n"
297 " ret void\n"
298 "}\n"
299 "\n"
300 "define void @indirectbr_repeated() {\n"
301 "entry:\n"
302 " indirectbr i8* blockaddress(@indirectbr_repeated, %bb0), [label %bb0, label %bb0]\n"
303 "bb0:\n"
304 " ret void\n"
305 "}\n"
306 "\n"
307 "define void @indirectbr_unreachable() {\n"
308 "entry:\n"
309 " indirectbr i8* blockaddress(@indirectbr_unreachable, %bb0), [label %bb1]\n"
310 "bb0:\n"
311 " ret void\n"
312 "bb1:\n"
313 " ret void\n"
314 "}\n"
315 "\n"
316 );
317
318 auto CFAllTerminators = [&](Function &F, DominatorTree *DT) {
319 DeferredDominance DDT(*DT);
320 for (Function::iterator I = F.begin(), E = F.end(); I != E;) {
321 BasicBlock *BB = &*I++;
322 ConstantFoldTerminator(BB, true, nullptr, &DDT);
323 }
324
325 EXPECT_TRUE(DDT.flush().verify());
326 };
327
328 runWithDomTree(*M, "br_same_dest", CFAllTerminators);
329 runWithDomTree(*M, "br_different_dest", CFAllTerminators);
330 runWithDomTree(*M, "switch_2_different_dest", CFAllTerminators);
331 runWithDomTree(*M, "switch_2_different_dest_default", CFAllTerminators);
332 runWithDomTree(*M, "switch_3_different_dest", CFAllTerminators);
333 runWithDomTree(*M, "switch_variable_2_default_dest", CFAllTerminators);
334 runWithDomTree(*M, "switch_constant_2_default_dest", CFAllTerminators);
335 runWithDomTree(*M, "switch_constant_3_repeated_dest", CFAllTerminators);
336 runWithDomTree(*M, "indirectbr", CFAllTerminators);
337 runWithDomTree(*M, "indirectbr_repeated", CFAllTerminators);
338 runWithDomTree(*M, "indirectbr_unreachable", CFAllTerminators);
339}