Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2392,7 +2392,37 @@ return &BI; } - return nullptr; + // Propagate null op from cmp to next basic blocks + if (match(&BI, m_Br(m_OneUse(m_Cmp(Pred, m_Value(), m_Zero())), TrueDest, + FalseDest)) && + isCanonicalPredicate(Pred)) { + auto *Cmp = dyn_cast(BI.getOperand(0)); + Value *NullOp = Cmp->getOperand(0); // left side of cmp eq + bool NullOpPropagated = false; + BasicBlock *Next; + for (BasicBlock *B = TrueDest; B; B = Next) { + Next = nullptr; + for (Instruction &I : *B) { + for (unsigned i = 0; i < I.getNumOperands(); ++i) { + Value *Arg = I.getOperand(i); + if (match(Arg, m_Zero()) && NullOp->getType() == Arg->getType()) { + I.setOperand(i, NullOp); + NullOpPropagated |= true; + } + } + + if (BranchInst *BI = dyn_cast(&I)) { + if (BI->isUnconditional()) { + Next = dyn_cast(BI->getOperand(0)); + } + } + } + } + + if (NullOpPropagated) + return &BI; + + return nullptr; } Instruction *InstCombiner::visitSwitchInst(SwitchInst &SI) { Index: test/Transforms/InstCombine/cmp-propagate-zero-val.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/cmp-propagate-zero-val.ll @@ -0,0 +1,39 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +@.str = private unnamed_addr constant [1 x i8] zeroinitializer, align 1 + +define i8* @propagate_null(i8* %ptr) #0 { +; CHECK-LABEL: @propagate_null( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i8* [[PTR:%.*]], null +; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: br label [[RETURN:%.*]] +; CHECK: if.end: +; CHECK-NEXT: [[PUTCHAR:%.*]] = call i32 @putchar(i32 10) +; CHECK-NEXT: br label [[RETURN]] +; CHECK: return: +; CHECK-NEXT: ret i8* [[PTR]] +; +entry: + %retval = alloca i8*, align 4 + %tobool = icmp ne i8* %ptr, null + br i1 %tobool, label %if.end, label %if.then + +if.then: ; preds = %entry + store i8* null, i8** %retval, align 4 + br label %return + +if.end: ; preds = %entry + %call = call i32 @puts(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0)) + store i8* %ptr, i8** %retval, align 4 + br label %return + +return: ; preds = %if.end, %if.then + %0 = load i8*, i8** %retval, align 4 + ret i8* %0 +} + +declare i32 @puts(i8*) #1 +