]> granicus.if.org Git - llvm/commitdiff
Recommit r310869, "[InstSimplify][InstCombine] Modify the interface of decomposeBitTe...
authorCraig Topper <craig.topper@intel.com>
Mon, 14 Aug 2017 21:39:51 +0000 (21:39 +0000)
committerCraig Topper <craig.topper@intel.com>
Mon, 14 Aug 2017 21:39:51 +0000 (21:39 +0000)
This recommits r310869, with the moved files and no extra changes.

Original commit message:

This addresses a fixme in InstSimplify about using decomposeBitTest. This also fixes InstSimplify to handle ugt and ult compares too.

I've modified the interface a little to return only the APInt version of the mask that InstSimplify needs. InstCombine now has a small wrapper routine to create a Constant out of it. I've also dropped the returning of 0 since InstSimplify doesn't need that. So InstCombine creates a zero constant itself.

I also had to make decomposeBitTest support vectors since InstSimplify needs that.

As InstSimplify can't use something from the Transforms library, I've moved the CmpInstAnalysis code to the Analysis library.

Differential Revision: https://reviews.llvm.org/D36593

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310889 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/CmpInstAnalysis.h [moved from include/llvm/Transforms/Utils/CmpInstAnalysis.h with 85% similarity]
lib/Analysis/CMakeLists.txt
lib/Analysis/CmpInstAnalysis.cpp [moved from lib/Transforms/Utils/CmpInstAnalysis.cpp with 80% similarity]
lib/Analysis/InstructionSimplify.cpp
lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
lib/Transforms/Utils/CMakeLists.txt
test/Transforms/InstSimplify/select.ll

similarity index 85%
rename from include/llvm/Transforms/Utils/CmpInstAnalysis.h
rename to include/llvm/Analysis/CmpInstAnalysis.h
index 5ec3888d4538caf36e830fc05265188560b8daba..1079d5abc7f8a87540bbafbc3586ce149ce1aab4 100644 (file)
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TRANSFORMS_UTILS_CMPINSTANALYSIS_H
-#define LLVM_TRANSFORMS_UTILS_CMPINSTANALYSIS_H
+#ifndef LLVM_ANALYSIS_CMPINSTANALYSIS_H
+#define LLVM_ANALYSIS_CMPINSTANALYSIS_H
 
 #include "llvm/IR/InstrTypes.h"
 
@@ -60,10 +60,11 @@ namespace llvm {
   /// equality comparison (which is signless).
   bool PredicatesFoldable(CmpInst::Predicate p1, CmpInst::Predicate p2);
 
-  /// Decompose an icmp into the form ((X & Y) pred Z) if possible. The returned
-  /// predicate is either == or !=. Returns false if decomposition fails.
-  bool decomposeBitTestICmp(const ICmpInst *I, CmpInst::Predicate &Pred,
-                            Value *&X, Value *&Y, Value *&Z);
+  /// Decompose an icmp into the form ((X & Mask) pred 0) if possible. The
+  /// returned predicate is either == or !=. Returns false if decomposition
+  /// fails.
+  bool decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate &Pred,
+                            Value *&X, APInt &Mask);
 
 } // end namespace llvm
 
index 161709a48466f8868ca34bc2e945343d4b58310e..45268dd5c7678e4ec764b06ece8608c00a54a9e9 100644 (file)
@@ -18,6 +18,7 @@ add_llvm_library(LLVMAnalysis
   CallGraphSCCPass.cpp
   CallPrinter.cpp
   CaptureTracking.cpp
+  CmpInstAnalysis.cpp
   CostModel.cpp
   CodeMetrics.cpp
   ConstantFolding.cpp
similarity index 80%
rename from lib/Transforms/Utils/CmpInstAnalysis.cpp
rename to lib/Analysis/CmpInstAnalysis.cpp
index d9294c49930916b855d2926a8b5053866d4b0156..079811fe9a280b64dea5e23603d820dfc2824c16 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Transforms/Utils/CmpInstAnalysis.h"
+#include "llvm/Analysis/CmpInstAnalysis.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/PatternMatch.h"
 
 using namespace llvm;
 
@@ -63,46 +64,46 @@ bool llvm::PredicatesFoldable(ICmpInst::Predicate p1, ICmpInst::Predicate p2) {
          (CmpInst::isSigned(p2) && ICmpInst::isEquality(p1));
 }
 
-bool llvm::decomposeBitTestICmp(const ICmpInst *I, CmpInst::Predicate &Pred,
-                                Value *&X, Value *&Y, Value *&Z) {
-  ConstantInt *C = dyn_cast<ConstantInt>(I->getOperand(1));
-  if (!C)
+bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
+                                CmpInst::Predicate &Pred,
+                                Value *&X, APInt &Mask) {
+  const APInt *C;
+  if (!match(RHS, PatternMatch::m_APInt(C)))
     return false;
 
-  switch (I->getPredicate()) {
+  switch (Pred) {
   default:
     return false;
   case ICmpInst::ICMP_SLT:
     // X < 0 is equivalent to (X & SignMask) != 0.
-    if (!C->isZero())
+    if (!C->isNullValue())
       return false;
-    Y = ConstantInt::get(I->getContext(), APInt::getSignMask(C->getBitWidth()));
+    Mask = APInt::getSignMask(C->getBitWidth());
     Pred = ICmpInst::ICMP_NE;
     break;
   case ICmpInst::ICMP_SGT:
     // X > -1 is equivalent to (X & SignMask) == 0.
-    if (!C->isMinusOne())
+    if (!C->isAllOnesValue())
       return false;
-    Y = ConstantInt::get(I->getContext(), APInt::getSignMask(C->getBitWidth()));
+    Mask = APInt::getSignMask(C->getBitWidth());
     Pred = ICmpInst::ICMP_EQ;
     break;
   case ICmpInst::ICMP_ULT:
     // X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
-    if (!C->getValue().isPowerOf2())
+    if (!C->isPowerOf2())
       return false;
-    Y = ConstantInt::get(I->getContext(), -C->getValue());
+    Mask = -*C;
     Pred = ICmpInst::ICMP_EQ;
     break;
   case ICmpInst::ICMP_UGT:
     // X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0.
-    if (!(C->getValue() + 1).isPowerOf2())
+    if (!(*C + 1).isPowerOf2())
       return false;
-    Y = ConstantInt::get(I->getContext(), ~C->getValue());
+    Mask = ~*C;
     Pred = ICmpInst::ICMP_NE;
     break;
   }
 
-  X = I->getOperand(0);
-  Z = ConstantInt::getNullValue(C->getType());
+  X = LHS;
   return true;
 }
index 9729629b1673c725e80af70ff366f6cd6c4a1a82..d155f6b4803d2df3d72c3b89f06b530d9f3a5c40 100644 (file)
@@ -23,6 +23,7 @@
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/CaptureTracking.h"
+#include "llvm/Analysis/CmpInstAnalysis.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/LoopAnalysisManager.h"
 #include "llvm/Analysis/MemoryBuiltins.h"
@@ -3620,32 +3621,29 @@ static Value *simplifySelectBitTest(Value *TrueVal, Value *FalseVal, Value *X,
 
 /// An alternative way to test if a bit is set or not uses sgt/slt instead of
 /// eq/ne.
-static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *TrueVal,
-                                           Value *FalseVal,
-                                           bool TrueWhenUnset) {
+static Value *simplifySelectWithFakeICmpEq(Value *CmpLHS, Value *CmpRHS,
+                                           ICmpInst::Predicate Pred,
+                                           Value *TrueVal, Value *FalseVal) {
+  Value *X;
+  APInt Mask;
+  if (!decomposeBitTestICmp(CmpLHS, CmpRHS, Pred, X, Mask))
+    return nullptr;
+
   unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits();
   if (!BitWidth)
     return nullptr;
 
-  APInt MinSignedValue;
-  Value *X;
-  if (match(CmpLHS, m_Trunc(m_Value(X))) && (X == TrueVal || X == FalseVal)) {
+  Value *ExtX;
+  if (match(X, m_Trunc(m_Value(ExtX))) &&
+      (ExtX == TrueVal || ExtX == FalseVal)) {
     // icmp slt (trunc X), 0  <--> icmp ne (and X, C), 0
     // icmp sgt (trunc X), -1 <--> icmp eq (and X, C), 0
-    unsigned DestSize = CmpLHS->getType()->getScalarSizeInBits();
-    MinSignedValue = APInt::getSignedMinValue(DestSize).zext(BitWidth);
-  } else {
-    // icmp slt X, 0  <--> icmp ne (and X, C), 0
-    // icmp sgt X, -1 <--> icmp eq (and X, C), 0
-    X = CmpLHS;
-    MinSignedValue = APInt::getSignedMinValue(BitWidth);
+    X = ExtX;
+    Mask = Mask.zext(BitWidth);
   }
 
-  if (Value *V = simplifySelectBitTest(TrueVal, FalseVal, X, &MinSignedValue,
-                                       TrueWhenUnset))
-    return V;
-
-  return nullptr;
+  return simplifySelectBitTest(TrueVal, FalseVal, X, &Mask,
+                               Pred == ICmpInst::ICMP_EQ);
 }
 
 /// Try to simplify a select instruction when its condition operand is an
@@ -3658,9 +3656,6 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
   if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
     return nullptr;
 
-  // FIXME: This code is nearly duplicated in InstCombine. Using/refactoring
-  // decomposeBitTestICmp() might help.
-  // FIXME this should support ICMP_SLE/SGE forms as well
   if (ICmpInst::isEquality(Pred) && match(CmpRHS, m_Zero())) {
     Value *X;
     const APInt *Y;
@@ -3668,18 +3663,13 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
       if (Value *V = simplifySelectBitTest(TrueVal, FalseVal, X, Y,
                                            Pred == ICmpInst::ICMP_EQ))
         return V;
-  } else if (Pred == ICmpInst::ICMP_SLT && match(CmpRHS, m_Zero())) {
-    // Comparing signed-less-than 0 checks if the sign bit is set.
-    if (Value *V = simplifySelectWithFakeICmpEq(CmpLHS, TrueVal, FalseVal,
-                                                false))
-      return V;
-  } else if (Pred == ICmpInst::ICMP_SGT && match(CmpRHS, m_AllOnes())) {
-    // Comparing signed-greater-than -1 checks if the sign bit is not set.
-    if (Value *V = simplifySelectWithFakeICmpEq(CmpLHS, TrueVal, FalseVal,
-                                                true))
-      return V;
   }
 
+  // Check for other compares that behave like bit test.
+  if (Value *V = simplifySelectWithFakeICmpEq(CmpLHS, CmpRHS, Pred,
+                                              TrueVal, FalseVal))
+    return V;
+
   if (CondVal->hasOneUse()) {
     const APInt *C;
     if (match(CmpRHS, m_APInt(C))) {
index dfc2ea3e4deb1ffa7ab7064e503024c29b1a1418..8f0254f21716914fdec65ad7145ebeccaee02f6f 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "InstCombineInternal.h"
+#include "llvm/Analysis/CmpInstAnalysis.h"
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/IR/ConstantRange.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/PatternMatch.h"
-#include "llvm/Transforms/Utils/CmpInstAnalysis.h"
 #include "llvm/Transforms/Utils/Local.h"
 using namespace llvm;
 using namespace PatternMatch;
@@ -292,6 +292,18 @@ static unsigned conjugateICmpMask(unsigned Mask) {
   return NewMask;
 }
 
+// Adapts the external decomposeBitTestICmp for local use.
+static bool decomposeBitTestICmp(Value *LHS, Value *RHS, CmpInst::Predicate &Pred,
+                                 Value *&X, Value *&Y, Value *&Z) {
+  APInt Mask;
+  if (!llvm::decomposeBitTestICmp(LHS, RHS, Pred, X, Mask))
+    return false;
+
+  Y = ConstantInt::get(LHS->getType(), Mask);
+  Z = ConstantInt::get(RHS->getType(), 0);
+  return true;
+}
+
 /// Handle (icmp(A & B) ==/!= C) &/| (icmp(A & D) ==/!= E).
 /// Return the set of pattern classes (from MaskedICmpType) that both LHS and
 /// RHS satisfy.
@@ -316,7 +328,7 @@ static unsigned getMaskedTypeForICmpPair(Value *&A, Value *&B, Value *&C,
   Value *L2 = LHS->getOperand(1);
   Value *L11, *L12, *L21, *L22;
   // Check whether the icmp can be decomposed into a bit test.
-  if (decomposeBitTestICmp(LHS, PredL, L11, L12, L2)) {
+  if (decomposeBitTestICmp(L1, L2, PredL, L11, L12, L2)) {
     L21 = L22 = L1 = nullptr;
   } else {
     // Look for ANDs in the LHS icmp.
@@ -347,7 +359,7 @@ static unsigned getMaskedTypeForICmpPair(Value *&A, Value *&B, Value *&C,
   Value *R2 = RHS->getOperand(1);
   Value *R11, *R12;
   bool Ok = false;
-  if (decomposeBitTestICmp(RHS, PredR, R11, R12, R2)) {
+  if (decomposeBitTestICmp(R1, R2, PredR, R11, R12, R2)) {
     if (R11 == L11 || R11 == L12 || R11 == L21 || R11 == L22) {
       A = R11;
       D = R12;
index 83bc05d0311caebbc841dfe8ac11c4b29152a6b5..8561ec78b1cdfe2a4cc27fd9e0729c8224e830bc 100644 (file)
@@ -7,7 +7,6 @@ add_llvm_library(LLVMTransformUtils
   BypassSlowDivision.cpp
   CloneFunction.cpp
   CloneModule.cpp
-  CmpInstAnalysis.cpp
   CodeExtractor.cpp
   CtorUtils.cpp
   DemoteRegToStack.cpp
index e9c94170a941322a63c156dab1d1b81d1e45f48c..4134191a3cf9e2d88011db19ca5b252a62834764 100644 (file)
@@ -160,13 +160,10 @@ define <2 x i8> @test11vec(<2 x i8> %X) {
   ret <2 x i8> %sel
 }
 
-; TODO: we should be able to simplify this
 define i32 @test12(i32 %X) {
 ; CHECK-LABEL: @test12(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[X:%.*]], 4
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], 3
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[AND]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %cmp = icmp ult i32 %X, 4
   %and = and i32 %X, 3
@@ -189,13 +186,10 @@ define i32 @test12noncanon(i32 %X) {
   ret i32 %cond
 }
 
-; TODO: we should be able to simplify this
 define i32 @test13(i32 %X) {
 ; CHECK-LABEL: @test13(
-; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], 3
-; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], 3
-; CHECK-NEXT:    [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[X]]
-; CHECK-NEXT:    ret i32 [[COND]]
+; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], 3
+; CHECK-NEXT:    ret i32 [[AND]]
 ;
   %cmp = icmp ugt i32 %X, 3
   %and = and i32 %X, 3