From a49dcbb743d822d05e5e091bf97378d38f36140d Mon Sep 17 00:00:00 2001 From: Kuba Brecka Date: Tue, 8 Nov 2016 21:30:41 +0000 Subject: [PATCH] [asan] Speed up compilation of large C++ stringmaps (tons of allocas) with ASan This addresses PR30746, . The ASan pass iterates over entry-block instructions and checks each alloca whether it's in NonInstrumentedStaticAllocaVec, which is apparently slow. This patch gathers the instructions to move during visitAllocaInst. Differential Revision: https://reviews.llvm.org/D26380 llvm-svn: 286296 --- .../Transforms/Instrumentation/AddressSanitizer.cpp | 18 ++++++++++++------ .../debug_info_noninstrumented_alloca2.ll | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca2.ll diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index df068e8..e487313 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -638,7 +638,7 @@ struct FunctionStackPoisoner : public InstVisitor { ShadowMapping Mapping; SmallVector AllocaVec; - SmallSetVector NonInstrumentedStaticAllocaVec; + SmallVector StaticAllocasToMoveUp; SmallVector RetVec; unsigned StackAlignment; @@ -766,7 +766,14 @@ struct FunctionStackPoisoner : public InstVisitor { /// \brief Collect Alloca instructions we want (and can) handle. void visitAllocaInst(AllocaInst &AI) { if (!ASan.isInterestingAlloca(AI)) { - if (AI.isStaticAlloca()) NonInstrumentedStaticAllocaVec.insert(&AI); + if (AI.isStaticAlloca()) { + // Skip over allocas that are present *before* the first instrumented + // alloca, we don't want to move those around. + if (AllocaVec.empty()) + return; + + StaticAllocasToMoveUp.push_back(&AI); + } return; } @@ -2231,10 +2238,9 @@ void FunctionStackPoisoner::processStaticAllocas() { // regular stack slots. auto InsBeforeB = InsBefore->getParent(); assert(InsBeforeB == &F.getEntryBlock()); - for (BasicBlock::iterator I(InsBefore); I != InsBeforeB->end(); ++I) - if (auto *AI = dyn_cast(I)) - if (NonInstrumentedStaticAllocaVec.count(AI) > 0) - AI->moveBefore(InsBefore); + for (auto *AI : StaticAllocasToMoveUp) + if (AI->getParent() == InsBeforeB) + AI->moveBefore(InsBefore); // If we have a call to llvm.localescape, keep it in the entry block. if (LocalEscapeCall) LocalEscapeCall->moveBefore(InsBefore); diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca2.ll b/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca2.ll new file mode 100644 index 0000000..b6d393d --- /dev/null +++ b/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca2.ll @@ -0,0 +1,21 @@ +; Make sure we don't break the IR when moving non-instrumented allocas + +; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -asan-instrument-dynamic-allocas -S | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +define i32 @foo() sanitize_address { +entry: + %non_instrumented1 = alloca i32, align 4 + %t = load i32, i32* %non_instrumented1, align 4 + %instrumented = alloca i32, align 4 + %ptr = ptrtoint i32* %instrumented to i32 + ret i32 %t +} + +; CHECK: entry: +; CHECK: %non_instrumented1 = alloca i32, align 4 +; CHECK: load i32, i32* %non_instrumented1 +; CHECK: load i32, i32* @__asan_option_detect_stack_use_after_return -- 2.7.4