Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -765,6 +765,16 @@ if (SSAUpdate.HasValueForBlock(BB)) continue; + // We must clear nuw/nsw for original value. Otherwise we + // can see the poison value where it was not originally. + Value *V = AV.AV.Val.getPointer(); + if (V) + if (auto *I = dyn_cast(V)) + if (isa(I)) { + I->setHasNoSignedWrap(false); + I->setHasNoUnsignedWrap(false); + } + SSAUpdate.AddAvailableValue(BB, AV.MaterializeAdjustedValue(LI, gvn)); } Index: test/Transforms/GVN/PRE/pre-jt-load.ll =================================================================== --- /dev/null +++ test/Transforms/GVN/PRE/pre-jt-load.ll @@ -0,0 +1,39 @@ +; RUN: opt < %s -gvn -enable-pre -jump-threading -S | FileCheck %s + +@H = common global i32 0 +@G = common global i32 0 + +define i32 @test(i1 %cond, i32 %v) nounwind { +; CHECK-LABEL: @test +entry: + br i1 %cond, label %bb, label %bb1 + +bb: +; CHECK: store +; CHECK-NOT: br label %return + %add.1 = add nuw nsw i32 %v, -1 + store i32 %add.1, i32* @G, align 4 + br label %merge + +bb1: +; CHECK: store +; CHECK-NOT: br label %return + %add.2 = add i32 %v, -1 + store i32 %add.2, i32* @G, align 4 + br label %merge + +merge: + %foo = load i32, i32* @G, align 4 + %cmp = icmp sgt i32 %foo, 0 + br i1 %cmp, label %action, label %return + +action: +; CHECK: store +; CHECK-NEXT: br label %return + store i32 %foo, i32* @H, align 4 + br label %return + +return: + %p = phi i32 [0, %merge], [1, %action] + ret i32 %p +}