[PATCH] D84250: [InstSimplify] ExpandBinOp should fold an expression only when it's safe

Sanjay Patel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 22 08:00:27 PDT 2020


spatel added a comment.

How about reducing the code duplication with a preliminary clean-up patch?

  diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
  index 8fbcee84a15..22b1dac8d65 100644
  --- a/llvm/lib/Analysis/InstructionSimplify.cpp
  +++ b/llvm/lib/Analysis/InstructionSimplify.cpp
  @@ -228,64 +228,54 @@ static bool valueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {
     return false;
   }
  
  -/// Simplify "A op (B op' C)" by distributing op over op', turning it into
  -/// "(A op B) op' (A op C)".  Here "op" is given by Opcode and "op'" is
  -/// given by OpcodeToExpand, while "A" corresponds to LHS and "B op' C" to RHS.
  -/// Also performs the transform "(A op' B) op C" -> "(A op C) op' (B op C)".
  -/// Returns the simplified value, or null if no simplification was performed.
  -static Value *ExpandBinOp(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS,
  -                          Instruction::BinaryOps OpcodeToExpand,
  +/// Try to simplify a binary operator of form "V op OtherOp" where V is
  +/// "(B0 opex B1)" by distributing 'op' across 'opex' as
  +/// "(B0 op OtherOp) opex (B1 op OtherOp)".
  +static Value *expandBinOp(Instruction::BinaryOps Opcode, Value *V,
  +                          Value *OtherOp, Instruction::BinaryOps OpcodeToExpand,
                             const SimplifyQuery &Q, unsigned MaxRecurse) {
  -  // Recursion is always used, so bail out at once if we already hit the limit.
  -  if (!MaxRecurse--)
  +  auto *B = dyn_cast<BinaryOperator>(V);
  +  if (!B || B->getOpcode() != OpcodeToExpand)
  +    return nullptr;
  +  Value *B0 = B->getOperand(0), *B1 = B->getOperand(1);
  +  Value *L = SimplifyBinOp(Opcode, B0, OtherOp, Q, MaxRecurse);
  +  if (!L)
  +    return nullptr;
  +  Value *R = SimplifyBinOp(Opcode, B1, OtherOp, Q, MaxRecurse);
  +  if (!R)
       return nullptr;
  
  -  // Check whether the expression has the form "(A op' B) op C".
  -  if (BinaryOperator *Op0 = dyn_cast<BinaryOperator>(LHS))
  -    if (Op0->getOpcode() == OpcodeToExpand) {
  -      // It does!  Try turning it into "(A op C) op' (B op C)".
  -      Value *A = Op0->getOperand(0), *B = Op0->getOperand(1), *C = RHS;
  -      // Do "A op C" and "B op C" both simplify?
  -      if (Value *L = SimplifyBinOp(Opcode, A, C, Q, MaxRecurse))
  -        if (Value *R = SimplifyBinOp(Opcode, B, C, Q, MaxRecurse)) {
  -          // They do! Return "L op' R" if it simplifies or is already available.
  -          // If "L op' R" equals "A op' B" then "L op' R" is just the LHS.
  -          if ((L == A && R == B) || (Instruction::isCommutative(OpcodeToExpand)
  -                                     && L == B && R == A)) {
  -            ++NumExpand;
  -            return LHS;
  -          }
  -          // Otherwise return "L op' R" if it simplifies.
  -          if (Value *V = SimplifyBinOp(OpcodeToExpand, L, R, Q, MaxRecurse)) {
  -            ++NumExpand;
  -            return V;
  -          }
  -        }
  -    }
  +  // Does the expanded pair of binops simplify to the existing binop?
  +  if ((L == B0 && R == B1) ||
  +      (Instruction::isCommutative(OpcodeToExpand) && L == B1 && R == B0)) {
  +    ++NumExpand;
  +    return B;
  +  }
  
  -  // Check whether the expression has the form "A op (B op' C)".
  -  if (BinaryOperator *Op1 = dyn_cast<BinaryOperator>(RHS))
  -    if (Op1->getOpcode() == OpcodeToExpand) {
  -      // It does!  Try turning it into "(A op B) op' (A op C)".
  -      Value *A = LHS, *B = Op1->getOperand(0), *C = Op1->getOperand(1);
  -      // Do "A op B" and "A op C" both simplify?
  -      if (Value *L = SimplifyBinOp(Opcode, A, B, Q, MaxRecurse))
  -        if (Value *R = SimplifyBinOp(Opcode, A, C, Q, MaxRecurse)) {
  -          // They do! Return "L op' R" if it simplifies or is already available.
  -          // If "L op' R" equals "B op' C" then "L op' R" is just the RHS.
  -          if ((L == B && R == C) || (Instruction::isCommutative(OpcodeToExpand)
  -                                     && L == C && R == B)) {
  -            ++NumExpand;
  -            return RHS;
  -          }
  -          // Otherwise return "L op' R" if it simplifies.
  -          if (Value *V = SimplifyBinOp(OpcodeToExpand, L, R, Q, MaxRecurse)) {
  -            ++NumExpand;
  -            return V;
  -          }
  -        }
  -    }
  +  // Otherwise, return "L op' R" if it simplifies.
  +  Value *S = SimplifyBinOp(OpcodeToExpand, L, R, Q, MaxRecurse);
  +  if (!S)
  +    return nullptr;
  
  +  ++NumExpand;
  +  return S;
  +}
  +
  +/// Try to simplify binops of form "A op (B op' C)" or the commuted variant by
  +/// distributing op over op'.
  +static Value *expandCommutativeBinOp(Instruction::BinaryOps Opcode,
  +                                     Value *L, Value *R,
  +                                     Instruction::BinaryOps OpcodeToExpand,
  +                                     const SimplifyQuery &Q,
  +                                     unsigned MaxRecurse) {
  +  // Recursion is always used, so bail out at once if we already hit the limit.
  +  if (!MaxRecurse--)
  +    return nullptr;
  +
  +  if (Value *V = expandBinOp(Opcode, L, R, OpcodeToExpand, Q, MaxRecurse))
  +    return V;
  +  if (Value *V = expandBinOp(Opcode, R, L, OpcodeToExpand, Q, MaxRecurse))
  +    return V;
     return nullptr;
   }
  
  @@ -901,8 +891,8 @@ static Value *SimplifyMulInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
       return V;
  
     // Mul distributes over Add. Try some generic simplifications based on this.
  -  if (Value *V = ExpandBinOp(Instruction::Mul, Op0, Op1, Instruction::Add,
  -                             Q, MaxRecurse))
  +  if (Value *V = expandCommutativeBinOp(Instruction::Mul, Op0, Op1,
  +                                        Instruction::Add, Q, MaxRecurse))
       return V;
  
     // If the operation is with the result of a select instruction, check whether
  @@ -2095,13 +2085,13 @@ static Value *SimplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
       return V;
  
     // And distributes over Or.  Try some generic simplifications based on this.
  -  if (Value *V = ExpandBinOp(Instruction::And, Op0, Op1, Instruction::Or,
  -                             Q, MaxRecurse))
  +  if (Value *V = expandCommutativeBinOp(Instruction::And, Op0, Op1,
  +                                        Instruction::Or, Q, MaxRecurse))
       return V;
  
     // And distributes over Xor.  Try some generic simplifications based on this.
  -  if (Value *V = ExpandBinOp(Instruction::And, Op0, Op1, Instruction::Xor,
  -                             Q, MaxRecurse))
  +  if (Value *V = expandCommutativeBinOp(Instruction::And, Op0, Op1,
  +                                        Instruction::Xor, Q, MaxRecurse))
       return V;
  
     // If the operation is with the result of a select instruction, check whether
  @@ -2253,8 +2243,8 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
       return V;
  
     // Or distributes over And.  Try some generic simplifications based on this.
  -  if (Value *V = ExpandBinOp(Instruction::Or, Op0, Op1, Instruction::And, Q,
  -                             MaxRecurse))
  +  if (Value *V = expandCommutativeBinOp(Instruction::Or, Op0, Op1,
  +                                        Instruction::And, Q, MaxRecurse))
       return V;
  
     // If the operation is with the result of a select instruction, check whether


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D84250





More information about the llvm-commits mailing list