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
This commit is contained in:
Evgeniy Stepanov 2013-12-19 13:29:56 +00:00
parent e493a9976c
commit a7eb2b83ba
6 changed files with 62 additions and 42 deletions

View File

@ -183,27 +183,27 @@ ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB,
BasicBlock *Pred); BasicBlock *Pred);
/// SplitBlockAndInsertIfThen - Split the containing block at the /// SplitBlockAndInsertIfThen - Split the containing block at the
/// specified instruction - everything before and including Cmp stays /// specified instruction - everything before and including SplitBefore stays
/// in the old basic block, and everything after Cmp is moved to a /// in the old basic block, and everything after SplitBefore is moved to a
/// new block. The two blocks are connected by a conditional branch /// new block. The two blocks are connected by a conditional branch
/// (with value of Cmp being the condition). /// (with value of Cmp being the condition).
/// Before: /// Before:
/// Head /// Head
/// Cmp /// SplitBefore
/// Tail /// Tail
/// After: /// After:
/// Head /// Head
/// Cmp /// if (Cond)
/// if (Cmp)
/// ThenBlock /// ThenBlock
/// SplitBefore
/// Tail /// Tail
/// ///
/// If Unreachable is true, then ThenBlock ends with /// If Unreachable is true, then ThenBlock ends with
/// UnreachableInst, otherwise it branches to Tail. /// UnreachableInst, otherwise it branches to Tail.
/// Returns the NewBasicBlock's terminator. /// Returns the NewBasicBlock's terminator.
TerminatorInst *SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore,
TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp, bool Unreachable,
bool Unreachable, MDNode *BranchWeights = 0); MDNode *BranchWeights = 0);
/// ///
/// GetIfCondition - Check whether BB is the merge point of a if-region. /// 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 /// 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 from if the condition is true, and the block that will be
/// entered if the condition is false. /// entered if the condition is false.
Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue, Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
BasicBlock *&IfFalse); BasicBlock *&IfFalse);
} // End llvm namespace } // End llvm namespace

View File

@ -617,7 +617,7 @@ bool AddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {
Value *Cmp = IRB.CreateICmpNE(Length, Value *Cmp = IRB.CreateICmpNE(Length,
Constant::getNullValue(Length->getType())); Constant::getNullValue(Length->getType()));
InsertBefore = SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false); InsertBefore = SplitBlockAndInsertIfThen(Cmp, InsertBefore, false);
} }
instrumentMemIntrinsicParam(MI, Dst, Length, InsertBefore, true); instrumentMemIntrinsicParam(MI, Dst, Length, InsertBefore, true);
@ -780,7 +780,7 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
if (ClAlwaysSlowPath || (TypeSize < 8 * Granularity)) { if (ClAlwaysSlowPath || (TypeSize < 8 * Granularity)) {
TerminatorInst *CheckTerm = TerminatorInst *CheckTerm =
SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false); SplitBlockAndInsertIfThen(Cmp, InsertBefore, false);
assert(dyn_cast<BranchInst>(CheckTerm)->isUnconditional()); assert(dyn_cast<BranchInst>(CheckTerm)->isUnconditional());
BasicBlock *NextBB = CheckTerm->getSuccessor(0); BasicBlock *NextBB = CheckTerm->getSuccessor(0);
IRB.SetInsertPoint(CheckTerm); IRB.SetInsertPoint(CheckTerm);
@ -791,7 +791,7 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
BranchInst *NewTerm = BranchInst::Create(CrashBlock, NextBB, Cmp2); BranchInst *NewTerm = BranchInst::Create(CrashBlock, NextBB, Cmp2);
ReplaceInstWithInst(CheckTerm, NewTerm); ReplaceInstWithInst(CheckTerm, NewTerm);
} else { } else {
CrashTerm = SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), true); CrashTerm = SplitBlockAndInsertIfThen(Cmp, InsertBefore, true);
} }
Instruction *Crash = generateCrashCode( Instruction *Crash = generateCrashCode(
@ -1188,7 +1188,7 @@ bool AddressSanitizer::InjectCoverage(Function &F) {
Load->setAtomic(Monotonic); Load->setAtomic(Monotonic);
Load->setAlignment(1); Load->setAlignment(1);
Value *Cmp = IRB.CreateICmpEQ(Constant::getNullValue(Int8Ty), Load); Value *Cmp = IRB.CreateICmpEQ(Constant::getNullValue(Int8Ty), Load);
Instruction *Ins = SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false); Instruction *Ins = SplitBlockAndInsertIfThen(Cmp, IP, false);
IRB.SetInsertPoint(Ins); IRB.SetInsertPoint(Ins);
// We pass &F to __sanitizer_cov. We could avoid this and rely on // 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. // GET_CALLER_PC, but having the PC of the first instruction is just nice.
@ -1448,8 +1448,7 @@ void FunctionStackPoisoner::poisonStack() {
kAsanOptionDetectUAR, IRB.getInt32Ty()); kAsanOptionDetectUAR, IRB.getInt32Ty());
Value *Cmp = IRB.CreateICmpNE(IRB.CreateLoad(OptionDetectUAR), Value *Cmp = IRB.CreateICmpNE(IRB.CreateLoad(OptionDetectUAR),
Constant::getNullValue(IRB.getInt32Ty())); Constant::getNullValue(IRB.getInt32Ty()));
Instruction *Term = Instruction *Term = SplitBlockAndInsertIfThen(Cmp, InsBefore, false);
SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false);
BasicBlock *CmpBlock = cast<Instruction>(Cmp)->getParent(); BasicBlock *CmpBlock = cast<Instruction>(Cmp)->getParent();
IRBuilder<> IRBIf(Term); IRBuilder<> IRBIf(Term);
LocalStackBase = IRBIf.CreateCall2( LocalStackBase = IRBIf.CreateCall2(
@ -1529,8 +1528,7 @@ void FunctionStackPoisoner::poisonStack() {
// **SavedFlagPtr(LocalStackBase) = 0 // **SavedFlagPtr(LocalStackBase) = 0
// FIXME: if LocalStackBase != OrigStackBase don't call poisonRedZones. // FIXME: if LocalStackBase != OrigStackBase don't call poisonRedZones.
Value *Cmp = IRBRet.CreateICmpNE(LocalStackBase, OrigStackBase); Value *Cmp = IRBRet.CreateICmpNE(LocalStackBase, OrigStackBase);
TerminatorInst *PoisonTerm = TerminatorInst *PoisonTerm = SplitBlockAndInsertIfThen(Cmp, Ret, false);
SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false);
IRBuilder<> IRBPoison(PoisonTerm); IRBuilder<> IRBPoison(PoisonTerm);
int ClassSize = kMinStackMallocSize << StackMallocIdx; int ClassSize = kMinStackMallocSize << StackMallocIdx;
SetShadowToStackAfterReturnInlined(IRBPoison, ShadowBase, SetShadowToStackAfterReturnInlined(IRBPoison, ShadowBase,

View File

@ -735,10 +735,9 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos)) while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
Pos = Pos->getNextNode(); Pos = Pos->getNextNode();
IRBuilder<> IRB(Pos); IRBuilder<> IRB(Pos);
Instruction *NeInst = cast<Instruction>( Value *Ne = IRB.CreateICmpNE(*i, DFSF.DFS.ZeroShadow);
IRB.CreateICmpNE(*i, DFSF.DFS.ZeroShadow));
BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen( BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen(
NeInst, /*Unreachable=*/ false, ColdCallWeights)); Ne, Pos, /*Unreachable=*/false, ColdCallWeights));
IRBuilder<> ThenIRB(BI); IRBuilder<> ThenIRB(BI);
ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn); ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn);
} }
@ -838,10 +837,9 @@ Value *DataFlowSanitizer::combineShadows(Value *V1, Value *V2,
IRBuilder<> IRB(Pos); IRBuilder<> IRB(Pos);
BasicBlock *Head = Pos->getParent(); BasicBlock *Head = Pos->getParent();
Value *Ne = IRB.CreateICmpNE(V1, V2); Value *Ne = IRB.CreateICmpNE(V1, V2);
Instruction *NeInst = dyn_cast<Instruction>(Ne); if (Ne) {
if (NeInst) {
BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen( BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen(
NeInst, /*Unreachable=*/ false, ColdCallWeights)); Ne, Pos, /*Unreachable=*/false, ColdCallWeights));
IRBuilder<> ThenIRB(BI); IRBuilder<> ThenIRB(BI);
CallInst *Call = ThenIRB.CreateCall2(DFSanUnionFn, V1, V2); CallInst *Call = ThenIRB.CreateCall2(DFSanUnionFn, V1, V2);
Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);

View File

@ -565,8 +565,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
Value *Cmp = IRB.CreateICmpNE(ConvertedShadow, Value *Cmp = IRB.CreateICmpNE(ConvertedShadow,
getCleanShadow(ConvertedShadow), "_mscmp"); getCleanShadow(ConvertedShadow), "_mscmp");
Instruction *CheckTerm = Instruction *CheckTerm =
SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), false, SplitBlockAndInsertIfThen(Cmp, &I, false, MS.OriginStoreWeights);
MS.OriginStoreWeights);
IRBuilder<> IRBNew(CheckTerm); IRBuilder<> IRBNew(CheckTerm);
IRBNew.CreateAlignedStore(getOrigin(Val), getOriginPtr(Addr, IRBNew), IRBNew.CreateAlignedStore(getOrigin(Val), getOriginPtr(Addr, IRBNew),
Alignment); Alignment);
@ -588,10 +587,9 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
continue; continue;
Value *Cmp = IRB.CreateICmpNE(ConvertedShadow, Value *Cmp = IRB.CreateICmpNE(ConvertedShadow,
getCleanShadow(ConvertedShadow), "_mscmp"); getCleanShadow(ConvertedShadow), "_mscmp");
Instruction *CheckTerm = Instruction *CheckTerm = SplitBlockAndInsertIfThen(
SplitBlockAndInsertIfThen(cast<Instruction>(Cmp), Cmp, OrigIns,
/* Unreachable */ !ClKeepGoing, /* Unreachable */ !ClKeepGoing, MS.ColdCallWeights);
MS.ColdCallWeights);
IRB.SetInsertPoint(CheckTerm); IRB.SetInsertPoint(CheckTerm);
if (MS.TrackOrigins) { if (MS.TrackOrigins) {
@ -629,7 +627,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
IRB.CreatePHI(Fn0->getType(), 2, "msandr.indirect_target"); IRB.CreatePHI(Fn0->getType(), 2, "msandr.indirect_target");
Instruction *CheckTerm = SplitBlockAndInsertIfThen( Instruction *CheckTerm = SplitBlockAndInsertIfThen(
cast<Instruction>(NotInThisModule), NotInThisModule, NewFnPhi,
/* Unreachable */ false, MS.ColdCallWeights); /* Unreachable */ false, MS.ColdCallWeights);
IRB.SetInsertPoint(CheckTerm); IRB.SetInsertPoint(CheckTerm);

View File

@ -630,28 +630,29 @@ ReturnInst *llvm::FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB,
} }
/// SplitBlockAndInsertIfThen - Split the containing block at the /// SplitBlockAndInsertIfThen - Split the containing block at the
/// specified instruction - everything before and including Cmp stays /// specified instruction - everything before and including SplitBefore stays
/// in the old basic block, and everything after Cmp is moved to a /// in the old basic block, and everything after SplitBefore is moved to a
/// new block. The two blocks are connected by a conditional branch /// new block. The two blocks are connected by a conditional branch
/// (with value of Cmp being the condition). /// (with value of Cmp being the condition).
/// Before: /// Before:
/// Head /// Head
/// Cmp /// SplitBefore
/// Tail /// Tail
/// After: /// After:
/// Head /// Head
/// Cmp /// if (Cond)
/// if (Cmp)
/// ThenBlock /// ThenBlock
/// SplitBefore
/// Tail /// Tail
/// ///
/// If Unreachable is true, then ThenBlock ends with /// If Unreachable is true, then ThenBlock ends with
/// UnreachableInst, otherwise it branches to Tail. /// UnreachableInst, otherwise it branches to Tail.
/// Returns the NewBasicBlock's terminator. /// Returns the NewBasicBlock's terminator.
TerminatorInst *llvm::SplitBlockAndInsertIfThen(Instruction *Cmp, TerminatorInst *llvm::SplitBlockAndInsertIfThen(Value *Cond,
bool Unreachable, MDNode *BranchWeights) { Instruction *SplitBefore,
Instruction *SplitBefore = Cmp->getNextNode(); bool Unreachable,
MDNode *BranchWeights) {
BasicBlock *Head = SplitBefore->getParent(); BasicBlock *Head = SplitBefore->getParent();
BasicBlock *Tail = Head->splitBasicBlock(SplitBefore); BasicBlock *Tail = Head->splitBasicBlock(SplitBefore);
TerminatorInst *HeadOldTerm = Head->getTerminator(); TerminatorInst *HeadOldTerm = Head->getTerminator();
@ -663,7 +664,7 @@ TerminatorInst *llvm::SplitBlockAndInsertIfThen(Instruction *Cmp,
else else
CheckTerm = BranchInst::Create(Tail, ThenBlock); CheckTerm = BranchInst::Create(Tail, ThenBlock);
BranchInst *HeadNewTerm = BranchInst *HeadNewTerm =
BranchInst::Create(/*ifTrue*/ThenBlock, /*ifFalse*/Tail, Cmp); BranchInst::Create(/*ifTrue*/ThenBlock, /*ifFalse*/Tail, Cond);
HeadNewTerm->setMetadata(LLVMContext::MD_prof, BranchWeights); HeadNewTerm->setMetadata(LLVMContext::MD_prof, BranchWeights);
ReplaceInstWithInst(HeadOldTerm, HeadNewTerm); ReplaceInstWithInst(HeadOldTerm, HeadNewTerm);
return CheckTerm; return CheckTerm;

View File

@ -8,20 +8,20 @@ target triple = "x86_64-unknown-linux-gnu"
; wrapper function. ; wrapper function.
; This does not depend on the sanitize_memory attribute. ; 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: entry:
%call = tail call i32 %f(i32 %x, i32 %y) %call = tail call i32 %f(i32 %x, i32 %y)
ret i32 %call ret i32 %call
} }
; CHECK: @func ; CHECK: @func1
; CHECK: bitcast i32 (i32, i32)* %f to void ()* ; CHECK: bitcast i32 (i32, i32)* %f to void ()*
; CHECK: call void ()* (void ()*)* @zzz(void ()* ; CHECK: call void ()* (void ()*)* @zzz(void ()*
; CHECK: [[A:%[01-9a-z_.]+]] = bitcast void ()* {{.*}} to i32 (i32, i32)* ; CHECK: [[A:%[01-9a-z_.]+]] = bitcast void ()* {{.*}} to i32 (i32, i32)*
; CHECK: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}}) ; CHECK: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}})
; CHECK: ret i32 ; CHECK: ret i32
; CHECK-FAST: @func ; CHECK-FAST: @func1
; CHECK-FAST: bitcast i32 (i32, i32)* %f to void ()* ; 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 ult void ()* {{.*}}, bitcast (i32* @__executable_start to void ()*)
; CHECK-FAST-DAG: icmp uge void ()* {{.*}}, bitcast (i32* @_end 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: [[A:%[01-9a-z_.]+]] = phi i32 (i32, i32)* [ %f, %entry ], [ {{.*}} ]
; CHECK-FAST: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}}) ; CHECK-FAST: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}})
; CHECK-FAST: ret 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*