From c2eccc67ce07e9cb374eb0ecdb3038fcb8be08cd Mon Sep 17 00:00:00 2001 From: Serguei Katkov Date: Wed, 25 May 2022 13:37:06 +0700 Subject: [PATCH] [GuardWidening] Remove nuw/nsw flags for hoisted instructions When we hoist instructions over guard we must clear flags due to these flags might be implied using this guard, so they make sense only after the guard. As an example of the bug due to current behavior. L is known to be in range say [0, 100) c1 = x u< L guard (c1) x1 = add x, 1 c2 = x1 u< L guard(c2) basing on guard(c1) we can say that x1 = add nuw nsw x, 1 after guard widening we get c1 = x u< L x1 = add nuw nsw x, 1 c2 = x1 u< L c = and c1, c2 guard(c) now, basing on fact that x + 1 < L and x >= 0 due to x + 1 is nuw we can prove that x + 1 u< L implies that x u< L, so we can just remove c1 x1 = add nuw nsw x, 1 c2 = x1 u< L guard(c2) But that is not correct due to we will pass x == -1 value. Reviewed By: mkazantsev Subscribers: llvm-commits, nikic Differential Revision: https://reviews.llvm.org/D126354 --- llvm/lib/Transforms/Scalar/GuardWidening.cpp | 3 +++ llvm/test/Transforms/GuardWidening/range-check-merging.ll | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Scalar/GuardWidening.cpp b/llvm/lib/Transforms/Scalar/GuardWidening.cpp index 40c99e17ffea..5032f3106d50 100644 --- a/llvm/lib/Transforms/Scalar/GuardWidening.cpp +++ b/llvm/lib/Transforms/Scalar/GuardWidening.cpp @@ -495,6 +495,9 @@ void GuardWideningImpl::makeAvailableAt(Value *V, Instruction *Loc) const { makeAvailableAt(Op, Loc); Inst->moveBefore(Loc); + // If we moved instruction before guard we must clean nuw, nsw flags. + Inst->setHasNoUnsignedWrap(false); + Inst->setHasNoSignedWrap(false); } bool GuardWideningImpl::widenCondCommon(Value *Cond0, Value *Cond1, diff --git a/llvm/test/Transforms/GuardWidening/range-check-merging.ll b/llvm/test/Transforms/GuardWidening/range-check-merging.ll index b4ab9b32ff48..b2e229fd7211 100644 --- a/llvm/test/Transforms/GuardWidening/range-check-merging.ll +++ b/llvm/test/Transforms/GuardWidening/range-check-merging.ll @@ -340,7 +340,7 @@ define void @f_8(i32 %x, i32* %length_buf) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_BUF:%.*]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[CHK0:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] -; CHECK-NEXT: [[X_INC1:%.*]] = add nuw nsw i32 [[X]], 1 +; CHECK-NEXT: [[X_INC1:%.*]] = add i32 [[X]], 1 ; CHECK-NEXT: [[CHK1:%.*]] = icmp ult i32 [[X_INC1]], [[LENGTH]] ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[CHK0]], [[CHK1]] ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]