[PATCH] D149077: [InstCombine] Add !noundef if is guaranteed do not violate !range

luxufan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 24 09:54:31 PDT 2023


StephenFan created this revision.
StephenFan added a reviewer: nikic.
Herald added a subscriber: hiraditya.
Herald added a project: All.
StephenFan requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Since D141386 <https://reviews.llvm.org/D141386>, violating !range would return poison. But folding select
to and/or i1 isn't poison safe in general. If we can prove that the
!range can never be violated, adding a !noundef can assume it is
guaranteed not to be posion value.

Even though violating !noundef would cause immediate undefine behavior,
in other words this instruction would not be speculatable, but metadatas
that may raise IUB is not considered in `isSafeToSpeculativelyExecute`
since these metadatas can be dropped.

Therefore, adding !noundef can improve folding of select and there is no
foreseeable side-effect at the same time.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D149077

Files:
  llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
  llvm/test/Transforms/InstCombine/ctpop.ll
  llvm/test/Transforms/InstCombine/cttz.ll


Index: llvm/test/Transforms/InstCombine/cttz.ll
===================================================================
--- llvm/test/Transforms/InstCombine/cttz.ll
+++ llvm/test/Transforms/InstCombine/cttz.ll
@@ -118,3 +118,14 @@
   %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 false)
   ret <2 x i64> %tz
 }
+
+define i32 @cttz_arg_noundef(i16 noundef %x) {
+; CHECK-LABEL: @cttz_arg_noundef(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 true), !range [[RNG0]], !noundef !3
+; CHECK-NEXT:    [[TZ:%.*]] = zext i16 [[TMP1]] to i32
+; CHECK-NEXT:    ret i32 [[TZ]]
+;
+  %z = zext i16 %x to i32
+  %tz = call i32 @llvm.cttz.i32(i32 %z, i1 true)
+  ret i32 %tz
+}
Index: llvm/test/Transforms/InstCombine/ctpop.ll
===================================================================
--- llvm/test/Transforms/InstCombine/ctpop.ll
+++ llvm/test/Transforms/InstCombine/ctpop.ll
@@ -475,3 +475,12 @@
   %i5 = xor i32 %i2, %i4
   ret i32 %i5
 }
+
+define i8 @arg_noundef(i8 noundef %arg) {
+; CHECK-LABEL: @arg_noundef(
+; CHECK-NEXT:    [[CNT:%.*]] = call i8 @llvm.ctpop.i8(i8 [[ARG:%.*]]), !range [[RNG0]], !noundef !6
+; CHECK-NEXT:    ret i8 [[CNT]]
+;
+  %cnt = call i8 @llvm.ctpop.i8(i8 %arg)
+  ret i8 %cnt
+}
Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -505,6 +505,19 @@
   return cast<Instruction>(Result);
 }
 
+static bool isGuaranteedDoNotViolateRangeMetadata(Instruction *I,
+                                                  unsigned KnownMin,
+                                                  unsigned KnownMax) {
+  if (MDNode *Node = I->getMetadata(LLVMContext::MD_range))
+    if (mdconst::extract<ConstantInt>(Node->getOperand(0))
+            ->equalsInt(KnownMin) &&
+        mdconst::extract<ConstantInt>(Node->getOperand(1))->equalsInt(KnownMax))
+      if (all_of(I->operands(),
+                 [&](Value *V) { return isGuaranteedNotToBeUndefOrPoison(V); }))
+        return true;
+  return false;
+}
+
 static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
   assert((II.getIntrinsicID() == Intrinsic::cttz ||
           II.getIntrinsicID() == Intrinsic::ctlz) &&
@@ -602,6 +615,12 @@
     return &II;
   }
 
+  if (!II.getMetadata(LLVMContext::MD_noundef) &&
+      isGuaranteedDoNotViolateRangeMetadata(&II, DefiniteZeros,
+                                            PossibleZeros + 1))
+    II.setMetadata(LLVMContext::MD_noundef,
+                   MDNode::get(II.getContext(), nullptr));
+
   return nullptr;
 }
 
@@ -683,6 +702,11 @@
     return &II;
   }
 
+  if (!II.getMetadata(LLVMContext::MD_noundef) &&
+      isGuaranteedDoNotViolateRangeMetadata(&II, MinCount, MaxCount + 1))
+    II.setMetadata(LLVMContext::MD_noundef,
+                   MDNode::get(II.getContext(), nullptr));
+
   return nullptr;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D149077.516447.patch
Type: text/x-patch
Size: 3007 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230424/113aa5fd/attachment.bin>


More information about the llvm-commits mailing list