[llvm] [InstCombine] Try optimizing with knownbits which determined from Cond (PR #91762)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 14 10:22:58 PDT 2024


================
@@ -1809,6 +1809,198 @@ static Instruction *foldSelectICmpEq(SelectInst &SI, ICmpInst *ICI,
   return nullptr;
 }
 
+// ICmpInst of SelectInst is not included in the calculation of KnownBits
+// so we are missing the opportunity to optimize the Value of the True or
+// False Condition via ICmpInst with KnownBits.
+//
+// Consider:
+//   %or = or i32 %x, %y
+//   %or0 = icmp eq i32 %or, 0
+//   %and = and i32 %x, %y
+//   %cond = select i1 %or0, i32 %and, i32 %or
+//   ret i32 %cond
+//
+// Expect:
+//   %or = or i32 %x, %y
+//   ret i32 %or
+//
+// We could know what bit was enabled for %x, %y by ICmpInst in SelectInst.
+static Instruction *foldSelectICmpBinOp(SelectInst &SI, ICmpInst *ICI,
+                                        Value *CmpLHS, Value *CmpRHS,
+                                        Value *TVal, Value *FVal,
+                                        InstCombinerImpl &IC) {
+  Value *X, *Y;
+  const APInt *C;
+  unsigned CmpLHSOpc;
+  bool IsDisjoint = false;
+  // Specially handling for X^Y==0 transformed to X==Y
+  if (match(TVal, m_c_BitwiseLogic(m_Specific(CmpLHS), m_Specific(CmpRHS)))) {
+    X = CmpLHS;
+    Y = CmpRHS;
+    APInt ZeroVal = APInt::getZero(CmpLHS->getType()->getScalarSizeInBits());
+    C = const_cast<APInt *>(&ZeroVal);
+    CmpLHSOpc = Instruction::Xor;
+  } else if ((match(CmpLHS, m_BinOp(m_Value(X), m_Value(Y))) &&
+              match(CmpRHS, m_APInt(C))) &&
+             (match(TVal, m_c_BinOp(m_Specific(X), m_Value())) ||
+              match(TVal, m_c_BinOp(m_Specific(Y), m_Value())))) {
+    if (auto Inst = dyn_cast<PossiblyDisjointInst>(CmpLHS)) {
+      if (Inst->isDisjoint())
+        IsDisjoint = true;
+      CmpLHSOpc = Instruction::Or;
+    } else
+      CmpLHSOpc = cast<BinaryOperator>(CmpLHS)->getOpcode();
+  } else
+    return nullptr;
+
+  enum SpecialKnownBits {
+    NothingSpecial = 0,
+    NoCommonBits = 1 << 1,
+    AllCommonBits = 1 << 2,
+    AllBitsEnabled = 1 << 3,
+  };
+
+  // We cannot know exactly what bits is known in X Y.
+  // Instead, we just know what relationship exist for.
+  auto isSpecialKnownBitsFor = [&]() -> unsigned {
+    if (CmpLHSOpc == Instruction::And) {
+      if (C->isZero())
+        return NoCommonBits;
+    } else if (CmpLHSOpc == Instruction::Xor) {
+      if (C->isAllOnes())
+        return NoCommonBits | AllBitsEnabled;
+      if (C->isZero())
+        return AllCommonBits;
+    } else if (CmpLHSOpc == Instruction::Or && IsDisjoint) {
+      if (C->isAllOnes())
+        return NoCommonBits | AllBitsEnabled;
+      return NoCommonBits;
+    }
----------------
goldsteinn wrote:

`(x | y == -1)` you can do `AllBitsEnabled` irrelivant of disjoint

https://github.com/llvm/llvm-project/pull/91762


More information about the llvm-commits mailing list