[PATCH] D12096: [InstCombineAddSub opportunities]: More opportunities to factorize FAdd/FSub when unsafeAlgebra is present for Inst
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 20 17:53:05 PDT 2015
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.
> + 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