diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 8a9d2821b44f6..586699d588935 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1863,6 +1863,14 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { return nullptr; } +static bool isNeverEqualToUnescapedAlloc(Value *V) { + if (isa(V)) + return true; + if (auto *LI = dyn_cast(V)) + return isa(LI->getPointerOperand()); + return false; +} + static bool isAllocSiteRemovable(Instruction *AI, SmallVectorImpl &Users, const TargetLibraryInfo *TLI) { @@ -1887,7 +1895,12 @@ isAllocSiteRemovable(Instruction *AI, SmallVectorImpl &Users, case Instruction::ICmp: { ICmpInst *ICI = cast(I); // We can fold eq/ne comparisons with null to false/true, respectively. - if (!ICI->isEquality() || !isa(ICI->getOperand(1))) + // We fold comparisons in some conditions provided the alloc has not + // escaped. + if (!ICI->isEquality()) + return false; + unsigned OtherIndex = (ICI->getOperand(0) == PI) ? 1 : 0; + if (!isNeverEqualToUnescapedAlloc(ICI->getOperand(OtherIndex))) return false; Users.emplace_back(I); continue; diff --git a/llvm/test/Transforms/InstCombine/compare-unescaped.ll b/llvm/test/Transforms/InstCombine/compare-unescaped.ll new file mode 100644 index 0000000000000..ce8f31ea9c374 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/compare-unescaped.ll @@ -0,0 +1,42 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +@gp = global i32* null, align 8 + +declare i8* @malloc(i64) #1 + +define i1 @compare_global_trivialeq() { + %m = call i8* @malloc(i64 4) + %bc = bitcast i8* %m to i32* + %lgp = load i32*, i32** @gp, align 8 + %cmp = icmp eq i32* %bc, %lgp + ret i1 %cmp +; CHECK-LABEL: compare_global_trivialeq +; CHECK: ret i1 false +} + +define i1 @compare_global_trivialne() { + %m = call i8* @malloc(i64 4) + %bc = bitcast i8* %m to i32* + %lgp = load i32*, i32** @gp, align 8 + %cmp = icmp ne i32* %bc, %lgp + ret i1 %cmp +; CHECK-LABEL: compare_global_trivialne +; CHECK: ret i1 true +} + + +; Although the %m is marked nocapture in the deopt operand in call to function f, +; we cannot remove the alloc site: call to malloc +; FIXME: The comparison should fold to false irrespective of whether the call to malloc can be elided or not +declare void @f() +define i32 @compare_and_call_with_deopt() { +; CHECK-LABEL: compare_and_call_with_deopt + %m = call i8* @malloc(i64 24) + %bc = bitcast i8* %m to i32* + %lgp = load i32*, i32** @gp, align 8 + %cmp = icmp eq i32* %bc, %lgp + %rt = zext i1 %cmp to i32 + tail call void @f() [ "deopt"(i8* %m) ] + ret i32 %rt +; CHECK: ret i32 %rt +}