Skip to content

Commit 47571c3

Browse files
committed
[Analysis][EphemeralValuesCache] Adds an ephemeral values cache analysis pass
This analysis pass collects the ephemeral values of a function and caches them for fast lookups. The collection of the ephemeral values is done lazily when the user calls `EphemeralValuesCache::ephValues()`.
1 parent 3b33560 commit 47571c3

File tree

7 files changed

+165
-0
lines changed

7 files changed

+165
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//===- llvm/Analysis/EphemeralValuesCache.h ---------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This pass caches ephemeral values, i.e., values that are only used by
10+
// @llvm.assume intrinsics, for cheap access after the initial collection.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_ANALYSIS_EPHEMERALVALUESCACHE_H
15+
#define LLVM_ANALYSIS_EPHEMERALVALUESCACHE_H
16+
17+
#include "llvm/ADT/SmallPtrSet.h"
18+
#include "llvm/Analysis/AssumptionCache.h"
19+
#include "llvm/IR/PassManager.h"
20+
21+
namespace llvm {
22+
23+
class Function;
24+
25+
/// A cache of ephemeral values within a function.
26+
class EphemeralValuesCache {
27+
SmallPtrSet<const Value *, 32> EphValues;
28+
Function &F;
29+
AssumptionCache &AC;
30+
bool Collected = false;
31+
32+
void collectEphemeralValues();
33+
34+
public:
35+
EphemeralValuesCache(Function &F, AssumptionCache &AC) : F(F), AC(AC) {}
36+
void clear() {
37+
EphValues.clear();
38+
Collected = false;
39+
}
40+
const SmallPtrSetImpl<const Value *> &ephValues() {
41+
if (!Collected)
42+
collectEphemeralValues();
43+
return EphValues;
44+
}
45+
};
46+
47+
class EphemeralValuesAnalysis
48+
: public AnalysisInfoMixin<EphemeralValuesAnalysis> {
49+
friend AnalysisInfoMixin<EphemeralValuesAnalysis>;
50+
static AnalysisKey Key;
51+
52+
public:
53+
using Result = EphemeralValuesCache;
54+
Result run(Function &F, FunctionAnalysisManager &FAM);
55+
};
56+
57+
} // namespace llvm
58+
59+
#endif // LLVM_ANALYSIS_EPHEMERALVALUESCACHE_H

llvm/lib/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ add_llvm_component_library(LLVMAnalysis
6262
DominanceFrontier.cpp
6363
DXILResource.cpp
6464
DXILMetadataAnalysis.cpp
65+
EphemeralValuesCache.cpp
6566
FunctionPropertiesAnalysis.cpp
6667
GlobalsModRef.cpp
6768
GuardUtils.cpp
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===- EphemeralValuesCache.cpp - Cache collecting ephemeral values -------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Analysis/EphemeralValuesCache.h"
10+
#include "llvm/Analysis/AssumptionCache.h"
11+
#include "llvm/Analysis/CodeMetrics.h"
12+
13+
namespace llvm {
14+
15+
void EphemeralValuesCache::collectEphemeralValues() {
16+
CodeMetrics::collectEphemeralValues(&F, &AC, EphValues);
17+
Collected = true;
18+
}
19+
20+
AnalysisKey EphemeralValuesAnalysis::Key;
21+
22+
EphemeralValuesCache
23+
EphemeralValuesAnalysis::run(Function &F, FunctionAnalysisManager &FAM) {
24+
auto &AC = FAM.getResult<AssumptionAnalysis>(F);
25+
return EphemeralValuesCache(F, AC);
26+
}
27+
28+
} // namespace llvm

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/Analysis/DependenceAnalysis.h"
4040
#include "llvm/Analysis/DomPrinter.h"
4141
#include "llvm/Analysis/DominanceFrontier.h"
42+
#include "llvm/Analysis/EphemeralValuesCache.h"
4243
#include "llvm/Analysis/FunctionPropertiesAnalysis.h"
4344
#include "llvm/Analysis/GlobalsModRef.h"
4445
#include "llvm/Analysis/IRSimilarityIdentifier.h"

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ FUNCTION_ANALYSIS("debug-ata", DebugAssignmentTrackingAnalysis())
290290
FUNCTION_ANALYSIS("demanded-bits", DemandedBitsAnalysis())
291291
FUNCTION_ANALYSIS("domfrontier", DominanceFrontierAnalysis())
292292
FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis())
293+
FUNCTION_ANALYSIS("ephemerals", EphemeralValuesAnalysis())
293294
FUNCTION_ANALYSIS("func-properties", FunctionPropertiesAnalysis())
294295
FUNCTION_ANALYSIS("machine-function-info", MachineFunctionAnalysis(TM))
295296
FUNCTION_ANALYSIS("gc-function", GCFunctionAnalysis())

llvm/unittests/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ set(ANALYSIS_TEST_SOURCES
2727
DDGTest.cpp
2828
DomTreeUpdaterTest.cpp
2929
DXILResourceTest.cpp
30+
EphemeralValuesCacheTest.cpp
3031
GraphWriterTest.cpp
3132
GlobalsModRefTest.cpp
3233
FunctionPropertiesAnalysisTest.cpp
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//===--- EphemeralValuesCache.cpp -----------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Analysis/EphemeralValuesCache.h"
10+
#include "llvm/Analysis/AssumptionCache.h"
11+
#include "llvm/AsmParser/Parser.h"
12+
#include "llvm/IR/LLVMContext.h"
13+
#include "llvm/IR/Module.h"
14+
#include "llvm/Support/SourceMgr.h"
15+
#include "gmock/gmock-matchers.h"
16+
#include "gtest/gtest.h"
17+
18+
using namespace llvm;
19+
20+
namespace {
21+
22+
struct EphemeralValuesCacheTest : public testing::Test {
23+
LLVMContext Ctx;
24+
std::unique_ptr<Module> M;
25+
26+
void parseIR(const char *Assembly) {
27+
SMDiagnostic Error;
28+
M = parseAssemblyString(Assembly, Error, Ctx);
29+
if (!M)
30+
Error.print("EphemeralValuesCacheTest", errs());
31+
}
32+
};
33+
34+
TEST_F(EphemeralValuesCacheTest, basic) {
35+
parseIR(R"IR(
36+
declare void @llvm.assume(i1)
37+
38+
define void @foo(i8 %arg0, i8 %arg1) {
39+
%c0 = icmp eq i8 %arg0, 0
40+
call void @llvm.assume(i1 %c0)
41+
call void @foo(i8 %arg0, i8 %arg1)
42+
%c1 = icmp eq i8 %arg1, 0
43+
call void @llvm.assume(i1 %c1)
44+
ret void
45+
}
46+
)IR");
47+
Function *F = M->getFunction("foo");
48+
auto *BB = &*F->begin();
49+
AssumptionCache AC(*F);
50+
EphemeralValuesCache EVC(*F, AC);
51+
auto It = BB->begin();
52+
auto *C0 = &*It++;
53+
auto *Assume0 = &*It++;
54+
[[maybe_unused]] auto *NotEph = &*It++;
55+
auto *C1 = &*It++;
56+
auto *Assume1 = &*It++;
57+
[[maybe_unused]] auto *Ret = &*It++;
58+
// Check emphemeral values.
59+
EXPECT_THAT(EVC.ephValues(),
60+
testing::UnorderedElementsAre(C0, Assume0, C1, Assume1));
61+
// Clear the cache and try again.
62+
EVC.clear();
63+
EXPECT_THAT(EVC.ephValues(),
64+
testing::UnorderedElementsAre(C0, Assume0, C1, Assume1));
65+
// Modify the IR, clear cache and recompute.
66+
Assume1->eraseFromParent();
67+
C1->eraseFromParent();
68+
EXPECT_THAT(EVC.ephValues(),
69+
testing::UnorderedElementsAre(C0, Assume0, C1, Assume1));
70+
EVC.clear();
71+
EXPECT_THAT(EVC.ephValues(), testing::UnorderedElementsAre(C0, Assume0));
72+
}
73+
74+
} // namespace

0 commit comments

Comments
 (0)