<HTML><HEAD><TITLE>Samsung Enterprise Portal mySingle</TITLE>
<META content=IE=5 http-equiv=X-UA-Compatible>
<META content="text/html; charset=windows-1252" http-equiv=Content-Type>
<STYLE id=mysingle_style type=text/css>P {
        MARGIN-BOTTOM: 5px; FONT-SIZE: 9pt; FONT-FAMILY: Arial, arial; MARGIN-TOP: 5px
}
TD {
        MARGIN-BOTTOM: 5px; FONT-SIZE: 9pt; FONT-FAMILY: Arial, arial; MARGIN-TOP: 5px
}
LI {
        MARGIN-BOTTOM: 5px; FONT-SIZE: 9pt; FONT-FAMILY: Arial, arial; MARGIN-TOP: 5px
}
BODY {
        FONT-SIZE: 9pt; FONT-FAMILY: Arial, arial; MARGIN: 10px; LINE-HEIGHT: 1.4
}
</STYLE>

<META name=GENERATOR content=ActiveSquare></HEAD>
<BODY>
<META name=GENERATOR content=ActiveSquare><X-BODY>
<P>Hi Richard,</P>
<P>This should be fixed in r235287. Sorry for the inconvenience.</P>
<P>Thanks and Regards</P>
<P>Karthik Bhat</P>
<P> </P>
<P>------- <B>Original Message</B> -------</P>
<P><B>Sender</B> : Richard Smith<richard@metafoo.co.uk></P>
<P><B>Date</B> : Apr 20, 2015 13:48 (GMT+09:00)</P>
<P><B>Title</B> : Re: [llvm] r235284 - [NFC] Refactor identification of reductions as common utility function.</P>
<P> </P>
<DIV dir=ltr>Looks like this caused: 
<DIV><BR></DIV>
<DIV><PRE style="COLOR: rgb(0,0,0)"><FONT face="monospace, monospace">include/llvm/Transforms/Utils/LoopUtils.h:75:16: warning: private field 'PatternLastInst' is not used [-Wunused-private-field]</FONT></PRE></DIV></DIV>
<DIV class=gmail_extra><BR>
<DIV class=gmail_quote>On Sun, Apr 19, 2015 at 9:38 PM, Karthik Bhat <SPAN dir=ltr><<A href="mailto:kv.bhat@samsung.com" target=_blank>kv.bhat@samsung.com</A>></SPAN> wrote:<BR>
<BLOCKQUOTE class=gmail_quote style="PADDING-LEFT: 1ex; MARGIN: 0px 0px 0px 0.8ex; BORDER-LEFT: rgb(204,204,204) 1px solid">Author: karthik<BR>Date: Sun Apr 19 23:38:33 2015<BR>New Revision: 235284<BR><BR>URL: <A href="http://llvm.org/viewvc/llvm-project?rev=235284&view=rev" target=_blank>http://llvm.org/viewvc/llvm-project?rev=235284&view=rev</A><BR>Log:<BR>[NFC] Refactor identification of reductions as common utility function.<BR>This patch refactors reduction identification code out of LoopVectorizer and<BR>exposes them as common utilities.<BR>No functional change.<BR>Review: <A href="http://reviews.llvm.org/D9046" target=_blank>http://reviews.llvm.org/D9046</A><BR><BR><BR>Added:<BR>    llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp<BR>Modified:<BR>    llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h<BR>    llvm/trunk/lib/Transforms/Utils/CMakeLists.txt<BR>    llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp<BR><BR>Modified: llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h<BR>URL: <A href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h?rev=235284&r1=235283&r2=235284&view=diff" target=_blank>http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h?rev=235284&r1=235283&r2=235284&view=diff</A><BR>==============================================================================<BR>--- llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h (original)<BR>+++ llvm/trunk/include/llvm/Transforms/Utils/LoopUtils.h Sun Apr 19 23:38:33 2015<BR>@@ -16,6 +16,7 @@<BR><BR> #include "llvm/ADT/SmallVector.h"<BR> #include "llvm/IR/Dominators.h"<BR>+#include "llvm/IR/IRBuilder.h"<BR><BR> namespace llvm {<BR> class AliasAnalysis;<BR>@@ -42,6 +43,132 @@ struct LICMSafetyInfo {<BR>   {}<BR> };<BR><BR>+/// This POD struct holds information about a potential reduction operation.<BR>+class ReductionInstDesc {<BR>+<BR>+public:<BR>+  // This enum represents the kind of minmax reduction.<BR>+  enum MinMaxReductionKind {<BR>+    MRK_Invalid,<BR>+    MRK_UIntMin,<BR>+    MRK_UIntMax,<BR>+    MRK_SIntMin,<BR>+    MRK_SIntMax,<BR>+    MRK_FloatMin,<BR>+    MRK_FloatMax<BR>+  };<BR>+  ReductionInstDesc(bool IsRedux, Instruction *I)<BR>+      : IsReduction(IsRedux), PatternLastInst(I), MinMaxKind(MRK_Invalid) {}<BR>+<BR>+  ReductionInstDesc(Instruction *I, MinMaxReductionKind K)<BR>+      : IsReduction(true), PatternLastInst(I), MinMaxKind(K) {}<BR>+<BR>+  bool isReduction() { return IsReduction; }<BR>+<BR>+  MinMaxReductionKind getMinMaxKind() { return MinMaxKind; }<BR>+<BR>+private:<BR>+  // Is this instruction a reduction candidate.<BR>+  bool IsReduction;<BR>+  // The last instruction in a min/max pattern (select of the select(icmp())<BR>+  // pattern), or the current reduction instruction otherwise.<BR>+  Instruction *PatternLastInst;<BR>+  // If this is a min/max pattern the comparison predicate.<BR>+  MinMaxReductionKind MinMaxKind;<BR>+};<BR>+<BR>+/// This struct holds information about reduction variables.<BR>+class ReductionDescriptor {<BR>+<BR>+public:<BR>+  /// This enum represents the kinds of reductions that we support.<BR>+  enum ReductionKind {<BR>+    RK_NoReduction,   ///< Not a reduction.<BR>+    RK_IntegerAdd,    ///< Sum of integers.<BR>+    RK_IntegerMult,   ///< Product of integers.<BR>+    RK_IntegerOr,     ///< Bitwise or logical OR of numbers.<BR>+    RK_IntegerAnd,    ///< Bitwise or logical AND of numbers.<BR>+    RK_IntegerXor,    ///< Bitwise or logical XOR of numbers.<BR>+    RK_IntegerMinMax, ///< Min/max implemented in terms of select(cmp()).<BR>+    RK_FloatAdd,      ///< Sum of floats.<BR>+    RK_FloatMult,     ///< Product of floats.<BR>+    RK_FloatMinMax    ///< Min/max implemented in terms of select(cmp()).<BR>+  };<BR>+<BR>+  ReductionDescriptor()<BR>+      : StartValue(nullptr), LoopExitInstr(nullptr), Kind(RK_NoReduction),<BR>+        MinMaxKind(ReductionInstDesc::MRK_Invalid) {}<BR>+<BR>+  ReductionDescriptor(Value *Start, Instruction *Exit, ReductionKind K,<BR>+                      ReductionInstDesc::MinMaxReductionKind MK)<BR>+      : StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK) {}<BR>+<BR>+  /// Returns a struct describing if the instruction 'I' can be a reduction<BR>+  /// variable of type 'Kind'. If the reduction is a min/max pattern of<BR>+  /// select(icmp()) this function advances the instruction pointer 'I' from the<BR>+  /// compare instruction to the select instruction and stores this pointer in<BR>+  /// 'PatternLastInst' member of the returned struct.<BR>+  static ReductionInstDesc isReductionInstr(Instruction *I, ReductionKind Kind,<BR>+                                            ReductionInstDesc &Prev,<BR>+                                            bool HasFunNoNaNAttr);<BR>+<BR>+  /// Returns true if instuction I has multiple uses in Insts<BR>+  static bool hasMultipleUsesOf(Instruction *I,<BR>+                                SmallPtrSetImpl<Instruction *> &Insts);<BR>+<BR>+  /// Returns true if all uses of the instruction I is within the Set.<BR>+  static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set);<BR>+<BR>+  /// Returns a struct describing if the instruction if the instruction is a<BR>+  /// Select(ICmp(X, Y), X, Y) instruction pattern corresponding to a min(X, Y)<BR>+  /// or max(X, Y).<BR>+  static ReductionInstDesc isMinMaxSelectCmpPattern(Instruction *I,<BR>+                                                    ReductionInstDesc &Prev);<BR>+<BR>+  /// Returns identity corresponding to the ReductionKind.<BR>+  static Constant *getReductionIdentity(ReductionKind K, Type *Tp);<BR>+<BR>+  /// Returns the opcode of binary operation corresponding to the ReductionKind.<BR>+  static unsigned getReductionBinOp(ReductionKind Kind);<BR>+<BR>+  /// Returns a Min/Max operation corresponding to MinMaxReductionKind.<BR>+  static Value *createMinMaxOp(IRBuilder<> &Builder,<BR>+                               ReductionInstDesc::MinMaxReductionKind RK,<BR>+                               Value *Left, Value *Right);<BR>+<BR>+  /// Returns true if Phi is a reduction of type Kind and adds it to the<BR>+  /// ReductionDescriptor.<BR>+  static bool AddReductionVar(PHINode *Phi, ReductionKind Kind, Loop *TheLoop,<BR>+                              bool HasFunNoNaNAttr,<BR>+                              ReductionDescriptor &RedDes);<BR>+<BR>+  /// Returns true if Phi is a reduction in TheLoop. The ReductionDescriptor is<BR>+  /// returned in RedDes.<BR>+  static bool isReductionPHI(PHINode *Phi, Loop *TheLoop,<BR>+                             ReductionDescriptor &RedDes);<BR>+<BR>+  ReductionKind getReductionKind() { return Kind; }<BR>+<BR>+  ReductionInstDesc::MinMaxReductionKind getMinMaxReductionKind() {<BR>+    return MinMaxKind;<BR>+  }<BR>+<BR>+  TrackingVH<Value> getReductionStartValue() { return StartValue; }<BR>+<BR>+  Instruction *getLoopExitInstr() { return LoopExitInstr; }<BR>+<BR>+private:<BR>+  // The starting value of the reduction.<BR>+  // It does not have to be zero!<BR>+  TrackingVH<Value> StartValue;<BR>+  // The instruction who's value is used outside the loop.<BR>+  Instruction *LoopExitInstr;<BR>+  // The kind of the reduction.<BR>+  ReductionKind Kind;<BR>+  // If this a min/max reduction the kind of reduction.<BR>+  ReductionInstDesc::MinMaxReductionKind MinMaxKind;<BR>+};<BR>+<BR> BasicBlock *InsertPreheaderForLoop(Loop *L, Pass *P);<BR><BR> /// \brief Simplify each loop in a loop nest recursively.<BR><BR>Modified: llvm/trunk/lib/Transforms/Utils/CMakeLists.txt<BR>URL: <A href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=235284&r1=235283&r2=235284&view=diff" target=_blank>http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=235284&r1=235283&r2=235284&view=diff</A><BR>==============================================================================<BR>--- llvm/trunk/lib/Transforms/Utils/CMakeLists.txt (original)<BR>+++ llvm/trunk/lib/Transforms/Utils/CMakeLists.txt Sun Apr 19 23:38:33 2015<BR>@@ -21,6 +21,7 @@ add_llvm_library(LLVMTransformUtils<BR>   LoopSimplify.cpp<BR>   LoopUnroll.cpp<BR>   LoopUnrollRuntime.cpp<BR>+  LoopUtils.cpp<BR>   LowerInvoke.cpp<BR>   LowerSwitch.cpp<BR>   Mem2Reg.cpp<BR><BR>Added: llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp<BR>URL: <A href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp?rev=235284&view=auto" target=_blank>http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp?rev=235284&view=auto</A><BR>==============================================================================<BR>--- llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp (added)<BR>+++ llvm/trunk/lib/Transforms/Utils/LoopUtils.cpp Sun Apr 19 23:38:33 2015<BR>@@ -0,0 +1,453 @@<BR>+//===-- LoopUtils.cpp - Loop Utility functions -------------------------===//<BR>+//<BR>+//                     The LLVM Compiler Infrastructure<BR>+//<BR>+// This file is distributed under the University of Illinois Open Source<BR>+// License. See LICENSE.TXT for details.<BR>+//<BR>+//===----------------------------------------------------------------------===//<BR>+//<BR>+// This file defines common loop utility functions.<BR>+//<BR>+//===----------------------------------------------------------------------===//<BR>+<BR>+#include "llvm/Analysis/LoopInfo.h"<BR>+#include "llvm/IR/Instructions.h"<BR>+#include "llvm/IR/PatternMatch.h"<BR>+#include "llvm/IR/ValueHandle.h"<BR>+#include "llvm/Support/Debug.h"<BR>+#include "llvm/Transforms/Utils/LoopUtils.h"<BR>+<BR>+using namespace llvm;<BR>+using namespace llvm::PatternMatch;<BR>+<BR>+#define DEBUG_TYPE "loop-utils"<BR>+<BR>+bool ReductionDescriptor::areAllUsesIn(Instruction *I,<BR>+                                       SmallPtrSetImpl<Instruction *> &Set) {<BR>+  for (User::op_iterator Use = I->op_begin(), E = I->op_end(); Use != E; ++Use)<BR>+    if (!Set.count(dyn_cast<Instruction>(*Use)))<BR>+      return false;<BR>+  return true;<BR>+}<BR>+<BR>+bool ReductionDescriptor::AddReductionVar(PHINode *Phi, ReductionKind Kind,<BR>+                                          Loop *TheLoop, bool HasFunNoNaNAttr,<BR>+                                          ReductionDescriptor &RedDes) {<BR>+  if (Phi->getNumIncomingValues() != 2)<BR>+    return false;<BR>+<BR>+  // Reduction variables are only found in the loop header block.<BR>+  if (Phi->getParent() != TheLoop->getHeader())<BR>+    return false;<BR>+<BR>+  // Obtain the reduction start value from the value that comes from the loop<BR>+  // preheader.<BR>+  Value *RdxStart = Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader());<BR>+<BR>+  // ExitInstruction is the single value which is used outside the loop.<BR>+  // We only allow for a single reduction value to be used outside the loop.<BR>+  // This includes users of the reduction, variables (which form a cycle<BR>+  // which ends in the phi node).<BR>+  Instruction *ExitInstruction = nullptr;<BR>+  // Indicates that we found a reduction operation in our scan.<BR>+  bool FoundReduxOp = false;<BR>+<BR>+  // We start with the PHI node and scan for all of the users of this<BR>+  // instruction. All users must be instructions that can be used as reduction<BR>+  // variables (such as ADD). We must have a single out-of-block user. The cycle<BR>+  // must include the original PHI.<BR>+  bool FoundStartPHI = false;<BR>+<BR>+  // To recognize min/max patterns formed by a icmp select sequence, we store<BR>+  // the number of instruction we saw from the recognized min/max pattern,<BR>+  //  to make sure we only see exactly the two instructions.<BR>+  unsigned NumCmpSelectPatternInst = 0;<BR>+  ReductionInstDesc ReduxDesc(false, nullptr);<BR>+<BR>+  SmallPtrSet<Instruction *, 8> VisitedInsts;<BR>+  SmallVector<Instruction *, 8> Worklist;<BR>+  Worklist.push_back(Phi);<BR>+  VisitedInsts.insert(Phi);<BR>+<BR>+  // A value in the reduction can be used:<BR>+  //  - By the reduction:<BR>+  //      - Reduction operation:<BR>+  //        - One use of reduction value (safe).<BR>+  //        - Multiple use of reduction value (not safe).<BR>+  //      - PHI:<BR>+  //        - All uses of the PHI must be the reduction (safe).<BR>+  //        - Otherwise, not safe.<BR>+  //  - By one instruction outside of the loop (safe).<BR>+  //  - By further instructions outside of the loop (not safe).<BR>+  //  - By an instruction that is not part of the reduction (not safe).<BR>+  //    This is either:<BR>+  //      * An instruction type other than PHI or the reduction operation.<BR>+  //      * A PHI in the header other than the initial PHI.<BR>+  while (!Worklist.empty()) {<BR>+    Instruction *Cur = Worklist.back();<BR>+    Worklist.pop_back();<BR>+<BR>+    // No Users.<BR>+    // If the instruction has no users then this is a broken chain and can't be<BR>+    // a reduction variable.<BR>+    if (Cur->use_empty())<BR>+      return false;<BR>+<BR>+    bool IsAPhi = isa<PHINode>(Cur);<BR>+<BR>+    // A header PHI use other than the original PHI.<BR>+    if (Cur != Phi && IsAPhi && Cur->getParent() == Phi->getParent())<BR>+      return false;<BR>+<BR>+    // Reductions of instructions such as Div, and Sub is only possible if the<BR>+    // LHS is the reduction variable.<BR>+    if (!Cur->isCommutative() && !IsAPhi && !isa<SelectInst>(Cur) &&<BR>+        !isa<ICmpInst>(Cur) && !isa<FCmpInst>(Cur) &&<BR>+        !VisitedInsts.count(dyn_cast<Instruction>(Cur->getOperand(0))))<BR>+      return false;<BR>+<BR>+    // Any reduction instruction must be of one of the allowed kinds.<BR>+    ReduxDesc = isReductionInstr(Cur, Kind, ReduxDesc, HasFunNoNaNAttr);<BR>+    if (!ReduxDesc.isReduction())<BR>+      return false;<BR>+<BR>+    // A reduction operation must only have one use of the reduction value.<BR>+    if (!IsAPhi && Kind != RK_IntegerMinMax && Kind != RK_FloatMinMax &&<BR>+        hasMultipleUsesOf(Cur, VisitedInsts))<BR>+      return false;<BR>+<BR>+    // All inputs to a PHI node must be a reduction value.<BR>+    if (IsAPhi && Cur != Phi && !areAllUsesIn(Cur, VisitedInsts))<BR>+      return false;<BR>+<BR>+    if (Kind == RK_IntegerMinMax &&<BR>+        (isa<ICmpInst>(Cur) || isa<SelectInst>(Cur)))<BR>+      ++NumCmpSelectPatternInst;<BR>+    if (Kind == RK_FloatMinMax && (isa<FCmpInst>(Cur) || isa<SelectInst>(Cur)))<BR>+      ++NumCmpSelectPatternInst;<BR>+<BR>+    // Check  whether we found a reduction operator.<BR>+    FoundReduxOp |= !IsAPhi;<BR>+<BR>+    // Process users of current instruction. Push non-PHI nodes after PHI nodes<BR>+    // onto the stack. This way we are going to have seen all inputs to PHI<BR>+    // nodes once we get to them.<BR>+    SmallVector<Instruction *, 8> NonPHIs;<BR>+    SmallVector<Instruction *, 8> PHIs;<BR>+    for (User *U : Cur->users()) {<BR>+      Instruction *UI = cast<Instruction>(U);<BR>+<BR>+      // Check if we found the exit user.<BR>+      BasicBlock *Parent = UI->getParent();<BR>+      if (!TheLoop->contains(Parent)) {<BR>+        // Exit if you find multiple outside users or if the header phi node is<BR>+        // being used. In this case the user uses the value of the previous<BR>+        // iteration, in which case we would loose "VF-1" iterations of the<BR>+        // reduction operation if we vectorize.<BR>+        if (ExitInstruction != nullptr || Cur == Phi)<BR>+          return false;<BR>+<BR>+        // The instruction used by an outside user must be the last instruction<BR>+        // before we feed back to the reduction phi. Otherwise, we loose VF-1<BR>+        // operations on the value.<BR>+        if (std::find(Phi->op_begin(), Phi->op_end(), Cur) == Phi->op_end())<BR>+          return false;<BR>+<BR>+        ExitInstruction = Cur;<BR>+        continue;<BR>+      }<BR>+<BR>+      // Process instructions only once (termination). Each reduction cycle<BR>+      // value must only be used once, except by phi nodes and min/max<BR>+      // reductions which are represented as a cmp followed by a select.<BR>+      ReductionInstDesc IgnoredVal(false, nullptr);<BR>+      if (VisitedInsts.insert(UI).second) {<BR>+        if (isa<PHINode>(UI))<BR>+          PHIs.push_back(UI);<BR>+        else<BR>+          NonPHIs.push_back(UI);<BR>+      } else if (!isa<PHINode>(UI) &&<BR>+                 ((!isa<FCmpInst>(UI) && !isa<ICmpInst>(UI) &&<BR>+                   !isa<SelectInst>(UI)) ||<BR>+                  !isMinMaxSelectCmpPattern(UI, IgnoredVal).isReduction()))<BR>+        return false;<BR>+<BR>+      // Remember that we completed the cycle.<BR>+      if (UI == Phi)<BR>+        FoundStartPHI = true;<BR>+    }<BR>+    Worklist.append(PHIs.begin(), PHIs.end());<BR>+    Worklist.append(NonPHIs.begin(), NonPHIs.end());<BR>+  }<BR>+<BR>+  // This means we have seen one but not the other instruction of the<BR>+  // pattern or more than just a select and cmp.<BR>+  if ((Kind == RK_IntegerMinMax || Kind == RK_FloatMinMax) &&<BR>+      NumCmpSelectPatternInst != 2)<BR>+    return false;<BR>+<BR>+  if (!FoundStartPHI || !FoundReduxOp || !ExitInstruction)<BR>+    return false;<BR>+<BR>+  // We found a reduction var if we have reached the original phi node and we<BR>+  // only have a single instruction with out-of-loop users.<BR>+<BR>+  // The ExitInstruction(Instruction which is allowed to have out-of-loop users)<BR>+  // is saved as part of the ReductionDescriptor.<BR>+<BR>+  // Save the description of this reduction variable.<BR>+  ReductionDescriptor RD(RdxStart, ExitInstruction, Kind,<BR>+                         ReduxDesc.getMinMaxKind());<BR>+<BR>+  RedDes = RD;<BR>+<BR>+  return true;<BR>+}<BR>+<BR>+/// Returns true if the instruction is a Select(ICmp(X, Y), X, Y) instruction<BR>+/// pattern corresponding to a min(X, Y) or max(X, Y).<BR>+ReductionInstDesc<BR>+ReductionDescriptor::isMinMaxSelectCmpPattern(Instruction *I,<BR>+                                              ReductionInstDesc &Prev) {<BR>+<BR>+  assert((isa<ICmpInst>(I) || isa<FCmpInst>(I) || isa<SelectInst>(I)) &&<BR>+         "Expect a select instruction");<BR>+  Instruction *Cmp = nullptr;<BR>+  SelectInst *Select = nullptr;<BR>+<BR>+  // We must handle the select(cmp()) as a single instruction. Advance to the<BR>+  // select.<BR>+  if ((Cmp = dyn_cast<ICmpInst>(I)) || (Cmp = dyn_cast<FCmpInst>(I))) {<BR>+    if (!Cmp->hasOneUse() || !(Select = dyn_cast<SelectInst>(*I->user_begin())))<BR>+      return ReductionInstDesc(false, I);<BR>+    return ReductionInstDesc(Select, Prev.getMinMaxKind());<BR>+  }<BR>+<BR>+  // Only handle single use cases for now.<BR>+  if (!(Select = dyn_cast<SelectInst>(I)))<BR>+    return ReductionInstDesc(false, I);<BR>+  if (!(Cmp = dyn_cast<ICmpInst>(I->getOperand(0))) &&<BR>+      !(Cmp = dyn_cast<FCmpInst>(I->getOperand(0))))<BR>+    return ReductionInstDesc(false, I);<BR>+  if (!Cmp->hasOneUse())<BR>+    return ReductionInstDesc(false, I);<BR>+<BR>+  Value *CmpLeft;<BR>+  Value *CmpRight;<BR>+<BR>+  // Look for a min/max pattern.<BR>+  if (m_UMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>+    return ReductionInstDesc(Select, ReductionInstDesc::MRK_UIntMin);<BR>+  else if (m_UMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>+    return ReductionInstDesc(Select, ReductionInstDesc::MRK_UIntMax);<BR>+  else if (m_SMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>+    return ReductionInstDesc(Select, ReductionInstDesc::MRK_SIntMax);<BR>+  else if (m_SMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>+    return ReductionInstDesc(Select, ReductionInstDesc::MRK_SIntMin);<BR>+  else if (m_OrdFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>+    return ReductionInstDesc(Select, ReductionInstDesc::MRK_FloatMin);<BR>+  else if (m_OrdFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>+    return ReductionInstDesc(Select, ReductionInstDesc::MRK_FloatMax);<BR>+  else if (m_UnordFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>+    return ReductionInstDesc(Select, ReductionInstDesc::MRK_FloatMin);<BR>+  else if (m_UnordFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>+    return ReductionInstDesc(Select, ReductionInstDesc::MRK_FloatMax);<BR>+<BR>+  return ReductionInstDesc(false, I);<BR>+}<BR>+<BR>+ReductionInstDesc ReductionDescriptor::isReductionInstr(Instruction *I,<BR>+                                                        ReductionKind Kind,<BR>+                                                        ReductionInstDesc &Prev,<BR>+                                                        bool HasFunNoNaNAttr) {<BR>+  bool FP = I->getType()->isFloatingPointTy();<BR>+  bool FastMath = FP && I->hasUnsafeAlgebra();<BR>+  switch (I->getOpcode()) {<BR>+  default:<BR>+    return ReductionInstDesc(false, I);<BR>+  case Instruction::PHI:<BR>+    if (FP &&<BR>+        (Kind != RK_FloatMult && Kind != RK_FloatAdd && Kind != RK_FloatMinMax))<BR>+      return ReductionInstDesc(false, I);<BR>+    return ReductionInstDesc(I, Prev.getMinMaxKind());<BR>+  case Instruction::Sub:<BR>+  case Instruction::Add:<BR>+    return ReductionInstDesc(Kind == RK_IntegerAdd, I);<BR>+  case Instruction::Mul:<BR>+    return ReductionInstDesc(Kind == RK_IntegerMult, I);<BR>+  case Instruction::And:<BR>+    return ReductionInstDesc(Kind == RK_IntegerAnd, I);<BR>+  case Instruction::Or:<BR>+    return ReductionInstDesc(Kind == RK_IntegerOr, I);<BR>+  case Instruction::Xor:<BR>+    return ReductionInstDesc(Kind == RK_IntegerXor, I);<BR>+  case Instruction::FMul:<BR>+    return ReductionInstDesc(Kind == RK_FloatMult && FastMath, I);<BR>+  case Instruction::FSub:<BR>+  case Instruction::FAdd:<BR>+    return ReductionInstDesc(Kind == RK_FloatAdd && FastMath, I);<BR>+  case Instruction::FCmp:<BR>+  case Instruction::ICmp:<BR>+  case Instruction::Select:<BR>+    if (Kind != RK_IntegerMinMax &&<BR>+        (!HasFunNoNaNAttr || Kind != RK_FloatMinMax))<BR>+      return ReductionInstDesc(false, I);<BR>+    return isMinMaxSelectCmpPattern(I, Prev);<BR>+  }<BR>+}<BR>+<BR>+bool ReductionDescriptor::hasMultipleUsesOf(<BR>+    Instruction *I, SmallPtrSetImpl<Instruction *> &Insts) {<BR>+  unsigned NumUses = 0;<BR>+  for (User::op_iterator Use = I->op_begin(), E = I->op_end(); Use != E;<BR>+       ++Use) {<BR>+    if (Insts.count(dyn_cast<Instruction>(*Use)))<BR>+      ++NumUses;<BR>+    if (NumUses > 1)<BR>+      return true;<BR>+  }<BR>+<BR>+  return false;<BR>+}<BR>+bool ReductionDescriptor::isReductionPHI(PHINode *Phi, Loop *TheLoop,<BR>+                                         ReductionDescriptor &RedDes) {<BR>+<BR>+  bool HasFunNoNaNAttr = false;<BR>+  BasicBlock *Header = TheLoop->getHeader();<BR>+  Function &F = *Header->getParent();<BR>+  if (F.hasFnAttribute("no-nans-fp-math"))<BR>+    HasFunNoNaNAttr =<BR>+        F.getFnAttribute("no-nans-fp-math").getValueAsString() == "true";<BR>+<BR>+  if (AddReductionVar(Phi, RK_IntegerAdd, TheLoop, HasFunNoNaNAttr, RedDes)) {<BR>+    DEBUG(dbgs() << "Found an ADD reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  if (AddReductionVar(Phi, RK_IntegerMult, TheLoop, HasFunNoNaNAttr, RedDes)) {<BR>+    DEBUG(dbgs() << "Found a MUL reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  if (AddReductionVar(Phi, RK_IntegerOr, TheLoop, HasFunNoNaNAttr, RedDes)) {<BR>+    DEBUG(dbgs() << "Found an OR reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  if (AddReductionVar(Phi, RK_IntegerAnd, TheLoop, HasFunNoNaNAttr, RedDes)) {<BR>+    DEBUG(dbgs() << "Found an AND reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  if (AddReductionVar(Phi, RK_IntegerXor, TheLoop, HasFunNoNaNAttr, RedDes)) {<BR>+    DEBUG(dbgs() << "Found a XOR reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  if (AddReductionVar(Phi, RK_IntegerMinMax, TheLoop, HasFunNoNaNAttr,<BR>+                      RedDes)) {<BR>+    DEBUG(dbgs() << "Found a MINMAX reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  if (AddReductionVar(Phi, RK_FloatMult, TheLoop, HasFunNoNaNAttr, RedDes)) {<BR>+    DEBUG(dbgs() << "Found an FMult reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  if (AddReductionVar(Phi, RK_FloatAdd, TheLoop, HasFunNoNaNAttr, RedDes)) {<BR>+    DEBUG(dbgs() << "Found an FAdd reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  if (AddReductionVar(Phi, RK_FloatMinMax, TheLoop, HasFunNoNaNAttr, RedDes)) {<BR>+    DEBUG(dbgs() << "Found an float MINMAX reduction PHI." << *Phi << "\n");<BR>+    return true;<BR>+  }<BR>+  // Not a reduction of known type.<BR>+  return false;<BR>+}<BR>+<BR>+/// This function returns the identity element (or neutral element) for<BR>+/// the operation K.<BR>+Constant *ReductionDescriptor::getReductionIdentity(ReductionKind K, Type *Tp) {<BR>+  switch (K) {<BR>+  case RK_IntegerXor:<BR>+  case RK_IntegerAdd:<BR>+  case RK_IntegerOr:<BR>+    // Adding, Xoring, Oring zero to a number does not change it.<BR>+    return ConstantInt::get(Tp, 0);<BR>+  case RK_IntegerMult:<BR>+    // Multiplying a number by 1 does not change it.<BR>+    return ConstantInt::get(Tp, 1);<BR>+  case RK_IntegerAnd:<BR>+    // AND-ing a number with an all-1 value does not change it.<BR>+    return ConstantInt::get(Tp, -1, true);<BR>+  case RK_FloatMult:<BR>+    // Multiplying a number by 1 does not change it.<BR>+    return ConstantFP::get(Tp, 1.0L);<BR>+  case RK_FloatAdd:<BR>+    // Adding zero to a number does not change it.<BR>+    return ConstantFP::get(Tp, 0.0L);<BR>+  default:<BR>+    llvm_unreachable("Unknown reduction kind");<BR>+  }<BR>+}<BR>+<BR>+/// This function translates the reduction kind to an LLVM binary operator.<BR>+unsigned ReductionDescriptor::getReductionBinOp(ReductionKind Kind) {<BR>+  switch (Kind) {<BR>+  case RK_IntegerAdd:<BR>+    return Instruction::Add;<BR>+  case RK_IntegerMult:<BR>+    return Instruction::Mul;<BR>+  case RK_IntegerOr:<BR>+    return Instruction::Or;<BR>+  case RK_IntegerAnd:<BR>+    return Instruction::And;<BR>+  case RK_IntegerXor:<BR>+    return Instruction::Xor;<BR>+  case RK_FloatMult:<BR>+    return Instruction::FMul;<BR>+  case RK_FloatAdd:<BR>+    return Instruction::FAdd;<BR>+  case RK_IntegerMinMax:<BR>+    return Instruction::ICmp;<BR>+  case RK_FloatMinMax:<BR>+    return Instruction::FCmp;<BR>+  default:<BR>+    llvm_unreachable("Unknown reduction operation");<BR>+  }<BR>+}<BR>+<BR>+Value *<BR>+ReductionDescriptor::createMinMaxOp(IRBuilder<> &Builder,<BR>+                                    ReductionInstDesc::MinMaxReductionKind RK,<BR>+                                    Value *Left, Value *Right) {<BR>+  CmpInst::Predicate P = CmpInst::ICMP_NE;<BR>+  switch (RK) {<BR>+  default:<BR>+    llvm_unreachable("Unknown min/max reduction kind");<BR>+  case ReductionInstDesc::MRK_UIntMin:<BR>+    P = CmpInst::ICMP_ULT;<BR>+    break;<BR>+  case ReductionInstDesc::MRK_UIntMax:<BR>+    P = CmpInst::ICMP_UGT;<BR>+    break;<BR>+  case ReductionInstDesc::MRK_SIntMin:<BR>+    P = CmpInst::ICMP_SLT;<BR>+    break;<BR>+  case ReductionInstDesc::MRK_SIntMax:<BR>+    P = CmpInst::ICMP_SGT;<BR>+    break;<BR>+  case ReductionInstDesc::MRK_FloatMin:<BR>+    P = CmpInst::FCMP_OLT;<BR>+    break;<BR>+  case ReductionInstDesc::MRK_FloatMax:<BR>+    P = CmpInst::FCMP_OGT;<BR>+    break;<BR>+  }<BR>+<BR>+  Value *Cmp;<BR>+  if (RK == ReductionInstDesc::MRK_FloatMin ||<BR>+      RK == ReductionInstDesc::MRK_FloatMax)<BR>+    Cmp = Builder.CreateFCmp(P, Left, Right, "rdx.minmax.cmp");<BR>+  else<BR>+    Cmp = Builder.CreateICmp(P, Left, Right, "rdx.minmax.cmp");<BR>+<BR>+  Value *Select = Builder.CreateSelect(Cmp, Left, Right, "rdx.minmax.select");<BR>+  return Select;<BR>+}<BR><BR>Modified: llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp<BR>URL: <A href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp?rev=235284&r1=235283&r2=235284&view=diff" target=_blank>http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp?rev=235284&r1=235283&r2=235284&view=diff</A><BR>==============================================================================<BR>--- llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp (original)<BR>+++ llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp Sun Apr 19 23:38:33 2015<BR>@@ -568,20 +568,6 @@ public:<BR>         TTI(TTI), DT(DT), LAA(LAA), LAI(nullptr), Induction(nullptr),<BR>         WidestIndTy(nullptr), HasFunNoNaNAttr(false) {}<BR><BR>-  /// This enum represents the kinds of reductions that we support.<BR>-  enum ReductionKind {<BR>-    RK_NoReduction, ///< Not a reduction.<BR>-    RK_IntegerAdd,  ///< Sum of integers.<BR>-    RK_IntegerMult, ///< Product of integers.<BR>-    RK_IntegerOr,   ///< Bitwise or logical OR of numbers.<BR>-    RK_IntegerAnd,  ///< Bitwise or logical AND of numbers.<BR>-    RK_IntegerXor,  ///< Bitwise or logical XOR of numbers.<BR>-    RK_IntegerMinMax, ///< Min/max implemented in terms of select(cmp()).<BR>-    RK_FloatAdd,    ///< Sum of floats.<BR>-    RK_FloatMult,   ///< Product of floats.<BR>-    RK_FloatMinMax  ///< Min/max implemented in terms of select(cmp()).<BR>-  };<BR>-<BR>   /// This enum represents the kinds of inductions that we support.<BR>   enum InductionKind {<BR>     IK_NoInduction,  ///< Not an induction variable.<BR>@@ -589,54 +575,6 @@ public:<BR>     IK_PtrInduction  ///< Pointer induction var. Step = C / sizeof(elem).<BR>   };<BR><BR>-  // This enum represents the kind of minmax reduction.<BR>-  enum MinMaxReductionKind {<BR>-    MRK_Invalid,<BR>-    MRK_UIntMin,<BR>-    MRK_UIntMax,<BR>-    MRK_SIntMin,<BR>-    MRK_SIntMax,<BR>-    MRK_FloatMin,<BR>-    MRK_FloatMax<BR>-  };<BR>-<BR>-  /// This struct holds information about reduction variables.<BR>-  struct ReductionDescriptor {<BR>-    ReductionDescriptor() : StartValue(nullptr), LoopExitInstr(nullptr),<BR>-      Kind(RK_NoReduction), MinMaxKind(MRK_Invalid) {}<BR>-<BR>-    ReductionDescriptor(Value *Start, Instruction *Exit, ReductionKind K,<BR>-                        MinMaxReductionKind MK)<BR>-        : StartValue(Start), LoopExitInstr(Exit), Kind(K), MinMaxKind(MK) {}<BR>-<BR>-    // The starting value of the reduction.<BR>-    // It does not have to be zero!<BR>-    TrackingVH<Value> StartValue;<BR>-    // The instruction who's value is used outside the loop.<BR>-    Instruction *LoopExitInstr;<BR>-    // The kind of the reduction.<BR>-    ReductionKind Kind;<BR>-    // If this a min/max reduction the kind of reduction.<BR>-    MinMaxReductionKind MinMaxKind;<BR>-  };<BR>-<BR>-  /// This POD struct holds information about a potential reduction operation.<BR>-  struct ReductionInstDesc {<BR>-    ReductionInstDesc(bool IsRedux, Instruction *I) :<BR>-      IsReduction(IsRedux), PatternLastInst(I), MinMaxKind(MRK_Invalid) {}<BR>-<BR>-    ReductionInstDesc(Instruction *I, MinMaxReductionKind K) :<BR>-      IsReduction(true), PatternLastInst(I), MinMaxKind(K) {}<BR>-<BR>-    // Is this instruction a reduction candidate.<BR>-    bool IsReduction;<BR>-    // The last instruction in a min/max pattern (select of the select(icmp())<BR>-    // pattern), or the current reduction instruction otherwise.<BR>-    Instruction *PatternLastInst;<BR>-    // If this is a min/max pattern the comparison predicate.<BR>-    MinMaxReductionKind MinMaxKind;<BR>-  };<BR>-<BR>   /// A struct for saving information about induction variables.<BR>   struct InductionInfo {<BR>     InductionInfo(Value *Start, InductionKind K, ConstantInt *Step)<BR>@@ -759,10 +697,6 @@ public:<BR>     return LAI;<BR>   }<BR><BR>-  /// This function returns the identity element (or neutral element) for<BR>-  /// the operation K.<BR>-  static Constant *getReductionIdentity(ReductionKind K, Type *Tp);<BR>-<BR>   unsigned getMaxSafeDepDistBytes() { return LAI->getMaxSafeDepDistBytes(); }<BR><BR>   bool hasStride(Value *V) { return StrideSet.count(V); }<BR>@@ -820,20 +754,6 @@ private:<BR>   /// and we know that we can read from them without segfault.<BR>   bool blockCanBePredicated(BasicBlock *BB, SmallPtrSetImpl<Value *> &SafePtrs);<BR><BR>-  /// Returns True, if 'Phi' is the kind of reduction variable for type<BR>-  /// 'Kind'. If this is a reduction variable, it adds it to ReductionList.<BR>-  bool AddReductionVar(PHINode *Phi, ReductionKind Kind);<BR>-  /// Returns a struct describing if the instruction 'I' can be a reduction<BR>-  /// variable of type 'Kind'. If the reduction is a min/max pattern of<BR>-  /// select(icmp()) this function advances the instruction pointer 'I' from the<BR>-  /// compare instruction to the select instruction and stores this pointer in<BR>-  /// 'PatternLastInst' member of the returned struct.<BR>-  ReductionInstDesc isReductionInstr(Instruction *I, ReductionKind Kind,<BR>-                                     ReductionInstDesc &Desc);<BR>-  /// Returns true if the instruction is a Select(ICmp(X, Y), X, Y) instruction<BR>-  /// pattern corresponding to a min(X, Y) or max(X, Y).<BR>-  static ReductionInstDesc isMinMaxSelectCmpPattern(Instruction *I,<BR>-                                                    ReductionInstDesc &Prev);<BR>   /// Returns the induction kind of Phi and record the step. This function may<BR>   /// return NoInduction if the PHI is not an induction variable.<BR>   InductionKind isInductionVariable(PHINode *Phi, ConstantInt *&StepValue);<BR>@@ -2469,98 +2389,6 @@ void InnerLoopVectorizer::createEmptyLoo<BR>   Hints.setAlreadyVectorized();<BR> }<BR><BR>-/// This function returns the identity element (or neutral element) for<BR>-/// the operation K.<BR>-Constant*<BR>-LoopVectorizationLegality::getReductionIdentity(ReductionKind K, Type *Tp) {<BR>-  switch (K) {<BR>-  case RK_IntegerXor:<BR>-  case RK_IntegerAdd:<BR>-  case RK_IntegerOr:<BR>-    // Adding, Xoring, Oring zero to a number does not change it.<BR>-    return ConstantInt::get(Tp, 0);<BR>-  case RK_IntegerMult:<BR>-    // Multiplying a number by 1 does not change it.<BR>-    return ConstantInt::get(Tp, 1);<BR>-  case RK_IntegerAnd:<BR>-    // AND-ing a number with an all-1 value does not change it.<BR>-    return ConstantInt::get(Tp, -1, true);<BR>-  case  RK_FloatMult:<BR>-    // Multiplying a number by 1 does not change it.<BR>-    return ConstantFP::get(Tp, 1.0L);<BR>-  case  RK_FloatAdd:<BR>-    // Adding zero to a number does not change it.<BR>-    return ConstantFP::get(Tp, 0.0L);<BR>-  default:<BR>-    llvm_unreachable("Unknown reduction kind");<BR>-  }<BR>-}<BR>-<BR>-/// This function translates the reduction kind to an LLVM binary operator.<BR>-static unsigned<BR>-getReductionBinOp(LoopVectorizationLegality::ReductionKind Kind) {<BR>-  switch (Kind) {<BR>-    case LoopVectorizationLegality::RK_IntegerAdd:<BR>-      return Instruction::Add;<BR>-    case LoopVectorizationLegality::RK_IntegerMult:<BR>-      return Instruction::Mul;<BR>-    case LoopVectorizationLegality::RK_IntegerOr:<BR>-      return Instruction::Or;<BR>-    case LoopVectorizationLegality::RK_IntegerAnd:<BR>-      return Instruction::And;<BR>-    case LoopVectorizationLegality::RK_IntegerXor:<BR>-      return Instruction::Xor;<BR>-    case LoopVectorizationLegality::RK_FloatMult:<BR>-      return Instruction::FMul;<BR>-    case LoopVectorizationLegality::RK_FloatAdd:<BR>-      return Instruction::FAdd;<BR>-    case LoopVectorizationLegality::RK_IntegerMinMax:<BR>-      return Instruction::ICmp;<BR>-    case LoopVectorizationLegality::RK_FloatMinMax:<BR>-      return Instruction::FCmp;<BR>-    default:<BR>-      llvm_unreachable("Unknown reduction operation");<BR>-  }<BR>-}<BR>-<BR>-static Value *createMinMaxOp(IRBuilder<> &Builder,<BR>-                             LoopVectorizationLegality::MinMaxReductionKind RK,<BR>-                             Value *Left, Value *Right) {<BR>-  CmpInst::Predicate P = CmpInst::ICMP_NE;<BR>-  switch (RK) {<BR>-  default:<BR>-    llvm_unreachable("Unknown min/max reduction kind");<BR>-  case LoopVectorizationLegality::MRK_UIntMin:<BR>-    P = CmpInst::ICMP_ULT;<BR>-    break;<BR>-  case LoopVectorizationLegality::MRK_UIntMax:<BR>-    P = CmpInst::ICMP_UGT;<BR>-    break;<BR>-  case LoopVectorizationLegality::MRK_SIntMin:<BR>-    P = CmpInst::ICMP_SLT;<BR>-    break;<BR>-  case LoopVectorizationLegality::MRK_SIntMax:<BR>-    P = CmpInst::ICMP_SGT;<BR>-    break;<BR>-  case LoopVectorizationLegality::MRK_FloatMin:<BR>-    P = CmpInst::FCMP_OLT;<BR>-    break;<BR>-  case LoopVectorizationLegality::MRK_FloatMax:<BR>-    P = CmpInst::FCMP_OGT;<BR>-    break;<BR>-  }<BR>-<BR>-  Value *Cmp;<BR>-  if (RK == LoopVectorizationLegality::MRK_FloatMin ||<BR>-      RK == LoopVectorizationLegality::MRK_FloatMax)<BR>-    Cmp = Builder.CreateFCmp(P, Left, Right, "rdx.minmax.cmp");<BR>-  else<BR>-    Cmp = Builder.CreateICmp(P, Left, Right, "rdx.minmax.cmp");<BR>-<BR>-  Value *Select = Builder.CreateSelect(Cmp, Left, Right, "rdx.minmax.select");<BR>-  return Select;<BR>-}<BR>-<BR> namespace {<BR> struct CSEDenseMapInfo {<BR>   static bool canHandle(Instruction *I) {<BR>@@ -2772,10 +2600,14 @@ void InnerLoopVectorizer::vectorizeLoop(<BR>     // Find the reduction variable descriptor.<BR>     assert(Legal->getReductionVars()->count(RdxPhi) &&<BR>            "Unable to find the reduction variable");<BR>-    LoopVectorizationLegality::ReductionDescriptor RdxDesc =<BR>-    (*Legal->getReductionVars())[RdxPhi];<BR>+    ReductionDescriptor RdxDesc = (*Legal->getReductionVars())[RdxPhi];<BR><BR>-    setDebugLocFromInst(Builder, RdxDesc.StartValue);<BR>+    ReductionDescriptor::ReductionKind RK = RdxDesc.getReductionKind();<BR>+    TrackingVH<Value> ReductionStartValue = RdxDesc.getReductionStartValue();<BR>+    Instruction *LoopExitInst = RdxDesc.getLoopExitInstr();<BR>+    ReductionInstDesc::MinMaxReductionKind MinMaxKind =<BR>+        RdxDesc.getMinMaxReductionKind();<BR>+    setDebugLocFromInst(Builder, ReductionStartValue);<BR><BR>     // We need to generate a reduction vector from the incoming scalar.<BR>     // To do so, we need to generate the 'identity' vector and override<BR>@@ -2784,40 +2616,38 @@ void InnerLoopVectorizer::vectorizeLoop(<BR>     Builder.SetInsertPoint(LoopBypassBlocks[1]->getTerminator());<BR><BR>     // This is the vector-clone of the value that leaves the loop.<BR>-    VectorParts &VectorExit = getVectorValue(RdxDesc.LoopExitInstr);<BR>+    VectorParts &VectorExit = getVectorValue(LoopExitInst);<BR>     Type *VecTy = VectorExit[0]->getType();<BR><BR>     // Find the reduction identity variable. Zero for addition, or, xor,<BR>     // one for multiplication, -1 for And.<BR>     Value *Identity;<BR>     Value *VectorStart;<BR>-    if (RdxDesc.Kind == LoopVectorizationLegality::RK_IntegerMinMax ||<BR>-        RdxDesc.Kind == LoopVectorizationLegality::RK_FloatMinMax) {<BR>+    if (RK == ReductionDescriptor::RK_IntegerMinMax ||<BR>+        RK == ReductionDescriptor::RK_FloatMinMax) {<BR>       // MinMax reduction have the start value as their identify.<BR>       if (VF == 1) {<BR>-        VectorStart = Identity = RdxDesc.StartValue;<BR>+        VectorStart = Identity = ReductionStartValue;<BR>       } else {<BR>-        VectorStart = Identity = Builder.CreateVectorSplat(VF,<BR>-                                                           RdxDesc.StartValue,<BR>-                                                           "minmax.ident");<BR>+        VectorStart = Identity =<BR>+            Builder.CreateVectorSplat(VF, ReductionStartValue, "minmax.ident");<BR>       }<BR>     } else {<BR>       // Handle other reduction kinds:<BR>       Constant *Iden =<BR>-      LoopVectorizationLegality::getReductionIdentity(RdxDesc.Kind,<BR>-                                                      VecTy->getScalarType());<BR>+          ReductionDescriptor::getReductionIdentity(RK, VecTy->getScalarType());<BR>       if (VF == 1) {<BR>         Identity = Iden;<BR>         // This vector is the Identity vector where the first element is the<BR>         // incoming scalar reduction.<BR>-        VectorStart = RdxDesc.StartValue;<BR>+        VectorStart = ReductionStartValue;<BR>       } else {<BR>         Identity = ConstantVector::getSplat(VF, Iden);<BR><BR>         // This vector is the Identity vector where the first element is the<BR>         // incoming scalar reduction.<BR>-        VectorStart = Builder.CreateInsertElement(Identity,<BR>-                                                  RdxDesc.StartValue, Zero);<BR>+        VectorStart =<BR>+            Builder.CreateInsertElement(Identity, ReductionStartValue, Zero);<BR>       }<BR>     }<BR><BR>@@ -2846,11 +2676,11 @@ void InnerLoopVectorizer::vectorizeLoop(<BR>     Builder.SetInsertPoint(LoopMiddleBlock->getFirstInsertionPt());<BR><BR>     VectorParts RdxParts;<BR>-    setDebugLocFromInst(Builder, RdxDesc.LoopExitInstr);<BR>+    setDebugLocFromInst(Builder, LoopExitInst);<BR>     for (unsigned part = 0; part < UF; ++part) {<BR>       // This PHINode contains the vectorized reduction variable, or<BR>       // the initial value vector, if we bypass the vector loop.<BR>-      VectorParts &RdxExitVal = getVectorValue(RdxDesc.LoopExitInstr);<BR>+      VectorParts &RdxExitVal = getVectorValue(LoopExitInst);<BR>       PHINode *NewPhi = Builder.CreatePHI(VecTy, 2, "rdx.vec.exit.phi");<BR>       Value *StartVal = (part == 0) ? VectorStart : Identity;<BR>       for (unsigned I = 1, E = LoopBypassBlocks.size(); I != E; ++I)<BR>@@ -2862,7 +2692,7 @@ void InnerLoopVectorizer::vectorizeLoop(<BR><BR>     // Reduce all of the unrolled parts into a single vector.<BR>     Value *ReducedPartRdx = RdxParts[0];<BR>-    unsigned Op = getReductionBinOp(RdxDesc.Kind);<BR>+    unsigned Op = ReductionDescriptor::getReductionBinOp(RK);<BR>     setDebugLocFromInst(Builder, ReducedPartRdx);<BR>     for (unsigned part = 1; part < UF; ++part) {<BR>       if (Op != Instruction::ICmp && Op != Instruction::FCmp)<BR>@@ -2871,8 +2701,8 @@ void InnerLoopVectorizer::vectorizeLoop(<BR>             Builder.CreateBinOp((Instruction::BinaryOps)Op, RdxParts[part],<BR>                                 ReducedPartRdx, "bin.rdx"));<BR>       else<BR>-        ReducedPartRdx = createMinMaxOp(Builder, RdxDesc.MinMaxKind,<BR>-                                        ReducedPartRdx, RdxParts[part]);<BR>+        ReducedPartRdx = ReductionDescriptor::createMinMaxOp(<BR>+            Builder, MinMaxKind, ReducedPartRdx, RdxParts[part]);<BR>     }<BR><BR>     if (VF > 1) {<BR>@@ -2903,7 +2733,8 @@ void InnerLoopVectorizer::vectorizeLoop(<BR>           TmpVec = addFastMathFlag(Builder.CreateBinOp(<BR>               (Instruction::BinaryOps)Op, TmpVec, Shuf, "bin.rdx"));<BR>         else<BR>-          TmpVec = createMinMaxOp(Builder, RdxDesc.MinMaxKind, TmpVec, Shuf);<BR>+          TmpVec = ReductionDescriptor::createMinMaxOp(Builder, MinMaxKind,<BR>+                                                       TmpVec, Shuf);<BR>       }<BR><BR>       // The result is in the first element of the vector.<BR>@@ -2915,7 +2746,7 @@ void InnerLoopVectorizer::vectorizeLoop(<BR>     // block and the middle block.<BR>     PHINode *BCBlockPhi = PHINode::Create(RdxPhi->getType(), 2, "bc.merge.rdx",<BR>                                           LoopScalarPreHeader->getTerminator());<BR>-    BCBlockPhi->addIncoming(RdxDesc.StartValue, LoopBypassBlocks[0]);<BR>+    BCBlockPhi->addIncoming(ReductionStartValue, LoopBypassBlocks[0]);<BR>     BCBlockPhi->addIncoming(ReducedPartRdx, LoopMiddleBlock);<BR><BR>     // Now, we need to fix the users of the reduction variable<BR>@@ -2933,7 +2764,7 @@ void InnerLoopVectorizer::vectorizeLoop(<BR><BR>       // We found our reduction value exit-PHI. Update it with the<BR>       // incoming bypass edge.<BR>-      if (LCSSAPhi->getIncomingValue(0) == RdxDesc.LoopExitInstr) {<BR>+      if (LCSSAPhi->getIncomingValue(0) == LoopExitInst) {<BR>         // Add an edge coming from the bypass.<BR>         LCSSAPhi->addIncoming(ReducedPartRdx, LoopMiddleBlock);<BR>         break;<BR>@@ -2948,7 +2779,7 @@ void InnerLoopVectorizer::vectorizeLoop(<BR>     // Pick the other block.<BR>     int SelfEdgeBlockIdx = (IncomingEdgeBlockIdx ? 0 : 1);<BR>     (RdxPhi)->setIncomingValue(SelfEdgeBlockIdx, BCBlockPhi);<BR>-    (RdxPhi)->setIncomingValue(IncomingEdgeBlockIdx, RdxDesc.LoopExitInstr);<BR>+    (RdxPhi)->setIncomingValue(IncomingEdgeBlockIdx, LoopExitInst);<BR>   }// end of for each redux variable.<BR><BR>   fixLCSSAPHIs();<BR>@@ -3712,41 +3543,9 @@ bool LoopVectorizationLegality::canVecto<BR>           continue;<BR>         }<BR><BR>-        if (AddReductionVar(Phi, RK_IntegerAdd)) {<BR>-          DEBUG(dbgs() << "LV: Found an ADD reduction PHI."<< *Phi <<"\n");<BR>-          continue;<BR>-        }<BR>-        if (AddReductionVar(Phi, RK_IntegerMult)) {<BR>-          DEBUG(dbgs() << "LV: Found a MUL reduction PHI."<< *Phi <<"\n");<BR>-          continue;<BR>-        }<BR>-        if (AddReductionVar(Phi, RK_IntegerOr)) {<BR>-          DEBUG(dbgs() << "LV: Found an OR reduction PHI."<< *Phi <<"\n");<BR>-          continue;<BR>-        }<BR>-        if (AddReductionVar(Phi, RK_IntegerAnd)) {<BR>-          DEBUG(dbgs() << "LV: Found an AND reduction PHI."<< *Phi <<"\n");<BR>-          continue;<BR>-        }<BR>-        if (AddReductionVar(Phi, RK_IntegerXor)) {<BR>-          DEBUG(dbgs() << "LV: Found a XOR reduction PHI."<< *Phi <<"\n");<BR>-          continue;<BR>-        }<BR>-        if (AddReductionVar(Phi, RK_IntegerMinMax)) {<BR>-          DEBUG(dbgs() << "LV: Found a MINMAX reduction PHI."<< *Phi <<"\n");<BR>-          continue;<BR>-        }<BR>-        if (AddReductionVar(Phi, RK_FloatMult)) {<BR>-          DEBUG(dbgs() << "LV: Found an FMult reduction PHI."<< *Phi <<"\n");<BR>-          continue;<BR>-        }<BR>-        if (AddReductionVar(Phi, RK_FloatAdd)) {<BR>-          DEBUG(dbgs() << "LV: Found an FAdd reduction PHI."<< *Phi <<"\n");<BR>-          continue;<BR>-        }<BR>-        if (AddReductionVar(Phi, RK_FloatMinMax)) {<BR>-          DEBUG(dbgs() << "LV: Found an float MINMAX reduction PHI."<< *Phi <<<BR>-                "\n");<BR>+        if (ReductionDescriptor::isReductionPHI(Phi, TheLoop,<BR>+                                                Reductions[Phi])) {<BR>+          AllowedExit.insert(Reductions[Phi].getLoopExitInstr());<BR>           continue;<BR>         }<BR><BR>@@ -4029,294 +3828,6 @@ bool LoopVectorizationLegality::canVecto<BR>   return true;<BR> }<BR><BR>-static bool hasMultipleUsesOf(Instruction *I,<BR>-                              SmallPtrSetImpl<Instruction *> &Insts) {<BR>-  unsigned NumUses = 0;<BR>-  for(User::op_iterator Use = I->op_begin(), E = I->op_end(); Use != E; ++Use) {<BR>-    if (Insts.count(dyn_cast<Instruction>(*Use)))<BR>-      ++NumUses;<BR>-    if (NumUses > 1)<BR>-      return true;<BR>-  }<BR>-<BR>-  return false;<BR>-}<BR>-<BR>-static bool areAllUsesIn(Instruction *I, SmallPtrSetImpl<Instruction *> &Set) {<BR>-  for(User::op_iterator Use = I->op_begin(), E = I->op_end(); Use != E; ++Use)<BR>-    if (!Set.count(dyn_cast<Instruction>(*Use)))<BR>-      return false;<BR>-  return true;<BR>-}<BR>-<BR>-bool LoopVectorizationLegality::AddReductionVar(PHINode *Phi,<BR>-                                                ReductionKind Kind) {<BR>-  if (Phi->getNumIncomingValues() != 2)<BR>-    return false;<BR>-<BR>-  // Reduction variables are only found in the loop header block.<BR>-  if (Phi->getParent() != TheLoop->getHeader())<BR>-    return false;<BR>-<BR>-  // Obtain the reduction start value from the value that comes from the loop<BR>-  // preheader.<BR>-  Value *RdxStart = Phi->getIncomingValueForBlock(TheLoop->getLoopPreheader());<BR>-<BR>-  // ExitInstruction is the single value which is used outside the loop.<BR>-  // We only allow for a single reduction value to be used outside the loop.<BR>-  // This includes users of the reduction, variables (which form a cycle<BR>-  // which ends in the phi node).<BR>-  Instruction *ExitInstruction = nullptr;<BR>-  // Indicates that we found a reduction operation in our scan.<BR>-  bool FoundReduxOp = false;<BR>-<BR>-  // We start with the PHI node and scan for all of the users of this<BR>-  // instruction. All users must be instructions that can be used as reduction<BR>-  // variables (such as ADD). We must have a single out-of-block user. The cycle<BR>-  // must include the original PHI.<BR>-  bool FoundStartPHI = false;<BR>-<BR>-  // To recognize min/max patterns formed by a icmp select sequence, we store<BR>-  // the number of instruction we saw from the recognized min/max pattern,<BR>-  //  to make sure we only see exactly the two instructions.<BR>-  unsigned NumCmpSelectPatternInst = 0;<BR>-  ReductionInstDesc ReduxDesc(false, nullptr);<BR>-<BR>-  SmallPtrSet<Instruction *, 8> VisitedInsts;<BR>-  SmallVector<Instruction *, 8> Worklist;<BR>-  Worklist.push_back(Phi);<BR>-  VisitedInsts.insert(Phi);<BR>-<BR>-  // A value in the reduction can be used:<BR>-  //  - By the reduction:<BR>-  //      - Reduction operation:<BR>-  //        - One use of reduction value (safe).<BR>-  //        - Multiple use of reduction value (not safe).<BR>-  //      - PHI:<BR>-  //        - All uses of the PHI must be the reduction (safe).<BR>-  //        - Otherwise, not safe.<BR>-  //  - By one instruction outside of the loop (safe).<BR>-  //  - By further instructions outside of the loop (not safe).<BR>-  //  - By an instruction that is not part of the reduction (not safe).<BR>-  //    This is either:<BR>-  //      * An instruction type other than PHI or the reduction operation.<BR>-  //      * A PHI in the header other than the initial PHI.<BR>-  while (!Worklist.empty()) {<BR>-    Instruction *Cur = Worklist.back();<BR>-    Worklist.pop_back();<BR>-<BR>-    // No Users.<BR>-    // If the instruction has no users then this is a broken chain and can't be<BR>-    // a reduction variable.<BR>-    if (Cur->use_empty())<BR>-      return false;<BR>-<BR>-    bool IsAPhi = isa<PHINode>(Cur);<BR>-<BR>-    // A header PHI use other than the original PHI.<BR>-    if (Cur != Phi && IsAPhi && Cur->getParent() == Phi->getParent())<BR>-      return false;<BR>-<BR>-    // Reductions of instructions such as Div, and Sub is only possible if the<BR>-    // LHS is the reduction variable.<BR>-    if (!Cur->isCommutative() && !IsAPhi && !isa<SelectInst>(Cur) &&<BR>-        !isa<ICmpInst>(Cur) && !isa<FCmpInst>(Cur) &&<BR>-        !VisitedInsts.count(dyn_cast<Instruction>(Cur->getOperand(0))))<BR>-      return false;<BR>-<BR>-    // Any reduction instruction must be of one of the allowed kinds.<BR>-    ReduxDesc = isReductionInstr(Cur, Kind, ReduxDesc);<BR>-    if (!ReduxDesc.IsReduction)<BR>-      return false;<BR>-<BR>-    // A reduction operation must only have one use of the reduction value.<BR>-    if (!IsAPhi && Kind != RK_IntegerMinMax && Kind != RK_FloatMinMax &&<BR>-        hasMultipleUsesOf(Cur, VisitedInsts))<BR>-      return false;<BR>-<BR>-    // All inputs to a PHI node must be a reduction value.<BR>-    if(IsAPhi && Cur != Phi && !areAllUsesIn(Cur, VisitedInsts))<BR>-      return false;<BR>-<BR>-    if (Kind == RK_IntegerMinMax && (isa<ICmpInst>(Cur) ||<BR>-                                     isa<SelectInst>(Cur)))<BR>-      ++NumCmpSelectPatternInst;<BR>-    if (Kind == RK_FloatMinMax && (isa<FCmpInst>(Cur) ||<BR>-                                   isa<SelectInst>(Cur)))<BR>-      ++NumCmpSelectPatternInst;<BR>-<BR>-    // Check  whether we found a reduction operator.<BR>-    FoundReduxOp |= !IsAPhi;<BR>-<BR>-    // Process users of current instruction. Push non-PHI nodes after PHI nodes<BR>-    // onto the stack. This way we are going to have seen all inputs to PHI<BR>-    // nodes once we get to them.<BR>-    SmallVector<Instruction *, 8> NonPHIs;<BR>-    SmallVector<Instruction *, 8> PHIs;<BR>-    for (User *U : Cur->users()) {<BR>-      Instruction *UI = cast<Instruction>(U);<BR>-<BR>-      // Check if we found the exit user.<BR>-      BasicBlock *Parent = UI->getParent();<BR>-      if (!TheLoop->contains(Parent)) {<BR>-        // Exit if you find multiple outside users or if the header phi node is<BR>-        // being used. In this case the user uses the value of the previous<BR>-        // iteration, in which case we would loose "VF-1" iterations of the<BR>-        // reduction operation if we vectorize.<BR>-        if (ExitInstruction != nullptr || Cur == Phi)<BR>-          return false;<BR>-<BR>-        // The instruction used by an outside user must be the last instruction<BR>-        // before we feed back to the reduction phi. Otherwise, we loose VF-1<BR>-        // operations on the value.<BR>-        if (std::find(Phi->op_begin(), Phi->op_end(), Cur) == Phi->op_end())<BR>-         return false;<BR>-<BR>-        ExitInstruction = Cur;<BR>-        continue;<BR>-      }<BR>-<BR>-      // Process instructions only once (termination). Each reduction cycle<BR>-      // value must only be used once, except by phi nodes and min/max<BR>-      // reductions which are represented as a cmp followed by a select.<BR>-      ReductionInstDesc IgnoredVal(false, nullptr);<BR>-      if (VisitedInsts.insert(UI).second) {<BR>-        if (isa<PHINode>(UI))<BR>-          PHIs.push_back(UI);<BR>-        else<BR>-          NonPHIs.push_back(UI);<BR>-      } else if (!isa<PHINode>(UI) &&<BR>-                 ((!isa<FCmpInst>(UI) &&<BR>-                   !isa<ICmpInst>(UI) &&<BR>-                   !isa<SelectInst>(UI)) ||<BR>-                  !isMinMaxSelectCmpPattern(UI, IgnoredVal).IsReduction))<BR>-        return false;<BR>-<BR>-      // Remember that we completed the cycle.<BR>-      if (UI == Phi)<BR>-        FoundStartPHI = true;<BR>-    }<BR>-    Worklist.append(PHIs.begin(), PHIs.end());<BR>-    Worklist.append(NonPHIs.begin(), NonPHIs.end());<BR>-  }<BR>-<BR>-  // This means we have seen one but not the other instruction of the<BR>-  // pattern or more than just a select and cmp.<BR>-  if ((Kind == RK_IntegerMinMax || Kind == RK_FloatMinMax) &&<BR>-      NumCmpSelectPatternInst != 2)<BR>-    return false;<BR>-<BR>-  if (!FoundStartPHI || !FoundReduxOp || !ExitInstruction)<BR>-    return false;<BR>-<BR>-  // We found a reduction var if we have reached the original phi node and we<BR>-  // only have a single instruction with out-of-loop users.<BR>-<BR>-  // This instruction is allowed to have out-of-loop users.<BR>-  AllowedExit.insert(ExitInstruction);<BR>-<BR>-  // Save the description of this reduction variable.<BR>-  ReductionDescriptor RD(RdxStart, ExitInstruction, Kind,<BR>-                         ReduxDesc.MinMaxKind);<BR>-  Reductions[Phi] = RD;<BR>-  // We've ended the cycle. This is a reduction variable if we have an<BR>-  // outside user and it has a binary op.<BR>-<BR>-  return true;<BR>-}<BR>-<BR>-/// Returns true if the instruction is a Select(ICmp(X, Y), X, Y) instruction<BR>-/// pattern corresponding to a min(X, Y) or max(X, Y).<BR>-LoopVectorizationLegality::ReductionInstDesc<BR>-LoopVectorizationLegality::isMinMaxSelectCmpPattern(Instruction *I,<BR>-                                                    ReductionInstDesc &Prev) {<BR>-<BR>-  assert((isa<ICmpInst>(I) || isa<FCmpInst>(I) || isa<SelectInst>(I)) &&<BR>-         "Expect a select instruction");<BR>-  Instruction *Cmp = nullptr;<BR>-  SelectInst *Select = nullptr;<BR>-<BR>-  // We must handle the select(cmp()) as a single instruction. Advance to the<BR>-  // select.<BR>-  if ((Cmp = dyn_cast<ICmpInst>(I)) || (Cmp = dyn_cast<FCmpInst>(I))) {<BR>-    if (!Cmp->hasOneUse() || !(Select = dyn_cast<SelectInst>(*I->user_begin())))<BR>-      return ReductionInstDesc(false, I);<BR>-    return ReductionInstDesc(Select, Prev.MinMaxKind);<BR>-  }<BR>-<BR>-  // Only handle single use cases for now.<BR>-  if (!(Select = dyn_cast<SelectInst>(I)))<BR>-    return ReductionInstDesc(false, I);<BR>-  if (!(Cmp = dyn_cast<ICmpInst>(I->getOperand(0))) &&<BR>-      !(Cmp = dyn_cast<FCmpInst>(I->getOperand(0))))<BR>-    return ReductionInstDesc(false, I);<BR>-  if (!Cmp->hasOneUse())<BR>-    return ReductionInstDesc(false, I);<BR>-<BR>-  Value *CmpLeft;<BR>-  Value *CmpRight;<BR>-<BR>-  // Look for a min/max pattern.<BR>-  if (m_UMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>-    return ReductionInstDesc(Select, MRK_UIntMin);<BR>-  else if (m_UMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>-    return ReductionInstDesc(Select, MRK_UIntMax);<BR>-  else if (m_SMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>-    return ReductionInstDesc(Select, MRK_SIntMax);<BR>-  else if (m_SMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>-    return ReductionInstDesc(Select, MRK_SIntMin);<BR>-  else if (m_OrdFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>-    return ReductionInstDesc(Select, MRK_FloatMin);<BR>-  else if (m_OrdFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>-    return ReductionInstDesc(Select, MRK_FloatMax);<BR>-  else if (m_UnordFMin(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>-    return ReductionInstDesc(Select, MRK_FloatMin);<BR>-  else if (m_UnordFMax(m_Value(CmpLeft), m_Value(CmpRight)).match(Select))<BR>-    return ReductionInstDesc(Select, MRK_FloatMax);<BR>-<BR>-  return ReductionInstDesc(false, I);<BR>-}<BR>-<BR>-LoopVectorizationLegality::ReductionInstDesc<BR>-LoopVectorizationLegality::isReductionInstr(Instruction *I,<BR>-                                            ReductionKind Kind,<BR>-                                            ReductionInstDesc &Prev) {<BR>-  bool FP = I->getType()->isFloatingPointTy();<BR>-  bool FastMath = FP && I->hasUnsafeAlgebra();<BR>-  switch (I->getOpcode()) {<BR>-  default:<BR>-    return ReductionInstDesc(false, I);<BR>-  case Instruction::PHI:<BR>-      if (FP && (Kind != RK_FloatMult && Kind != RK_FloatAdd &&<BR>-                 Kind != RK_FloatMinMax))<BR>-        return ReductionInstDesc(false, I);<BR>-    return ReductionInstDesc(I, Prev.MinMaxKind);<BR>-  case Instruction::Sub:<BR>-  case Instruction::Add:<BR>-    return ReductionInstDesc(Kind == RK_IntegerAdd, I);<BR>-  case Instruction::Mul:<BR>-    return ReductionInstDesc(Kind == RK_IntegerMult, I);<BR>-  case Instruction::And:<BR>-    return ReductionInstDesc(Kind == RK_IntegerAnd, I);<BR>-  case Instruction::Or:<BR>-    return ReductionInstDesc(Kind == RK_IntegerOr, I);<BR>-  case Instruction::Xor:<BR>-    return ReductionInstDesc(Kind == RK_IntegerXor, I);<BR>-  case Instruction::FMul:<BR>-    return ReductionInstDesc(Kind == RK_FloatMult && FastMath, I);<BR>-  case Instruction::FSub:<BR>-  case Instruction::FAdd:<BR>-    return ReductionInstDesc(Kind == RK_FloatAdd && FastMath, I);<BR>-  case Instruction::FCmp:<BR>-  case Instruction::ICmp:<BR>-  case Instruction::Select:<BR>-    if (Kind != RK_IntegerMinMax &&<BR>-        (!HasFunNoNaNAttr || Kind != RK_FloatMinMax))<BR>-      return ReductionInstDesc(false, I);<BR>-    return isMinMaxSelectCmpPattern(I, Prev);<BR>-  }<BR>-}<BR>-<BR> bool llvm::isInductionPHI(PHINode *Phi, ScalarEvolution *SE,<BR>                           ConstantInt *&StepValue) {<BR>   Type *PhiTy = Phi->getType();<BR><BR><BR>_______________________________________________<BR>llvm-commits mailing list<BR><A href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</A><BR><A href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target=_blank>http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</A><BR></BLOCKQUOTE></DIV><BR></DIV>
<P> </P><!--SP:kv.bhat--><!--kv.bhat:EP-->
<P> </P>
<TABLE id=confidentialsignimg>
<TBODY>
<TR>
<TD namo_lock="">
<P><IMG border=0 src="cid:T9SZN3WZA6X7@namo.co.kr"></P></TD></TR></TBODY></TABLE></X-BODY></BODY></HTML><img src='http://ext.samsung.net/mailcheck/SeenTimeChecker?do=deb3de73a46b1d55364771ae7a433ce96fc9428a5fabacd61046eb2a7007a79e6a34984216ac66b0a34d950c0c4aaac5e1f93dc7001c940a07805447a154a46fcf878f9a26ce15a0' border=0 width=0 height=0 style='display:none'>