Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1862,6 +1862,18 @@ return nullptr; } +static bool isNeverEqualToUnescapedAlloc(Instruction *I) { + switch (I->getOpcode()) { + default: + return false; + case Instruction::Load: { + LoadInst *LI = cast(I); + // Comparison to global pointer. + return isa(LI->getPointerOperand()); + } + } +} + static bool isAllocSiteRemovable(Instruction *AI, SmallVectorImpl &Users, const TargetLibraryInfo *TLI) { @@ -1886,8 +1898,17 @@ 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))) + if (!ICI->isEquality()) return false; + + if (!isa(ICI->getOperand(1))) { + unsigned OtherIndex = (ICI->getOperand(0) == PI)? 1:0; + Instruction *OtherOp = dyn_cast(ICI->getOperand(OtherIndex)); + // We fold comparisons in some conditions provided the alloc has not + // escaped. + if (!OtherOp || !isNeverEqualToUnescapedAlloc(OtherOp)) + return false; + } Users.emplace_back(I); continue; } Index: test/Transforms/InstCombine/compared-unescaped.ll =================================================================== --- test/Transforms/InstCombine/compared-unescaped.ll +++ test/Transforms/InstCombine/compared-unescaped.ll @@ -0,0 +1,40 @@ +; 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 +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 +}