[PATCH] D126354: [GuardWidening] Remove nuw/nsw flags for hoisted instructions

Serguei Katkov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 25 00:49:29 PDT 2022


skatkov created this revision.
skatkov added reviewers: reames, mkazantsev.
Herald added a subscriber: hiraditya.
Herald added a project: All.
skatkov requested review of this revision.
Herald added a project: LLVM.

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.


https://reviews.llvm.org/D126354

Files:
  llvm/lib/Transforms/Scalar/GuardWidening.cpp
  llvm/test/Transforms/GuardWidening/range-check-merging.ll


Index: llvm/test/Transforms/GuardWidening/range-check-merging.ll
===================================================================
--- llvm/test/Transforms/GuardWidening/range-check-merging.ll
+++ llvm/test/Transforms/GuardWidening/range-check-merging.ll
@@ -231,5 +231,23 @@
   ret void
 }
 
+define void @f_8(i32 %x, i32* %length_buf) {
+; Check that we clean nuw nsw flags
+; CHECK-LABEL: @f_8(
+; CHECK: %x.inc1 = add i32 %x, 1
+; CHECK:  call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK:  ret void
+entry:
+  %length = load i32, i32* %length_buf, !range !0
+  %chk0 = icmp ult i32 %x, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk0) [ "deopt"() ]
+
+  %x.inc1 = add nuw nsw i32 %x, 1
+  %chk1 = icmp ult i32 %x.inc1, %length
+  call void(i1, ...) @llvm.experimental.guard(i1 %chk1) [ "deopt"() ]
+  ret void
+}
+
+
 
 !0 = !{i32 0, i32 2147483648}
Index: llvm/lib/Transforms/Scalar/GuardWidening.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/GuardWidening.cpp
+++ llvm/lib/Transforms/Scalar/GuardWidening.cpp
@@ -495,6 +495,9 @@
     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,


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D126354.431895.patch
Type: text/x-patch
Size: 1423 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220525/67922abe/attachment.bin>


More information about the llvm-commits mailing list