diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2014-08-06 00:33:40 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2014-08-06 00:33:40 +0000 |
commit | df240b252ab4224bb9851687b74faf3135ab2f09 (patch) | |
tree | 9609ef6324bd67e66d81bd21d591c299b8a0e63c /llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp | |
parent | d5f4de27b6ae4ce7712e1e60c331a175c8ce3f40 (diff) | |
download | llvm-df240b252ab4224bb9851687b74faf3135ab2f09.zip llvm-df240b252ab4224bb9851687b74faf3135ab2f09.tar.gz llvm-df240b252ab4224bb9851687b74faf3135ab2f09.tar.bz2 |
[dfsan] Try not to create too many additional basic blocks in functions which
already have a large number of blocks. Works around a performance issue with
the greedy register allocator.
llvm-svn: 214944
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp | 66 |
1 files changed, 46 insertions, 20 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index aa68ff5..3e11efc 100644 --- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -234,6 +234,7 @@ class DataFlowSanitizer : public ModulePass { FunctionType *DFSanSetLabelFnTy; FunctionType *DFSanNonzeroLabelFnTy; Constant *DFSanUnionFn; + Constant *DFSanCheckedUnionFn; Constant *DFSanUnionLoadFn; Constant *DFSanUnimplementedFn; Constant *DFSanSetLabelFn; @@ -280,6 +281,7 @@ struct DFSanFunction { std::vector<std::pair<PHINode *, PHINode *> > PHIFixups; DenseSet<Instruction *> SkipInsts; DenseSet<Value *> NonZeroChecks; + bool AvoidNewBlocks; struct CachedCombinedShadow { BasicBlock *Block; @@ -294,6 +296,9 @@ struct DFSanFunction { IsNativeABI(IsNativeABI), ArgTLSPtr(nullptr), RetvalTLSPtr(nullptr), LabelReturnAlloca(nullptr) { DT.recalculate(*F); + // FIXME: Need to track down the register allocator issue which causes poor + // performance in pathological cases with large numbers of basic blocks. + AvoidNewBlocks = F->size() > 1000; } Value *getArgTLSPtr(); Value *getArgTLS(unsigned Index, Instruction *Pos); @@ -577,6 +582,15 @@ bool DataFlowSanitizer::runOnModule(Module &M) { DFSanUnionFn = Mod->getOrInsertFunction("__dfsan_union", DFSanUnionFnTy); if (Function *F = dyn_cast<Function>(DFSanUnionFn)) { + F->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); + F->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); + F->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); + F->addAttribute(1, Attribute::ZExt); + F->addAttribute(2, Attribute::ZExt); + } + DFSanCheckedUnionFn = Mod->getOrInsertFunction("dfsan_union", DFSanUnionFnTy); + if (Function *F = dyn_cast<Function>(DFSanCheckedUnionFn)) { + F->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); F->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); F->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); F->addAttribute(1, Attribute::ZExt); @@ -585,6 +599,7 @@ bool DataFlowSanitizer::runOnModule(Module &M) { DFSanUnionLoadFn = Mod->getOrInsertFunction("__dfsan_union_load", DFSanUnionLoadFnTy); if (Function *F = dyn_cast<Function>(DFSanUnionLoadFn)) { + F->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); F->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); F->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); } @@ -603,6 +618,7 @@ bool DataFlowSanitizer::runOnModule(Module &M) { for (Module::iterator i = M.begin(), e = M.end(); i != e; ++i) { if (!i->isIntrinsic() && i != DFSanUnionFn && + i != DFSanCheckedUnionFn && i != DFSanUnionLoadFn && i != DFSanUnimplementedFn && i != DFSanSetLabelFn && @@ -922,23 +938,33 @@ Value *DFSanFunction::combineShadows(Value *V1, Value *V2, Instruction *Pos) { return CCS.Shadow; IRBuilder<> IRB(Pos); - BasicBlock *Head = Pos->getParent(); - Value *Ne = IRB.CreateICmpNE(V1, V2); - BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen( - Ne, Pos, /*Unreachable=*/false, DFS.ColdCallWeights, &DT)); - IRBuilder<> ThenIRB(BI); - CallInst *Call = ThenIRB.CreateCall2(DFS.DFSanUnionFn, V1, V2); - Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); - Call->addAttribute(1, Attribute::ZExt); - Call->addAttribute(2, Attribute::ZExt); - - BasicBlock *Tail = BI->getSuccessor(0); - PHINode *Phi = PHINode::Create(DFS.ShadowTy, 2, "", Tail->begin()); - Phi->addIncoming(Call, Call->getParent()); - Phi->addIncoming(V1, Head); - - CCS.Block = Tail; - CCS.Shadow = Phi; + if (AvoidNewBlocks) { + CallInst *Call = IRB.CreateCall2(DFS.DFSanCheckedUnionFn, V1, V2); + Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); + Call->addAttribute(1, Attribute::ZExt); + Call->addAttribute(2, Attribute::ZExt); + + CCS.Block = Pos->getParent(); + CCS.Shadow = Call; + } else { + BasicBlock *Head = Pos->getParent(); + Value *Ne = IRB.CreateICmpNE(V1, V2); + BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen( + Ne, Pos, /*Unreachable=*/false, DFS.ColdCallWeights, &DT)); + IRBuilder<> ThenIRB(BI); + CallInst *Call = ThenIRB.CreateCall2(DFS.DFSanUnionFn, V1, V2); + Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); + Call->addAttribute(1, Attribute::ZExt); + Call->addAttribute(2, Attribute::ZExt); + + BasicBlock *Tail = BI->getSuccessor(0); + PHINode *Phi = PHINode::Create(DFS.ShadowTy, 2, "", Tail->begin()); + Phi->addIncoming(Call, Call->getParent()); + Phi->addIncoming(V1, Head); + + CCS.Block = Tail; + CCS.Shadow = Phi; + } std::set<Value *> UnionElems; if (V1Elems != ShadowElements.end()) { @@ -951,9 +977,9 @@ Value *DFSanFunction::combineShadows(Value *V1, Value *V2, Instruction *Pos) { } else { UnionElems.insert(V2); } - ShadowElements[Phi] = std::move(UnionElems); + ShadowElements[CCS.Shadow] = std::move(UnionElems); - return Phi; + return CCS.Shadow; } // A convenience function which folds the shadows of each of the operands @@ -1022,7 +1048,7 @@ Value *DFSanFunction::loadShadow(Value *Addr, uint64_t Size, uint64_t Align, IRB.CreateAlignedLoad(ShadowAddr1, ShadowAlign), Pos); } } - if (Size % (64 / DFS.ShadowWidth) == 0) { + if (!AvoidNewBlocks && Size % (64 / DFS.ShadowWidth) == 0) { // Fast path for the common case where each byte has identical shadow: load // shadow 64 bits at a time, fall out to a __dfsan_union_load call if any // shadow is non-equal. |