diff --git a/llvm/include/llvm/Analysis/StructuralHash.h b/llvm/include/llvm/Analysis/StructuralHash.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Analysis/StructuralHash.h @@ -0,0 +1,31 @@ +//=- StructuralHash.h - Structural Hash Printing --*- C++ -*-----------------=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_STRUCTURALHASH_H +#define LLVM_ANALYSIS_STRUCTURALHASH_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// Printer pass for StructuralHashes +class StructuralHashPrinterPass + : public PassInfoMixin { + raw_ostream &OS; + bool EnableDetailedStructuralHash; + +public: + explicit StructuralHashPrinterPass(raw_ostream &OS, bool Detailed) + : OS(OS), EnableDetailedStructuralHash(Detailed) {} + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); +}; + +} // namespace llvm + +#endif // LLVM_ANALYSIS_STRUCTURALHASH_H diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -124,6 +124,7 @@ ScalarEvolutionNormalization.cpp StackLifetime.cpp StackSafetyAnalysis.cpp + StructuralHash.cpp SyntheticCountsUtils.cpp TFLiteUtils.cpp TargetLibraryInfo.cpp diff --git a/llvm/lib/Analysis/StructuralHash.cpp b/llvm/lib/Analysis/StructuralHash.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Analysis/StructuralHash.cpp @@ -0,0 +1,31 @@ +//===- StructuralHash.cpp - Function Hash Printing ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the StructuralHashPrinterPass which is used to show +// the structural hash of all functions in a module and the module itself. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/StructuralHash.h" +#include "llvm/IR/StructuralHash.h" +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + +PreservedAnalyses StructuralHashPrinterPass::run(Module &M, + ModuleAnalysisManager &MAM) { + OS << "Module Hash: " + << Twine::utohexstr(StructuralHash(M, EnableDetailedStructuralHash)) + << "\n"; + for (Function &F : M) { + OS << "Function " << F.getName() << " Hash: " + << Twine::utohexstr(StructuralHash(F, EnableDetailedStructuralHash)) + << "\n"; + } + return PreservedAnalyses::all(); +} diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -67,6 +67,7 @@ #include "llvm/Analysis/ScopedNoAliasAA.h" #include "llvm/Analysis/StackLifetime.h" #include "llvm/Analysis/StackSafetyAnalysis.h" +#include "llvm/Analysis/StructuralHash.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TypeBasedAliasAnalysis.h" @@ -1093,6 +1094,11 @@ return Result; } +Expected parseStructuralHashPrinterPassOptions(StringRef Params) { + return parseSinglePassOption(Params, "enable-detailed-structural-hash", + "StructuralHashPrinterPass"); +} + } // namespace /// Tests whether a pass name starts with a valid prefix for a default pipeline diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -191,6 +191,15 @@ }, parseMemProfUsePassOptions, "profile-filename=S") +MODULE_PASS_WITH_PARAMS("print", + "StructuralHashPrinterPass", + [](bool EnableDetailedStructuralHash) { + return StructuralHashPrinterPass( + dbgs(), + EnableDetailedStructuralHash); + }, + parseStructuralHashPrinterPassOptions, + "enable-detailed-structural-hash") #undef MODULE_PASS_WITH_PARAMS #ifndef CGSCC_ANALYSIS diff --git a/llvm/test/Analysis/StructuralHash/structural-hash-detailed.ll b/llvm/test/Analysis/StructuralHash/structural-hash-detailed.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/StructuralHash/structural-hash-detailed.ll @@ -0,0 +1,13 @@ +; Require 64 bits here as the hash will change depending upon whether we are on a 32-bit +; or 64-bit platform. +; REQUIRE: llvm-64-bits + +; RUN: opt -passes='print' -disable-output %s 2>&1 | FileCheck %s + +define i64 @f1(i64 %a) { + ret i64 %a +} + +; CHECK: Module Hash: 81f1328ced269bd +; CHECK: Function f1 Hash: 81f1328ced269bd + diff --git a/llvm/test/Analysis/StructuralHash/structural-hash-printer.ll b/llvm/test/Analysis/StructuralHash/structural-hash-printer.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/StructuralHash/structural-hash-printer.ll @@ -0,0 +1,21 @@ +; RUN: opt -passes='print' -disable-output %s 2>&1 | FileCheck %s +; RUN: opt -passes='print' -disable-output %s 2>&1 | FileCheck %s -check-prefix=DETAILED-HASH + +define i64 @f1(i64 %a) { + %b = add i64 %a, 1 + ret i64 %b +} + +define i32 @f2(i32 %a) { + %b = add i32 %a, 2 + ret i32 %b +} + +; CHECK: Module Hash: 39c8037f62da229 +; CHECK: Function f1 Hash: b677567fe628d557 +; CHECK: Function f2 Hash: b677567fe628d557 + +; DETAILED-HASH: Module Hash: {{([a-z0-9]{16})}} +; DETAILED-HASH: Function f1 Hash: {{([a-z0-9]{16})}} +; DETAILED-HASH: Function f2 Hash: {{([a-z0-9]{16})}} +