[llvm] r257769 - [ValueTracking] Understand more select patterns in ComputeKnownBits

James Molloy via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 14 07:23:19 PST 2016


Author: jamesm
Date: Thu Jan 14 09:23:19 2016
New Revision: 257769

URL: http://llvm.org/viewvc/llvm-project?rev=257769&view=rev
Log:
[ValueTracking] Understand more select patterns in ComputeKnownBits

Some patterns of select+compare allow us to know exactly the value of the uppermost bits in the select result. For example:

  %b = icmp ugt i32 %a, 5
  %c = select i1 %b, i32 2, i32 %a

Here we know that %c is bounded by 5, and therefore KnownZero = ~APInt(5).getActiveBits() = ~7.

There are several such patterns, and this patch attempts to understand a reasonable subset of them - namely when the base values are the same (as above), and when they are related by a simple (add nsw), for example (add nsw %a, 4) and %a.

Added:
    llvm/trunk/test/Analysis/ValueTracking/select-maxbits.ll
Modified:
    llvm/trunk/lib/Analysis/ValueTracking.cpp

Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=257769&r1=257768&r2=257769&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ValueTracking.cpp (original)
+++ llvm/trunk/lib/Analysis/ValueTracking.cpp Thu Jan 14 09:23:19 2016
@@ -1140,14 +1140,52 @@ static void computeKnownBitsFromOperator
     KnownZero = APInt::getHighBitsSet(BitWidth, LeadZ);
     break;
   }
-  case Instruction::Select:
+  case Instruction::Select: {
     computeKnownBits(I->getOperand(2), KnownZero, KnownOne, DL, Depth + 1, Q);
     computeKnownBits(I->getOperand(1), KnownZero2, KnownOne2, DL, Depth + 1, Q);
 
     // Only known if known in both the LHS and RHS.
     KnownOne &= KnownOne2;
     KnownZero &= KnownZero2;
+
+    // There are several cmp+select patterns that ensure their result will be no
+    // greater than a constant. Detect a number of these.
+    Value *X, *Y;
+    ConstantInt *C1, *C2;
+    ICmpInst::Predicate Pred;
+
+    auto IsLessThanOrEqualTo = [](Value *X, Value *Y) {
+      if (X == Y)
+        return true;
+      Value *M1, *M2;
+      ConstantInt *C1, *C2;
+      if (!match(X, m_NSWAdd(m_Value(M1), m_ConstantInt(C1))))
+        C1 = nullptr;
+      if (!match(Y, m_NSWAdd(m_Value(M2), m_ConstantInt(C2))))
+        C2 = nullptr;
+      if (C1 && M1 == Y && C1->isNegative())
+        return true;
+      if (C2 && M2 == X && !C2->isNegative())
+        return true;
+      if (C1 && C2 && M1 == M2 && !C1->isNegative() && !C2->isNegative() &&
+          C1->getValue().ule(C2->getValue()))
+        return true;
+      return false;
+    };
+
+    // (select (icmp ugt X, C1), C2, Y)
+    //   if Y <= X and C2 <= C1
+    //   then maximum value = C1.
+    if (match(I, m_Select(m_ICmp(Pred, m_Value(X), m_ConstantInt(C1)),
+                          m_ConstantInt(C2), m_Value(Y)))) {
+      if (Pred == ICmpInst::ICMP_UGT && IsLessThanOrEqualTo(Y, X) &&
+          C2->getValue().ule(C1->getValue())) {
+        auto V = cast<ConstantInt>(C1)->getValue() - 1;
+        KnownZero = ~APInt::getLowBitsSet(V.getBitWidth(), V.getActiveBits());
+      }
+    }
     break;
+  }
   case Instruction::FPTrunc:
   case Instruction::FPExt:
   case Instruction::FPToUI:

Added: llvm/trunk/test/Analysis/ValueTracking/select-maxbits.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ValueTracking/select-maxbits.ll?rev=257769&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/ValueTracking/select-maxbits.ll (added)
+++ llvm/trunk/test/Analysis/ValueTracking/select-maxbits.ll Thu Jan 14 09:23:19 2016
@@ -0,0 +1,62 @@
+; RUN: opt -S -instsimplify < %s | FileCheck %s
+
+; CHECK-LABEL: @one
+define i32 @one(i32 %a) {
+; CHECK: ret i32 0
+  %b = icmp ugt i32 %a, 5
+  %c = select i1 %b, i32 2, i32 %a
+  %d = lshr i32 %c, 24
+  ret i32 %d
+}
+
+; CHECK-LABEL: @two
+define i32 @two(i32 %a) {
+; CHECK: ret i32 0
+  %x = add nsw i32 %a, 4
+  %b = icmp ugt i32 %x, 5
+  %c = select i1 %b, i32 2, i32 %a
+  %d = lshr i32 %c, 24
+  ret i32 %d
+}
+
+; CHECK-LABEL: @two_no_nsw
+define i32 @two_no_nsw(i32 %a) {
+; CHECK: ret i32 %d
+  %x = add i32 %a, 4
+  %b = icmp ugt i32 %x, 5
+  %c = select i1 %b, i32 2, i32 %a
+  %d = lshr i32 %c, 24
+  ret i32 %d
+}
+
+; CHECK-LABEL: @three
+define i32 @three(i32 %a) {
+; CHECK: ret i32 0
+  %x = add nsw i32 %a, -4
+  %b = icmp ugt i32 %a, 5
+  %c = select i1 %b, i32 2, i32 %x
+  %d = lshr i32 %c, 24
+  ret i32 %d
+}
+
+; CHECK-LABEL: @four
+define i32 @four(i32 %a) {
+; CHECK: ret i32 0
+  %x = add nsw i32 %a, 42
+  %y = add nsw i32 %a, 64
+  %b = icmp ugt i32 %y, 5
+  %c = select i1 %b, i32 2, i32 %x
+  %d = lshr i32 %c, 24
+  ret i32 %d
+}
+
+; CHECK-LABEL: @four_swapped
+define i32 @four_swapped(i32 %a) {
+; CHECK: ret i32 %d
+  %x = add nsw i32 %a, 42
+  %y = add nsw i32 %a, 64
+  %b = icmp ugt i32 %x, 5
+  %c = select i1 %b, i32 2, i32 %y
+  %d = lshr i32 %c, 24
+  ret i32 %d
+}
\ No newline at end of file




More information about the llvm-commits mailing list