[asan] Speed up isInterestingAlloca check

We make many redundant calls to isInterestingAlloca in the AddressSanitzier
pass. This is especially inefficient for allocas that have many uses. Let's
cache the results to speed up compilation.

The compile time improvements depend on the input. I did not see much
difference on benchmarks; however, I have a test case where compile time
goes from minutes to under a second.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233397 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anna Zaks
2015-03-27 18:52:01 +00:00
parent 4193093152
commit 8ea048fa83

View File

@ -401,12 +401,12 @@ struct AddressSanitizer : public FunctionPass {
return SizeInBytes; return SizeInBytes;
} }
/// Check if we want (and can) handle this alloca. /// Check if we want (and can) handle this alloca.
bool isInterestingAlloca(AllocaInst &AI) const; bool isInterestingAlloca(AllocaInst &AI);
/// If it is an interesting memory access, return the PointerOperand /// If it is an interesting memory access, return the PointerOperand
/// and set IsWrite/Alignment. Otherwise return nullptr. /// and set IsWrite/Alignment. Otherwise return nullptr.
Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite, Value *isInterestingMemoryAccess(Instruction *I, bool *IsWrite,
uint64_t *TypeSize, uint64_t *TypeSize,
unsigned *Alignment) const; unsigned *Alignment);
void instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis, Instruction *I, void instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis, Instruction *I,
bool UseCalls, const DataLayout &DL); bool UseCalls, const DataLayout &DL);
void instrumentPointerComparisonOrSubtraction(Instruction *I); void instrumentPointerComparisonOrSubtraction(Instruction *I);
@ -458,6 +458,7 @@ struct AddressSanitizer : public FunctionPass {
Function *AsanMemmove, *AsanMemcpy, *AsanMemset; Function *AsanMemmove, *AsanMemcpy, *AsanMemset;
InlineAsm *EmptyAsm; InlineAsm *EmptyAsm;
GlobalsMetadata GlobalsMD; GlobalsMetadata GlobalsMD;
DenseMap<AllocaInst *, bool> ProcessedAllocas;
friend struct FunctionStackPoisoner; friend struct FunctionStackPoisoner;
}; };
@ -804,13 +805,21 @@ void AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
} }
/// Check if we want (and can) handle this alloca. /// Check if we want (and can) handle this alloca.
bool AddressSanitizer::isInterestingAlloca(AllocaInst &AI) const { bool AddressSanitizer::isInterestingAlloca(AllocaInst &AI) {
return (AI.getAllocatedType()->isSized() && auto PreviouslySeenAllocaInfo = ProcessedAllocas.find(&AI);
// alloca() may be called with 0 size, ignore it.
getAllocaSizeInBytes(&AI) > 0 && if (PreviouslySeenAllocaInfo != ProcessedAllocas.end())
// We are only interested in allocas not promotable to registers. return PreviouslySeenAllocaInfo->getSecond();
// Promotable allocas are common under -O0.
(!ClSkipPromotableAllocas || !isAllocaPromotable(&AI))); bool IsInteresting = (AI.getAllocatedType()->isSized() &&
// 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)));
ProcessedAllocas[&AI] = IsInteresting;
return IsInteresting;
} }
/// If I is an interesting memory access, return the PointerOperand /// If I is an interesting memory access, return the PointerOperand
@ -818,7 +827,7 @@ bool AddressSanitizer::isInterestingAlloca(AllocaInst &AI) const {
Value *AddressSanitizer::isInterestingMemoryAccess(Instruction *I, Value *AddressSanitizer::isInterestingMemoryAccess(Instruction *I,
bool *IsWrite, bool *IsWrite,
uint64_t *TypeSize, uint64_t *TypeSize,
unsigned *Alignment) const { unsigned *Alignment) {
// Skip memory accesses inserted by another instrumentation. // Skip memory accesses inserted by another instrumentation.
if (I->getMetadata("nosanitize")) return nullptr; if (I->getMetadata("nosanitize")) return nullptr;