/// given test.
template <typename T>
void runDeltaPassInt(
- TestRunner &Test, int Targets,
+ TestRunner &Test,
function_ref<void(Oracle &, T &)> ExtractChunksFromModule) {
- assert(Targets >= 0);
+ int Targets;
+ {
+ // Count the number of targets by counting the number of calls to
+ // Oracle::shouldKeep() but always returning true so no changes are
+ // made.
+ std::vector<Chunk> AllChunks = {{0, INT_MAX}};
+ Oracle Counter(AllChunks);
+ ExtractChunksFromModule(Counter, Test.getProgram());
+ Targets = Counter.count();
+ }
if (!Targets) {
errs() << "\nNothing to reduce\n";
return;
assert(!verifyReducerWorkItem(Test.getProgram(), &errs()) &&
"input module is broken before making changes");
- std::vector<Chunk> ChunksStillConsideredInteresting = {{1, Targets}};
+ std::vector<Chunk> ChunksStillConsideredInteresting = {{0, Targets - 1}};
std::unique_ptr<ReducerWorkItem> ReducedProgram;
for (unsigned int Level = 0; Level < StartingGranularityLevel; Level++) {
}
void llvm::runDeltaPass(
- TestRunner &Test, int Targets,
+ TestRunner &Test,
function_ref<void(Oracle &, Module &)> ExtractChunksFromModule) {
- runDeltaPassInt<Module>(Test, Targets, ExtractChunksFromModule);
+ runDeltaPassInt<Module>(Test, ExtractChunksFromModule);
}
void llvm::runDeltaPass(
- TestRunner &Test, int Targets,
+ TestRunner &Test,
function_ref<void(Oracle &, MachineFunction &)> ExtractChunksFromModule) {
- runDeltaPassInt<MachineFunction>(Test, Targets, ExtractChunksFromModule);
+ runDeltaPassInt<MachineFunction>(Test, ExtractChunksFromModule);
}
/// actually understand what is going on.
class Oracle {
/// Out of all the features that we promised to be,
- /// how many have we already processed? 1-based!
- int Index = 1;
+ /// how many have we already processed?
+ int Index = 0;
/// The actual workhorse, contains the knowledge whether or not
/// some particular feature should be preserved this time.
/// Should be called for each feature on which we are operating.
/// Name is self-explanatory - if returns true, then it should be preserved.
bool shouldKeep() {
- if (ChunksToKeep.empty())
+ if (ChunksToKeep.empty()) {
+ ++Index;
return false; // All further features are to be discarded.
+ }
// Does the current (front) chunk contain such a feature?
bool ShouldKeep = ChunksToKeep.front().contains(Index);
- auto _ = make_scope_exit([&]() { ++Index; }); // Next time - next feature.
// Is this the last feature in the chunk?
if (ChunksToKeep.front().End == Index)
ChunksToKeep = ChunksToKeep.drop_front(); // Onto next chunk.
+ ++Index;
+
return ShouldKeep;
}
+
+ int count() { return Index; }
};
/// This function implements the Delta Debugging algorithm, it receives a
/// RemoveFunctions) and receives three key parameters:
/// * Test: The main TestRunner instance which is used to run the provided
/// interesting-ness test, as well as to store and access the reduced Program.
-/// * Targets: The amount of Targets that are going to be reduced by the
-/// algorithm, for example, the RemoveGlobalVars pass would send the amount of
-/// initialized GVs.
/// * ExtractChunksFromModule: A function used to tailor the main program so it
/// only contains Targets that are inside Chunks of the given iteration.
/// Note: This function is implemented by each specialized Delta pass
/// Other implementations of the Delta Debugging algorithm can also be found in
/// the CReduce, Delta, and Lithium projects.
void runDeltaPass(
- TestRunner &Test, int Targets,
+ TestRunner &Test,
function_ref<void(Oracle &, Module &)> ExtractChunksFromModule);
void runDeltaPass(
- TestRunner &Test, int Targets,
+ TestRunner &Test,
function_ref<void(Oracle &, MachineFunction &)> ExtractChunksFromModule);
} // namespace llvm
}
}
-/// Counts the amount of aliases and prints their respective name & index.
-static int countAliases(Module &Program) {
- // TODO: Silence index with --quiet flag
- errs() << "----------------------------\n";
- errs() << "Aliases Index Reference:\n";
- int Count = 0;
- for (auto &GA : Program.aliases())
- errs() << "\t" << ++Count << ": " << GA.getName() << "\n";
-
- errs() << "----------------------------\n";
- return Count;
-}
-
void llvm::reduceAliasesDeltaPass(TestRunner &Test) {
errs() << "*** Reducing Aliases ...\n";
- int Functions = countAliases(Test.getProgram());
- runDeltaPass(Test, Functions, extractAliasesFromModule);
+ runDeltaPass(Test, extractAliasesFromModule);
errs() << "----------------------------\n";
}
}
}
-/// Counts the amount of arguments in functions and prints their respective
-/// name, index, and parent function name
-static int countArguments(Module &Program) {
- // TODO: Silence index with --quiet flag
- outs() << "----------------------------\n";
- outs() << "Param Index Reference:\n";
- int ArgsCount = 0;
- for (auto &F : Program)
- if (shouldRemoveArguments(F)) {
- outs() << " " << F.getName() << "\n";
- for (auto &A : F.args())
- outs() << "\t" << ++ArgsCount << ": " << A.getName() << "\n";
-
- outs() << "----------------------------\n";
- }
-
- return ArgsCount;
-}
-
void llvm::reduceArgumentsDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Arguments...\n";
- int ArgCount = countArguments(Test.getProgram());
- runDeltaPass(Test, ArgCount, extractArgumentsFromModule);
+ runDeltaPass(Test, extractArgumentsFromModule);
}
I.first->setAttributes(convertAttributeRefVecToAttributeList(C, I.second));
}
-/// Counts the amount of attributes.
-static int countAttributes(Module &Program) {
- AttributeCounter C;
-
- // TODO: Silence index with --quiet flag
- outs() << "----------------------------\n";
- C.visit(Program);
- outs() << "Number of attributes: " << C.AttributeCount << "\n";
-
- return C.AttributeCount;
-}
-
void llvm::reduceAttributesDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Attributes...\n";
- int AttributeCount = countAttributes(Test.getProgram());
- runDeltaPass(Test, AttributeCount, extractAttributesFromModule);
+ runDeltaPass(Test, extractAttributesFromModule);
}
}
}
-/// Counts the amount of basic blocks and prints their name & respective index
-static int countBasicBlocks(Module &Program) {
- // TODO: Silence index with --quiet flag
- outs() << "----------------------------\n";
- int BBCount = 0;
- for (auto &F : Program)
- for (auto &BB : F) {
- if (BB.hasName())
- outs() << "\t" << ++BBCount << ": " << BB.getName() << "\n";
- else
- outs() << "\t" << ++BBCount << ": Unnamed\n";
- }
-
- return BBCount;
-}
-
void llvm::reduceBasicBlocksDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Basic Blocks...\n";
- int BBCount = countBasicBlocks(Test.getProgram());
- runDeltaPass(Test, BBCount, extractBasicBlocksFromModule);
+ runDeltaPass(Test, extractBasicBlocksFromModule);
}
}
}
-/// Counts the amount of non-declaration functions and prints their
-/// respective name & index
-static int countFunctionDefinitions(Module &Program) {
- // TODO: Silence index with --quiet flag
- errs() << "----------------------------\n";
- errs() << "Function Definition Index Reference:\n";
- int FunctionDefinitionCount = 0;
- for (auto &F : Program)
- if (!F.isDeclaration())
- errs() << "\t" << ++FunctionDefinitionCount << ": " << F.getName()
- << "\n";
-
- errs() << "----------------------------\n";
- return FunctionDefinitionCount;
-}
-
void llvm::reduceFunctionBodiesDeltaPass(TestRunner &Test) {
errs() << "*** Reducing Function Bodies...\n";
- int Functions = countFunctionDefinitions(Test.getProgram());
- runDeltaPass(Test, Functions, extractFunctionBodiesFromModule);
+ runDeltaPass(Test, extractFunctionBodiesFromModule);
errs() << "----------------------------\n";
}
}
}
-/// Counts the amount of functions and prints their
-/// respective name & index
-static int countFunctions(Module &Program) {
- // TODO: Silence index with --quiet flag
- errs() << "----------------------------\n";
- errs() << "Function Index Reference:\n";
- int FunctionCount = 0;
- for (auto &F : Program) {
- if (F.isIntrinsic() && !F.use_empty())
- continue;
-
- errs() << '\t' << ++FunctionCount << ": " << F.getName() << '\n';
- }
-
- errs() << "----------------------------\n";
- return FunctionCount;
-}
-
void llvm::reduceFunctionsDeltaPass(TestRunner &Test) {
errs() << "*** Reducing Functions...\n";
- int Functions = countFunctions(Test.getProgram());
- runDeltaPass(Test, Functions, extractFunctionsFromModule);
+ runDeltaPass(Test, extractFunctionsFromModule);
errs() << "----------------------------\n";
}
}
}
-static int countGOs(Module &Program) {
- int SectionCount = count_if(Program.global_objects(), [](GlobalObject &GO) {
- return shouldReduceSection(GO);
- });
- int AlignCount = count_if(Program.global_objects(), [](GlobalObject &GO) {
- return shouldReduceAlign(GO);
- });
- return SectionCount + AlignCount;
-}
-
void llvm::reduceGlobalObjectsDeltaPass(TestRunner &Test) {
outs() << "*** Reducing GlobalObjects...\n";
- int GVCount = countGOs(Test.getProgram());
- runDeltaPass(Test, GVCount, reduceGOs);
+ runDeltaPass(Test, reduceGOs);
}
}
}
-static int countGVs(Module &Program) {
- int DSOLocalCount = count_if(Program.global_values(), [](GlobalValue &GV) {
- return shouldReduceDSOLocal(GV);
- });
- int VisibilityCount = count_if(Program.global_values(), [](GlobalValue &GV) {
- return shouldReduceVisibility(GV);
- });
- int UnnamedAddrCount = count_if(Program.global_values(), [](GlobalValue &GV) {
- return shouldReduceUnnamedAddress(GV);
- });
- int DLLStorageClassCount =
- count_if(Program.global_values(),
- [](GlobalValue &GV) { return shouldReduceDLLStorageClass(GV); });
- int ThreadLocalCount = count_if(Program.global_values(), [](GlobalValue &GV) {
- return shouldReduceThreadLocal(GV);
- });
- return DSOLocalCount + VisibilityCount + UnnamedAddrCount +
- DLLStorageClassCount + ThreadLocalCount;
-}
-
void llvm::reduceGlobalValuesDeltaPass(TestRunner &Test) {
outs() << "*** Reducing GlobalValues...\n";
- int GVCount = countGVs(Test.getProgram());
- runDeltaPass(Test, GVCount, reduceGVs);
+ runDeltaPass(Test, reduceGVs);
}
}
}
-/// Counts the amount of initialized GVs and displays their
-/// respective name & index
-static int countGVs(Module &Program) {
- // TODO: Silence index with --quiet flag
- outs() << "----------------------------\n";
- outs() << "GlobalVariable Index Reference:\n";
- int GVCount = 0;
- for (auto &GV : Program.globals())
- if (GV.hasInitializer())
- outs() << "\t" << ++GVCount << ": " << GV.getName() << "\n";
- outs() << "----------------------------\n";
- return GVCount;
-}
-
void llvm::reduceGlobalsInitializersDeltaPass(TestRunner &Test) {
outs() << "*** Reducing GVs initializers...\n";
- int GVCount = countGVs(Test.getProgram());
- runDeltaPass(Test, GVCount, extractGVsFromModule);
+ runDeltaPass(Test, extractGVsFromModule);
}
GV->eraseFromParent();
}
-/// Counts the amount of GVs and displays their
-/// respective name & index
-static int countGVs(Module &Program) {
- // TODO: Silence index with --quiet flag
- outs() << "----------------------------\n";
- outs() << "GlobalVariable Index Reference:\n";
- int GVCount = 0;
- for (auto &GV : Program.globals())
- outs() << "\t" << ++GVCount << ": " << GV.getName() << "\n";
- outs() << "----------------------------\n";
- return GVCount;
-}
-
void llvm::reduceGlobalsDeltaPass(TestRunner &Test) {
outs() << "*** Reducing GVs...\n";
- int GVCount = countGVs(Test.getProgram());
- runDeltaPass(Test, GVCount, extractGVsFromModule);
+ runDeltaPass(Test, extractGVsFromModule);
}
I->eraseFromParent();
}
-/// Counts the amount of basic blocks and prints their name & respective index
-static unsigned countInstructions(Module &Program) {
- // TODO: Silence index with --quiet flag
- outs() << "----------------------------\n";
- int InstCount = 0;
- for (auto &F : Program)
- for (auto &BB : F)
- // Well-formed blocks have terminators, which we cannot remove.
- InstCount += BB.getInstList().size() - 1;
- outs() << "Number of instructions: " << InstCount << "\n";
-
- return InstCount;
-}
-
void llvm::reduceInstructionsDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Instructions...\n";
- unsigned InstCount = countInstructions(Test.getProgram());
- runDeltaPass(Test, InstCount, extractInstrFromModule);
+ runDeltaPass(Test, extractInstrFromModule);
}
return 0;
}
-static unsigned countInstructions(MachineFunction &MF) {
- unsigned Count = 0;
- MachineInstr *TopMI = nullptr;
- for (auto &MBB : MF) {
- for (auto &MI : MBB) {
- if (MI.isTerminator())
- continue;
- if (MBB.isEntryBlock() && !TopMI) {
- TopMI = &MI;
- continue;
- }
- Count++;
- }
- }
- return Count;
-}
-
static void extractInstrFromModule(Oracle &O, MachineFunction &MF) {
MachineDominatorTree MDT;
MDT.runOnMachineFunction(MF);
void llvm::reduceInstructionsMIRDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Instructions...\n";
- unsigned InstCount = countInstructions(Test.getProgram());
- runDeltaPass(Test, InstCount, extractInstrFromModule);
+ runDeltaPass(Test, extractInstrFromModule);
}
}
}
-static int countMetadataTargets(Module &Program) {
- int NamedMetadataNodes = Program.named_metadata_size();
-
- // Get metadata attached to globals.
- int GlobalMetadataArgs = 0;
- SmallVector<std::pair<unsigned, MDNode *>> MDs;
- for (GlobalVariable &GV : Program.globals()) {
- GV.getAllMetadata(MDs);
- GlobalMetadataArgs += MDs.size();
- }
-
- // Get metadata attached to functions & instructions.
- int FunctionMetadataArgs = 0;
- int InstructionMetadataArgs = 0;
- for (Function &F : Program) {
- F.getAllMetadata(MDs);
- FunctionMetadataArgs += MDs.size();
-
- for (Instruction &I : instructions(F)) {
- I.getAllMetadata(MDs);
- InstructionMetadataArgs += MDs.size();
- }
- }
-
- return NamedMetadataNodes + GlobalMetadataArgs + FunctionMetadataArgs +
- InstructionMetadataArgs;
-}
-
void llvm::reduceMetadataDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Metadata...\n";
- int MDCount = countMetadataTargets(Test.getProgram());
- runDeltaPass(Test, MDCount, extractMetadataFromModule);
+ runDeltaPass(Test, extractMetadataFromModule);
outs() << "----------------------------\n";
}
Program.setModuleInlineAsm("");
}
-static int countModuleData(Module &M) {
- int Count = 0;
- if (!M.getModuleIdentifier().empty())
- ++Count;
- if (!M.getSourceFileName().empty())
- ++Count;
- if (!M.getDataLayoutStr().empty())
- ++Count;
- if (!M.getTargetTriple().empty())
- ++Count;
- if (!M.getModuleInlineAsm().empty())
- ++Count;
- return Count;
-}
-
void llvm::reduceModuleDataDeltaPass(TestRunner &Test) {
outs() << "*** Reducing Module Data...\n";
- int Count = countModuleData(Test.getProgram());
- runDeltaPass(Test, Count, clearModuleData);
+ runDeltaPass(Test, clearModuleData);
}
maybeRewriteCallWithDifferentBundles(I.first, I.second);
}
-/// Counts the amount of operand bundles.
-static int countOperandBundes(Module &Program) {
- OperandBundleCounter C;
-
- // TODO: Silence index with --quiet flag
- outs() << "----------------------------\n";
- C.visit(Program);
- outs() << "Number of operand bundles: " << C.OperandBundeCount << "\n";
-
- return C.OperandBundeCount;
-}
-
void llvm::reduceOperandBundesDeltaPass(TestRunner &Test) {
outs() << "*** Reducing OperandBundes...\n";
- int OperandBundeCount = countOperandBundes(Test.getProgram());
- runDeltaPass(Test, OperandBundeCount, extractOperandBundesFromModule);
+ runDeltaPass(Test, extractOperandBundesFromModule);
}
}
}
-static int countOperands(Module &Program,
- function_ref<Value *(Use &)> ReduceValue) {
- int Count = 0;
- for (auto &F : Program.functions()) {
- for (auto &I : instructions(&F)) {
- for (auto &Op : I.operands()) {
- if (ReduceValue(Op))
- Count++;
- }
- }
- }
- return Count;
-}
-
static bool isOne(Use &Op) {
auto *C = dyn_cast<Constant>(Op);
return C && C->isOneValue();
// Don't replace existing ConstantData Uses.
return isa<ConstantData>(*Op) ? nullptr : UndefValue::get(Op->getType());
};
- int Count = countOperands(Test.getProgram(), ReduceValue);
- runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
+ runDeltaPass(Test, [ReduceValue](Oracle &O, Module &Program) {
extractOperandsFromModule(O, Program, ReduceValue);
});
}
// Don't replace existing ones and zeroes.
return (isOne(Op) || isZero(Op)) ? nullptr : ConstantInt::get(Ty, 1);
};
- int Count = countOperands(Test.getProgram(), ReduceValue);
- runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
+ runDeltaPass(Test, [ReduceValue](Oracle &O, Module &Program) {
extractOperandsFromModule(O, Program, ReduceValue);
});
}
// Don't replace existing zeroes.
return isZero(Op) ? nullptr : Constant::getNullValue(Op->getType());
};
- int Count = countOperands(Test.getProgram(), ReduceValue);
- runDeltaPass(Test, Count, [ReduceValue](Oracle &O, Module &Program) {
+ runDeltaPass(Test, [ReduceValue](Oracle &O, Module &Program) {
extractOperandsFromModule(O, Program, ReduceValue);
});
}
}
}
-/// Counts the amount of operands in the module that can be reduced.
-static int countOperands(Module &Program) {
- int Count = 0;
-
- for (Function &F : Program.functions()) {
- if (!canReplaceFunction(&F))
- continue;
- for (Instruction &I : instructions(&F)) {
- for (Use &Op : I.operands()) {
- if (!canReduceUse(Op))
- continue;
- Count += 1;
- }
- }
- }
-
- return Count;
-}
-
void llvm::reduceOperandsToArgsDeltaPass(TestRunner &Test) {
outs() << "*** Converting operands to function arguments ...\n";
- int ArgCount = countOperands(Test.getProgram());
- return runDeltaPass(Test, ArgCount, reduceOperandsToArgs);
+ return runDeltaPass(Test, reduceOperandsToArgs);
}
}
}
-/// Counts the amount of special globals and prints their
-/// respective name & index
-static int countSpecialGlobals(Module &Program) {
- // TODO: Silence index with --quiet flag
- errs() << "----------------------------\n";
- errs() << "Special Globals Index Reference:\n";
- int Count = 0;
- for (StringRef Name : SpecialGlobalNames) {
- if (auto *Used = Program.getNamedGlobal(Name))
- errs() << "\t" << ++Count << ": " << Used->getName() << "\n";
- }
- errs() << "----------------------------\n";
- return Count;
-}
-
void llvm::reduceSpecialGlobalsDeltaPass(TestRunner &Test) {
errs() << "*** Reducing Special Globals ...\n";
- int Functions = countSpecialGlobals(Test.getProgram());
- runDeltaPass(Test, Functions, extractSpecialGlobalsFromModule);
+ runDeltaPass(Test, extractSpecialGlobalsFromModule);
errs() << "----------------------------\n";
}