Path: blob/main/contrib/llvm-project/llvm/tools/llvm-sim/llvm-sim.cpp
35258 views
//===-- llvm-sim.cpp - Find similar sections of programs -------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This program finds similar sections of a Module, and exports them as a JSON9// file.10//11// To find similarities contained across multiple modules, please use llvm-link12// first to merge the modules.13//14//===----------------------------------------------------------------------===//1516#include "llvm/Analysis/IRSimilarityIdentifier.h"17#include "llvm/IRReader/IRReader.h"18#include "llvm/Support/CommandLine.h"19#include "llvm/Support/FileSystem.h"20#include "llvm/Support/InitLLVM.h"21#include "llvm/Support/JSON.h"22#include "llvm/Support/SourceMgr.h"23#include "llvm/Support/ToolOutputFile.h"2425using namespace llvm;26using namespace IRSimilarity;2728static cl::opt<std::string> OutputFilename("o", cl::desc("Output Filename"),29cl::init("-"),30cl::value_desc("filename"));3132static cl::opt<std::string> InputSourceFile(cl::Positional,33cl::desc("<Source file>"),34cl::init("-"),35cl::value_desc("filename"));3637/// Retrieve the unique number \p I was mapped to in parseBitcodeFile.38///39/// \param I - The Instruction to find the instruction number for.40/// \param LLVMInstNum - The mapping of Instructions to their location in the41/// module represented by an unsigned integer.42/// \returns The instruction number for \p I if it exists.43std::optional<unsigned>44getPositionInModule(const Instruction *I,45const DenseMap<Instruction *, unsigned> &LLVMInstNum) {46assert(I && "Instruction is nullptr!");47DenseMap<Instruction *, unsigned>::const_iterator It = LLVMInstNum.find(I);48if (It == LLVMInstNum.end())49return std::nullopt;50return It->second;51}5253/// Exports the given SimilarityGroups to a JSON file at \p FilePath.54///55/// \param FilePath - The path to the output location.56/// \param SimSections - The similarity groups to process.57/// \param LLVMInstNum - The mapping of Instructions to their location in the58/// module represented by an unsigned integer.59/// \returns A nonzero error code if there was a failure creating the file.60std::error_code61exportToFile(const StringRef FilePath,62const SimilarityGroupList &SimSections,63const DenseMap<Instruction *, unsigned> &LLVMInstNum) {64std::error_code EC;65std::unique_ptr<ToolOutputFile> Out(66new ToolOutputFile(FilePath, EC, sys::fs::OF_None));67if (EC)68return EC;6970json::OStream J(Out->os(), 1);71J.objectBegin();7273unsigned SimOption = 1;74// Process each list of SimilarityGroups organized by the Module.75for (const SimilarityGroup &G : SimSections) {76std::string SimOptionStr = std::to_string(SimOption);77J.attributeBegin(SimOptionStr);78J.arrayBegin();79// For each file there is a list of the range where the similarity80// exists.81for (const IRSimilarityCandidate &C : G) {82std::optional<unsigned> Start =83getPositionInModule((*C.front()).Inst, LLVMInstNum);84std::optional<unsigned> End =85getPositionInModule((*C.back()).Inst, LLVMInstNum);8687assert(Start &&88"Could not find instruction number for first instruction");89assert(End && "Could not find instruction number for last instruction");9091J.object([&] {92J.attribute("start", *Start);93J.attribute("end", *End);94});95}96J.arrayEnd();97J.attributeEnd();98SimOption++;99}100J.objectEnd();101102Out->keep();103104return EC;105}106107int main(int argc, const char *argv[]) {108InitLLVM X(argc, argv);109110cl::ParseCommandLineOptions(argc, argv, "LLVM IR Similarity Visualizer\n");111112LLVMContext CurrContext;113SMDiagnostic Err;114std::unique_ptr<Module> ModuleToAnalyze =115parseIRFile(InputSourceFile, Err, CurrContext);116117if (!ModuleToAnalyze) {118Err.print(argv[0], errs());119return 1;120}121122// Mapping from an Instruction pointer to its occurrence in a sequential123// list of all the Instructions in a Module.124DenseMap<Instruction *, unsigned> LLVMInstNum;125126// We give each instruction a number, which gives us a start and end value127// for the beginning and end of each IRSimilarityCandidate.128unsigned InstructionNumber = 1;129for (Function &F : *ModuleToAnalyze)130for (BasicBlock &BB : F)131for (Instruction &I : BB.instructionsWithoutDebug())132LLVMInstNum[&I]= InstructionNumber++;133134// The similarity identifier we will use to find the similar sections.135IRSimilarityIdentifier SimIdent;136SimilarityGroupList SimilaritySections =137SimIdent.findSimilarity(*ModuleToAnalyze);138139std::error_code E =140exportToFile(OutputFilename, SimilaritySections, LLVMInstNum);141if (E) {142errs() << argv[0] << ": " << E.message() << '\n';143return 2;144}145146return 0;147}148149150