@@ -6869,165 +6869,3 @@ bool InsertBranchOpt::runOnFunction(Function &F) {
68696869
68706870 return false ;
68716871}
6872-
6873- // Canonicalize y*(x+1) => y*x+y. This will emit mad on supported platforms.
6874- // This pass is dedicated to run after instcombine, which transforms x*y+y => y*(x+1).
6875- namespace {
6876- class CanonicalizeMulAdd : public FunctionPass {
6877- public:
6878- static char ID;
6879- CanonicalizeMulAdd ();
6880-
6881- StringRef getPassName () const override { return " CanonicalizeMulAdd" ; }
6882-
6883- bool runOnFunction (Function &F) override ;
6884-
6885- private:
6886- bool visit (BasicBlock &BB);
6887- bool visitOneMad (Instruction &I);
6888- bool visitTwoMads (Instruction &I);
6889- bool visitRotate (Instruction &I);
6890- };
6891- } // namespace
6892-
6893- IGC_INITIALIZE_PASS_BEGIN (CanonicalizeMulAdd, " igc-canonicalize-mul-add" , " Canonicalize MulAdd" , false , false )
6894- IGC_INITIALIZE_PASS_END(CanonicalizeMulAdd, " igc-canonicalize-mul-add" , " Canonicalize MulAdd" , false , false )
6895-
6896- char CanonicalizeMulAdd::ID = 0;
6897- FunctionPass *IGC::createCanonicalizeMulAddPass () { return new CanonicalizeMulAdd (); }
6898-
6899- CanonicalizeMulAdd::CanonicalizeMulAdd () : FunctionPass(ID) {
6900- initializeCanonicalizeMulAddPass (*PassRegistry::getPassRegistry ());
6901- }
6902-
6903- bool CanonicalizeMulAdd::runOnFunction (Function &F) {
6904- bool Changed = false ;
6905- for (auto &BB : llvm::reverse (F))
6906- Changed |= visit (BB);
6907- return Changed;
6908- }
6909-
6910- bool CanonicalizeMulAdd::visit (BasicBlock &BB) {
6911-
6912- llvm::SmallVector<Instruction *, 8 > Replaced;
6913-
6914- for (auto II = BB.rbegin (), IE = BB.rend (); II != IE; ++II) {
6915-
6916- if (!II->getType ()->isIntegerTy () || II->getOpcode () != Instruction::Mul)
6917- continue ;
6918-
6919- if (visitTwoMads (*II) || visitOneMad (*II) || visitRotate (*II))
6920- Replaced.push_back (&*II);
6921- }
6922-
6923- for (auto *I : Replaced)
6924- RecursivelyDeleteTriviallyDeadInstructions (I);
6925-
6926- return !Replaced.empty ();
6927- }
6928-
6929- // x * (y + 1) => x*y + x
6930- // x * (y - 1) => x*y - x
6931- bool CanonicalizeMulAdd::visitOneMad (Instruction &I) {
6932- using namespace llvm ::PatternMatch;
6933-
6934- Value *X = nullptr , *Y = nullptr ;
6935- ConstantInt *CI = nullptr ;
6936-
6937- // sub1, sub2, since order of operands matters for sub
6938- bool IsAdd = match (&I, m_c_Mul (m_Value (X), m_c_Add (m_Value (Y), m_ConstantInt (CI))));
6939- bool IsSub1 = IsAdd ? false : match (&I, m_c_Mul (m_Value (X), m_Sub (m_Value (Y), m_ConstantInt (CI))));
6940- bool IsSub2 = IsAdd || IsSub1 ? false : match (&I, m_c_Mul (m_Value (X), m_Sub (m_One (), m_Value (Y))));
6941-
6942- if (!IsAdd && !IsSub1 && !IsSub2)
6943- return false ;
6944-
6945- if (!IsSub2 && !CI->isOne () && !CI->isMinusOne ())
6946- return false ;
6947-
6948- auto Opcode = (IsAdd && CI->isMinusOne () || IsSub1 && CI->isOne () || IsSub2) ? Instruction::Sub : Instruction::Add;
6949-
6950- llvm::IRBuilder<> Builder (&I);
6951-
6952- auto *Op1 = Builder.CreateMul (X, Y);
6953- auto *Op2 = X;
6954-
6955- if (IsSub2)
6956- std::swap (Op1, Op2);
6957-
6958- I.replaceAllUsesWith (Builder.CreateBinOp (Opcode, Op1, Op2));
6959- return true ;
6960- }
6961-
6962- // Check for pattern of two consecutive mads.
6963- // Example:
6964- // x * ((y + 1) * (z + 1))
6965- // Output:
6966- // mad1 = x*y + x
6967- // mad2 = mad1*z + mad1
6968- // Constant can be either 1 or -1
6969- bool CanonicalizeMulAdd::visitTwoMads (Instruction &I) {
6970- using namespace llvm ::PatternMatch;
6971-
6972- Value *Mul = nullptr , *LHS = nullptr , *RHS = nullptr ;
6973- ConstantInt *LHSConst = nullptr , *RHSConst = nullptr ;
6974-
6975- if (!match (&I, m_c_Mul (m_Value (Mul), m_Mul (m_c_Add (m_Value (LHS), m_ConstantInt (LHSConst)),
6976- m_c_Add (m_Value (RHS), m_ConstantInt (RHSConst))))))
6977- return false ;
6978-
6979- if (!LHSConst->isOne () && !LHSConst->isMinusOne ())
6980- return false ;
6981-
6982- if (!RHSConst->isOne () && !RHSConst->isMinusOne ())
6983- return false ;
6984-
6985- // For consistency with instcombine, first do side not equal to Mul.
6986- if (match (Mul, m_Specific (LHS))) {
6987- std::swap (LHS, RHS);
6988- std::swap (LHSConst, RHSConst);
6989- }
6990-
6991- auto Op1 = LHSConst->isOne () ? Instruction::Add : Instruction::Sub;
6992- auto Op2 = RHSConst->isOne () ? Instruction::Add : Instruction::Sub;
6993-
6994- llvm::IRBuilder<> Builder (&I);
6995- auto *Mad1 = Builder.CreateBinOp (Op1, Builder.CreateMul (Mul, LHS), Mul);
6996- auto *Mad2 = Builder.CreateBinOp (Op2, Builder.CreateMul (Mad1, RHS), Mad1);
6997-
6998- I.replaceAllUsesWith (Mad2);
6999- return true ;
7000- }
7001-
7002- // Pattern: x * (y + z)
7003- // If y=x*z, then it is better to rotate instructions to: y*x + y
7004- // This allows to emit more mads if y=x*z is also optimized later.
7005- bool CanonicalizeMulAdd::visitRotate (Instruction &I) {
7006- using namespace llvm ::PatternMatch;
7007-
7008- Value *Mul = nullptr , *LHS = nullptr , *RHS = nullptr ;
7009-
7010- bool IsAdd = match (&I, m_c_Mul (m_Value (Mul), m_c_Add (m_Value (LHS), m_Value (RHS))));
7011- bool IsSub = IsAdd ? false : match (&I, m_c_Mul (m_Value (Mul), m_Sub (m_Value (LHS), m_Value (RHS))));
7012-
7013- if (!IsAdd && !IsSub)
7014- return false ;
7015-
7016- bool UseLHS = match (LHS, m_c_Mul (m_Specific (Mul), m_Specific (RHS)));
7017- bool UseRHS = UseLHS ? false : match (RHS, m_c_Mul (m_Specific (Mul), m_Specific (LHS)));
7018-
7019- if (!UseLHS && !UseRHS)
7020- return false ;
7021-
7022- llvm::IRBuilder<> Builder (&I);
7023-
7024- auto *Op1 = Builder.CreateMul (UseLHS ? LHS : RHS, Mul);
7025- auto *Op2 = UseLHS ? LHS : RHS;
7026-
7027- // since order of operands matters for sub
7028- if (IsSub && UseRHS)
7029- std::swap (Op1, Op2);
7030-
7031- I.replaceAllUsesWith (Builder.CreateBinOp (IsAdd ? Instruction::Add : Instruction::Sub, Op1, Op2));
7032- return true ;
7033- }
0 commit comments