19f7d4150SCraig Topper //===-- X86PartialReduction.cpp -------------------------------------------===//
29f7d4150SCraig Topper //
39f7d4150SCraig Topper // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49f7d4150SCraig Topper // See https://llvm.org/LICENSE.txt for license information.
59f7d4150SCraig Topper // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69f7d4150SCraig Topper //
79f7d4150SCraig Topper //===----------------------------------------------------------------------===//
89f7d4150SCraig Topper //
99f7d4150SCraig Topper // This pass looks for add instructions used by a horizontal reduction to see
109f7d4150SCraig Topper // if we might be able to use pmaddwd or psadbw. Some cases of this require
119f7d4150SCraig Topper // cross basic block knowledge and can't be done in SelectionDAG.
129f7d4150SCraig Topper //
139f7d4150SCraig Topper //===----------------------------------------------------------------------===//
149f7d4150SCraig Topper 
159f7d4150SCraig Topper #include "X86.h"
169f7d4150SCraig Topper #include "llvm/Analysis/ValueTracking.h"
179f7d4150SCraig Topper #include "llvm/CodeGen/TargetPassConfig.h"
189f7d4150SCraig Topper #include "llvm/IR/Constants.h"
199f7d4150SCraig Topper #include "llvm/IR/Instructions.h"
209f7d4150SCraig Topper #include "llvm/IR/IntrinsicsX86.h"
219f7d4150SCraig Topper #include "llvm/IR/IRBuilder.h"
229f7d4150SCraig Topper #include "llvm/IR/Operator.h"
239f7d4150SCraig Topper #include "llvm/Pass.h"
249f7d4150SCraig Topper #include "X86TargetMachine.h"
259f7d4150SCraig Topper 
269f7d4150SCraig Topper using namespace llvm;
279f7d4150SCraig Topper 
289f7d4150SCraig Topper #define DEBUG_TYPE "x86-partial-reduction"
299f7d4150SCraig Topper 
309f7d4150SCraig Topper namespace {
319f7d4150SCraig Topper 
329f7d4150SCraig Topper class X86PartialReduction : public FunctionPass {
339f7d4150SCraig Topper   const DataLayout *DL;
349f7d4150SCraig Topper   const X86Subtarget *ST;
359f7d4150SCraig Topper 
369f7d4150SCraig Topper public:
379f7d4150SCraig Topper   static char ID; // Pass identification, replacement for typeid.
389f7d4150SCraig Topper 
399f7d4150SCraig Topper   X86PartialReduction() : FunctionPass(ID) { }
409f7d4150SCraig Topper 
419f7d4150SCraig Topper   bool runOnFunction(Function &Fn) override;
429f7d4150SCraig Topper 
439f7d4150SCraig Topper   void getAnalysisUsage(AnalysisUsage &AU) const override {
449f7d4150SCraig Topper     AU.setPreservesCFG();
459f7d4150SCraig Topper   }
469f7d4150SCraig Topper 
479f7d4150SCraig Topper   StringRef getPassName() const override {
489f7d4150SCraig Topper     return "X86 Partial Reduction";
499f7d4150SCraig Topper   }
509f7d4150SCraig Topper 
519f7d4150SCraig Topper private:
52*8abe8300SCraig Topper   bool tryMAddReplacement(Instruction *Op);
53*8abe8300SCraig Topper   bool trySADReplacement(Instruction *Op);
549f7d4150SCraig Topper };
559f7d4150SCraig Topper }
569f7d4150SCraig Topper 
579f7d4150SCraig Topper FunctionPass *llvm::createX86PartialReductionPass() {
589f7d4150SCraig Topper   return new X86PartialReduction();
599f7d4150SCraig Topper }
609f7d4150SCraig Topper 
619f7d4150SCraig Topper char X86PartialReduction::ID = 0;
629f7d4150SCraig Topper 
639f7d4150SCraig Topper INITIALIZE_PASS(X86PartialReduction, DEBUG_TYPE,
649f7d4150SCraig Topper                 "X86 Partial Reduction", false, false)
659f7d4150SCraig Topper 
66*8abe8300SCraig Topper bool X86PartialReduction::tryMAddReplacement(Instruction *Op) {
67*8abe8300SCraig Topper   if (!ST->hasSSE2())
689f7d4150SCraig Topper     return false;
699f7d4150SCraig Topper 
70*8abe8300SCraig Topper   // Need at least 8 elements.
71*8abe8300SCraig Topper   if (cast<VectorType>(Op->getType())->getNumElements() < 8)
729f7d4150SCraig Topper     return false;
739f7d4150SCraig Topper 
74*8abe8300SCraig Topper   // Element type should be i32.
75*8abe8300SCraig Topper   if (!cast<VectorType>(Op->getType())->getElementType()->isIntegerTy(32))
769f7d4150SCraig Topper     return false;
779f7d4150SCraig Topper 
78*8abe8300SCraig Topper   auto *Mul = dyn_cast<BinaryOperator>(Op);
79*8abe8300SCraig Topper   if (!Mul || Mul->getOpcode() != Instruction::Mul)
809f7d4150SCraig Topper     return false;
819f7d4150SCraig Topper 
82*8abe8300SCraig Topper   Value *LHS = Mul->getOperand(0);
83*8abe8300SCraig Topper   Value *RHS = Mul->getOperand(1);
849f7d4150SCraig Topper 
859f7d4150SCraig Topper   // LHS and RHS should be only used once or if they are the same then only
869f7d4150SCraig Topper   // used twice. Only check this when SSE4.1 is enabled and we have zext/sext
879f7d4150SCraig Topper   // instructions, otherwise we use punpck to emulate zero extend in stages. The
889f7d4150SCraig Topper   // trunc/ we need to do likely won't introduce new instructions in that case.
899f7d4150SCraig Topper   if (ST->hasSSE41()) {
909f7d4150SCraig Topper     if (LHS == RHS) {
919f7d4150SCraig Topper       if (!isa<Constant>(LHS) && !LHS->hasNUses(2))
929f7d4150SCraig Topper         return false;
939f7d4150SCraig Topper     } else {
949f7d4150SCraig Topper       if (!isa<Constant>(LHS) && !LHS->hasOneUse())
959f7d4150SCraig Topper         return false;
969f7d4150SCraig Topper       if (!isa<Constant>(RHS) && !RHS->hasOneUse())
979f7d4150SCraig Topper         return false;
989f7d4150SCraig Topper     }
999f7d4150SCraig Topper   }
1009f7d4150SCraig Topper 
1012b0b9b11SCraig Topper   auto CanShrinkOp = [&](Value *Op) {
1022b0b9b11SCraig Topper     auto IsFreeTruncation = [&](Value *Op) {
1039f7d4150SCraig Topper       if (auto *Cast = dyn_cast<CastInst>(Op)) {
104*8abe8300SCraig Topper         if (Cast->getParent() == Mul->getParent() &&
1059f7d4150SCraig Topper             (Cast->getOpcode() == Instruction::SExt ||
1069f7d4150SCraig Topper              Cast->getOpcode() == Instruction::ZExt) &&
1072b0b9b11SCraig Topper             Cast->getOperand(0)->getType()->getScalarSizeInBits() <= 16)
1082b0b9b11SCraig Topper           return true;
1092b0b9b11SCraig Topper       }
1102b0b9b11SCraig Topper 
1112b0b9b11SCraig Topper       return isa<Constant>(Op);
1122b0b9b11SCraig Topper     };
1132b0b9b11SCraig Topper 
1142b0b9b11SCraig Topper     // If the operation can be freely truncated and has enough sign bits we
1152b0b9b11SCraig Topper     // can shrink.
1162b0b9b11SCraig Topper     if (IsFreeTruncation(Op) &&
117*8abe8300SCraig Topper         ComputeNumSignBits(Op, *DL, 0, nullptr, Mul) > 16)
1182b0b9b11SCraig Topper       return true;
1192b0b9b11SCraig Topper 
1202b0b9b11SCraig Topper     // SelectionDAG has limited support for truncating through an add or sub if
1212b0b9b11SCraig Topper     // the inputs are freely truncatable.
1222b0b9b11SCraig Topper     if (auto *BO = dyn_cast<BinaryOperator>(Op)) {
123*8abe8300SCraig Topper       if (BO->getParent() == Mul->getParent() &&
1242b0b9b11SCraig Topper           IsFreeTruncation(BO->getOperand(0)) &&
1252b0b9b11SCraig Topper           IsFreeTruncation(BO->getOperand(1)) &&
126*8abe8300SCraig Topper           ComputeNumSignBits(Op, *DL, 0, nullptr, Mul) > 16)
1279f7d4150SCraig Topper         return true;
1289f7d4150SCraig Topper     }
1299f7d4150SCraig Topper 
1309f7d4150SCraig Topper     return false;
1319f7d4150SCraig Topper   };
1329f7d4150SCraig Topper 
1339f7d4150SCraig Topper   // Both Ops need to be shrinkable.
1342b0b9b11SCraig Topper   if (!CanShrinkOp(LHS) && !CanShrinkOp(RHS))
1359f7d4150SCraig Topper     return false;
1369f7d4150SCraig Topper 
137*8abe8300SCraig Topper   IRBuilder<> Builder(Mul);
1389f7d4150SCraig Topper 
139dd24fb38SChristopher Tetreault   auto *MulTy = cast<VectorType>(Op->getType());
140dd24fb38SChristopher Tetreault   unsigned NumElts = MulTy->getNumElements();
1419f7d4150SCraig Topper 
1429f7d4150SCraig Topper   // Extract even elements and odd elements and add them together. This will
1439f7d4150SCraig Topper   // be pattern matched by SelectionDAG to pmaddwd. This instruction will be
1449f7d4150SCraig Topper   // half the original width.
1456f64dacaSBenjamin Kramer   SmallVector<int, 16> EvenMask(NumElts / 2);
1466f64dacaSBenjamin Kramer   SmallVector<int, 16> OddMask(NumElts / 2);
1479f7d4150SCraig Topper   for (int i = 0, e = NumElts / 2; i != e; ++i) {
1489f7d4150SCraig Topper     EvenMask[i] = i * 2;
1499f7d4150SCraig Topper     OddMask[i] = i * 2 + 1;
1509f7d4150SCraig Topper   }
151*8abe8300SCraig Topper   // Creating a new mul so the replaceAllUsesWith below doesn't replace the
152*8abe8300SCraig Topper   // uses in the shuffles we're creating.
153*8abe8300SCraig Topper   Value *NewMul = Builder.CreateMul(Mul->getOperand(0), Mul->getOperand(1));
154*8abe8300SCraig Topper   Value *EvenElts = Builder.CreateShuffleVector(NewMul, NewMul, EvenMask);
155*8abe8300SCraig Topper   Value *OddElts = Builder.CreateShuffleVector(NewMul, NewMul, OddMask);
1569f7d4150SCraig Topper   Value *MAdd = Builder.CreateAdd(EvenElts, OddElts);
1579f7d4150SCraig Topper 
1589f7d4150SCraig Topper   // Concatenate zeroes to extend back to the original type.
1596f64dacaSBenjamin Kramer   SmallVector<int, 32> ConcatMask(NumElts);
1609f7d4150SCraig Topper   std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
1619f7d4150SCraig Topper   Value *Zero = Constant::getNullValue(MAdd->getType());
1629f7d4150SCraig Topper   Value *Concat = Builder.CreateShuffleVector(MAdd, Zero, ConcatMask);
1639f7d4150SCraig Topper 
164*8abe8300SCraig Topper   Mul->replaceAllUsesWith(Concat);
165*8abe8300SCraig Topper   Mul->eraseFromParent();
1669f7d4150SCraig Topper 
1679f7d4150SCraig Topper   return true;
1689f7d4150SCraig Topper }
1699f7d4150SCraig Topper 
170*8abe8300SCraig Topper bool X86PartialReduction::trySADReplacement(Instruction *Op) {
1719f7d4150SCraig Topper   if (!ST->hasSSE2())
1729f7d4150SCraig Topper     return false;
1739f7d4150SCraig Topper 
174*8abe8300SCraig Topper   // TODO: There's nothing special about i32, any integer type above i16 should
175*8abe8300SCraig Topper   // work just as well.
176*8abe8300SCraig Topper   if (!cast<VectorType>(Op->getType())->getElementType()->isIntegerTy(32))
1779f7d4150SCraig Topper     return false;
1789f7d4150SCraig Topper 
1799f7d4150SCraig Topper   // Operand should be a select.
1809f7d4150SCraig Topper   auto *SI = dyn_cast<SelectInst>(Op);
1819f7d4150SCraig Topper   if (!SI)
1829f7d4150SCraig Topper     return false;
1839f7d4150SCraig Topper 
1849f7d4150SCraig Topper   // Select needs to implement absolute value.
1859f7d4150SCraig Topper   Value *LHS, *RHS;
1869f7d4150SCraig Topper   auto SPR = matchSelectPattern(SI, LHS, RHS);
1879f7d4150SCraig Topper   if (SPR.Flavor != SPF_ABS)
1889f7d4150SCraig Topper     return false;
1899f7d4150SCraig Topper 
1909f7d4150SCraig Topper   // Need a subtract of two values.
1919f7d4150SCraig Topper   auto *Sub = dyn_cast<BinaryOperator>(LHS);
1929f7d4150SCraig Topper   if (!Sub || Sub->getOpcode() != Instruction::Sub)
1939f7d4150SCraig Topper     return false;
1949f7d4150SCraig Topper 
1959f7d4150SCraig Topper   // Look for zero extend from i8.
1969f7d4150SCraig Topper   auto getZeroExtendedVal = [](Value *Op) -> Value * {
1979f7d4150SCraig Topper     if (auto *ZExt = dyn_cast<ZExtInst>(Op))
198dd24fb38SChristopher Tetreault       if (cast<VectorType>(ZExt->getOperand(0)->getType())
199dd24fb38SChristopher Tetreault               ->getElementType()
200dd24fb38SChristopher Tetreault               ->isIntegerTy(8))
2019f7d4150SCraig Topper         return ZExt->getOperand(0);
2029f7d4150SCraig Topper 
2039f7d4150SCraig Topper     return nullptr;
2049f7d4150SCraig Topper   };
2059f7d4150SCraig Topper 
2069f7d4150SCraig Topper   // Both operands of the subtract should be extends from vXi8.
2079f7d4150SCraig Topper   Value *Op0 = getZeroExtendedVal(Sub->getOperand(0));
2089f7d4150SCraig Topper   Value *Op1 = getZeroExtendedVal(Sub->getOperand(1));
2099f7d4150SCraig Topper   if (!Op0 || !Op1)
2109f7d4150SCraig Topper     return false;
2119f7d4150SCraig Topper 
212*8abe8300SCraig Topper   IRBuilder<> Builder(SI);
2139f7d4150SCraig Topper 
214dd24fb38SChristopher Tetreault   auto *OpTy = cast<VectorType>(Op->getType());
215dd24fb38SChristopher Tetreault   unsigned NumElts = OpTy->getNumElements();
2169f7d4150SCraig Topper 
2179f7d4150SCraig Topper   unsigned IntrinsicNumElts;
2189f7d4150SCraig Topper   Intrinsic::ID IID;
2199f7d4150SCraig Topper   if (ST->hasBWI() && NumElts >= 64) {
2209f7d4150SCraig Topper     IID = Intrinsic::x86_avx512_psad_bw_512;
2219f7d4150SCraig Topper     IntrinsicNumElts = 64;
2229f7d4150SCraig Topper   } else if (ST->hasAVX2() && NumElts >= 32) {
2239f7d4150SCraig Topper     IID = Intrinsic::x86_avx2_psad_bw;
2249f7d4150SCraig Topper     IntrinsicNumElts = 32;
2259f7d4150SCraig Topper   } else {
2269f7d4150SCraig Topper     IID = Intrinsic::x86_sse2_psad_bw;
2279f7d4150SCraig Topper     IntrinsicNumElts = 16;
2289f7d4150SCraig Topper   }
2299f7d4150SCraig Topper 
230*8abe8300SCraig Topper   Function *PSADBWFn = Intrinsic::getDeclaration(SI->getModule(), IID);
2319f7d4150SCraig Topper 
2329f7d4150SCraig Topper   if (NumElts < 16) {
2339f7d4150SCraig Topper     // Pad input with zeroes.
2346f64dacaSBenjamin Kramer     SmallVector<int, 32> ConcatMask(16);
2359f7d4150SCraig Topper     for (unsigned i = 0; i != NumElts; ++i)
2369f7d4150SCraig Topper       ConcatMask[i] = i;
2379f7d4150SCraig Topper     for (unsigned i = NumElts; i != 16; ++i)
2389f7d4150SCraig Topper       ConcatMask[i] = (i % NumElts) + NumElts;
2399f7d4150SCraig Topper 
2409f7d4150SCraig Topper     Value *Zero = Constant::getNullValue(Op0->getType());
2419f7d4150SCraig Topper     Op0 = Builder.CreateShuffleVector(Op0, Zero, ConcatMask);
2429f7d4150SCraig Topper     Op1 = Builder.CreateShuffleVector(Op1, Zero, ConcatMask);
2439f7d4150SCraig Topper     NumElts = 16;
2449f7d4150SCraig Topper   }
2459f7d4150SCraig Topper 
2469f7d4150SCraig Topper   // Intrinsics produce vXi64 and need to be casted to vXi32.
2475a99ec10SChristopher Tetreault   auto *I32Ty =
2485a99ec10SChristopher Tetreault       FixedVectorType::get(Builder.getInt32Ty(), IntrinsicNumElts / 4);
2499f7d4150SCraig Topper 
2509f7d4150SCraig Topper   assert(NumElts % IntrinsicNumElts == 0 && "Unexpected number of elements!");
2519f7d4150SCraig Topper   unsigned NumSplits = NumElts / IntrinsicNumElts;
2529f7d4150SCraig Topper 
2539f7d4150SCraig Topper   // First collect the pieces we need.
2549f7d4150SCraig Topper   SmallVector<Value *, 4> Ops(NumSplits);
2559f7d4150SCraig Topper   for (unsigned i = 0; i != NumSplits; ++i) {
2566f64dacaSBenjamin Kramer     SmallVector<int, 64> ExtractMask(IntrinsicNumElts);
2579f7d4150SCraig Topper     std::iota(ExtractMask.begin(), ExtractMask.end(), i * IntrinsicNumElts);
2589f7d4150SCraig Topper     Value *ExtractOp0 = Builder.CreateShuffleVector(Op0, Op0, ExtractMask);
2599f7d4150SCraig Topper     Value *ExtractOp1 = Builder.CreateShuffleVector(Op1, Op0, ExtractMask);
2609f7d4150SCraig Topper     Ops[i] = Builder.CreateCall(PSADBWFn, {ExtractOp0, ExtractOp1});
2619f7d4150SCraig Topper     Ops[i] = Builder.CreateBitCast(Ops[i], I32Ty);
2629f7d4150SCraig Topper   }
2639f7d4150SCraig Topper 
2649f7d4150SCraig Topper   assert(isPowerOf2_32(NumSplits) && "Expected power of 2 splits");
2659f7d4150SCraig Topper   unsigned Stages = Log2_32(NumSplits);
2669f7d4150SCraig Topper   for (unsigned s = Stages; s > 0; --s) {
267dd24fb38SChristopher Tetreault     unsigned NumConcatElts =
268dd24fb38SChristopher Tetreault         cast<VectorType>(Ops[0]->getType())->getNumElements() * 2;
269d2dd0facSMichael Liao     for (unsigned i = 0; i != 1U << (s - 1); ++i) {
2706f64dacaSBenjamin Kramer       SmallVector<int, 64> ConcatMask(NumConcatElts);
2719f7d4150SCraig Topper       std::iota(ConcatMask.begin(), ConcatMask.end(), 0);
2729f7d4150SCraig Topper       Ops[i] = Builder.CreateShuffleVector(Ops[i*2], Ops[i*2+1], ConcatMask);
2739f7d4150SCraig Topper     }
2749f7d4150SCraig Topper   }
2759f7d4150SCraig Topper 
2769f7d4150SCraig Topper   // At this point the final value should be in Ops[0]. Now we need to adjust
2779f7d4150SCraig Topper   // it to the final original type.
278dd24fb38SChristopher Tetreault   NumElts = cast<VectorType>(OpTy)->getNumElements();
2799f7d4150SCraig Topper   if (NumElts == 2) {
2809f7d4150SCraig Topper     // Extract down to 2 elements.
2811ee6ec2bSEli Friedman     Ops[0] = Builder.CreateShuffleVector(Ops[0], Ops[0], ArrayRef<int>{0, 1});
2829f7d4150SCraig Topper   } else if (NumElts >= 8) {
2836f64dacaSBenjamin Kramer     SmallVector<int, 32> ConcatMask(NumElts);
284dd24fb38SChristopher Tetreault     unsigned SubElts = cast<VectorType>(Ops[0]->getType())->getNumElements();
2859f7d4150SCraig Topper     for (unsigned i = 0; i != SubElts; ++i)
2869f7d4150SCraig Topper       ConcatMask[i] = i;
2879f7d4150SCraig Topper     for (unsigned i = SubElts; i != NumElts; ++i)
2889f7d4150SCraig Topper       ConcatMask[i] = (i % SubElts) + SubElts;
2899f7d4150SCraig Topper 
2909f7d4150SCraig Topper     Value *Zero = Constant::getNullValue(Ops[0]->getType());
2919f7d4150SCraig Topper     Ops[0] = Builder.CreateShuffleVector(Ops[0], Zero, ConcatMask);
2929f7d4150SCraig Topper   }
2939f7d4150SCraig Topper 
294*8abe8300SCraig Topper   SI->replaceAllUsesWith(Ops[0]);
295*8abe8300SCraig Topper   SI->eraseFromParent();
2969f7d4150SCraig Topper 
297fa8c2ae7SCraig Topper   return true;
2989f7d4150SCraig Topper }
2999f7d4150SCraig Topper 
300*8abe8300SCraig Topper // Walk backwards from the ExtractElementInst and determine if it is the end of
301*8abe8300SCraig Topper // a horizontal reduction. Return the input to the reduction if we find one.
302*8abe8300SCraig Topper static Value *matchAddReduction(const ExtractElementInst &EE) {
303*8abe8300SCraig Topper   // Make sure we're extracting index 0.
304*8abe8300SCraig Topper   auto *Index = dyn_cast<ConstantInt>(EE.getIndexOperand());
305*8abe8300SCraig Topper   if (!Index || !Index->isNullValue())
306*8abe8300SCraig Topper     return nullptr;
307*8abe8300SCraig Topper 
308*8abe8300SCraig Topper   const auto *BO = dyn_cast<BinaryOperator>(EE.getVectorOperand());
309*8abe8300SCraig Topper   if (!BO || BO->getOpcode() != Instruction::Add || !BO->hasOneUse())
310*8abe8300SCraig Topper     return nullptr;
311*8abe8300SCraig Topper 
312*8abe8300SCraig Topper   unsigned NumElems = cast<VectorType>(BO->getType())->getNumElements();
313*8abe8300SCraig Topper   // Ensure the reduction size is a power of 2.
314*8abe8300SCraig Topper   if (!isPowerOf2_32(NumElems))
315*8abe8300SCraig Topper     return nullptr;
316*8abe8300SCraig Topper 
317*8abe8300SCraig Topper   const Value *Op = BO;
318*8abe8300SCraig Topper   unsigned Stages = Log2_32(NumElems);
319*8abe8300SCraig Topper   for (unsigned i = 0; i != Stages; ++i) {
320*8abe8300SCraig Topper     const auto *BO = dyn_cast<BinaryOperator>(Op);
321*8abe8300SCraig Topper     if (!BO || BO->getOpcode() != Instruction::Add)
322*8abe8300SCraig Topper       return nullptr;
323*8abe8300SCraig Topper 
324*8abe8300SCraig Topper     // If this isn't the first add, then it should only have 2 users, the
325*8abe8300SCraig Topper     // shuffle and another add which we checked in the previous iteration.
326*8abe8300SCraig Topper     if (i != 0 && !BO->hasNUses(2))
327*8abe8300SCraig Topper       return nullptr;
328*8abe8300SCraig Topper 
329*8abe8300SCraig Topper     Value *LHS = BO->getOperand(0);
330*8abe8300SCraig Topper     Value *RHS = BO->getOperand(1);
331*8abe8300SCraig Topper 
332*8abe8300SCraig Topper     auto *Shuffle = dyn_cast<ShuffleVectorInst>(LHS);
333*8abe8300SCraig Topper     if (Shuffle) {
334*8abe8300SCraig Topper       Op = RHS;
335*8abe8300SCraig Topper     } else {
336*8abe8300SCraig Topper       Shuffle = dyn_cast<ShuffleVectorInst>(RHS);
337*8abe8300SCraig Topper       Op = LHS;
338*8abe8300SCraig Topper     }
339*8abe8300SCraig Topper 
340*8abe8300SCraig Topper     // The first operand of the shuffle should be the same as the other operand
341*8abe8300SCraig Topper     // of the bin op.
342*8abe8300SCraig Topper     if (!Shuffle || Shuffle->getOperand(0) != Op)
343*8abe8300SCraig Topper       return nullptr;
344*8abe8300SCraig Topper 
345*8abe8300SCraig Topper     // Verify the shuffle has the expected (at this stage of the pyramid) mask.
346*8abe8300SCraig Topper     unsigned MaskEnd = 1 << i;
347*8abe8300SCraig Topper     for (unsigned Index = 0; Index < MaskEnd; ++Index)
348*8abe8300SCraig Topper       if (Shuffle->getMaskValue(Index) != (int)(MaskEnd + Index))
349*8abe8300SCraig Topper         return nullptr;
350*8abe8300SCraig Topper   }
351*8abe8300SCraig Topper 
352*8abe8300SCraig Topper   return const_cast<Value *>(Op);
353*8abe8300SCraig Topper }
354*8abe8300SCraig Topper 
355*8abe8300SCraig Topper // See if this BO is reachable from this Phi by walking forward through single
356*8abe8300SCraig Topper // use BinaryOperators with the same opcode. If we get back then we know we've
357*8abe8300SCraig Topper // found a loop and it is safe to step through this Add to find more leaves.
358*8abe8300SCraig Topper static bool isReachableFromPHI(PHINode *Phi, BinaryOperator *BO) {
359*8abe8300SCraig Topper   // The PHI itself should only have one use.
360*8abe8300SCraig Topper   if (!Phi->hasOneUse())
3619f7d4150SCraig Topper     return false;
3629f7d4150SCraig Topper 
363*8abe8300SCraig Topper   Instruction *U = cast<Instruction>(*Phi->user_begin());
364*8abe8300SCraig Topper   if (U == BO)
365*8abe8300SCraig Topper     return true;
3669f7d4150SCraig Topper 
367*8abe8300SCraig Topper   while (U->hasOneUse() && U->getOpcode() == BO->getOpcode())
368*8abe8300SCraig Topper     U = cast<Instruction>(*U->user_begin());
369*8abe8300SCraig Topper 
370*8abe8300SCraig Topper   return U == BO;
371*8abe8300SCraig Topper }
372*8abe8300SCraig Topper 
373*8abe8300SCraig Topper // Collect all the leaves of the tree of adds that feeds into the horizontal
374*8abe8300SCraig Topper // reduction. Root is the Value that is used by the horizontal reduction.
375*8abe8300SCraig Topper // We look through single use phis, single use adds, or adds that are used by
376*8abe8300SCraig Topper // a phi that forms a loop with the add.
377*8abe8300SCraig Topper static void collectLeaves(Value *Root, SmallVectorImpl<Instruction *> &Leaves) {
378*8abe8300SCraig Topper   SmallPtrSet<Value *, 8> Visited;
379*8abe8300SCraig Topper   SmallVector<Value *, 8> Worklist;
380*8abe8300SCraig Topper   Worklist.push_back(Root);
381*8abe8300SCraig Topper 
382*8abe8300SCraig Topper   while (!Worklist.empty()) {
383*8abe8300SCraig Topper     Value *V = Worklist.pop_back_val();
384*8abe8300SCraig Topper      if (!Visited.insert(V).second)
385*8abe8300SCraig Topper        continue;
386*8abe8300SCraig Topper 
387*8abe8300SCraig Topper     if (auto *PN = dyn_cast<PHINode>(V)) {
388*8abe8300SCraig Topper       // PHI node should have single use unless it is the root node, then it
389*8abe8300SCraig Topper       // has 2 uses.
390*8abe8300SCraig Topper       if (!PN->hasNUses(PN == Root ? 2 : 1))
391*8abe8300SCraig Topper         break;
392*8abe8300SCraig Topper 
393*8abe8300SCraig Topper       // Push incoming values to the worklist.
394*8abe8300SCraig Topper       for (Value *InV : PN->incoming_values())
395*8abe8300SCraig Topper         Worklist.push_back(InV);
396*8abe8300SCraig Topper 
397*8abe8300SCraig Topper       continue;
398*8abe8300SCraig Topper     }
399*8abe8300SCraig Topper 
400*8abe8300SCraig Topper     if (auto *BO = dyn_cast<BinaryOperator>(V)) {
401*8abe8300SCraig Topper       if (BO->getOpcode() == Instruction::Add) {
402*8abe8300SCraig Topper         // Simple case. Single use, just push its operands to the worklist.
403*8abe8300SCraig Topper         if (BO->hasNUses(BO == Root ? 2 : 1)) {
404*8abe8300SCraig Topper           for (Value *Op : BO->operands())
405*8abe8300SCraig Topper             Worklist.push_back(Op);
406*8abe8300SCraig Topper           continue;
407*8abe8300SCraig Topper         }
408*8abe8300SCraig Topper 
409*8abe8300SCraig Topper         // If there is additional use, make sure it is an unvisited phi that
410*8abe8300SCraig Topper         // gets us back to this node.
411*8abe8300SCraig Topper         if (BO->hasNUses(BO == Root ? 3 : 2)) {
412*8abe8300SCraig Topper           PHINode *PN = nullptr;
413*8abe8300SCraig Topper           for (auto *U : Root->users())
414*8abe8300SCraig Topper             if (auto *P = dyn_cast<PHINode>(U))
415*8abe8300SCraig Topper               if (!Visited.count(P))
416*8abe8300SCraig Topper                 PN = P;
417*8abe8300SCraig Topper 
418*8abe8300SCraig Topper           // If we didn't find a 2-input PHI then this isn't a case we can
419*8abe8300SCraig Topper           // handle.
420*8abe8300SCraig Topper           if (!PN || PN->getNumIncomingValues() != 2)
421*8abe8300SCraig Topper             continue;
422*8abe8300SCraig Topper 
423*8abe8300SCraig Topper           // Walk forward from this phi to see if it reaches back to this add.
424*8abe8300SCraig Topper           if (!isReachableFromPHI(PN, BO))
425*8abe8300SCraig Topper             continue;
426*8abe8300SCraig Topper 
427*8abe8300SCraig Topper           // The phi forms a loop with this Add, push its operands.
428*8abe8300SCraig Topper           for (Value *Op : BO->operands())
429*8abe8300SCraig Topper             Worklist.push_back(Op);
430*8abe8300SCraig Topper         }
431*8abe8300SCraig Topper       }
432*8abe8300SCraig Topper     }
433*8abe8300SCraig Topper 
434*8abe8300SCraig Topper     // Not an add or phi, make it a leaf.
435*8abe8300SCraig Topper     if (auto *I = dyn_cast<Instruction>(V)) {
436*8abe8300SCraig Topper       if (!V->hasNUses(I == Root ? 2 : 1))
437*8abe8300SCraig Topper         continue;
438*8abe8300SCraig Topper 
439*8abe8300SCraig Topper       // Add this as a leaf.
440*8abe8300SCraig Topper       Leaves.push_back(I);
441*8abe8300SCraig Topper     }
442*8abe8300SCraig Topper   }
4439f7d4150SCraig Topper }
4449f7d4150SCraig Topper 
4459f7d4150SCraig Topper bool X86PartialReduction::runOnFunction(Function &F) {
4469f7d4150SCraig Topper   if (skipFunction(F))
4479f7d4150SCraig Topper     return false;
4489f7d4150SCraig Topper 
4499f7d4150SCraig Topper   auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
4509f7d4150SCraig Topper   if (!TPC)
4519f7d4150SCraig Topper     return false;
4529f7d4150SCraig Topper 
4539f7d4150SCraig Topper   auto &TM = TPC->getTM<X86TargetMachine>();
4549f7d4150SCraig Topper   ST = TM.getSubtargetImpl(F);
4559f7d4150SCraig Topper 
4569f7d4150SCraig Topper   DL = &F.getParent()->getDataLayout();
4579f7d4150SCraig Topper 
4589f7d4150SCraig Topper   bool MadeChange = false;
4599f7d4150SCraig Topper   for (auto &BB : F) {
4609f7d4150SCraig Topper     for (auto &I : BB) {
461*8abe8300SCraig Topper       auto *EE = dyn_cast<ExtractElementInst>(&I);
462*8abe8300SCraig Topper       if (!EE)
4639f7d4150SCraig Topper         continue;
4649f7d4150SCraig Topper 
465*8abe8300SCraig Topper       // First find a reduction tree.
466*8abe8300SCraig Topper       // FIXME: Do we need to handle other opcodes than Add?
467*8abe8300SCraig Topper       Value *Root = matchAddReduction(*EE);
468*8abe8300SCraig Topper       if (!Root)
4699f7d4150SCraig Topper         continue;
4709f7d4150SCraig Topper 
471*8abe8300SCraig Topper       SmallVector<Instruction *, 8> Leaves;
472*8abe8300SCraig Topper       collectLeaves(Root, Leaves);
473*8abe8300SCraig Topper 
474*8abe8300SCraig Topper       for (Instruction *I : Leaves) {
475*8abe8300SCraig Topper         if (tryMAddReplacement(I)) {
4769f7d4150SCraig Topper           MadeChange = true;
4779f7d4150SCraig Topper           continue;
4789f7d4150SCraig Topper         }
479*8abe8300SCraig Topper 
480*8abe8300SCraig Topper         // Don't do SAD matching on the root node. SelectionDAG already
481*8abe8300SCraig Topper         // has support for that and currently generates better code.
482*8abe8300SCraig Topper         if (I != Root && trySADReplacement(I))
4839f7d4150SCraig Topper           MadeChange = true;
4849f7d4150SCraig Topper       }
4859f7d4150SCraig Topper     }
4869f7d4150SCraig Topper   }
4879f7d4150SCraig Topper 
4889f7d4150SCraig Topper   return MadeChange;
4899f7d4150SCraig Topper }
490