forked from OSchip/llvm-project
				
			[asan] Skip promotable allocas to improve performance at -O0
Currently, the ASan executables built with -O0 are unnecessarily slow. The main reason is that ASan instrumentation pass inserts redundant checks around promotable allocas. These allocas do not get instrumented under -O1 because they get converted to virtual registered by mem2reg. With this patch, ASan instrumentation pass will only instrument non promotable allocas, giving us a speedup of 39% on a collection of benchmarks with -O0. (There is no measurable speedup at -O1.) llvm-svn: 230724
This commit is contained in:
		
							parent
							
								
									2249049db2
								
							
						
					
					
						commit
						8ed1d8196b
					
				| 
						 | 
					@ -49,6 +49,7 @@
 | 
				
			||||||
#include "llvm/Transforms/Utils/Cloning.h"
 | 
					#include "llvm/Transforms/Utils/Cloning.h"
 | 
				
			||||||
#include "llvm/Transforms/Utils/Local.h"
 | 
					#include "llvm/Transforms/Utils/Local.h"
 | 
				
			||||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
 | 
					#include "llvm/Transforms/Utils/ModuleUtils.h"
 | 
				
			||||||
 | 
					#include "llvm/Transforms/Utils/PromoteMemToReg.h"
 | 
				
			||||||
#include <algorithm>
 | 
					#include <algorithm>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <system_error>
 | 
					#include <system_error>
 | 
				
			||||||
| 
						 | 
					@ -165,6 +166,9 @@ static cl::opt<std::string> ClMemoryAccessCallbackPrefix(
 | 
				
			||||||
       cl::init("__asan_"));
 | 
					       cl::init("__asan_"));
 | 
				
			||||||
static cl::opt<bool> ClInstrumentAllocas("asan-instrument-allocas",
 | 
					static cl::opt<bool> ClInstrumentAllocas("asan-instrument-allocas",
 | 
				
			||||||
       cl::desc("instrument dynamic allocas"), cl::Hidden, cl::init(false));
 | 
					       cl::desc("instrument dynamic allocas"), cl::Hidden, cl::init(false));
 | 
				
			||||||
 | 
					static cl::opt<bool> ClSkipPromotableAllocas("asan-skip-promotable-allocas",
 | 
				
			||||||
 | 
					       cl::desc("Do not instrument promotable allocas"),
 | 
				
			||||||
 | 
					       cl::Hidden, cl::init(true));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// These flags allow to change the shadow mapping.
 | 
					// These flags allow to change the shadow mapping.
 | 
				
			||||||
// The shadow mapping looks like
 | 
					// The shadow mapping looks like
 | 
				
			||||||
| 
						 | 
					@ -372,6 +376,17 @@ struct AddressSanitizer : public FunctionPass {
 | 
				
			||||||
  void getAnalysisUsage(AnalysisUsage &AU) const override {
 | 
					  void getAnalysisUsage(AnalysisUsage &AU) const override {
 | 
				
			||||||
    AU.addRequired<DominatorTreeWrapperPass>();
 | 
					    AU.addRequired<DominatorTreeWrapperPass>();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  uint64_t getAllocaSizeInBytes(AllocaInst *AI) const {
 | 
				
			||||||
 | 
					    Type *Ty = AI->getAllocatedType();
 | 
				
			||||||
 | 
					    uint64_t SizeInBytes = DL->getTypeAllocSize(Ty);
 | 
				
			||||||
 | 
					    return SizeInBytes;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  /// Check if we want (and can) handle this alloca.
 | 
				
			||||||
 | 
					  bool isInterestingAlloca(AllocaInst &AI) const;
 | 
				
			||||||
 | 
					  /// If it is an interesting memory access, return the PointerOperand
 | 
				
			||||||
 | 
					  /// and set IsWrite/Alignment. Otherwise return nullptr.
 | 
				
			||||||
 | 
					  Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
 | 
				
			||||||
 | 
					                                   unsigned *Alignment) const;
 | 
				
			||||||
  void instrumentMop(Instruction *I, bool UseCalls);
 | 
					  void instrumentMop(Instruction *I, bool UseCalls);
 | 
				
			||||||
  void instrumentPointerComparisonOrSubtraction(Instruction *I);
 | 
					  void instrumentPointerComparisonOrSubtraction(Instruction *I);
 | 
				
			||||||
  void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
 | 
					  void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
 | 
				
			||||||
| 
						 | 
					@ -599,7 +614,7 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Collect Alloca instructions we want (and can) handle.
 | 
					  /// \brief Collect Alloca instructions we want (and can) handle.
 | 
				
			||||||
  void visitAllocaInst(AllocaInst &AI) {
 | 
					  void visitAllocaInst(AllocaInst &AI) {
 | 
				
			||||||
    if (!isInterestingAlloca(AI)) return;
 | 
					    if (!ASan.isInterestingAlloca(AI)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    StackAlignment = std::max(StackAlignment, AI.getAlignment());
 | 
					    StackAlignment = std::max(StackAlignment, AI.getAlignment());
 | 
				
			||||||
    if (isDynamicAlloca(AI))
 | 
					    if (isDynamicAlloca(AI))
 | 
				
			||||||
| 
						 | 
					@ -653,19 +668,6 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> {
 | 
				
			||||||
  bool isDynamicAlloca(AllocaInst &AI) const {
 | 
					  bool isDynamicAlloca(AllocaInst &AI) const {
 | 
				
			||||||
    return AI.isArrayAllocation() || !AI.isStaticAlloca();
 | 
					    return AI.isArrayAllocation() || !AI.isStaticAlloca();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  // Check if we want (and can) handle this alloca.
 | 
					 | 
				
			||||||
  bool isInterestingAlloca(AllocaInst &AI) const {
 | 
					 | 
				
			||||||
    return (AI.getAllocatedType()->isSized() &&
 | 
					 | 
				
			||||||
            // alloca() may be called with 0 size, ignore it.
 | 
					 | 
				
			||||||
            getAllocaSizeInBytes(&AI) > 0);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  uint64_t getAllocaSizeInBytes(AllocaInst *AI) const {
 | 
					 | 
				
			||||||
    Type *Ty = AI->getAllocatedType();
 | 
					 | 
				
			||||||
    uint64_t SizeInBytes = ASan.DL->getTypeAllocSize(Ty);
 | 
					 | 
				
			||||||
    return SizeInBytes;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  /// Finds alloca where the value comes from.
 | 
					  /// Finds alloca where the value comes from.
 | 
				
			||||||
  AllocaInst *findAllocaForValue(Value *V);
 | 
					  AllocaInst *findAllocaForValue(Value *V);
 | 
				
			||||||
  void poisonRedZones(ArrayRef<uint8_t> ShadowBytes, IRBuilder<> &IRB,
 | 
					  void poisonRedZones(ArrayRef<uint8_t> ShadowBytes, IRBuilder<> &IRB,
 | 
				
			||||||
| 
						 | 
					@ -775,38 +777,56 @@ void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
 | 
				
			||||||
  MI->eraseFromParent();
 | 
					  MI->eraseFromParent();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// If I is an interesting memory access, return the PointerOperand
 | 
					/// Check if we want (and can) handle this alloca.
 | 
				
			||||||
// and set IsWrite/Alignment. Otherwise return nullptr.
 | 
					bool AddressSanitizer::isInterestingAlloca(AllocaInst &AI) const {
 | 
				
			||||||
static Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
 | 
					  return (AI.getAllocatedType()->isSized() &&
 | 
				
			||||||
                                        unsigned *Alignment) {
 | 
					          // alloca() may be called with 0 size, ignore it.
 | 
				
			||||||
 | 
					          getAllocaSizeInBytes(&AI) > 0 &&
 | 
				
			||||||
 | 
					          // We are only interested in allocas not promotable to registers.
 | 
				
			||||||
 | 
					          // Promotable allocas are common under -O0.
 | 
				
			||||||
 | 
					          (!ClSkipPromotableAllocas || !isAllocaPromotable(&AI)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// If I is an interesting memory access, return the PointerOperand
 | 
				
			||||||
 | 
					/// and set IsWrite/Alignment. Otherwise return nullptr.
 | 
				
			||||||
 | 
					Value *AddressSanitizer::isInterestingMemoryAccess(Instruction *I,
 | 
				
			||||||
 | 
					                                                   bool *IsWrite,
 | 
				
			||||||
 | 
					                                                   unsigned *Alignment) const {
 | 
				
			||||||
  // Skip memory accesses inserted by another instrumentation.
 | 
					  // Skip memory accesses inserted by another instrumentation.
 | 
				
			||||||
  if (I->getMetadata("nosanitize"))
 | 
					  if (I->getMetadata("nosanitize"))
 | 
				
			||||||
    return nullptr;
 | 
					    return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Value *PtrOperand = nullptr;
 | 
				
			||||||
  if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
 | 
					  if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
 | 
				
			||||||
    if (!ClInstrumentReads) return nullptr;
 | 
					    if (!ClInstrumentReads) return nullptr;
 | 
				
			||||||
    *IsWrite = false;
 | 
					    *IsWrite = false;
 | 
				
			||||||
    *Alignment = LI->getAlignment();
 | 
					    *Alignment = LI->getAlignment();
 | 
				
			||||||
    return LI->getPointerOperand();
 | 
					    PtrOperand = LI->getPointerOperand();
 | 
				
			||||||
  }
 | 
					  } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
 | 
				
			||||||
  if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
 | 
					 | 
				
			||||||
    if (!ClInstrumentWrites) return nullptr;
 | 
					    if (!ClInstrumentWrites) return nullptr;
 | 
				
			||||||
    *IsWrite = true;
 | 
					    *IsWrite = true;
 | 
				
			||||||
    *Alignment = SI->getAlignment();
 | 
					    *Alignment = SI->getAlignment();
 | 
				
			||||||
    return SI->getPointerOperand();
 | 
					    PtrOperand = SI->getPointerOperand();
 | 
				
			||||||
  }
 | 
					  } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
 | 
				
			||||||
  if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(I)) {
 | 
					 | 
				
			||||||
    if (!ClInstrumentAtomics) return nullptr;
 | 
					    if (!ClInstrumentAtomics) return nullptr;
 | 
				
			||||||
    *IsWrite = true;
 | 
					    *IsWrite = true;
 | 
				
			||||||
    *Alignment = 0;
 | 
					    *Alignment = 0;
 | 
				
			||||||
    return RMW->getPointerOperand();
 | 
					    PtrOperand = RMW->getPointerOperand();
 | 
				
			||||||
  }
 | 
					  } else if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
 | 
				
			||||||
  if (AtomicCmpXchgInst *XCHG = dyn_cast<AtomicCmpXchgInst>(I)) {
 | 
					 | 
				
			||||||
    if (!ClInstrumentAtomics) return nullptr;
 | 
					    if (!ClInstrumentAtomics) return nullptr;
 | 
				
			||||||
    *IsWrite = true;
 | 
					    *IsWrite = true;
 | 
				
			||||||
    *Alignment = 0;
 | 
					    *Alignment = 0;
 | 
				
			||||||
    return XCHG->getPointerOperand();
 | 
					    PtrOperand = XCHG->getPointerOperand();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return nullptr;
 | 
					
 | 
				
			||||||
 | 
					  // Treat memory accesses to promotable allocas as non-interesting since they
 | 
				
			||||||
 | 
					  // will not cause memory violations. This greatly speeds up the instrumented
 | 
				
			||||||
 | 
					  // executable at -O0.
 | 
				
			||||||
 | 
					  if (ClSkipPromotableAllocas)
 | 
				
			||||||
 | 
					    if (auto AI = dyn_cast_or_null<AllocaInst>(PtrOperand))
 | 
				
			||||||
 | 
					      return isInterestingAlloca(*AI) ? AI : nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return PtrOperand;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool isPointerOperand(Value *V) {
 | 
					static bool isPointerOperand(Value *V) {
 | 
				
			||||||
| 
						 | 
					@ -1665,7 +1685,7 @@ void FunctionStackPoisoner::poisonStack() {
 | 
				
			||||||
  SVD.reserve(AllocaVec.size());
 | 
					  SVD.reserve(AllocaVec.size());
 | 
				
			||||||
  for (AllocaInst *AI : AllocaVec) {
 | 
					  for (AllocaInst *AI : AllocaVec) {
 | 
				
			||||||
    ASanStackVariableDescription D = { AI->getName().data(),
 | 
					    ASanStackVariableDescription D = { AI->getName().data(),
 | 
				
			||||||
                                   getAllocaSizeInBytes(AI),
 | 
					                                   ASan.getAllocaSizeInBytes(AI),
 | 
				
			||||||
                                   AI->getAlignment(), AI, 0};
 | 
					                                   AI->getAlignment(), AI, 0};
 | 
				
			||||||
    SVD.push_back(D);
 | 
					    SVD.push_back(D);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -1856,7 +1876,7 @@ void FunctionStackPoisoner::poisonAlloca(Value *V, uint64_t Size,
 | 
				
			||||||
AllocaInst *FunctionStackPoisoner::findAllocaForValue(Value *V) {
 | 
					AllocaInst *FunctionStackPoisoner::findAllocaForValue(Value *V) {
 | 
				
			||||||
  if (AllocaInst *AI = dyn_cast<AllocaInst>(V))
 | 
					  if (AllocaInst *AI = dyn_cast<AllocaInst>(V))
 | 
				
			||||||
    // We're intested only in allocas we can handle.
 | 
					    // We're intested only in allocas we can handle.
 | 
				
			||||||
    return isInterestingAlloca(*AI) ? AI : nullptr;
 | 
					    return ASan.isInterestingAlloca(*AI) ? AI : nullptr;
 | 
				
			||||||
  // See if we've already calculated (or started to calculate) alloca for a
 | 
					  // See if we've already calculated (or started to calculate) alloca for a
 | 
				
			||||||
  // given value.
 | 
					  // given value.
 | 
				
			||||||
  AllocaForValueMapTy::iterator I = AllocaForValue.find(V);
 | 
					  AllocaForValueMapTy::iterator I = AllocaForValue.find(V);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,12 +10,12 @@ define i32 @_Z3zzzi(i32 %p) nounwind uwtable sanitize_address {
 | 
				
			||||||
entry:
 | 
					entry:
 | 
				
			||||||
  %p.addr = alloca i32, align 4
 | 
					  %p.addr = alloca i32, align 4
 | 
				
			||||||
  %r = alloca i32, align 4
 | 
					  %r = alloca i32, align 4
 | 
				
			||||||
  store i32 %p, i32* %p.addr, align 4
 | 
					  store volatile i32 %p, i32* %p.addr, align 4
 | 
				
			||||||
  call void @llvm.dbg.declare(metadata i32* %p.addr, metadata !10, metadata !{!"0x102"}), !dbg !11
 | 
					  call void @llvm.dbg.declare(metadata i32* %p.addr, metadata !10, metadata !{!"0x102"}), !dbg !11
 | 
				
			||||||
  call void @llvm.dbg.declare(metadata i32* %r, metadata !12, metadata !{!"0x102"}), !dbg !14
 | 
					  call void @llvm.dbg.declare(metadata i32* %r, metadata !12, metadata !{!"0x102"}), !dbg !14
 | 
				
			||||||
  %0 = load i32* %p.addr, align 4, !dbg !14
 | 
					  %0 = load i32* %p.addr, align 4, !dbg !14
 | 
				
			||||||
  %add = add nsw i32 %0, 1, !dbg !14
 | 
					  %add = add nsw i32 %0, 1, !dbg !14
 | 
				
			||||||
  store i32 %add, i32* %r, align 4, !dbg !14
 | 
					  store volatile i32 %add, i32* %r, align 4, !dbg !14
 | 
				
			||||||
  %1 = load i32* %r, align 4, !dbg !15
 | 
					  %1 = load i32* %r, align 4, !dbg !15
 | 
				
			||||||
  ret i32 %1, !dbg !15
 | 
					  ret i32 %1, !dbg !15
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					; RUN: opt < %s -asan -asan-module -asan-instrument-allocas=1 -S | FileCheck %s --check-prefix=CHECK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
 | 
				
			||||||
 | 
					target triple = "x86_64-apple-macosx10.10.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					define i32 @test_promotable_allocas() sanitize_address {
 | 
				
			||||||
 | 
					entry:
 | 
				
			||||||
 | 
					; CHECK: %0 = alloca i32, align 4
 | 
				
			||||||
 | 
					; CHECK: store i32 0, i32* %0, align 4
 | 
				
			||||||
 | 
					; CHECK: %1 = load i32* %0, align 4
 | 
				
			||||||
 | 
					; CHECK: ret i32 %1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					; CHECK-NOT: __asan_stack_malloc_0
 | 
				
			||||||
 | 
					; CHECK-NOT: icmp
 | 
				
			||||||
 | 
					; CHECK-NOT: call void @__asan_report_store4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  %0 = alloca i32, align 4
 | 
				
			||||||
 | 
					  store i32 0, i32* %0, align 4
 | 
				
			||||||
 | 
					  %1 = load i32* %0, align 4
 | 
				
			||||||
 | 
					  ret i32 %1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -15,10 +15,11 @@ entry:
 | 
				
			||||||
; CHECK-NOALLOCA-NOT: store i32 -875836469
 | 
					; CHECK-NOALLOCA-NOT: store i32 -875836469
 | 
				
			||||||
  %0 = alloca i32, align 4
 | 
					  %0 = alloca i32, align 4
 | 
				
			||||||
  %1 = alloca i8*
 | 
					  %1 = alloca i8*
 | 
				
			||||||
  store i32 %len, i32* %0, align 4
 | 
					  store volatile i32 %len, i32* %0, align 4
 | 
				
			||||||
  %2 = load i32* %0, align 4
 | 
					  %2 = load i32* %0, align 4
 | 
				
			||||||
  %3 = zext i32 %2 to i64
 | 
					  %3 = zext i32 %2 to i64
 | 
				
			||||||
  %4 = alloca i8, i64 %3, align 32
 | 
					  %4 = alloca i8, i64 %3, align 32
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %4
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,8 +17,8 @@ entry:
 | 
				
			||||||
  ; Memory is unpoisoned at llvm.lifetime.start
 | 
					  ; Memory is unpoisoned at llvm.lifetime.start
 | 
				
			||||||
  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 1)
 | 
					  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  store i32 0, i32* %retval
 | 
					  store volatile i32 0, i32* %retval
 | 
				
			||||||
  store i8 0, i8* %c, align 1
 | 
					  store volatile i8 0, i8* %c, align 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  call void @llvm.lifetime.end(i64 1, i8* %c)
 | 
					  call void @llvm.lifetime.end(i64 1, i8* %c)
 | 
				
			||||||
  ; Memory is poisoned at llvm.lifetime.end
 | 
					  ; Memory is poisoned at llvm.lifetime.end
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ entry:
 | 
				
			||||||
  %i = alloca i32, align 4
 | 
					  %i = alloca i32, align 4
 | 
				
			||||||
  %i.ptr = bitcast i32* %i to i8*
 | 
					  %i.ptr = bitcast i32* %i to i8*
 | 
				
			||||||
  call void @llvm.lifetime.start(i64 -1, i8* %i.ptr)
 | 
					  call void @llvm.lifetime.start(i64 -1, i8* %i.ptr)
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %i.ptr
 | 
				
			||||||
  call void @llvm.lifetime.end(i64 -1, i8* %i.ptr)
 | 
					  call void @llvm.lifetime.end(i64 -1, i8* %i.ptr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
; Check that lifetime with no size are ignored.
 | 
					; Check that lifetime with no size are ignored.
 | 
				
			||||||
| 
						 | 
					@ -30,6 +31,7 @@ define void @lifetime() sanitize_address {
 | 
				
			||||||
  %i = alloca i32, align 4
 | 
					  %i = alloca i32, align 4
 | 
				
			||||||
  %i.ptr = bitcast i32* %i to i8*
 | 
					  %i.ptr = bitcast i32* %i to i8*
 | 
				
			||||||
  call void @llvm.lifetime.start(i64 3, i8* %i.ptr)
 | 
					  call void @llvm.lifetime.start(i64 3, i8* %i.ptr)
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %i.ptr
 | 
				
			||||||
  ; Memory is unpoisoned at llvm.lifetime.start
 | 
					  ; Memory is unpoisoned at llvm.lifetime.start
 | 
				
			||||||
  ; CHECK: %[[VAR:[^ ]*]] = ptrtoint i32* %{{[^ ]+}} to i64
 | 
					  ; CHECK: %[[VAR:[^ ]*]] = ptrtoint i32* %{{[^ ]+}} to i64
 | 
				
			||||||
  ; CHECK-NEXT: call void @__asan_unpoison_stack_memory(i64 %[[VAR]], i64 3)
 | 
					  ; CHECK-NEXT: call void @__asan_unpoison_stack_memory(i64 %[[VAR]], i64 3)
 | 
				
			||||||
| 
						 | 
					@ -43,12 +45,14 @@ define void @lifetime() sanitize_address {
 | 
				
			||||||
  %arr = alloca [10 x i32], align 16
 | 
					  %arr = alloca [10 x i32], align 16
 | 
				
			||||||
  %arr.ptr = bitcast [10 x i32]* %arr to i8*
 | 
					  %arr.ptr = bitcast [10 x i32]* %arr to i8*
 | 
				
			||||||
  call void @llvm.lifetime.start(i64 40, i8* %arr.ptr)
 | 
					  call void @llvm.lifetime.start(i64 40, i8* %arr.ptr)
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr.ptr
 | 
				
			||||||
  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 40)
 | 
					  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 40)
 | 
				
			||||||
  call void @llvm.lifetime.end(i64 40, i8* %arr.ptr)
 | 
					  call void @llvm.lifetime.end(i64 40, i8* %arr.ptr)
 | 
				
			||||||
  ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 40)
 | 
					  ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 40)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ; One more lifetime start/end for the same variable %i.
 | 
					  ; One more lifetime start/end for the same variable %i.
 | 
				
			||||||
  call void @llvm.lifetime.start(i64 4, i8* %i.ptr)
 | 
					  call void @llvm.lifetime.start(i64 4, i8* %i.ptr)
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %i.ptr
 | 
				
			||||||
  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 4)
 | 
					  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 4)
 | 
				
			||||||
  call void @llvm.lifetime.end(i64 4, i8* %i.ptr)
 | 
					  call void @llvm.lifetime.end(i64 4, i8* %i.ptr)
 | 
				
			||||||
  ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 4)
 | 
					  ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 4)
 | 
				
			||||||
| 
						 | 
					@ -68,6 +72,7 @@ entry:
 | 
				
			||||||
  %i = alloca i64, align 4
 | 
					  %i = alloca i64, align 4
 | 
				
			||||||
  %i.ptr = bitcast i64* %i to i8*
 | 
					  %i.ptr = bitcast i64* %i to i8*
 | 
				
			||||||
  call void @llvm.lifetime.start(i64 8, i8* %i.ptr)
 | 
					  call void @llvm.lifetime.start(i64 8, i8* %i.ptr)
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %i.ptr
 | 
				
			||||||
  ; CHECK: __asan_unpoison_stack_memory
 | 
					  ; CHECK: __asan_unpoison_stack_memory
 | 
				
			||||||
  br i1 %x, label %bb0, label %bb1
 | 
					  br i1 %x, label %bb0, label %bb1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,8 @@ entry:
 | 
				
			||||||
; CHECK: ret void
 | 
					; CHECK: ret void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  %XXX = alloca [20 x i8], align 1
 | 
					  %XXX = alloca [20 x i8], align 1
 | 
				
			||||||
 | 
					  %arr.ptr = bitcast [20 x i8]* %XXX to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr.ptr
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +39,8 @@ entry:
 | 
				
			||||||
; CHECK: ret void
 | 
					; CHECK: ret void
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  %XXX = alloca [20 x i8], align 1
 | 
					  %XXX = alloca [20 x i8], align 1
 | 
				
			||||||
 | 
					  %arr.ptr = bitcast [20 x i8]* %XXX to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr.ptr
 | 
				
			||||||
  call void asm sideeffect "mov %%rbx, %%rcx", "~{dirflag},~{fpsr},~{flags}"() nounwind
 | 
					  call void asm sideeffect "mov %%rbx, %%rcx", "~{dirflag},~{fpsr},~{flags}"() nounwind
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,12 @@ entry:
 | 
				
			||||||
  %XXX = alloca [10 x i8], align 1
 | 
					  %XXX = alloca [10 x i8], align 1
 | 
				
			||||||
  %YYY = alloca [20 x i8], align 1
 | 
					  %YYY = alloca [20 x i8], align 1
 | 
				
			||||||
  %ZZZ = alloca [30 x i8], align 1
 | 
					  %ZZZ = alloca [30 x i8], align 1
 | 
				
			||||||
 | 
					  %arr1.ptr = bitcast [10 x i8]* %XXX to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr1.ptr
 | 
				
			||||||
 | 
					  %arr2.ptr = bitcast [20 x i8]* %YYY to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr2.ptr
 | 
				
			||||||
 | 
					  %arr3.ptr = bitcast [30 x i8]* %ZZZ to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr3.ptr
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +47,12 @@ entry:
 | 
				
			||||||
  %AAA = alloca [5 x i8], align 1
 | 
					  %AAA = alloca [5 x i8], align 1
 | 
				
			||||||
  %BBB = alloca [55 x i8], align 1
 | 
					  %BBB = alloca [55 x i8], align 1
 | 
				
			||||||
  %CCC = alloca [555 x i8], align 1
 | 
					  %CCC = alloca [555 x i8], align 1
 | 
				
			||||||
 | 
					  %arr1.ptr = bitcast [5 x i8]* %AAA to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr1.ptr
 | 
				
			||||||
 | 
					  %arr2.ptr = bitcast [55 x i8]* %BBB to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr2.ptr
 | 
				
			||||||
 | 
					  %arr3.ptr = bitcast [555 x i8]* %CCC to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr3.ptr
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,5 +69,11 @@ entry:
 | 
				
			||||||
  %AAA = alloca [128 x i8], align 16
 | 
					  %AAA = alloca [128 x i8], align 16
 | 
				
			||||||
  %BBB = alloca [128 x i8], align 64
 | 
					  %BBB = alloca [128 x i8], align 64
 | 
				
			||||||
  %CCC = alloca [128 x i8], align 256
 | 
					  %CCC = alloca [128 x i8], align 256
 | 
				
			||||||
 | 
					  %arr1.ptr = bitcast [128 x i8]* %AAA to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr1.ptr
 | 
				
			||||||
 | 
					  %arr2.ptr = bitcast [128 x i8]* %BBB to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr2.ptr
 | 
				
			||||||
 | 
					  %arr3.ptr = bitcast [128 x i8]* %CCC to i8*
 | 
				
			||||||
 | 
					  store volatile i8 0, i8* %arr3.ptr
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue