[PATCH] D124183: [InstCombine] Add one use limitation for (X * C2) << C1 --> X * (C2 << C1)

chenglin.bi via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 30 02:21:27 PDT 2022


bcl5980 added a comment.

@spatel, thanks for the answer.

Based on the discussion I review all one-use in instcombine and I find some more similar cases without TODO comments:

Instruction *InstCombinerImpl::visitAdd

  usub.sat(A, B) + B => umax(A, B)
      m_OneUse(m_Intrinsic<Intrinsic::usub_sat>(m_Value(A), m_Value(B)))

Instruction *InstCombinerImpl::visitSub

  X - usub.sat(X, Y) => umin(X, Y)
      m_OneUse(m_Intrinsic<Intrinsic::usub_sat>(m_Specific(Op0), m_Value(Y)))

Instruction *InstCombinerImpl::visitFAdd

  fadd (rdx 0.0, X), Y --> rdx Y, X
      m_OneUse(m_Intrinsic<Intrinsic::vector_reduce_fadd>(m_AnyZeroFP(), m_Value(X)))

Instruction *InstCombinerImpl::visitFNeg

  -(X - Y) --> (Y - X)
      m_OneUse(m_FSub(m_Value(X), m_Value(Y)))

static Instruction *foldComplexAndOrPatterns

  (~(A | B) & C) | ~(A | C) --> ~((B & C) | A)
  (~(A & B) | C) & ~(A & C) --> ~((B | C) & A)
      m_OneUse(m_c_BinOp(Opcode, m_Specific(A), m_Specific(C)))
  
  (~(A | B) & C) | ~(B | C) --> ~((A & C) | B)
  (~(A & B) | C) & ~(B & C) --> ~((A | C) & B)
      m_OneUse(m_c_BinOp(Opcode, m_Specific(B), m_Specific(C)))
  
  (~A & B & C) | ~(A | B) --> (C | ~B) & ~A
  (~A | B | C) & ~(A & B) --> (C & ~B) | ~A
      m_OneUse(m_c_BinOp(Opcode, m_Specific(A), m_Specific(B)))
  
  (~A & B & C) | ~(A | C) --> (B | ~C) & ~A
  (~A | B | C) & ~(A & C) --> (B & ~C) | ~A
      m_OneUse(m_c_BinOp(Opcode, m_Specific(A), m_Specific(C))

static Instruction *foldBitCastBitwiseLogic

  bitcast(logic(bitcast(X), Y)) --> logic'(X, bitcast(Y))
      m_OneUse(m_BitCast(m_Value(X)))
  
  bitcast(logic(Y, bitcast(X))) --> logic'(bitcast(Y), X)
      m_OneUse(m_BitCast(m_Value(X)))
  
  bitcast(select(Cond, bitcast(X), Y)) --> select'(Cond, X, bitcast(Y))
      m_OneUse(m_BitCast(m_Value(X))))
  
  bitcast(select(Cond, Y, bitcast(X))) --> select'(Cond, bitcast(Y), X)
      m_OneUse(m_BitCast(m_Value(X))))

Instruction *InstCombinerImpl::foldICmpEquality

  Transform "icmp eq (trunc (lshr(X, cst1)), cst" to "icmp (and X, mask), cst"
      m_OneUse(m_LShr(m_Value(A), m_ConstantInt(ShAmt)))

static Value *foldMulSelectToNegate

  mul (select Cond, 1, -1), OtherOp --> select Cond, OtherOp, -OtherOp
  mul OtherOp, (select Cond, 1, -1) --> select Cond, OtherOp, -OtherOp
      m_OneUse(m_Select(m_Value(Cond), m_One(), m_AllOnes()))
  
  mul (select Cond, -1, 1), OtherOp --> select Cond, -OtherOp, OtherOp
  mul OtherOp, (select Cond, -1, 1) --> select Cond, -OtherOp, OtherOp
      m_OneUse(m_Select(m_Value(Cond), m_AllOnes(), m_One()))
  
  fmul (select Cond, 1.0, -1.0), OtherOp --> select Cond, OtherOp, -OtherOp
  fmul OtherOp, (select Cond, 1.0, -1.0) --> select Cond, OtherOp, -OtherOp
      m_OneUse(m_Select(m_Value(Cond), m_SpecificFP(1.0), m_SpecificFP(-1.0)))
  
  fmul (select Cond, -1.0, 1.0), OtherOp --> select Cond, -OtherOp, OtherOp
  fmul OtherOp, (select Cond, -1.0, 1.0) --> select Cond, -OtherOp, OtherOp
      m_OneUse(m_Select(m_Value(Cond), m_SpecificFP(-1.0), m_SpecificFP(1.0)))

Instruction *InstCombinerImpl::visitFMul

  (C1 / X) * C --> (C * C1) / X; list here, but based on the discussion with div, I don't think we should remove one-use
      m_OneUse(m_FDiv(m_Constant(C1), m_Value(X)))

Instruction *InstCombinerImpl::visitShl

  (C2 << X) << C1 --> (C2 << C1) << X
      m_OneUse(m_Shl(m_Constant(C2), m_Value(X))))

Instruction *InstCombinerImpl::foldICmpBinOpEqualityWithConstant

  Replace ((add A, B) != C) with (A != C-B) if B & C are constants.
      BO->hasOneUse()
  
  For the xor case, we can xor two constants together, eliminating the explicit xor.
  Replace ((xor A, B) != 0) with (A != B)
      BO->hasOneUse()

Instruction *InstCombinerImpl::foldICmpEquality

  A^c1 == C^c2 --> A == C^(c1^c2)
      Op1->hasOneUse()
  
  Transform (zext A) == (B & (1<<X)-1) --> A == (trunc B)
      Op0->hasOneUse()
  and           (B & (1<<X)-1) == (zext A) --> A == (trunc B)
      Op1->hasOneUse()

@spatel @lebedev.ri
Do you think we need to remove these one-use?
If yes I will start on work it to help improve code consistent.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124183/new/

https://reviews.llvm.org/D124183



More information about the llvm-commits mailing list