Skip to content

Commit 0a02dcd

Browse files
committed
WIP: Loop pass
1 parent 15821d0 commit 0a02dcd

File tree

7 files changed

+50
-42
lines changed

7 files changed

+50
-42
lines changed

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -991,12 +991,18 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
991991
FPM.addPass(BoundsCheckingPass());
992992
});
993993

994-
if (LangOpts.Sanitize.has(SanitizerKind::Realtime))
994+
if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) {
995+
fprintf(stderr, "Adding RealtimeSanitizerPass\n");
996+
PB.registerLoopOptimizerEndEPCallback(
997+
[](LoopPassManager &LPM, OptimizationLevel Level) {
998+
LPM.addPass(RealtimeSanitizerLoopPass());
999+
});
9951000
PB.registerScalarOptimizerLateEPCallback(
9961001
[](FunctionPassManager &FPM, OptimizationLevel Level) {
9971002
RealtimeSanitizerOptions Opts;
9981003
FPM.addPass(RealtimeSanitizerPass(Opts));
9991004
});
1005+
}
10001006

10011007
// Don't add sanitizers if we are here from ThinLTO PostLink. That already
10021008
// done on PreLink stage.

llvm/include/llvm/Transforms/Instrumentation/RealtimeSanitizer.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#define LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H
2121

2222
#include "llvm/IR/PassManager.h"
23+
#include "llvm/Transforms/Scalar/LoopPassManager.h"
24+
2325

2426
namespace llvm {
2527

@@ -33,6 +35,13 @@ class RealtimeSanitizerPass : public PassInfoMixin<RealtimeSanitizerPass> {
3335
static bool isRequired() { return true; }
3436
};
3537

38+
struct RealtimeSanitizerLoopPass : PassInfoMixin<RealtimeSanitizerLoopPass> {
39+
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
40+
LoopStandardAnalysisResults &AR, LPMUpdater &U);
41+
static bool isRequired() { return true; }
42+
};
43+
44+
3645
} // namespace llvm
3746

3847
#endif // LLVM_TRANSFORMS_INSTRUMENTATION_REALTIMESANITIZER_H

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ LOOP_PASS("print<ddg>", DDGAnalysisPrinterPass(dbgs()))
659659
LOOP_PASS("print<iv-users>", IVUsersPrinterPass(dbgs()))
660660
LOOP_PASS("print<loop-cache-cost>", LoopCachePrinterPass(dbgs()))
661661
LOOP_PASS("print<loopnest>", LoopNestPrinterPass(dbgs()))
662+
LOOP_PASS("sanitize-unbound-loops", RealtimeSanitizerLoopPass())
662663
#undef LOOP_PASS
663664

664665
#ifndef LOOP_PASS_WITH_PARAMS

llvm/lib/Transforms/Instrumentation/RealtimeSanitizer.cpp

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -71,43 +71,43 @@ PreservedAnalyses RealtimeSanitizerPass::run(Function &F,
7171
PA.preserveSet<CFGAnalyses>();
7272
}
7373

74-
const LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
75-
ScalarEvolution &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
76-
for (Loop *L : LI) {
74+
return PA;
75+
}
7776

78-
const bool HasNoExits = L->hasNoExitBlocks();
79-
const bool CannotPredictLoopCount =
80-
isa<SCEVCouldNotCompute>(SE.getConstantMaxBackedgeTakenCount(L)) &&
81-
isa<SCEVCouldNotCompute>(SE.getBackedgeTakenCount(L));
82-
const bool LoopIsPotentiallyUnbound = HasNoExits || CannotPredictLoopCount;
77+
PreservedAnalyses RealtimeSanitizerLoopPass::run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U) {
78+
BasicBlock *Context =
79+
L.getLoopPreheader() ? L.getLoopPreheader() : L.getHeader();
80+
assert(Context && "Loop has no preheader or header block");
8381

84-
if (LoopIsPotentiallyUnbound) {
85-
BasicBlock *Context =
86-
L->getLoopPreheader() ? L->getLoopPreheader() : L->getHeader();
87-
assert(Context && "Loop has no preheader or header block");
82+
Function* F = Context->getParent();
83+
assert(F && "Loop has no parent function");
8884

89-
IRBuilder<> Builder{&Context->back()};
85+
const bool HasNoExits = L.hasNoExitBlocks();
86+
const bool CannotPredictLoopCount = isa<SCEVCouldNotCompute>(AR.SE.getConstantMaxBackedgeTakenCount(&L)) &&
87+
isa<SCEVCouldNotCompute>(AR.SE.getBackedgeTakenCount(&L));
88+
const bool LoopIsPotentiallyUnbound = HasNoExits || CannotPredictLoopCount;
9089

91-
std::string ReasonStr =
92-
demangle(F.getName().str()) + " contains a possibly unbounded loop ";
90+
if (LoopIsPotentiallyUnbound) {
91+
IRBuilder<> Builder{&Context->back()};
9392

94-
if (HasNoExits)
95-
ReasonStr += "(reason: no exit blocks).";
96-
else if (CannotPredictLoopCount)
97-
ReasonStr += "(reason: backedge taken count cannot be computed).";
98-
else
99-
assert(false);
93+
std::string ReasonStr =
94+
demangle(F->getName().str()) + " contains a possibly unbounded loop ";
10095

101-
Value *Reason = Builder.CreateGlobalStringPtr(ReasonStr);
102-
insertCallBeforeInstruction(F, Builder, "__rtsan_expect_not_realtime",
103-
{Reason});
96+
if (HasNoExits)
97+
ReasonStr += "(reason: no exit blocks).";
98+
else if (CannotPredictLoopCount)
99+
ReasonStr += "(reason: backedge taken count cannot be computed).";
100+
else
101+
assert(false);
104102

105-
// TODO: What is preserved here??
106-
PA = PreservedAnalyses::none();
103+
Value *Reason = Builder.CreateGlobalStringPtr(ReasonStr);
104+
insertCallBeforeInstruction(*F, Builder, "__rtsan_expect_not_realtime",
105+
{Reason});
107106

108-
// TODO: Tons of test cases
107+
// TODO: What is preserved here??
108+
return PreservedAnalyses::none();
109109
}
110-
}
111110

112-
return PA;
111+
return PreservedAnalyses::all();
113112
}
113+

llvm/test/Instrumentation/RealtimeSanitizer/rtsan_bound_loop.ll

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -passes='rtsan' -S | FileCheck %s
1+
; RUN: opt < %s -passes='sroa,sanitize-unbound-loops' -S | FileCheck %s
22

33

44
define void @procces(ptr noundef %buffer, i32 noundef %size) #0 {
@@ -40,9 +40,4 @@ for.end: ; preds = %for.cond
4040
attributes #0 = { sanitize_realtime }
4141

4242
; In this simple loop, we should not insert rtsan_expect_not_realtime
43-
; CHECK: call{{.*}}@__rtsan_realtime_enter
44-
45-
; TODO: This test fails when it shouldn't!!
46-
; XXXXX--CHECK-NOT: call{{.*}}@__rtsan_expect_not_realtime
47-
48-
; CHECK: call{{.*}}@__rtsan_realtime_exit
43+
; CHECK-NOT: call{{.*}}@__rtsan_expect_not_realtime

llvm/test/Instrumentation/RealtimeSanitizer/rtsan_cas_spinlock.ll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -passes=rtsan -S | FileCheck %s
1+
; RUN: opt < %s -passes='sanitize-unbound-loops' -S | FileCheck %s
22

33
%class.SpinLockTestAndSet = type { %"struct.std::__1::atomic_flag" }
44
%"struct.std::__1::atomic_flag" = type { %"struct.std::__1::__cxx_atomic_impl" }
@@ -25,6 +25,4 @@ SpinlockTestAndSet.exit: ; preds = %while.cond.i
2525

2626
attributes #0 = { sanitize_realtime }
2727

28-
; CHECK: call{{.*}}@__rtsan_realtime_enter
2928
; CHECK: call{{.*}}@__rtsan_expect_not_realtime
30-
; CHECK: call{{.*}}@__rtsan_realtime_exit

llvm/test/Instrumentation/RealtimeSanitizer/rtsan_infinite_loop.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -passes=rtsan -S | FileCheck %s
1+
; RUN: opt < %s -passes='sanitize-unbound-loops' -S | FileCheck %s
22

33
define void @process() #0 {
44
entry:
@@ -10,6 +10,5 @@ while.body: ; preds = %entry, %while.body
1010

1111
attributes #0 = { sanitize_realtime }
1212

13-
; CHECK: call{{.*}}@__rtsan_realtime_enter
1413
; CHECK: call{{.*}}@__rtsan_expect_not_realtime
1514
; CHECK-NEXT: br label %while.body

0 commit comments

Comments
 (0)