188 lines · cpp
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-exception7//8//===----------------------------------------------------------------------===//9//10// This file contains "buggy" passes that are used to test bugpoint, to check11// 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 intentionally29/// crashes on any call instructions.30class CrashOnCalls : public FunctionPass {31public:32 static char ID; // Pass ID, replacement for typeid33 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>(*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 intentionally58/// deletes some call instructions, "misoptimizing" the program.59class DeleteCalls : public FunctionPass {60public:61 static char ID; // Pass ID, replacement for typeid62 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>(I)) {69 if (!CI->use_empty())70 CI->replaceAllUsesWith(Constant::getNullValue(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 intentionally86/// crashes if the module has an undefined function (ie a function that is87/// defined in an external module).88class CrashOnDeclFunc : public ModulePass {89public:90 static char ID; // Pass ID, replacement for typeid91 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 intentionally111/// crashes if the Module has two or more compile units112class 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("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 typeid138 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("bugpoint-crash"))148 abort();149 return false;150 }151};152} // namespace153 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 typeid163 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. This171 // ensures the fadd instruction sticks around and we can check that the172 // metadata there is dropped correctly.173 bool runOnFunction(Function &F) override {174 for (Instruction &I : instructions(F))175 if (match(&I, m_FAbs(m_FAdd(m_Value(), m_Value()))) &&176 I.hasMetadata("fpmath"))177 abort();178 return false;179 }180};181} // namespace182 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