diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 221511e9aba0b..c1f5e286ab3ed 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -1011,6 +1011,21 @@ Value *InstCombinerImpl::simplifyNonNullOperand(Value *V, } } + if (auto *PHI = dyn_cast(V)) { + bool Changed = false; + for (Use &U : PHI->incoming_values()) { + // We set Depth to RecursionLimit to avoid expensive recursion. + if (auto *Res = simplifyNonNullOperand(U.get(), HasDereferenceable, + RecursionLimit)) { + replaceUse(U, Res); + Changed = true; + } + } + if (Changed) + addToWorklist(PHI); + return nullptr; + } + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/load.ll b/llvm/test/Transforms/InstCombine/load.ll index d10aabff6709a..736a31fc6ae0a 100644 --- a/llvm/test/Transforms/InstCombine/load.ll +++ b/llvm/test/Transforms/InstCombine/load.ll @@ -481,3 +481,30 @@ define i16 @load_select_with_null_gep3(i1 %cond, ptr %p, i64 %x, i64 %y) { %res = load i16, ptr %gep2, align 2 ret i16 %res } + +define i32 @test_load_phi_with_select(ptr %p, i1 %cond1) { +; CHECK-LABEL: @test_load_phi_with_select( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP_BODY:%.*]] +; CHECK: loop.body: +; CHECK-NEXT: [[TARGET:%.*]] = getelementptr inbounds nuw i8, ptr [[BASE:%.*]], i64 24 +; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[TARGET]], align 4 +; CHECK-NEXT: [[COND21:%.*]] = icmp eq i32 [[LOAD]], 0 +; CHECK-NEXT: br i1 [[COND21]], label [[LOOP_BODY]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: ret i32 [[LOAD]] +; +entry: + br label %loop.body + +loop.body: + %base = phi ptr [ %p, %entry ], [ %sel, %loop.body ] + %target = getelementptr inbounds i8, ptr %base, i64 24 + %load = load i32, ptr %target, align 4 + %sel = select i1 %cond1, ptr null, ptr %p + %cond2 = icmp eq i32 %load, 0 + br i1 %cond2, label %loop.body, label %exit + +exit: + ret i32 %load +}