[PATCH] D12096: [InstCombineAddSub opportunities]: More opportunities to factorize FAdd/FSub when unsafeAlgebra is present for Inst

Aditya Nandakumar via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 18:29:39 PDT 2015


> On Aug 20, 2015, at 5:53 PM, Justin Bogner <mail at justinbogner.com> wrote:
> 
> Aditya Nandakumar <aditya_nandakumar at apple.com> writes:
>> This change in signature for performFactorization is required.
>> Previously it accepted Instruction and would extract the two operands to see
>> if it could be factorized but now we try to factorize values across different
>> instructions.
>> Also the opcode and the operand order for factorization can change. For eg
>> (a - b) + c -> a + (c - b) which would roughly translate to factorize(c , b,
>> FSub).
> 
> My bad - I didn't notice the calls in performFactorizationAssociative.
> This makes sense.
> 
> Aditya Nandakumar via llvm-commits <llvm-commits at lists.llvm.org> writes:
>> +// If I is either FAdd or FSub, see if we can ...
>> +// -> Transform (A op1 B) op2 C -> A op3 (B op4 C) if (B op C) factorizes
>> +//    Eg. (A + X * C1) + X * C2 -> A + X * (C1 + C2)
>> +// -> Transform A op1 (B op2 C) -> (A op3 B) op4 C) if (A op3 B) factorizes
>> +//    Eg. (A + X * C1) - X * C2 -> A + X * (C1-C2)
>> +// -> Transform ( A op1 B) op2 C -> (A op3 C) op4 B if (A op3 C) factorizes
>> +//    Eg. (X * C1 - B) + X * C2 -> X * (C1 - C2) - B
>> +// -> Transform A op1 (B op2 C) -> (A op3 C) op4 B
>> +//    Eg. X * C1 - (B + X * C2) -> X * (C1 - C2) - B
>> +// This method should only be called when unsafeAlgebra is set for the inst
>> +Value *FAddCombine::performFactorizationAssociative(Instruction *I) {
>> +  assert(I->hasUnsafeAlgebra() &&
>> +         "This method can't be called without unsafe algebra");
>> +  if (I->getOpcode() != Instruction::FAdd &&
>> +      I->getOpcode() != Instruction::FSub)
>> +    return nullptr;
>> +  // TODO: Overly conservative?
>> +  if (I->getNumUses() != 1)
>> +    return nullptr;
>> +
>> +  BinaryOperator *Op0 = dyn_cast<BinaryOperator>(I->getOperand(0));
>> +  BinaryOperator *Op1 = dyn_cast<BinaryOperator>(I->getOperand(1));
>> +  {
>> +    // (A op B) op C -> Simplify?
> 
> These extra {} scopes aren't doing anything anymore.
Done
> 
>> +    if (Op0 && (Op0->getOpcode() == Instruction::FAdd ||
>> +                Op0->getOpcode() == Instruction::FSub)) {
>> +      unsigned FactorizeOpcode, FinalOpcode;
>> +      Value *OpFactor0, *OpFactor1;
>> +      bool IsOp0OpcodeAdd = (Op0->getOpcode() == Instruction::FAdd);
>> +      bool IsIOpcodeAdd = (I->getOpcode() == Instruction::FAdd);
>> +      Value *A = Op0->getOperand(0);
>> +      Value *B = Op0->getOperand(1);
>> +      Value *C = I->getOperand(1);
>> +      // (a + b) + c -> a + ( b + c ) ?
>> +      // (a + b) - c -> a + ( b - c ) ?
>> +      if (IsOp0OpcodeAdd) {
>> +        OpFactor0 = B;
>> +        OpFactor1 = C;
>> +        FactorizeOpcode = I->getOpcode();
>> +        FinalOpcode = Instruction::FAdd;
>> +      }
>> +      // (a - b) + c -> a + (c - b) ?
>> +      else if (!IsOp0OpcodeAdd && IsIOpcodeAdd) {
>> +        OpFactor0 = C;
>> +        OpFactor1 = B;
>> +        FactorizeOpcode = Instruction::FSub;
>> +        FinalOpcode = Instruction::FAdd;
>> +      }
>> +      // (a - b) - c -> a - (b + c) ?
>> +      else {
>> +        OpFactor0 = B;
>> +        OpFactor1 = C;
>> +        FactorizeOpcode = Instruction::FAdd;
>> +        FinalOpcode = Instruction::FSub;
>> +      }
>> +      if (Value *V = performFactorization(OpFactor0, OpFactor1, FactorizeOpcode,
>> +                                          I->getFastMathFlags())) {
>> +        Value *NewV = (FinalOpcode == Instruction::FAdd) ? createFAdd(A, V)
>> +                                                         : createFSub(A, V);
>> +        FastMathFlags Flags;
>> +        Flags.setUnsafeAlgebra();
>> +        Flags &= I->getFastMathFlags();
>> +        Instruction *NewI = cast<Instruction>(NewV);
>> +        NewI->setFastMathFlags(Flags);
>> +        return NewI;
>> +      }
>> +    }
>> +  }
>> +  {
>> +    // Transform: "A op (B op C)" ==> "(A op B) op C" if "A op B" factorizes.
>> +    if (Op1 && (Op1->getOpcode() == Instruction::FAdd ||
>> +                Op1->getOpcode() == Instruction::FSub)) {
>> +      unsigned FactorizeOpcode, FinalOpcode;
>> +      bool IsOp1OpcodeAdd = (Op1->getOpcode() == Instruction::FAdd);
>> +      bool IsIOpcodeAdd = (I->getOpcode() == Instruction::FAdd);
>> +      Value *A = I->getOperand(0);
>> +      Value *B = Op1->getOperand(0);
>> +      Value *C = Op1->getOperand(1);
>> +      // A + (B+C) -> (A + B) + C factorizes?
>> +      if (IsIOpcodeAdd && IsOp1OpcodeAdd) {
>> +        FactorizeOpcode = FinalOpcode = Instruction::FAdd;
>> +      }
>> +      // A + (B - C) -> (A + B) - C factorizes?
>> +      if (IsIOpcodeAdd && !IsOp1OpcodeAdd) {
>> +        FactorizeOpcode = Instruction::FAdd;
>> +        FinalOpcode = Instruction::FSub;
>> +      }
>> +      // A - (B + C) -> (A - B) - C factorizes?
>> +      if (!IsIOpcodeAdd && IsOp1OpcodeAdd) {
>> +        FactorizeOpcode = FinalOpcode = Instruction::FSub;
>> +      }
>> +      // A - (B - C) -> (A - B) + C factorizes?
>> +      if (!IsIOpcodeAdd && !IsOp1OpcodeAdd) {
>> +        FactorizeOpcode = Instruction::FSub;
>> +        FinalOpcode = Instruction::FAdd;
>> +      }
>> +      if (Value *V = performFactorization(A, B, FactorizeOpcode,
>> +                                          I->getFastMathFlags())) {
>> +        Value *NewV = (FinalOpcode == Instruction::FAdd) ? createFAdd(V, C)
>> +                                                         : createFSub(V, C);
>> +        FastMathFlags Flags;
>> +        Flags.setUnsafeAlgebra();
>> +        Flags &= I->getFastMathFlags();
>> +        Instruction *NewI = cast<Instruction>(NewV);
>> +        NewI->setFastMathFlags(Flags);
>> +        return NewI;
>> +      }
>> +    }
>> +  }
>> +  {
>> +    // We know that op1 and op2 can only be FAdd or FSub
>> +    // (A op1 B) op2 C -> (A op2 C) op1 B factorizes?
>> +    if (Op0 && (Op0->getOpcode() == Instruction::FAdd ||
>> +                Op0->getOpcode() == Instruction::FSub)) {
>> +      Value *A = Op0->getOperand(0);
>> +      Value *B = Op0->getOperand(1);
>> +      Value *C = I->getOperand(1);
>> +      if (Value *V = performFactorization(A, C, I->getOpcode(),
>> +                                          I->getFastMathFlags())) {
>> +        Value *NewV = (Op0->getOpcode() == Instruction::FAdd)
>> +                          ? createFAdd(V, B)
>> +                          : createFSub(V, B);
>> +        FastMathFlags Flags;
>> +        Flags.setUnsafeAlgebra();
>> +        Flags &= I->getFastMathFlags();
>> +        Instruction *NewI = cast<Instruction>(NewV);
>> +        NewI->setFastMathFlags(Flags);
>> +        return NewI;
>> +      }
>> +    }
>> +  }
>> +  {
>> +    // A op1 (B op2 C) -> (A op2 C) op1 B factorizes?
>> +    if (Op1 && (Op1->getOpcode() == Instruction::FAdd ||
>> +                Op1->getOpcode() == Instruction::FSub)) {
>> +      Value *A = I->getOperand(0);
>> +      Value *B = Op1->getOperand(0);
>> +      Value *C = Op1->getOperand(1);
>> +      unsigned FactorizeOpcode, FinalOpcode;
>> +      bool IsOp1OpcodeAdd = (Op1->getOpcode() == Instruction::FAdd);
>> +      bool IsIOpcodeAdd = (I->getOpcode() == Instruction::FAdd);
>> +      // A + (B + C) -> (A + C) + B simplifies?
>> +      // A + (B - C) -> (A - C) + B simplifies?
>> +      if (IsIOpcodeAdd) {
>> +        FactorizeOpcode = Op1->getOpcode();
>> +        FinalOpcode = Instruction::FAdd;
>> +      }
>> +      // A - (B + C) -> (A - C) - B
>> +      else if (IsOp1OpcodeAdd) {
>> +        FactorizeOpcode = FinalOpcode = Instruction::FSub;
>> +      } else {
>> +        // A - (B - C) -> (A + C) - B
>> +        FactorizeOpcode = Instruction::FAdd;
>> +        FinalOpcode = Instruction::FSub;
>> +      }
>> +      if (Value *V = performFactorization(A, C, FactorizeOpcode,
>> +                                          I->getFastMathFlags())) {
>> +        Value *NewV = (FinalOpcode == Instruction::FAdd) ? createFAdd(V, B)
>> +                                                         : createFSub(V, B);
>> +        FastMathFlags Flags;
>> +        Flags.setUnsafeAlgebra();
>> +        Flags &= I->getFastMathFlags();
>> +        Instruction *NewI = cast<Instruction>(NewV);
>> +        NewI->setFastMathFlags(Flags);
>> +        return NewI;
>> +      }
>> +    }
>> +  }
>> +  return nullptr;
>> +}



More information about the llvm-commits mailing list