From a7eb2b83ba102aed25fd7d0d09ae90f2fff458a1 Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 19 Dec 2013 13:29:56 +0000 Subject: Add an explicit insert point argument to SplitBlockAndInsertIfThen. Currently SplitBlockAndInsertIfThen requires that branch condition is an Instruction itself, which is very inconvenient, because it is sometimes an Operator, or even a Constant. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197677 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Transforms/Utils/BasicBlockUtils.h | 17 ++++++------ .../Instrumentation/AddressSanitizer.cpp | 14 ++++------ .../Instrumentation/DataFlowSanitizer.cpp | 10 +++---- lib/Transforms/Instrumentation/MemorySanitizer.cpp | 12 ++++---- lib/Transforms/Utils/BasicBlockUtils.cpp | 19 +++++++------ .../MemorySanitizer/wrap_indirect_calls.ll | 32 ++++++++++++++++++++-- 6 files changed, 62 insertions(+), 42 deletions(-) diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 65cafe2ec2..6bdf53facb 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -183,27 +183,27 @@ ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, BasicBlock *Pred); /// SplitBlockAndInsertIfThen - Split the containing block at the -/// specified instruction - everything before and including Cmp stays -/// in the old basic block, and everything after Cmp is moved to a +/// specified instruction - everything before and including SplitBefore stays +/// in the old basic block, and everything after SplitBefore is moved to a /// new block. The two blocks are connected by a conditional branch /// (with value of Cmp being the condition). /// Before: /// Head -/// Cmp +/// SplitBefore /// Tail /// After: /// Head -/// Cmp -/// if (Cmp) +/// if (Cond) /// ThenBlock +/// SplitBefore /// Tail /// /// If Unreachable is true, then ThenBlock ends with /// UnreachableInst, otherwise it branches to Tail. /// Returns the NewBasicBlock's terminator. - -TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp, - bool Unreachable, MDNode *BranchWeights = 0); +TerminatorInst *SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, + bool Unreachable, + MDNode *BranchWeights = 0); /// /// GetIfCondition - Check whether BB is the merge point of a if-region. @@ -211,7 +211,6 @@ TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp, /// BB will be taken. Also, return by references the block that will be /// entered from if the condition is true, and the block that will be /// entered if the condition is false. - Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue, BasicBlock *&IfFalse); } // End llvm namespace diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index f683bfb16c..b4c789c5f8 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -617,7 +617,7 @@ bool AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) { Value *Cmp = IRB.CreateICmpNE(Length, Constant::getNullValue(Length->getType())); - InsertBefore = SplitBlockAndInsertIfThen(cast(Cmp), false); + InsertBefore = SplitBlockAndInsertIfThen(Cmp, InsertBefore, false); } instrumentMemIntrinsicParam(MI, Dst, Length, InsertBefore, true); @@ -780,7 +780,7 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns, if (ClAlwaysSlowPath || (TypeSize < 8 * Granularity)) { TerminatorInst *CheckTerm = - SplitBlockAndInsertIfThen(cast(Cmp), false); + SplitBlockAndInsertIfThen(Cmp, InsertBefore, false); assert(dyn_cast(CheckTerm)->isUnconditional()); BasicBlock *NextBB = CheckTerm->getSuccessor(0); IRB.SetInsertPoint(CheckTerm); @@ -791,7 +791,7 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns, BranchInst *NewTerm = BranchInst::Create(CrashBlock, NextBB, Cmp2); ReplaceInstWithInst(CheckTerm, NewTerm); } else { - CrashTerm = SplitBlockAndInsertIfThen(cast(Cmp), true); + CrashTerm = SplitBlockAndInsertIfThen(Cmp, InsertBefore, true); } Instruction *Crash = generateCrashCode( @@ -1188,7 +1188,7 @@ bool AddressSanitizer::InjectCoverage(Function &F) { Load->setAtomic(Monotonic); Load->setAlignment(1); Value *Cmp = IRB.CreateICmpEQ(Constant::getNullValue(Int8Ty), Load); - Instruction *Ins = SplitBlockAndInsertIfThen(cast(Cmp), false); + Instruction *Ins = SplitBlockAndInsertIfThen(Cmp, IP, false); IRB.SetInsertPoint(Ins); // We pass &F to __sanitizer_cov. We could avoid this and rely on // GET_CALLER_PC, but having the PC of the first instruction is just nice. @@ -1448,8 +1448,7 @@ void FunctionStackPoisoner::poisonStack() { kAsanOptionDetectUAR, IRB.getInt32Ty()); Value *Cmp = IRB.CreateICmpNE(IRB.CreateLoad(OptionDetectUAR), Constant::getNullValue(IRB.getInt32Ty())); - Instruction *Term = - SplitBlockAndInsertIfThen(cast(Cmp), false); + Instruction *Term = SplitBlockAndInsertIfThen(Cmp, InsBefore, false); BasicBlock *CmpBlock = cast(Cmp)->getParent(); IRBuilder<> IRBIf(Term); LocalStackBase = IRBIf.CreateCall2( @@ -1529,8 +1528,7 @@ void FunctionStackPoisoner::poisonStack() { // **SavedFlagPtr(LocalStackBase) = 0 // FIXME: if LocalStackBase != OrigStackBase don't call poisonRedZones. Value *Cmp = IRBRet.CreateICmpNE(LocalStackBase, OrigStackBase); - TerminatorInst *PoisonTerm = - SplitBlockAndInsertIfThen(cast(Cmp), false); + TerminatorInst *PoisonTerm = SplitBlockAndInsertIfThen(Cmp, Ret, false); IRBuilder<> IRBPoison(PoisonTerm); int ClassSize = kMinStackMallocSize << StackMallocIdx; SetShadowToStackAfterReturnInlined(IRBPoison, ShadowBase, diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index c539be93a7..653ad7ff84 100644 --- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -735,10 +735,9 @@ bool DataFlowSanitizer::runOnModule(Module &M) { while (isa(Pos) || isa(Pos)) Pos = Pos->getNextNode(); IRBuilder<> IRB(Pos); - Instruction *NeInst = cast( - IRB.CreateICmpNE(*i, DFSF.DFS.ZeroShadow)); + Value *Ne = IRB.CreateICmpNE(*i, DFSF.DFS.ZeroShadow); BranchInst *BI = cast(SplitBlockAndInsertIfThen( - NeInst, /*Unreachable=*/ false, ColdCallWeights)); + Ne, Pos, /*Unreachable=*/false, ColdCallWeights)); IRBuilder<> ThenIRB(BI); ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn); } @@ -838,10 +837,9 @@ Value *DataFlowSanitizer::combineShadows(Value *V1, Value *V2, IRBuilder<> IRB(Pos); BasicBlock *Head = Pos->getParent(); Value *Ne = IRB.CreateICmpNE(V1, V2); - Instruction *NeInst = dyn_cast(Ne); - if (NeInst) { + if (Ne) { BranchInst *BI = cast(SplitBlockAndInsertIfThen( - NeInst, /*Unreachable=*/ false, ColdCallWeights)); + Ne, Pos, /*Unreachable=*/false, ColdCallWeights)); IRBuilder<> ThenIRB(BI); CallInst *Call = ThenIRB.CreateCall2(DFSanUnionFn, V1, V2); Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index f2e1ab7513..8a52a4444b 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -565,8 +565,7 @@ struct MemorySanitizerVisitor : public InstVisitor { Value *Cmp = IRB.CreateICmpNE(ConvertedShadow, getCleanShadow(ConvertedShadow), "_mscmp"); Instruction *CheckTerm = - SplitBlockAndInsertIfThen(cast(Cmp), false, - MS.OriginStoreWeights); + SplitBlockAndInsertIfThen(Cmp, &I, false, MS.OriginStoreWeights); IRBuilder<> IRBNew(CheckTerm); IRBNew.CreateAlignedStore(getOrigin(Val), getOriginPtr(Addr, IRBNew), Alignment); @@ -588,10 +587,9 @@ struct MemorySanitizerVisitor : public InstVisitor { continue; Value *Cmp = IRB.CreateICmpNE(ConvertedShadow, getCleanShadow(ConvertedShadow), "_mscmp"); - Instruction *CheckTerm = - SplitBlockAndInsertIfThen(cast(Cmp), - /* Unreachable */ !ClKeepGoing, - MS.ColdCallWeights); + Instruction *CheckTerm = SplitBlockAndInsertIfThen( + Cmp, OrigIns, + /* Unreachable */ !ClKeepGoing, MS.ColdCallWeights); IRB.SetInsertPoint(CheckTerm); if (MS.TrackOrigins) { @@ -629,7 +627,7 @@ struct MemorySanitizerVisitor : public InstVisitor { IRB.CreatePHI(Fn0->getType(), 2, "msandr.indirect_target"); Instruction *CheckTerm = SplitBlockAndInsertIfThen( - cast(NotInThisModule), + NotInThisModule, NewFnPhi, /* Unreachable */ false, MS.ColdCallWeights); IRB.SetInsertPoint(CheckTerm); diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp index 12de9eed4b..17bd115ee9 100644 --- a/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -630,28 +630,29 @@ ReturnInst *llvm::FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, } /// SplitBlockAndInsertIfThen - Split the containing block at the -/// specified instruction - everything before and including Cmp stays -/// in the old basic block, and everything after Cmp is moved to a +/// specified instruction - everything before and including SplitBefore stays +/// in the old basic block, and everything after SplitBefore is moved to a /// new block. The two blocks are connected by a conditional branch /// (with value of Cmp being the condition). /// Before: /// Head -/// Cmp +/// SplitBefore /// Tail /// After: /// Head -/// Cmp -/// if (Cmp) +/// if (Cond) /// ThenBlock +/// SplitBefore /// Tail /// /// If Unreachable is true, then ThenBlock ends with /// UnreachableInst, otherwise it branches to Tail. /// Returns the NewBasicBlock's terminator. -TerminatorInst *llvm::SplitBlockAndInsertIfThen(Instruction *Cmp, - bool Unreachable, MDNode *BranchWeights) { - Instruction *SplitBefore = Cmp->getNextNode(); +TerminatorInst *llvm::SplitBlockAndInsertIfThen(Value *Cond, + Instruction *SplitBefore, + bool Unreachable, + MDNode *BranchWeights) { BasicBlock *Head = SplitBefore->getParent(); BasicBlock *Tail = Head->splitBasicBlock(SplitBefore); TerminatorInst *HeadOldTerm = Head->getTerminator(); @@ -663,7 +664,7 @@ TerminatorInst *llvm::SplitBlockAndInsertIfThen(Instruction *Cmp, else CheckTerm = BranchInst::Create(Tail, ThenBlock); BranchInst *HeadNewTerm = - BranchInst::Create(/*ifTrue*/ThenBlock, /*ifFalse*/Tail, Cmp); + BranchInst::Create(/*ifTrue*/ThenBlock, /*ifFalse*/Tail, Cond); HeadNewTerm->setMetadata(LLVMContext::MD_prof, BranchWeights); ReplaceInstWithInst(HeadOldTerm, HeadNewTerm); return CheckTerm; diff --git a/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll b/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll index 555695d258..65037cb479 100644 --- a/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll +++ b/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll @@ -8,20 +8,20 @@ target triple = "x86_64-unknown-linux-gnu" ; wrapper function. ; This does not depend on the sanitize_memory attribute. -define i32 @func(i32 (i32, i32)* nocapture %f, i32 %x, i32 %y) { +define i32 @func1(i32 (i32, i32)* nocapture %f, i32 %x, i32 %y) { entry: %call = tail call i32 %f(i32 %x, i32 %y) ret i32 %call } -; CHECK: @func +; CHECK: @func1 ; CHECK: bitcast i32 (i32, i32)* %f to void ()* ; CHECK: call void ()* (void ()*)* @zzz(void ()* ; CHECK: [[A:%[01-9a-z_.]+]] = bitcast void ()* {{.*}} to i32 (i32, i32)* ; CHECK: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}}) ; CHECK: ret i32 -; CHECK-FAST: @func +; CHECK-FAST: @func1 ; CHECK-FAST: bitcast i32 (i32, i32)* %f to void ()* ; CHECK-FAST-DAG: icmp ult void ()* {{.*}}, bitcast (i32* @__executable_start to void ()*) ; CHECK-FAST-DAG: icmp uge void ()* {{.*}}, bitcast (i32* @_end to void ()*) @@ -32,3 +32,29 @@ entry: ; CHECK-FAST: [[A:%[01-9a-z_.]+]] = phi i32 (i32, i32)* [ %f, %entry ], [ {{.*}} ] ; CHECK-FAST: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}}) ; CHECK-FAST: ret i32 + + +; The same test, but with a complex expression as the call target. + +declare i8* @callee(i32) + +define i8* @func2(i64 %x) #1 { +entry: + %call = tail call i8* bitcast (i8* (i32)* @callee to i8* (i64)*)(i64 %x) + ret i8* %call +} + +; CHECK: @func2 +; CHECK: call {{.*}} @zzz +; CHECK: [[A:%[01-9a-z_.]+]] = bitcast void ()* {{.*}} to i8* (i64)* +; CHECK: call i8* {{.*}}[[A]](i64 {{.*}}) +; CHECK: ret i8* + +; CHECK-FAST: @func2 +; CHECK-FAST: {{br i1 or .* icmp ult .* bitcast .* @callee .* @__executable_start.* icmp uge .* bitcast .* @callee .* @_end}} +; CHECK-FAST: {{call .* @zzz.* bitcast .*@callee}} +; CHECK-FAST: bitcast void ()* {{.*}} to i8* (i64)* +; CHECK-FAST: br label +; CHECK-FAST: [[A:%[01-9a-z_.]+]] = phi i8* (i64)* [{{.*bitcast .* @callee.*, %entry.*}}], [ {{.*}} ] +; CHECK-FAST: call i8* {{.*}}[[A]](i64 {{.*}}) +; CHECK-FAST: ret i8* -- cgit v1.2.3