1//===- TestPasses.cpp - "buggy" passes used to test bugpoint --------------===//
2//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains "buggy" passes that are used to test bugpoint, to check
11// that it is narrowing down testcases correctly.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/IR/BasicBlock.h"
16#include "llvm/IR/Constant.h"
17#include "llvm/IR/InstIterator.h"
18#include "llvm/IR/InstVisitor.h"
19#include "llvm/IR/Instructions.h"
20#include "llvm/IR/Type.h"
21#include "llvm/Pass.h"
22
23#include "llvm/IR/PatternMatch.h"
24using namespace llvm::PatternMatch;
25using namespace llvm;
26
27namespace {
28/// CrashOnCalls - This pass is used to test bugpoint. It intentionally
29/// crashes on any call instructions.
30class CrashOnCalls : public FunctionPass {
31public:
32 static char ID; // Pass ID, replacement for typeid
33 CrashOnCalls() : FunctionPass(ID) {}
34
35private:
36 void getAnalysisUsage(AnalysisUsage &AU) const override {
37 AU.setPreservesAll();
38 }
39
40 bool runOnFunction(Function &F) override {
41 for (auto &BB : F)
42 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
43 if (isa<CallInst>(Val: *I))
44 abort();
45
46 return false;
47 }
48};
49}
50
51char CrashOnCalls::ID = 0;
52static RegisterPass<CrashOnCalls>
53 X("bugpoint-crashcalls",
54 "BugPoint Test Pass - Intentionally crash on CallInsts");
55
56namespace {
57/// DeleteCalls - This pass is used to test bugpoint. It intentionally
58/// deletes some call instructions, "misoptimizing" the program.
59class DeleteCalls : public FunctionPass {
60public:
61 static char ID; // Pass ID, replacement for typeid
62 DeleteCalls() : FunctionPass(ID) {}
63
64private:
65 bool runOnFunction(Function &F) override {
66 for (auto &BB : F)
67 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
68 if (CallInst *CI = dyn_cast<CallInst>(Val&: I)) {
69 if (!CI->use_empty())
70 CI->replaceAllUsesWith(V: Constant::getNullValue(Ty: CI->getType()));
71 CI->eraseFromParent();
72 break;
73 }
74 return false;
75 }
76};
77}
78
79char DeleteCalls::ID = 0;
80static RegisterPass<DeleteCalls>
81 Y("bugpoint-deletecalls",
82 "BugPoint Test Pass - Intentionally 'misoptimize' CallInsts");
83
84namespace {
85 /// CrashOnDeclFunc - This pass is used to test bugpoint. It intentionally
86/// crashes if the module has an undefined function (ie a function that is
87/// defined in an external module).
88class CrashOnDeclFunc : public ModulePass {
89public:
90 static char ID; // Pass ID, replacement for typeid
91 CrashOnDeclFunc() : ModulePass(ID) {}
92
93private:
94 bool runOnModule(Module &M) override {
95 for (auto &F : M.functions()) {
96 if (F.isDeclaration())
97 abort();
98 }
99 return false;
100 }
101 };
102}
103
104char CrashOnDeclFunc::ID = 0;
105static RegisterPass<CrashOnDeclFunc>
106 Z("bugpoint-crash-decl-funcs",
107 "BugPoint Test Pass - Intentionally crash on declared functions");
108
109namespace {
110/// CrashOnOneCU - This pass is used to test bugpoint. It intentionally
111/// crashes if the Module has two or more compile units
112class CrashOnTooManyCUs : public ModulePass {
113public:
114 static char ID;
115 CrashOnTooManyCUs() : ModulePass(ID) {}
116
117private:
118 bool runOnModule(Module &M) override {
119 NamedMDNode *CU_Nodes = M.getNamedMetadata(Name: "llvm.dbg.cu");
120 if (!CU_Nodes)
121 return false;
122 if (CU_Nodes->getNumOperands() >= 2)
123 abort();
124 return false;
125 }
126};
127}
128
129char CrashOnTooManyCUs::ID = 0;
130static RegisterPass<CrashOnTooManyCUs>
131 A("bugpoint-crash-too-many-cus",
132 "BugPoint Test Pass - Intentionally crash on too many CUs");
133
134namespace {
135class CrashOnFunctionAttribute : public FunctionPass {
136public:
137 static char ID; // Pass ID, replacement for typeid
138 CrashOnFunctionAttribute() : FunctionPass(ID) {}
139
140private:
141 void getAnalysisUsage(AnalysisUsage &AU) const override {
142 AU.setPreservesAll();
143 }
144
145 bool runOnFunction(Function &F) override {
146 AttributeSet A = F.getAttributes().getFnAttrs();
147 if (A.hasAttribute(Kind: "bugpoint-crash"))
148 abort();
149 return false;
150 }
151};
152} // namespace
153
154char CrashOnFunctionAttribute::ID = 0;
155static RegisterPass<CrashOnFunctionAttribute>
156 B("bugpoint-crashfuncattr", "BugPoint Test Pass - Intentionally crash on "
157 "function attribute 'bugpoint-crash'");
158
159namespace {
160class CrashOnMetadata : public FunctionPass {
161public:
162 static char ID; // Pass ID, replacement for typeid
163 CrashOnMetadata() : FunctionPass(ID) {}
164
165private:
166 void getAnalysisUsage(AnalysisUsage &AU) const override {
167 AU.setPreservesAll();
168 }
169
170 // Crash on fabs calls with fpmath metdata and an fadd as argument. This
171 // ensures the fadd instruction sticks around and we can check that the
172 // metadata there is dropped correctly.
173 bool runOnFunction(Function &F) override {
174 for (Instruction &I : instructions(F))
175 if (match(V: &I, P: m_FAbs(Op0: m_FAdd(L: m_Value(), R: m_Value()))) &&
176 I.hasMetadata(Kind: "fpmath"))
177 abort();
178 return false;
179 }
180};
181} // namespace
182
183char CrashOnMetadata::ID = 0;
184static RegisterPass<CrashOnMetadata>
185 C("bugpoint-crashmetadata",
186 "BugPoint Test Pass - Intentionally crash on "
187 "fabs calls with fpmath metadata and an fadd as argument");
188