Index: llvm/lib/Analysis/MemoryBuiltins.cpp =================================================================== --- llvm/lib/Analysis/MemoryBuiltins.cpp +++ llvm/lib/Analysis/MemoryBuiltins.cpp @@ -520,6 +520,44 @@ 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 (const Use &U : I->uses()) { + ICmpInst *CI = dyn_cast(U.getUser()); + if (!CI) + continue; + + // Get the other operand. + int op = U.getOperandNo() ^ 1; + + ConstantInt *Cst = dyn_cast(CI->getOperand(op)); + + // 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 +597,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 = Index: llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll =================================================================== --- llvm/test/Transforms/InstCombine/builtin-dynamic-object-size.ll +++ 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)