diff --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp --- a/llvm/lib/Analysis/MemoryBuiltins.cpp +++ b/llvm/lib/Analysis/MemoryBuiltins.cpp @@ -520,6 +520,52 @@ return true; } +// Eliminate all branches that contain __builtin_dynamic_object_size when it +// returns a non-constant expression. The non-constant expression is a valid +// size and hence is never -1. +static void foldNonConstantCompares(Instruction *I) { + // Walk through all conditional branch users. + for (User *U : I->users()) { + ICmpInst *CI = dyn_cast(U); + if (!CI) + continue; + + Value *Op0 = CI->getOperand(0); + Value *Op1 = CI->getOperand(1); + ConstantInt *Cst = nullptr; + + // Find the constant part of the conditional branch. If there is none, + // we bail out. + if (isa(Op0)) + Cst = dyn_cast(Op0); + else if (isa(Op1)) + Cst = dyn_cast(Op1); + else + continue; + + // If the constant is not -1 then too we bail out. + if (!Cst || !Cst->isMinusOne()) + continue; + + ICmpInst::Predicate Pred = CI->getUnsignedPredicate(); + LLVMContext &Ctx = I->getFunction()->getContext(); + switch(Pred) { + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_ULE: + case ICmpInst::ICMP_ULT: + CI->replaceAllUsesWith(ConstantInt::getTrue(Ctx)); + break; + case ICmpInst::ICMP_EQ: + case ICmpInst::ICMP_UGE: + case ICmpInst::ICMP_UGT: + CI->replaceAllUsesWith(ConstantInt::getFalse(Ctx)); + break; + default: + continue; + } + } +} + Value *llvm::lowerObjectSizeCall(IntrinsicInst *ObjectSize, const DataLayout &DL, const TargetLibraryInfo *TLI, @@ -559,6 +605,10 @@ IRBuilder Builder(Ctx, TargetFolder(DL)); Builder.SetInsertPoint(ObjectSize); + if (!isa(SizeOffsetPair.first) || + !isa(SizeOffsetPair.second)) + foldNonConstantCompares(ObjectSize); + // If we've outside the end of the object, then we can always access // exactly 0 bytes. Value *ResultSize = diff --git a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll --- a/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll +++ b/llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll @@ -101,6 +101,30 @@ ; CHECK: define void @f() ; CHECK: call i64 @llvm.objectsize.i64.p0i8( +define void @bdos_impl(i64 %alloc) { +entry: + %obj = call i8* @malloc(i64 %alloc) + %objsize = call i64 @llvm.objectsize.i64.p0i8(i8* %obj, i1 0, i1 0, i1 1) + %cmp.not = icmp eq i64 %objsize, -1 + br i1 %cmp.not, label %if.else, label %if.then + +if.then: + call void @fortified_chk(i8* %obj, i64 %alloc) + br label %if.end + +if.else: + call void @unfortified(i8* %obj, i64 %alloc) + br label %if.end + +if.end: ; preds = %if.else, %if.then + ret void +} + +; CHECK: define void @bdos_impl( +; CHECK: br i1 false, label %if.else, label %if.then +; CHECK: call void @fortified_chk(i8* %obj, i64 %alloc) + + declare void @bury(i32) local_unnamed_addr #2 ; Function Attrs: nounwind allocsize(0) @@ -113,3 +137,7 @@ ; Function Attrs: nounwind readnone speculatable declare i64 @llvm.objectsize.i64.p0i8(i8*, i1, i1, i1) + +declare void @fortified_chk(i8*, i64) + +declare void @unfortified(i8*, i64)