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

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 1 05:16:13 PDT 2023


nikic wrote:

To expand on my initial comment, what I had in mind is something like this (completely untested, probably will not compile):

```
if (match(Add, m_c_Add(m_CombineAnd(m_Instruction(Ext0), m_OneUse(m_ZExtOrSExt(m_Value(Op0)))),
                       m_CombineAnd(m_Instruction(Ext1), m_OneUse(m_ZExtOrSExt(m_Value(Op1)))))) &&
    Op0->getType()->isIntOrIntVectorTy(1) &&
    Op1->getType()->isIntOrIntVectorTy(1)) {
  std::bitset<4> Table;
  auto ComputeTable = [&](bool Op0Val, bool Op1Val) {
    int Res = 0;
    if (Op0Val)
      Res += isa<ZExtInst>(Ext0) ? 1 : -1;
    if (Op1Val)
      Res += isa<ZExtInst>(Ext1) ? 1 : -1;
    return ICmpInst::compare(APInt(BW, Res, true), C, Pred);
  };
  Table[0] = ComputeTable(false, false);
  Table[1] = ComputeTable(false, true);
  Table[2] = ComputeTable(true, false);
  Table[3] = ComputeTable(true, true);
  return createLogicFromTable(Table, Op0, Op1);
}

// ...

static Value *createLogicFromTable(const std::bitset<4> &Table, Value *Op0, Value *Op1, IRBuilderBase &Builder) {
  switch (Table.to_ulong()) {
  case 0: // 0 0 0 0
    return Builder.getTrue();
  case 1: // 0 0 0 1
    return Builder.CreateAnd(Op0, Op1);
  // etc.
  }
}
```

The computation of the logic table is pretty straightforward and can be done explicitly, without a static lookup table. The conversion from the table to logic is generic and not specific to this transform.

This approach also automatically works with all predicates, not just equality predicates, so I think this would also subsume the code from D143373 linked above.

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


More information about the llvm-commits mailing list