llvm.org GIT mirror llvm / f32aa7a
[dfsan] Introduce an optimization to reduce the number of union queries. Specifically, when building a union query, if we are dominated by an identical query then use the result of that query instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213047 91177308-0d34-0410-b5e6-96231b3b80d8 Peter Collingbourne 5 years ago
2 changed file(s) with 75 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
4949 #include "llvm/ADT/DepthFirstIterator.h"
5050 #include "llvm/ADT/StringExtras.h"
5151 #include "llvm/Analysis/ValueTracking.h"
52 #include "llvm/IR/Dominators.h"
5253 #include "llvm/IR/IRBuilder.h"
5354 #include "llvm/IR/InlineAsm.h"
5455 #include "llvm/IR/InstVisitor.h"
264265 struct DFSanFunction {
265266 DataFlowSanitizer &DFS;
266267 Function *F;
268 DominatorTree DT;
267269 DataFlowSanitizer::InstrumentedABI IA;
268270 bool IsNativeABI;
269271 Value *ArgTLSPtr;
275277 DenseSet SkipInsts;
276278 DenseSet NonZeroChecks;
277279
280 struct CachedCombinedShadow {
281 BasicBlock *Block;
282 Value *Shadow;
283 };
284 DenseMap, CachedCombinedShadow>
285 CachedCombinedShadows;
286
278287 DFSanFunction(DataFlowSanitizer &DFS, Function *F, bool IsNativeABI)
279288 : DFS(DFS), F(F), IA(DFS.getInstrumentedABI()),
280289 IsNativeABI(IsNativeABI), ArgTLSPtr(nullptr), RetvalTLSPtr(nullptr),
281 LabelReturnAlloca(nullptr) {}
290 LabelReturnAlloca(nullptr) {
291 DT.recalculate(*F);
292 }
282293 Value *getArgTLSPtr();
283294 Value *getArgTLS(unsigned Index, Instruction *Pos);
284295 Value *getRetvalTLS();
879890 return V1;
880891 if (V1 == V2)
881892 return V1;
893
894 auto Key = std::make_pair(V1, V2);
895 if (V1 > V2)
896 std::swap(Key.first, Key.second);
897 CachedCombinedShadow &CCS = CachedCombinedShadows[Key];
898 if (CCS.Block && DT.dominates(CCS.Block, Pos->getParent()))
899 return CCS.Shadow;
900
882901 IRBuilder<> IRB(Pos);
883902 BasicBlock *Head = Pos->getParent();
884903 Value *Ne = IRB.CreateICmpNE(V1, V2);
894913 PHINode *Phi = PHINode::Create(DFS.ShadowTy, 2, "", Tail->begin());
895914 Phi->addIncoming(Call, Call->getParent());
896915 Phi->addIncoming(V1, Head);
916
917 CCS.Block = Tail;
918 CCS.Shadow = Phi;
897919 return Phi;
898920 }
899921
9871009
9881010 BasicBlock *Head = Pos->getParent();
9891011 BasicBlock *Tail = Head->splitBasicBlock(Pos);
1012
1013 if (DomTreeNode *OldNode = DT.getNode(Head)) {
1014 std::vector Children(OldNode->begin(), OldNode->end());
1015
1016 DomTreeNode *NewNode = DT.addNewBlock(Tail, Head);
1017 for (auto Child : Children)
1018 DT.changeImmediateDominator(Child, NewNode);
1019 }
1020
9901021 // In the following code LastBr will refer to the previous basic block's
9911022 // conditional branch instruction, whose true successor is fixed up to point
9921023 // to the next block during the loop below or to the tail after the final
9931024 // iteration.
9941025 BranchInst *LastBr = BranchInst::Create(FallbackBB, FallbackBB, ShadowsEq);
9951026 ReplaceInstWithInst(Head->getTerminator(), LastBr);
1027 DT.addNewBlock(FallbackBB, Head);
9961028
9971029 for (uint64_t Ofs = 64 / DFS.ShadowWidth; Ofs != Size;
9981030 Ofs += 64 / DFS.ShadowWidth) {
9991031 BasicBlock *NextBB = BasicBlock::Create(*DFS.Ctx, "", F);
1032 DT.addNewBlock(NextBB, LastBr->getParent());
10001033 IRBuilder<> NextIRB(NextBB);
10011034 WideAddr = NextIRB.CreateGEP(WideAddr, ConstantInt::get(DFS.IntptrTy, 1));
10021035 Value *NextWideShadow = NextIRB.CreateAlignedLoad(WideAddr, ShadowAlign);
0 ; RUN: opt < %s -dfsan -S | FileCheck %s
1 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
2
3 @a = common global i32 0
4 @b = common global i32 0
5
6 ; Check that we reuse unions where possible.
7
8 ; CHECK-LABEL: @"dfs$f"
9 define void @f(i32 %x, i32 %y) {
10 ; CHECK: __dfsan_union
11 %xay = add i32 %x, %y
12 store i32 %xay, i32* @a
13 ; CHECK-NOT: __dfsan_union
14 %xmy = mul i32 %x, %y
15 store i32 %xmy, i32* @b
16 ret void
17 }
18
19 ; In this case, we compute the unions on both sides because neither block
20 ; dominates the other.
21
22 ; CHECK-LABEL: @"dfs$g"
23 define void @g(i1 %p, i32 %x, i32 %y) {
24 br i1 %p, label %l1, label %l2
25
26 l1:
27 ; CHECK: __dfsan_union
28 %xay = add i32 %x, %y
29 store i32 %xay, i32* @a
30 br label %l3
31
32 l2:
33 ; CHECK: __dfsan_union
34 %xmy = mul i32 %x, %y
35 store i32 %xmy, i32* @b
36 br label %l3
37
38 l3:
39 ret void
40 }