[clang] Add optional pass to remove UBSAN traps using PGO (#84214)
With #83471 it reduces UBSAN overhead from 44% to 6%. Measured as "Geomean difference" on "test-suite/MultiSource/Benchmarks" with PGO build. On real large server binary we see 95% of code is still instrumented, with 10% -> 1.5% UBSAN overhead improvements. We can pass this test only with subset of UBSAN, so base overhead is smaller. We have followup patches to improve it even further.
This commit is contained in:
parent
08a9207f94
commit
eaa71a97f9
@ -76,6 +76,7 @@
|
||||
#include "llvm/Transforms/Instrumentation/MemProfiler.h"
|
||||
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
|
||||
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
|
||||
#include "llvm/Transforms/Instrumentation/RemoveTrapsPass.h"
|
||||
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
|
||||
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
|
||||
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
|
||||
@ -83,6 +84,7 @@
|
||||
#include "llvm/Transforms/Scalar/EarlyCSE.h"
|
||||
#include "llvm/Transforms/Scalar/GVN.h"
|
||||
#include "llvm/Transforms/Scalar/JumpThreading.h"
|
||||
#include "llvm/Transforms/Scalar/SimplifyCFG.h"
|
||||
#include "llvm/Transforms/Utils/Debugify.h"
|
||||
#include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
@ -98,6 +100,10 @@ using namespace llvm;
|
||||
namespace llvm {
|
||||
extern cl::opt<bool> PrintPipelinePasses;
|
||||
|
||||
cl::opt<bool> ClRemoveTraps("clang-remove-traps", cl::Optional,
|
||||
cl::desc("Insert remove-traps pass."),
|
||||
cl::init(false));
|
||||
|
||||
// Experiment to move sanitizers earlier.
|
||||
static cl::opt<bool> ClSanitizeOnOptimizerEarlyEP(
|
||||
"sanitizer-early-opt-ep", cl::Optional,
|
||||
@ -744,6 +750,21 @@ static void addSanitizers(const Triple &TargetTriple,
|
||||
// LastEP does not need GlobalsAA.
|
||||
PB.registerOptimizerLastEPCallback(SanitizersCallback);
|
||||
}
|
||||
|
||||
if (ClRemoveTraps) {
|
||||
// We can optimize after inliner, and PGO profile matching. The hook below
|
||||
// is called at the end `buildFunctionSimplificationPipeline`, which called
|
||||
// from `buildInlinerPipeline`, which called after profile matching.
|
||||
PB.registerScalarOptimizerLateEPCallback(
|
||||
[](FunctionPassManager &FPM, OptimizationLevel Level) {
|
||||
// RemoveTrapsPass expects trap blocks preceded by conditional
|
||||
// branches, which usually is not the case without SimplifyCFG.
|
||||
// TODO: Remove `SimplifyCFGPass` after switching to dedicated
|
||||
// intrinsic.
|
||||
FPM.addPass(SimplifyCFGPass());
|
||||
FPM.addPass(RemoveTrapsPass());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void EmitAssemblyHelper::RunOptimizationPipeline(
|
||||
|
||||
15
clang/test/CodeGen/remote-traps.c
Normal file
15
clang/test/CodeGen/remote-traps.c
Normal file
@ -0,0 +1,15 @@
|
||||
// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -O1 -emit-llvm -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow -mllvm -clang-remove-traps -mllvm -remove-traps-random-rate=1 %s -o - | FileCheck %s --implicit-check-not="call void @llvm.ubsantrap" --check-prefixes=REMOVE
|
||||
|
||||
int f(int x) {
|
||||
return x + 123;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define dso_local noundef i32 @f(
|
||||
// CHECK: call { i32, i1 } @llvm.sadd.with.overflow.i32(
|
||||
// CHECK: trap:
|
||||
// CHECK-NEXT: call void @llvm.ubsantrap(i8 0)
|
||||
// CHECK-NEXT: unreachable
|
||||
|
||||
// REMOVE-LABEL: define dso_local noundef i32 @f(
|
||||
// REMOVE: call { i32, i1 } @llvm.sadd.with.overflow.i32(
|
||||
Loading…
x
Reference in New Issue
Block a user