[llvm] [InstCombine] Fold comparison of adding two z/sext booleans (PR #67895)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 1 03:17:53 PDT 2023


dtcxzyw wrote:

Hi! I wrote a Python script to generate the lookup table.
Python script: https://paste.ubuntu.com/p/HTqRkYJ7hT/
Generated code: 
```
Instruction *ExtA, *ExtB;
if (Cmp.isEquality() &&
      match(Add, m_c_Add(m_CombineAnd(m_Instruciton(ExtA), m_OneUse(m_ZExtOrSExt(m_Value(Op0)))),
                         m_CombineAnd(m_Instruciton(ExtB), m_OneUse(m_ZExtOrSExt(m_Value(Op1)))))) &&
      Op0->getType()->isIntOrIntVectorTy(1) &&
      Op1->getType()->isIntOrIntVectorTy(1) &&
      C.sge(-2) && C.sle(2)) {
    bool ZExtA = ExtA->getOpcode() == Instruction::ZExt;
    bool ZExtB = ExtB->getOpcode() == Instruction::ZExt;
    bool PredNe = Cmp.getPredicate() == CmpInst::ICMP_NE;
    // (zextA, zextB, pred, val, inv) -> op
    // op: 0 - false, 1 - true, 2 - and, 3 - or, 4 - xor, 5 - nand, 6 - nor, 7 - xnor, 8 - invalid
    const unsigned LUT[2][2][2][5][3] = {
2 ,8 ,8 ,4 ,8 ,8 ,6 ,8 ,8 ,0 ,8 ,8 ,0 ,8 ,8 ,5 ,8 ,8 ,7 ,8 ,8 ,3 ,8 ,8 ,1 ,8 ,8 ,1 ,8 ,8 ,0 ,8 ,8 ,8 ,6 ,2 ,7 ,8 ,8 ,8 ,2 ,6 ,0 ,8 ,8 ,1 ,8 ,8 ,8 ,3 ,5 ,4 ,8 ,8 ,8 ,5 ,3 ,1 ,8 ,8 ,0 ,8 ,8 ,8 ,2 ,6 ,7 ,8 ,8 ,8 ,6 ,2 ,0 ,8 ,8 ,1 ,8 ,8 ,8 ,5 ,3 ,4 ,8 ,8 ,8 ,3 ,5 ,1 ,8 ,8 ,0 ,8 ,8 ,0 ,8 ,8 ,6 ,8 ,8 ,4 ,8 ,8 ,2 ,8 ,8 ,1 ,8 ,8 ,1 ,8 ,8 ,3 ,8 ,8 ,7 ,8 ,8 ,5 ,8 ,8 ,};
    unsigned op = LUT[ZExtA][ZExtB][PredNe][C.getSExtValue() + 2][0];
    if (op == 8) {
      if (isFreeToInvert(Op0, Op0->hasOneUse())) {
        Op0 = Builder.CreateNot(Op0);
        op = LUT[ZExtA][ZExtB][PredNe][C.getSExtValue() + 2][1];
      }
      else {
        Op1 = Builder.CreateNot(Op1);
        op = LUT[ZExtA][ZExtB][PredNe][C.getSExtValue() + 2][2];
      }
    }
    switch(op) {
      case 0: return replaceInstUsesWith(Cmp, Builder.getFalse());
      case 1: return replaceInstUsesWith(Cmp, Builder.getTrue());
      case 2: return BinaryOperator::CreateAnd(Op0, Op1);
      case 3: return BinaryOperator::CreateOr(Op0, Op1);
      case 4: return BinaryOperator::CreateXor(Op0, Op1);
      case 5: return BinaryOperator::CreateNot(Builder.CreateAnd(Op0, Op1));
      case 6: return BinaryOperator::CreateNot(Builder.CreateOr(Op0, Op1));
      case 7: return BinaryOperator::CreateNot(Builder.CreateXor(Op0, Op1));
      default: llvm_unreachable("Invalid Ops");
    }
}
```
Alive2: https://alive2.llvm.org/ce/z/JgcfFJ

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


More information about the llvm-commits mailing list