<div dir="ltr">FYI, I missed a test that landed after this commit. However, I think Quentin ended up fixing it when he re-generated its output in r<span style="color:rgb(33,33,33)">325421. Just to try and explain what's going on when you re-land...</span></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Feb 16, 2018 at 6:29 PM Chandler Carruth <<a href="mailto:chandlerc@gmail.com">chandlerc@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">FYI, this caused PR36312. Despite that being a fuzzer-found bug, we're seeing this any lots of real code as well and its blocking us from using newer versions of LLVM.<div><br></div><div>I've reverted in r325420 for now. Sorry for any trouble.</div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Feb 6, 2018 at 8:16 AM Nirav Dave via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: niravd<br>
Date: Tue Feb  6 08:14:29 2018<br>
New Revision: 324359<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=324359&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=324359&view=rev</a><br>
Log:<br>
[DAG, X86] Improve Dependency analysis when doing multi-node<br>
Instruction Selection<br>
<br>
Cleanup cycle/validity checks in ISel (IsLegalToFold,<br>
HandleMergeInputChains) and X86 (isFusableLoadOpStore). Now do a full<br>
search for cycles / dependencies pruning the search when topological<br>
property of NodeId allows.<br>
<br>
As part of this propogate the NodeId-based cutoffs to narrow<br>
hasPreprocessorHelper searches.<br>
<br>
Reviewers: craig.topper, bogner<br>
<br>
Subscribers: llvm-commits, hiraditya<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D41293" rel="noreferrer" target="_blank">https://reviews.llvm.org/D41293</a><br>
<br>
Added:<br>
    llvm/trunk/test/CodeGen/X86/foldmem_cycle.ll<br>
    llvm/trunk/test/CodeGen/X86/load-op-store-fusion.ll<br>
Modified:<br>
    llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h<br>
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp<br>
    llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp<br>
    llvm/trunk/test/CodeGen/X86/avg.ll<br>
    llvm/trunk/test/CodeGen/X86/avx-vbroadcastf128.ll<br>
    llvm/trunk/test/CodeGen/X86/avx2-vbroadcast.ll<br>
    llvm/trunk/test/CodeGen/X86/avx2-vbroadcasti128.ll<br>
    llvm/trunk/test/CodeGen/X86/avx512-vbroadcasti128.ll<br>
    llvm/trunk/test/CodeGen/X86/i256-add.ll<br>
    llvm/trunk/test/CodeGen/X86/masked_memop.ll<br>
    llvm/trunk/test/CodeGen/X86/merge-consecutive-stores.ll<br>
    llvm/trunk/test/CodeGen/X86/nontemporal.ll<br>
    llvm/trunk/test/CodeGen/X86/store_op_load_fold2.ll<br>
    llvm/trunk/test/CodeGen/X86/subvector-broadcast.ll<br>
    llvm/trunk/test/CodeGen/X86/var-permute-256.ll<br>
    llvm/trunk/test/CodeGen/X86/vector-shuffle-variable-256.ll<br>
<br>
Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)<br>
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Tue Feb  6 08:14:29 2018<br>
@@ -796,16 +796,38 @@ public:<br>
   /// searches to be performed in parallel, caching of results across<br>
   /// queries and incremental addition to Worklist. Stops early if N is<br>
   /// found but will resume. Remember to clear Visited and Worklists<br>
-  /// if DAG changes.<br>
+  /// if DAG changes. MaxSteps gives a maximum number of nodes to visit before<br>
+  /// giving up. The TopologicalPrune flag signals that positive NodeIds are<br>
+  /// topologically ordered (Operands have strictly smaller node id) and search<br>
+  /// can be pruned leveraging this.<br>
   static bool hasPredecessorHelper(const SDNode *N,<br>
                                    SmallPtrSetImpl<const SDNode *> &Visited,<br>
                                    SmallVectorImpl<const SDNode *> &Worklist,<br>
-                                   unsigned int MaxSteps = 0) {<br>
+                                   unsigned int MaxSteps = 0,<br>
+                                   bool TopologicalPrune = false) {<br>
+    SmallVector<const SDNode *, 8> DeferredNodes;<br>
     if (Visited.count(N))<br>
       return true;<br>
+<br>
+    // Node Id's are assigned in three places: As a topological<br>
+    // ordering (> 0), during legalization (results in values set to<br>
+    // 0), and new nodes (set to -1). If N has a topolgical id then we<br>
+    // know that all nodes with ids smaller than it cannot be<br>
+    // successors and we need not check them. Filter out all node<br>
+    // that can't be matches. We add them to the worklist before exit<br>
+    // in case of multiple calls.<br>
+<br>
+    int NId = N->getNodeId();<br>
+<br>
+    bool Found = false;<br>
     while (!Worklist.empty()) {<br>
       const SDNode *M = Worklist.pop_back_val();<br>
-      bool Found = false;<br>
+      int MId = M->getNodeId();<br>
+      if (TopologicalPrune && M->getOpcode() != ISD::TokenFactor && (NId > 0) &&<br>
+          (MId > 0) && (MId < NId)) {<br>
+        DeferredNodes.push_back(M);<br>
+        continue;<br>
+      }<br>
       for (const SDValue &OpV : M->op_values()) {<br>
         SDNode *Op = OpV.getNode();<br>
         if (Visited.insert(Op).second)<br>
@@ -814,11 +836,13 @@ public:<br>
           Found = true;<br>
       }<br>
       if (Found)<br>
-        return true;<br>
+        break;<br>
       if (MaxSteps != 0 && Visited.size() >= MaxSteps)<br>
-        return false;<br>
+        break;<br>
     }<br>
-    return false;<br>
+    // Push deferred nodes back on worklist.<br>
+    Worklist.append(DeferredNodes.begin(), DeferredNodes.end());<br>
+    return Found;<br>
   }<br>
<br>
   /// Return true if all the users of N are contained in Nodes.<br>
<br>
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Tue Feb  6 08:14:29 2018<br>
@@ -2137,54 +2137,44 @@ static SDNode *findGlueUse(SDNode *N) {<br>
   return nullptr;<br>
 }<br>
<br>
-/// findNonImmUse - Return true if "Use" is a non-immediate use of "Def".<br>
-/// This function iteratively traverses up the operand chain, ignoring<br>
-/// certain nodes.<br>
-static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse,<br>
-                          SDNode *Root, SmallPtrSetImpl<SDNode*> &Visited,<br>
+/// findNonImmUse - Return true if "Def" is a predecessor of "Root" via a path<br>
+/// beyond "ImmedUse".  We may ignore chains as they are checked separately.<br>
+static bool findNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse,<br>
                           bool IgnoreChains) {<br>
-  // The NodeID's are given uniques ID's where a node ID is guaranteed to be<br>
-  // greater than all of its (recursive) operands.  If we scan to a point where<br>
-  // 'use' is smaller than the node we're scanning for, then we know we will<br>
-  // never find it.<br>
-  //<br>
-  // The Use may be -1 (unassigned) if it is a newly allocated node.  This can<br>
-  // happen because we scan down to newly selected nodes in the case of glue<br>
-  // uses.<br>
-  std::vector<SDNode *> WorkList;<br>
-  WorkList.push_back(Use);<br>
-<br>
-  while (!WorkList.empty()) {<br>
-    Use = WorkList.back();<br>
-    WorkList.pop_back();<br>
-    // NodeId topological order of TokenFactors is not guaranteed. Do not skip.<br>
-    if (Use->getOpcode() != ISD::TokenFactor &&<br>
-        Use->getNodeId() < Def->getNodeId() && Use->getNodeId() != -1)<br>
+  SmallPtrSet<const SDNode *, 16> Visited;<br>
+  SmallVector<const SDNode *, 16> WorkList;<br>
+  // Only check if we have non-immediate uses of Def.<br>
+  if (ImmedUse->isOnlyUserOf(Def))<br>
+    return false;<br>
+<br>
+  // We don't care about paths to Def that go through ImmedUse so mark it<br>
+  // visited and mark non-def operands as used.<br>
+  Visited.insert(ImmedUse);<br>
+  for (const SDValue &Op : ImmedUse->op_values()) {<br>
+    SDNode *N = Op.getNode();<br>
+    // Ignore chain deps (they are validated by<br>
+    // HandleMergeInputChains) and immediate uses<br>
+    if ((Op.getValueType() == MVT::Other && IgnoreChains) || N == Def)<br>
       continue;<br>
-<br>
-    // Don't revisit nodes if we already scanned it and didn't fail, we know we<br>
-    // won't fail if we scan it again.<br>
-    if (!Visited.insert(Use).second)<br>
+    if (!Visited.insert(N).second)<br>
       continue;<br>
+    WorkList.push_back(N);<br>
+  }<br>
<br>
-    for (const SDValue &Op : Use->op_values()) {<br>
-      // Ignore chain uses, they are validated by HandleMergeInputChains.<br>
-      if (Op.getValueType() == MVT::Other && IgnoreChains)<br>
-        continue;<br>
-<br>
+  // Initialize worklist to operands of Root.<br>
+  if (Root != ImmedUse) {<br>
+    for (const SDValue &Op : Root->op_values()) {<br>
       SDNode *N = Op.getNode();<br>
-      if (N == Def) {<br>
-        if (Use == ImmedUse || Use == Root)<br>
-          continue;  // We are not looking for immediate use.<br>
-        assert(N != Root);<br>
-        return true;<br>
-      }<br>
-<br>
-      // Traverse up the operand chain.<br>
+      // Ignore chains (they are validated by HandleMergeInputChains)<br>
+      if ((Op.getValueType() == MVT::Other && IgnoreChains) || N == Def)<br>
+        continue;<br>
+      if (!Visited.insert(N).second)<br>
+        continue;<br>
       WorkList.push_back(N);<br>
     }<br>
   }<br>
-  return false;<br>
+<br>
+  return SDNode::hasPredecessorHelper(Def, Visited, WorkList, 0, true);<br>
 }<br>
<br>
 /// IsProfitableToFold - Returns true if it's profitable to fold the specific<br>
@@ -2256,13 +2246,12 @@ bool SelectionDAGISel::IsLegalToFold(SDV<br>
<br>
     // If our query node has a glue result with a use, we've walked up it.  If<br>
     // the user (which has already been selected) has a chain or indirectly uses<br>
-    // the chain, our WalkChainUsers predicate will not consider it.  Because of<br>
+    // the chain, HandleMergeInputChains will not consider it.  Because of<br>
     // this, we cannot ignore chains in this predicate.<br>
     IgnoreChains = false;<br>
   }<br>
<br>
-  SmallPtrSet<SDNode*, 16> Visited;<br>
-  return !findNonImmUse(Root, N.getNode(), U, Root, Visited, IgnoreChains);<br>
+  return !findNonImmUse(Root, N.getNode(), U, IgnoreChains);<br>
 }<br>
<br>
 void SelectionDAGISel::Select_INLINEASM(SDNode *N) {<br>
@@ -2381,143 +2370,6 @@ void SelectionDAGISel::UpdateChains(<br>
   DEBUG(dbgs() << "ISEL: Match complete!\n");<br>
 }<br>
<br>
-enum ChainResult {<br>
-  CR_Simple,<br>
-  CR_InducesCycle,<br>
-  CR_LeadsToInteriorNode<br>
-};<br>
-<br>
-/// WalkChainUsers - Walk down the users of the specified chained node that is<br>
-/// part of the pattern we're matching, looking at all of the users we find.<br>
-/// This determines whether something is an interior node, whether we have a<br>
-/// non-pattern node in between two pattern nodes (which prevent folding because<br>
-/// it would induce a cycle) and whether we have a TokenFactor node sandwiched<br>
-/// between pattern nodes (in which case the TF becomes part of the pattern).<br>
-///<br>
-/// The walk we do here is guaranteed to be small because we quickly get down to<br>
-/// already selected nodes "below" us.<br>
-static ChainResult<br>
-WalkChainUsers(const SDNode *ChainedNode,<br>
-               SmallVectorImpl<SDNode *> &ChainedNodesInPattern,<br>
-               DenseMap<const SDNode *, ChainResult> &TokenFactorResult,<br>
-               SmallVectorImpl<SDNode *> &InteriorChainedNodes) {<br>
-  ChainResult Result = CR_Simple;<br>
-<br>
-  for (SDNode::use_iterator UI = ChainedNode->use_begin(),<br>
-         E = ChainedNode->use_end(); UI != E; ++UI) {<br>
-    // Make sure the use is of the chain, not some other value we produce.<br>
-    if (UI.getUse().getValueType() != MVT::Other) continue;<br>
-<br>
-    SDNode *User = *UI;<br>
-<br>
-    if (User->getOpcode() == ISD::HANDLENODE)  // Root of the graph.<br>
-      continue;<br>
-<br>
-    // If we see an already-selected machine node, then we've gone beyond the<br>
-    // pattern that we're selecting down into the already selected chunk of the<br>
-    // DAG.<br>
-    unsigned UserOpcode = User->getOpcode();<br>
-    if (User->isMachineOpcode() ||<br>
-        UserOpcode == ISD::CopyToReg ||<br>
-        UserOpcode == ISD::CopyFromReg ||<br>
-        UserOpcode == ISD::INLINEASM ||<br>
-        UserOpcode == ISD::EH_LABEL ||<br>
-        UserOpcode == ISD::LIFETIME_START ||<br>
-        UserOpcode == ISD::LIFETIME_END) {<br>
-      // If their node ID got reset to -1 then they've already been selected.<br>
-      // Treat them like a MachineOpcode.<br>
-      if (User->getNodeId() == -1)<br>
-        continue;<br>
-    }<br>
-<br>
-    // If we have a TokenFactor, we handle it specially.<br>
-    if (User->getOpcode() != ISD::TokenFactor) {<br>
-      // If the node isn't a token factor and isn't part of our pattern, then it<br>
-      // must be a random chained node in between two nodes we're selecting.<br>
-      // This happens when we have something like:<br>
-      //   x = load ptr<br>
-      //   call<br>
-      //   y = x+4<br>
-      //   store y -> ptr<br>
-      // Because we structurally match the load/store as a read/modify/write,<br>
-      // but the call is chained between them.  We cannot fold in this case<br>
-      // because it would induce a cycle in the graph.<br>
-      if (!std::count(ChainedNodesInPattern.begin(),<br>
-                      ChainedNodesInPattern.end(), User))<br>
-        return CR_InducesCycle;<br>
-<br>
-      // Otherwise we found a node that is part of our pattern.  For example in:<br>
-      //   x = load ptr<br>
-      //   y = x+4<br>
-      //   store y -> ptr<br>
-      // This would happen when we're scanning down from the load and see the<br>
-      // store as a user.  Record that there is a use of ChainedNode that is<br>
-      // part of the pattern and keep scanning uses.<br>
-      Result = CR_LeadsToInteriorNode;<br>
-      InteriorChainedNodes.push_back(User);<br>
-      continue;<br>
-    }<br>
-<br>
-    // If we found a TokenFactor, there are two cases to consider: first if the<br>
-    // TokenFactor is just hanging "below" the pattern we're matching (i.e. no<br>
-    // uses of the TF are in our pattern) we just want to ignore it.  Second,<br>
-    // the TokenFactor can be sandwiched in between two chained nodes, like so:<br>
-    //     [Load chain]<br>
-    //         ^<br>
-    //         |<br>
-    //       [Load]<br>
-    //       ^    ^<br>
-    //       |    \                    DAG's like cheese<br>
-    //      /       \                       do you?<br>
-    //     /         |<br>
-    // [TokenFactor] [Op]<br>
-    //     ^          ^<br>
-    //     |          |<br>
-    //      \        /<br>
-    //       \      /<br>
-    //       [Store]<br>
-    //<br>
-    // In this case, the TokenFactor becomes part of our match and we rewrite it<br>
-    // as a new TokenFactor.<br>
-    //<br>
-    // To distinguish these two cases, do a recursive walk down the uses.<br>
-    auto MemoizeResult = TokenFactorResult.find(User);<br>
-    bool Visited = MemoizeResult != TokenFactorResult.end();<br>
-    // Recursively walk chain users only if the result is not memoized.<br>
-    if (!Visited) {<br>
-      auto Res = WalkChainUsers(User, ChainedNodesInPattern, TokenFactorResult,<br>
-                                InteriorChainedNodes);<br>
-      MemoizeResult = TokenFactorResult.insert(std::make_pair(User, Res)).first;<br>
-    }<br>
-    switch (MemoizeResult->second) {<br>
-    case CR_Simple:<br>
-      // If the uses of the TokenFactor are just already-selected nodes, ignore<br>
-      // it, it is "below" our pattern.<br>
-      continue;<br>
-    case CR_InducesCycle:<br>
-      // If the uses of the TokenFactor lead to nodes that are not part of our<br>
-      // pattern that are not selected, folding would turn this into a cycle,<br>
-      // bail out now.<br>
-      return CR_InducesCycle;<br>
-    case CR_LeadsToInteriorNode:<br>
-      break;  // Otherwise, keep processing.<br>
-    }<br>
-<br>
-    // Okay, we know we're in the interesting interior case.  The TokenFactor<br>
-    // is now going to be considered part of the pattern so that we rewrite its<br>
-    // uses (it may have uses that are not part of the pattern) with the<br>
-    // ultimate chain result of the generated code.  We will also add its chain<br>
-    // inputs as inputs to the ultimate TokenFactor we create.<br>
-    Result = CR_LeadsToInteriorNode;<br>
-    if (!Visited) {<br>
-      ChainedNodesInPattern.push_back(User);<br>
-      InteriorChainedNodes.push_back(User);<br>
-    }<br>
-  }<br>
-<br>
-  return Result;<br>
-}<br>
-<br>
 /// HandleMergeInputChains - This implements the OPC_EmitMergeInputChains<br>
 /// operation for when the pattern matched at least one node with a chains.  The<br>
 /// input vector contains a list of all of the chained nodes that we match.  We<br>
@@ -2527,47 +2379,60 @@ WalkChainUsers(const SDNode *ChainedNode<br>
 static SDValue<br>
 HandleMergeInputChains(SmallVectorImpl<SDNode*> &ChainNodesMatched,<br>
                        SelectionDAG *CurDAG) {<br>
-  // Used for memoization. Without it WalkChainUsers could take exponential<br>
-  // time to run.<br>
-  DenseMap<const SDNode *, ChainResult> TokenFactorResult;<br>
-  // Walk all of the chained nodes we've matched, recursively scanning down the<br>
-  // users of the chain result. This adds any TokenFactor nodes that are caught<br>
-  // in between chained nodes to the chained and interior nodes list.<br>
-  SmallVector<SDNode*, 3> InteriorChainedNodes;<br>
-  for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) {<br>
-    if (WalkChainUsers(ChainNodesMatched[i], ChainNodesMatched,<br>
-                       TokenFactorResult,<br>
-                       InteriorChainedNodes) == CR_InducesCycle)<br>
-      return SDValue(); // Would induce a cycle.<br>
-  }<br>
<br>
-  // Okay, we have walked all the matched nodes and collected TokenFactor nodes<br>
-  // that we are interested in.  Form our input TokenFactor node.<br>
+  SmallPtrSet<const SDNode *, 16> Visited;<br>
+  SmallVector<const SDNode *, 8> Worklist;<br>
   SmallVector<SDValue, 3> InputChains;<br>
-  for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) {<br>
-    // Add the input chain of this node to the InputChains list (which will be<br>
-    // the operands of the generated TokenFactor) if it's not an interior node.<br>
-    SDNode *N = ChainNodesMatched[i];<br>
-    if (N->getOpcode() != ISD::TokenFactor) {<br>
-      if (std::count(InteriorChainedNodes.begin(),InteriorChainedNodes.end(),N))<br>
-        continue;<br>
+  unsigned int Max = 8192;<br>
<br>
-      // Otherwise, add the input chain.<br>
-      SDValue InChain = ChainNodesMatched[i]->getOperand(0);<br>
-      assert(InChain.getValueType() == MVT::Other && "Not a chain");<br>
-      InputChains.push_back(InChain);<br>
-      continue;<br>
-    }<br>
-<br>
-    // If we have a token factor, we want to add all inputs of the token factor<br>
-    // that are not part of the pattern we're matching.<br>
-    for (const SDValue &Op : N->op_values()) {<br>
-      if (!std::count(ChainNodesMatched.begin(), ChainNodesMatched.end(),<br>
-                      Op.getNode()))<br>
-        InputChains.push_back(Op);<br>
-    }<br>
+  // Quick exit on trivial merge.<br>
+  if (ChainNodesMatched.size() == 1)<br>
+    return ChainNodesMatched[0]->getOperand(0);<br>
+<br>
+  // Add chains that aren't already added (internal). Peek through<br>
+  // token factors.<br>
+  std::function<void(const SDValue)> AddChains = [&](const SDValue V) {<br>
+    if (V.getValueType() != MVT::Other)<br>
+      return;<br>
+    if (V->getOpcode() == ISD::EntryToken)<br>
+      return;<br>
+    // Newly selected nodes (-1) are always added directly.<br>
+    if (V->getNodeId() == -1)<br>
+      InputChains.push_back(V);<br>
+    else if (V->getOpcode() == ISD::TokenFactor) {<br>
+      for (int i = 0, e = V->getNumOperands(); i != e; ++i)<br>
+        AddChains(V->getOperand(i));<br>
+    } else if (!Visited.count(V.getNode()))<br>
+      InputChains.push_back(V);<br>
+  };<br>
+<br>
+  for (auto *N : ChainNodesMatched) {<br>
+    Worklist.push_back(N);<br>
+    Visited.insert(N);<br>
   }<br>
<br>
+  while (!Worklist.empty())<br>
+    AddChains(Worklist.pop_back_val()->getOperand(0));<br>
+<br>
+  // Skip the search if there are no chain dependencies.<br>
+  if (InputChains.size() == 0)<br>
+    return CurDAG->getEntryNode();<br>
+<br>
+  // If one of these chains is a successor of input, we must have a<br>
+  // node that is both the predecessor and successor of the<br>
+  // to-be-merged nodes. Fail.<br>
+  Visited.clear();<br>
+  for (SDValue V : InputChains)<br>
+    Worklist.push_back(V.getNode());<br>
+<br>
+  for (auto *N : ChainNodesMatched)<br>
+    if (SDNode::hasPredecessorHelper(N, Visited, Worklist, Max, true))<br>
+      return SDValue();<br>
+  // Fail conservatively if we stopped searching early.<br>
+  if (Visited.size() >= Max)<br>
+    return SDValue();<br>
+<br>
+  // Return merged chain.<br>
   if (InputChains.size() == 1)<br>
     return InputChains[0];<br>
   return CurDAG->getNode(ISD::TokenFactor, SDLoc(ChainNodesMatched[0]),<br>
<br>
Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)<br>
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Tue Feb  6 08:14:29 2018<br>
@@ -2104,47 +2104,58 @@ static bool isFusableLoadOpStorePattern(<br>
   // the load output chain as an operand. Return InputChain by reference.<br>
   SDValue Chain = StoreNode->getChain();<br>
<br>
-  bool ChainCheck = false;<br>
   if (Chain == Load.getValue(1)) {<br>
-    ChainCheck = true;<br>
     InputChain = LoadNode->getChain();<br>
-  } else if (Chain.getOpcode() == ISD::TokenFactor) {<br>
+    return true;<br>
+  }<br>
+<br>
+  if (Chain.getOpcode() == ISD::TokenFactor) {<br>
+    // Fusing Load-Op-Store requires predecessors of store must also<br>
+    // be predecessors of the load. This addition may cause a loop. We<br>
+    // can check this by doing a search for Load in the new<br>
+    // dependencies. As this can be expensive, heuristically prune<br>
+    // this search by visiting the uses and make sure they all have<br>
+    // smaller node id than the load.<br>
+<br>
+    bool FoundLoad = false;<br>
     SmallVector<SDValue, 4> ChainOps;<br>
+    SmallVector<const SDNode *, 4> LoopWorklist;<br>
+    SmallPtrSet<const SDNode *, 16> Visited;<br>
     for (unsigned i = 0, e = Chain.getNumOperands(); i != e; ++i) {<br>
       SDValue Op = Chain.getOperand(i);<br>
       if (Op == Load.getValue(1)) {<br>
-        ChainCheck = true;<br>
+        FoundLoad = true;<br>
         // Drop Load, but keep its chain. No cycle check necessary.<br>
         ChainOps.push_back(Load.getOperand(0));<br>
         continue;<br>
       }<br>
+      LoopWorklist.push_back(Op.getNode());<br>
+      ChainOps.push_back(Op);<br>
+    }<br>
<br>
-      // Make sure using Op as part of the chain would not cause a cycle here.<br>
-      // In theory, we could check whether the chain node is a predecessor of<br>
-      // the load. But that can be very expensive. Instead visit the uses and<br>
-      // make sure they all have smaller node id than the load.<br>
-      int LoadId = LoadNode->getNodeId();<br>
-      for (SDNode::use_iterator UI = Op.getNode()->use_begin(),<br>
-             UE = UI->use_end(); UI != UE; ++UI) {<br>
-        if (UI.getUse().getResNo() != 0)<br>
-          continue;<br>
-        if (UI->getNodeId() > LoadId)<br>
-          return false;<br>
-      }<br>
+    if (!FoundLoad)<br>
+      return false;<br>
<br>
-      ChainOps.push_back(Op);<br>
+    // If Loop Worklist is not empty. Check if we would make a loop.<br>
+    if (!LoopWorklist.empty()) {<br>
+      const unsigned int Max = 8192;<br>
+      // if Load is predecessor to potentially loop inducing chain<br>
+      // dependencies.<br>
+      if (SDNode::hasPredecessorHelper(Load.getNode(), Visited, LoopWorklist,<br>
+                                       Max, true))<br>
+        return false;<br>
+      // Fail conservatively if we ended loop search early.<br>
+      if (Visited.size() >= Max)<br>
+        return false;<br>
     }<br>
<br>
-    if (ChainCheck)<br>
-      // Make a new TokenFactor with all the other input chains except<br>
-      // for the load.<br>
-      InputChain = CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain),<br>
-                                   MVT::Other, ChainOps);<br>
+    // Make a new TokenFactor with all the other input chains except<br>
+    // for the load.<br>
+    InputChain =<br>
+        CurDAG->getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, ChainOps);<br>
+    return true;<br>
   }<br>
-  if (!ChainCheck)<br>
-    return false;<br>
-<br>
-  return true;<br>
+  return false;<br>
 }<br>
<br>
 // Change a chain of {load; op; store} of the same value into a simple op<br>
@@ -2374,6 +2385,8 @@ bool X86DAGToDAGISel::foldLoadStoreIntoM<br>
   MemOp[1] = LoadNode->getMemOperand();<br>
   Result->setMemRefs(MemOp, MemOp + 2);<br>
<br>
+  // Update Load Chain uses as well.<br>
+  ReplaceUses(SDValue(LoadNode, 1), SDValue(Result, 1));<br>
   ReplaceUses(SDValue(StoreNode, 0), SDValue(Result, 1));<br>
   ReplaceUses(SDValue(StoredVal.getNode(), 1), SDValue(Result, 0));<br>
   CurDAG->RemoveDeadNode(Node);<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/avg.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avg.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avg.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/avg.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/avg.ll Tue Feb  6 08:14:29 2018<br>
@@ -90,12 +90,12 @@ define void @avg_v16i8(<16 x i8>* %a, <1<br>
 define void @avg_v32i8(<32 x i8>* %a, <32 x i8>* %b) nounwind {<br>
 ; SSE2-LABEL: avg_v32i8:<br>
 ; SSE2:       # %bb.0:<br>
-; SSE2-NEXT:    movdqa 16(%rdi), %xmm0<br>
-; SSE2-NEXT:    movdqa (%rsi), %xmm1<br>
-; SSE2-NEXT:    pavgb (%rdi), %xmm1<br>
-; SSE2-NEXT:    pavgb 16(%rsi), %xmm0<br>
-; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
+; SSE2-NEXT:    movdqa (%rsi), %xmm0<br>
+; SSE2-NEXT:    movdqa 16(%rsi), %xmm1<br>
+; SSE2-NEXT:    pavgb (%rdi), %xmm0<br>
+; SSE2-NEXT:    pavgb 16(%rdi), %xmm1<br>
 ; SSE2-NEXT:    movdqu %xmm1, (%rax)<br>
+; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    retq<br>
 ;<br>
 ; AVX1-LABEL: avg_v32i8:<br>
@@ -545,18 +545,18 @@ define void @avg_v48i8(<48 x i8>* %a, <4<br>
 define void @avg_v64i8(<64 x i8>* %a, <64 x i8>* %b) nounwind {<br>
 ; SSE2-LABEL: avg_v64i8:<br>
 ; SSE2:       # %bb.0:<br>
-; SSE2-NEXT:    movdqa 32(%rdi), %xmm0<br>
-; SSE2-NEXT:    movdqa (%rsi), %xmm1<br>
-; SSE2-NEXT:    movdqa 16(%rsi), %xmm2<br>
+; SSE2-NEXT:    movdqa (%rsi), %xmm0<br>
+; SSE2-NEXT:    movdqa 16(%rsi), %xmm1<br>
+; SSE2-NEXT:    movdqa 32(%rsi), %xmm2<br>
 ; SSE2-NEXT:    movdqa 48(%rsi), %xmm3<br>
-; SSE2-NEXT:    pavgb (%rdi), %xmm1<br>
-; SSE2-NEXT:    pavgb 16(%rdi), %xmm2<br>
-; SSE2-NEXT:    pavgb 32(%rsi), %xmm0<br>
+; SSE2-NEXT:    pavgb (%rdi), %xmm0<br>
+; SSE2-NEXT:    pavgb 16(%rdi), %xmm1<br>
+; SSE2-NEXT:    pavgb 32(%rdi), %xmm2<br>
 ; SSE2-NEXT:    pavgb 48(%rdi), %xmm3<br>
 ; SSE2-NEXT:    movdqu %xmm3, (%rax)<br>
-; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    movdqu %xmm2, (%rax)<br>
 ; SSE2-NEXT:    movdqu %xmm1, (%rax)<br>
+; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    retq<br>
 ;<br>
 ; AVX1-LABEL: avg_v64i8:<br>
@@ -582,23 +582,23 @@ define void @avg_v64i8(<64 x i8>* %a, <6<br>
 ;<br>
 ; AVX2-LABEL: avg_v64i8:<br>
 ; AVX2:       # %bb.0:<br>
-; AVX2-NEXT:    vmovdqa 32(%rdi), %ymm0<br>
-; AVX2-NEXT:    vmovdqa (%rsi), %ymm1<br>
-; AVX2-NEXT:    vpavgb (%rdi), %ymm1, %ymm1<br>
-; AVX2-NEXT:    vpavgb 32(%rsi), %ymm0, %ymm0<br>
-; AVX2-NEXT:    vmovdqu %ymm0, (%rax)<br>
+; AVX2-NEXT:    vmovdqa (%rsi), %ymm0<br>
+; AVX2-NEXT:    vmovdqa 32(%rsi), %ymm1<br>
+; AVX2-NEXT:    vpavgb (%rdi), %ymm0, %ymm0<br>
+; AVX2-NEXT:    vpavgb 32(%rdi), %ymm1, %ymm1<br>
 ; AVX2-NEXT:    vmovdqu %ymm1, (%rax)<br>
+; AVX2-NEXT:    vmovdqu %ymm0, (%rax)<br>
 ; AVX2-NEXT:    vzeroupper<br>
 ; AVX2-NEXT:    retq<br>
 ;<br>
 ; AVX512F-LABEL: avg_v64i8:<br>
 ; AVX512F:       # %bb.0:<br>
-; AVX512F-NEXT:    vmovdqa 32(%rdi), %ymm0<br>
-; AVX512F-NEXT:    vmovdqa (%rsi), %ymm1<br>
-; AVX512F-NEXT:    vpavgb (%rdi), %ymm1, %ymm1<br>
-; AVX512F-NEXT:    vpavgb 32(%rsi), %ymm0, %ymm0<br>
-; AVX512F-NEXT:    vmovdqu %ymm0, (%rax)<br>
+; AVX512F-NEXT:    vmovdqa (%rsi), %ymm0<br>
+; AVX512F-NEXT:    vmovdqa 32(%rsi), %ymm1<br>
+; AVX512F-NEXT:    vpavgb (%rdi), %ymm0, %ymm0<br>
+; AVX512F-NEXT:    vpavgb 32(%rdi), %ymm1, %ymm1<br>
 ; AVX512F-NEXT:    vmovdqu %ymm1, (%rax)<br>
+; AVX512F-NEXT:    vmovdqu %ymm0, (%rax)<br>
 ; AVX512F-NEXT:    vzeroupper<br>
 ; AVX512F-NEXT:    retq<br>
 ;<br>
@@ -678,12 +678,12 @@ define void @avg_v8i16(<8 x i16>* %a, <8<br>
 define void @avg_v16i16(<16 x i16>* %a, <16 x i16>* %b) nounwind {<br>
 ; SSE2-LABEL: avg_v16i16:<br>
 ; SSE2:       # %bb.0:<br>
-; SSE2-NEXT:    movdqa 16(%rdi), %xmm0<br>
-; SSE2-NEXT:    movdqa (%rsi), %xmm1<br>
-; SSE2-NEXT:    pavgw (%rdi), %xmm1<br>
-; SSE2-NEXT:    pavgw 16(%rsi), %xmm0<br>
-; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
+; SSE2-NEXT:    movdqa (%rsi), %xmm0<br>
+; SSE2-NEXT:    movdqa 16(%rsi), %xmm1<br>
+; SSE2-NEXT:    pavgw (%rdi), %xmm0<br>
+; SSE2-NEXT:    pavgw 16(%rdi), %xmm1<br>
 ; SSE2-NEXT:    movdqu %xmm1, (%rax)<br>
+; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    retq<br>
 ;<br>
 ; AVX1-LABEL: avg_v16i16:<br>
@@ -729,18 +729,18 @@ define void @avg_v16i16(<16 x i16>* %a,<br>
 define void @avg_v32i16(<32 x i16>* %a, <32 x i16>* %b) nounwind {<br>
 ; SSE2-LABEL: avg_v32i16:<br>
 ; SSE2:       # %bb.0:<br>
-; SSE2-NEXT:    movdqa 32(%rdi), %xmm0<br>
-; SSE2-NEXT:    movdqa (%rsi), %xmm1<br>
-; SSE2-NEXT:    movdqa 16(%rsi), %xmm2<br>
+; SSE2-NEXT:    movdqa (%rsi), %xmm0<br>
+; SSE2-NEXT:    movdqa 16(%rsi), %xmm1<br>
+; SSE2-NEXT:    movdqa 32(%rsi), %xmm2<br>
 ; SSE2-NEXT:    movdqa 48(%rsi), %xmm3<br>
-; SSE2-NEXT:    pavgw (%rdi), %xmm1<br>
-; SSE2-NEXT:    pavgw 16(%rdi), %xmm2<br>
-; SSE2-NEXT:    pavgw 32(%rsi), %xmm0<br>
+; SSE2-NEXT:    pavgw (%rdi), %xmm0<br>
+; SSE2-NEXT:    pavgw 16(%rdi), %xmm1<br>
+; SSE2-NEXT:    pavgw 32(%rdi), %xmm2<br>
 ; SSE2-NEXT:    pavgw 48(%rdi), %xmm3<br>
 ; SSE2-NEXT:    movdqu %xmm3, (%rax)<br>
-; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    movdqu %xmm2, (%rax)<br>
 ; SSE2-NEXT:    movdqu %xmm1, (%rax)<br>
+; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    retq<br>
 ;<br>
 ; AVX1-LABEL: avg_v32i16:<br>
@@ -766,23 +766,23 @@ define void @avg_v32i16(<32 x i16>* %a,<br>
 ;<br>
 ; AVX2-LABEL: avg_v32i16:<br>
 ; AVX2:       # %bb.0:<br>
-; AVX2-NEXT:    vmovdqa 32(%rdi), %ymm0<br>
-; AVX2-NEXT:    vmovdqa (%rsi), %ymm1<br>
-; AVX2-NEXT:    vpavgw (%rdi), %ymm1, %ymm1<br>
-; AVX2-NEXT:    vpavgw 32(%rsi), %ymm0, %ymm0<br>
-; AVX2-NEXT:    vmovdqu %ymm0, (%rax)<br>
+; AVX2-NEXT:    vmovdqa (%rsi), %ymm0<br>
+; AVX2-NEXT:    vmovdqa 32(%rsi), %ymm1<br>
+; AVX2-NEXT:    vpavgw (%rdi), %ymm0, %ymm0<br>
+; AVX2-NEXT:    vpavgw 32(%rdi), %ymm1, %ymm1<br>
 ; AVX2-NEXT:    vmovdqu %ymm1, (%rax)<br>
+; AVX2-NEXT:    vmovdqu %ymm0, (%rax)<br>
 ; AVX2-NEXT:    vzeroupper<br>
 ; AVX2-NEXT:    retq<br>
 ;<br>
 ; AVX512F-LABEL: avg_v32i16:<br>
 ; AVX512F:       # %bb.0:<br>
-; AVX512F-NEXT:    vmovdqa 32(%rdi), %ymm0<br>
-; AVX512F-NEXT:    vmovdqa (%rsi), %ymm1<br>
-; AVX512F-NEXT:    vpavgw (%rdi), %ymm1, %ymm1<br>
-; AVX512F-NEXT:    vpavgw 32(%rsi), %ymm0, %ymm0<br>
-; AVX512F-NEXT:    vmovdqu %ymm0, (%rax)<br>
+; AVX512F-NEXT:    vmovdqa (%rsi), %ymm0<br>
+; AVX512F-NEXT:    vmovdqa 32(%rsi), %ymm1<br>
+; AVX512F-NEXT:    vpavgw (%rdi), %ymm0, %ymm0<br>
+; AVX512F-NEXT:    vpavgw 32(%rdi), %ymm1, %ymm1<br>
 ; AVX512F-NEXT:    vmovdqu %ymm1, (%rax)<br>
+; AVX512F-NEXT:    vmovdqu %ymm0, (%rax)<br>
 ; AVX512F-NEXT:    vzeroupper<br>
 ; AVX512F-NEXT:    retq<br>
 ;<br>
@@ -891,9 +891,9 @@ define void @avg_v32i8_2(<32 x i8>* %a,<br>
 ; SSE2-LABEL: avg_v32i8_2:<br>
 ; SSE2:       # %bb.0:<br>
 ; SSE2-NEXT:    movdqa (%rdi), %xmm0<br>
-; SSE2-NEXT:    movdqa 16(%rsi), %xmm1<br>
+; SSE2-NEXT:    movdqa 16(%rdi), %xmm1<br>
 ; SSE2-NEXT:    pavgb (%rsi), %xmm0<br>
-; SSE2-NEXT:    pavgb 16(%rdi), %xmm1<br>
+; SSE2-NEXT:    pavgb 16(%rsi), %xmm1<br>
 ; SSE2-NEXT:    movdqu %xmm1, (%rax)<br>
 ; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    retq<br>
@@ -1072,9 +1072,9 @@ define void @avg_v16i16_2(<16 x i16>* %a<br>
 ; SSE2-LABEL: avg_v16i16_2:<br>
 ; SSE2:       # %bb.0:<br>
 ; SSE2-NEXT:    movdqa (%rdi), %xmm0<br>
-; SSE2-NEXT:    movdqa 16(%rsi), %xmm1<br>
+; SSE2-NEXT:    movdqa 16(%rdi), %xmm1<br>
 ; SSE2-NEXT:    pavgw (%rsi), %xmm0<br>
-; SSE2-NEXT:    pavgw 16(%rdi), %xmm1<br>
+; SSE2-NEXT:    pavgw 16(%rsi), %xmm1<br>
 ; SSE2-NEXT:    movdqu %xmm1, (%rax)<br>
 ; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    retq<br>
@@ -1124,14 +1124,14 @@ define void @avg_v32i16_2(<32 x i16>* %a<br>
 ; SSE2:       # %bb.0:<br>
 ; SSE2-NEXT:    movdqa (%rdi), %xmm0<br>
 ; SSE2-NEXT:    movdqa 16(%rdi), %xmm1<br>
-; SSE2-NEXT:    movdqa 48(%rdi), %xmm2<br>
-; SSE2-NEXT:    movdqa 32(%rsi), %xmm3<br>
+; SSE2-NEXT:    movdqa 32(%rdi), %xmm2<br>
+; SSE2-NEXT:    movdqa 48(%rdi), %xmm3<br>
 ; SSE2-NEXT:    pavgw (%rsi), %xmm0<br>
 ; SSE2-NEXT:    pavgw 16(%rsi), %xmm1<br>
-; SSE2-NEXT:    pavgw 32(%rdi), %xmm3<br>
-; SSE2-NEXT:    pavgw 48(%rsi), %xmm2<br>
-; SSE2-NEXT:    movdqu %xmm2, (%rax)<br>
+; SSE2-NEXT:    pavgw 32(%rsi), %xmm2<br>
+; SSE2-NEXT:    pavgw 48(%rsi), %xmm3<br>
 ; SSE2-NEXT:    movdqu %xmm3, (%rax)<br>
+; SSE2-NEXT:    movdqu %xmm2, (%rax)<br>
 ; SSE2-NEXT:    movdqu %xmm1, (%rax)<br>
 ; SSE2-NEXT:    movdqu %xmm0, (%rax)<br>
 ; SSE2-NEXT:    retq<br>
@@ -1160,9 +1160,9 @@ define void @avg_v32i16_2(<32 x i16>* %a<br>
 ; AVX2-LABEL: avg_v32i16_2:<br>
 ; AVX2:       # %bb.0:<br>
 ; AVX2-NEXT:    vmovdqa (%rdi), %ymm0<br>
-; AVX2-NEXT:    vmovdqa 32(%rsi), %ymm1<br>
+; AVX2-NEXT:    vmovdqa 32(%rdi), %ymm1<br>
 ; AVX2-NEXT:    vpavgw (%rsi), %ymm0, %ymm0<br>
-; AVX2-NEXT:    vpavgw 32(%rdi), %ymm1, %ymm1<br>
+; AVX2-NEXT:    vpavgw 32(%rsi), %ymm1, %ymm1<br>
 ; AVX2-NEXT:    vmovdqu %ymm1, (%rax)<br>
 ; AVX2-NEXT:    vmovdqu %ymm0, (%rax)<br>
 ; AVX2-NEXT:    vzeroupper<br>
@@ -1171,9 +1171,9 @@ define void @avg_v32i16_2(<32 x i16>* %a<br>
 ; AVX512F-LABEL: avg_v32i16_2:<br>
 ; AVX512F:       # %bb.0:<br>
 ; AVX512F-NEXT:    vmovdqa (%rdi), %ymm0<br>
-; AVX512F-NEXT:    vmovdqa 32(%rsi), %ymm1<br>
+; AVX512F-NEXT:    vmovdqa 32(%rdi), %ymm1<br>
 ; AVX512F-NEXT:    vpavgw (%rsi), %ymm0, %ymm0<br>
-; AVX512F-NEXT:    vpavgw 32(%rdi), %ymm1, %ymm1<br>
+; AVX512F-NEXT:    vpavgw 32(%rsi), %ymm1, %ymm1<br>
 ; AVX512F-NEXT:    vmovdqu %ymm1, (%rax)<br>
 ; AVX512F-NEXT:    vmovdqu %ymm0, (%rax)<br>
 ; AVX512F-NEXT:    vzeroupper<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/avx-vbroadcastf128.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-vbroadcastf128.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-vbroadcastf128.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/avx-vbroadcastf128.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/avx-vbroadcastf128.ll Tue Feb  6 08:14:29 2018<br>
@@ -235,18 +235,16 @@ define <8 x i32> @PR29088(<4 x i32>* %p0<br>
 ; X32:       # %bb.0:<br>
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-NEXT:    vmovaps (%ecx), %xmm0<br>
 ; X32-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X32-NEXT:    vbroadcastf128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X32-NEXT:    vmovaps %ymm1, (%eax)<br>
-; X32-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X32-NEXT:    retl<br>
 ;<br>
 ; X64-LABEL: PR29088:<br>
 ; X64:       # %bb.0:<br>
-; X64-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X64-NEXT:    vbroadcastf128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-NEXT:    vmovaps %ymm1, (%rsi)<br>
-; X64-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-NEXT:    retq<br>
   %ld = load <4 x i32>, <4 x i32>* %p0<br>
   store <8 x float> zeroinitializer, <8 x float>* %p1<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/avx2-vbroadcast.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx2-vbroadcast.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx2-vbroadcast.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/avx2-vbroadcast.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/avx2-vbroadcast.ll Tue Feb  6 08:14:29 2018<br>
@@ -1065,9 +1065,7 @@ define void @isel_crash_16b(i8* %cV_R.ad<br>
 ; X64:       ## %bb.0: ## %eintry<br>
 ; X64-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
 ; X64-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-NEXT:    movb (%rdi), %al<br>
-; X64-NEXT:    vmovd %eax, %xmm1<br>
-; X64-NEXT:    vpbroadcastb %xmm1, %xmm1<br>
+; X64-NEXT:    vpbroadcastb (%rdi), %xmm1<br>
 ; X64-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
 ; X64-NEXT:    vmovdqa %xmm1, -{{[0-9]+}}(%rsp)<br>
 ; X64-NEXT:    retq<br>
@@ -1118,9 +1116,7 @@ define void @isel_crash_32b(i8* %cV_R.ad<br>
 ; X64-NEXT:    subq $128, %rsp<br>
 ; X64-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
 ; X64-NEXT:    vmovaps %ymm0, (%rsp)<br>
-; X64-NEXT:    movb (%rdi), %al<br>
-; X64-NEXT:    vmovd %eax, %xmm1<br>
-; X64-NEXT:    vpbroadcastb %xmm1, %ymm1<br>
+; X64-NEXT:    vpbroadcastb (%rdi), %ymm1<br>
 ; X64-NEXT:    vmovaps %ymm0, {{[0-9]+}}(%rsp)<br>
 ; X64-NEXT:    vmovdqa %ymm1, {{[0-9]+}}(%rsp)<br>
 ; X64-NEXT:    movq %rbp, %rsp<br>
@@ -1160,9 +1156,7 @@ define void @isel_crash_8w(i16* %cV_R.ad<br>
 ; X64:       ## %bb.0: ## %entry<br>
 ; X64-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
 ; X64-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-NEXT:    movzwl (%rdi), %eax<br>
-; X64-NEXT:    vmovd %eax, %xmm1<br>
-; X64-NEXT:    vpbroadcastw %xmm1, %xmm1<br>
+; X64-NEXT:    vpbroadcastw (%rdi), %xmm1<br>
 ; X64-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
 ; X64-NEXT:    vmovdqa %xmm1, -{{[0-9]+}}(%rsp)<br>
 ; X64-NEXT:    retq<br>
@@ -1213,9 +1207,7 @@ define void @isel_crash_16w(i16* %cV_R.a<br>
 ; X64-NEXT:    subq $128, %rsp<br>
 ; X64-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
 ; X64-NEXT:    vmovaps %ymm0, (%rsp)<br>
-; X64-NEXT:    movzwl (%rdi), %eax<br>
-; X64-NEXT:    vmovd %eax, %xmm1<br>
-; X64-NEXT:    vpbroadcastw %xmm1, %ymm1<br>
+; X64-NEXT:    vpbroadcastw (%rdi), %ymm1<br>
 ; X64-NEXT:    vmovaps %ymm0, {{[0-9]+}}(%rsp)<br>
 ; X64-NEXT:    vmovdqa %ymm1, {{[0-9]+}}(%rsp)<br>
 ; X64-NEXT:    movq %rbp, %rsp<br>
@@ -1251,26 +1243,14 @@ define void @isel_crash_4d(i32* %cV_R.ad<br>
 ; X32-NEXT:    addl $60, %esp<br>
 ; X32-NEXT:    retl<br>
 ;<br>
-; X64-AVX2-LABEL: isel_crash_4d:<br>
-; X64-AVX2:       ## %bb.0: ## %entry<br>
-; X64-AVX2-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
-; X64-AVX2-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    movl (%rdi), %eax<br>
-; X64-AVX2-NEXT:    vmovd %eax, %xmm1<br>
-; X64-AVX2-NEXT:    vpbroadcastd %xmm1, %xmm1<br>
-; X64-AVX2-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    vmovdqa %xmm1, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    retq<br>
-;<br>
-; X64-AVX512VL-LABEL: isel_crash_4d:<br>
-; X64-AVX512VL:       ## %bb.0: ## %entry<br>
-; X64-AVX512VL-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
-; X64-AVX512VL-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    movl (%rdi), %eax<br>
-; X64-AVX512VL-NEXT:    vpbroadcastd %eax, %xmm1<br>
-; X64-AVX512VL-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    vmovdqa %xmm1, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    retq<br>
+; X64-LABEL: isel_crash_4d:<br>
+; X64:       ## %bb.0: ## %entry<br>
+; X64-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
+; X64-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    vbroadcastss (%rdi), %xmm1<br>
+; X64-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    vmovaps %xmm1, -{{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    retq<br>
 entry:<br>
   %__a.addr.i = alloca <<a href="https://maps.google.com/?q=2+x+i64&entry=gmail&source=g" target="_blank">2 x i64</a>>, align 16<br>
   %__b.addr.i = alloca <<a href="https://maps.google.com/?q=2+x+i64&entry=gmail&source=g" target="_blank">2 x i64</a>>, align 16<br>
@@ -1307,46 +1287,24 @@ define void @isel_crash_8d(i32* %cV_R.ad<br>
 ; X32-NEXT:    vzeroupper<br>
 ; X32-NEXT:    retl<br>
 ;<br>
-; X64-AVX2-LABEL: isel_crash_8d:<br>
-; X64-AVX2:       ## %bb.0: ## %eintry<br>
-; X64-AVX2-NEXT:    pushq %rbp<br>
-; X64-AVX2-NEXT:    .cfi_def_cfa_offset 16<br>
-; X64-AVX2-NEXT:    .cfi_offset %rbp, -16<br>
-; X64-AVX2-NEXT:    movq %rsp, %rbp<br>
-; X64-AVX2-NEXT:    .cfi_def_cfa_register %rbp<br>
-; X64-AVX2-NEXT:    andq $-32, %rsp<br>
-; X64-AVX2-NEXT:    subq $128, %rsp<br>
-; X64-AVX2-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
-; X64-AVX2-NEXT:    vmovaps %ymm0, (%rsp)<br>
-; X64-AVX2-NEXT:    movl (%rdi), %eax<br>
-; X64-AVX2-NEXT:    vmovd %eax, %xmm1<br>
-; X64-AVX2-NEXT:    vpbroadcastd %xmm1, %ymm1<br>
-; X64-AVX2-NEXT:    vmovaps %ymm0, {{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    vmovdqa %ymm1, {{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    movq %rbp, %rsp<br>
-; X64-AVX2-NEXT:    popq %rbp<br>
-; X64-AVX2-NEXT:    vzeroupper<br>
-; X64-AVX2-NEXT:    retq<br>
-;<br>
-; X64-AVX512VL-LABEL: isel_crash_8d:<br>
-; X64-AVX512VL:       ## %bb.0: ## %eintry<br>
-; X64-AVX512VL-NEXT:    pushq %rbp<br>
-; X64-AVX512VL-NEXT:    .cfi_def_cfa_offset 16<br>
-; X64-AVX512VL-NEXT:    .cfi_offset %rbp, -16<br>
-; X64-AVX512VL-NEXT:    movq %rsp, %rbp<br>
-; X64-AVX512VL-NEXT:    .cfi_def_cfa_register %rbp<br>
-; X64-AVX512VL-NEXT:    andq $-32, %rsp<br>
-; X64-AVX512VL-NEXT:    subq $128, %rsp<br>
-; X64-AVX512VL-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
-; X64-AVX512VL-NEXT:    vmovaps %ymm0, (%rsp)<br>
-; X64-AVX512VL-NEXT:    movl (%rdi), %eax<br>
-; X64-AVX512VL-NEXT:    vpbroadcastd %eax, %ymm1<br>
-; X64-AVX512VL-NEXT:    vmovaps %ymm0, {{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    vmovdqa %ymm1, {{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    movq %rbp, %rsp<br>
-; X64-AVX512VL-NEXT:    popq %rbp<br>
-; X64-AVX512VL-NEXT:    vzeroupper<br>
-; X64-AVX512VL-NEXT:    retq<br>
+; X64-LABEL: isel_crash_8d:<br>
+; X64:       ## %bb.0: ## %eintry<br>
+; X64-NEXT:    pushq %rbp<br>
+; X64-NEXT:    .cfi_def_cfa_offset 16<br>
+; X64-NEXT:    .cfi_offset %rbp, -16<br>
+; X64-NEXT:    movq %rsp, %rbp<br>
+; X64-NEXT:    .cfi_def_cfa_register %rbp<br>
+; X64-NEXT:    andq $-32, %rsp<br>
+; X64-NEXT:    subq $128, %rsp<br>
+; X64-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
+; X64-NEXT:    vmovaps %ymm0, (%rsp)<br>
+; X64-NEXT:    vbroadcastss (%rdi), %ymm1<br>
+; X64-NEXT:    vmovaps %ymm0, {{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    vmovaps %ymm1, {{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    movq %rbp, %rsp<br>
+; X64-NEXT:    popq %rbp<br>
+; X64-NEXT:    vzeroupper<br>
+; X64-NEXT:    retq<br>
 eintry:<br>
   %__a.addr.i = alloca <<a href="https://maps.google.com/?q=4+x+i64&entry=gmail&source=g" target="_blank">4 x i64</a>>, align 16<br>
   %__b.addr.i = alloca <<a href="https://maps.google.com/?q=4+x+i64&entry=gmail&source=g" target="_blank">4 x i64</a>>, align 16<br>
@@ -1370,33 +1328,20 @@ define void @isel_crash_<a href="https://maps.google.com/?q=2q(i64*+%25cV&entry=gmail&source=g" target="_blank">2q(i64* %cV</a>_R.ad<br>
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
 ; X32-NEXT:    vmovaps %xmm0, (%esp)<br>
-; X32-NEXT:    vmovq {{.*#+}} xmm1 = mem[0],zero<br>
-; X32-NEXT:    vpbroadcastq %xmm1, %xmm1<br>
+; X32-NEXT:    vpbroadcastq (%eax), %xmm1<br>
 ; X32-NEXT:    vmovaps %xmm0, {{[0-9]+}}(%esp)<br>
 ; X32-NEXT:    vmovdqa %xmm1, {{[0-9]+}}(%esp)<br>
 ; X32-NEXT:    addl $60, %esp<br>
 ; X32-NEXT:    retl<br>
 ;<br>
-; X64-AVX2-LABEL: isel_crash_2q:<br>
-; X64-AVX2:       ## %bb.0: ## %entry<br>
-; X64-AVX2-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
-; X64-AVX2-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    movq (%rdi), %rax<br>
-; X64-AVX2-NEXT:    vmovq %rax, %xmm1<br>
-; X64-AVX2-NEXT:    vpbroadcastq %xmm1, %xmm1<br>
-; X64-AVX2-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    vmovdqa %xmm1, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    retq<br>
-;<br>
-; X64-AVX512VL-LABEL: isel_crash_2q:<br>
-; X64-AVX512VL:       ## %bb.0: ## %entry<br>
-; X64-AVX512VL-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
-; X64-AVX512VL-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    movq (%rdi), %rax<br>
-; X64-AVX512VL-NEXT:    vpbroadcastq %rax, %xmm1<br>
-; X64-AVX512VL-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    vmovdqa %xmm1, -{{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    retq<br>
+; X64-LABEL: isel_crash_2q:<br>
+; X64:       ## %bb.0: ## %entry<br>
+; X64-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
+; X64-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    vpbroadcastq (%rdi), %xmm1<br>
+; X64-NEXT:    vmovaps %xmm0, -{{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    vmovdqa %xmm1, -{{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    retq<br>
 entry:<br>
   %__a.addr.i = alloca <<a href="https://maps.google.com/?q=2+x+i64&entry=gmail&source=g" target="_blank">2 x i64</a>>, align 16<br>
   %__b.addr.i = alloca <<a href="https://maps.google.com/?q=2+x+i64&entry=gmail&source=g" target="_blank">2 x i64</a>>, align 16<br>
@@ -1433,46 +1378,24 @@ define void @isel_crash_<a href="https://maps.google.com/?q=4q(i64*+%25cV&entry=gmail&source=g" target="_blank">4q(i64* %cV</a>_R.ad<br>
 ; X32-NEXT:    vzeroupper<br>
 ; X32-NEXT:    retl<br>
 ;<br>
-; X64-AVX2-LABEL: isel_crash_4q:<br>
-; X64-AVX2:       ## %bb.0: ## %eintry<br>
-; X64-AVX2-NEXT:    pushq %rbp<br>
-; X64-AVX2-NEXT:    .cfi_def_cfa_offset 16<br>
-; X64-AVX2-NEXT:    .cfi_offset %rbp, -16<br>
-; X64-AVX2-NEXT:    movq %rsp, %rbp<br>
-; X64-AVX2-NEXT:    .cfi_def_cfa_register %rbp<br>
-; X64-AVX2-NEXT:    andq $-32, %rsp<br>
-; X64-AVX2-NEXT:    subq $128, %rsp<br>
-; X64-AVX2-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
-; X64-AVX2-NEXT:    vmovaps %ymm0, (%rsp)<br>
-; X64-AVX2-NEXT:    movq (%rdi), %rax<br>
-; X64-AVX2-NEXT:    vmovq %rax, %xmm1<br>
-; X64-AVX2-NEXT:    vpbroadcastq %xmm1, %ymm1<br>
-; X64-AVX2-NEXT:    vmovaps %ymm0, {{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    vmovdqa %ymm1, {{[0-9]+}}(%rsp)<br>
-; X64-AVX2-NEXT:    movq %rbp, %rsp<br>
-; X64-AVX2-NEXT:    popq %rbp<br>
-; X64-AVX2-NEXT:    vzeroupper<br>
-; X64-AVX2-NEXT:    retq<br>
-;<br>
-; X64-AVX512VL-LABEL: isel_crash_4q:<br>
-; X64-AVX512VL:       ## %bb.0: ## %eintry<br>
-; X64-AVX512VL-NEXT:    pushq %rbp<br>
-; X64-AVX512VL-NEXT:    .cfi_def_cfa_offset 16<br>
-; X64-AVX512VL-NEXT:    .cfi_offset %rbp, -16<br>
-; X64-AVX512VL-NEXT:    movq %rsp, %rbp<br>
-; X64-AVX512VL-NEXT:    .cfi_def_cfa_register %rbp<br>
-; X64-AVX512VL-NEXT:    andq $-32, %rsp<br>
-; X64-AVX512VL-NEXT:    subq $128, %rsp<br>
-; X64-AVX512VL-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
-; X64-AVX512VL-NEXT:    vmovaps %ymm0, (%rsp)<br>
-; X64-AVX512VL-NEXT:    movq (%rdi), %rax<br>
-; X64-AVX512VL-NEXT:    vpbroadcastq %rax, %ymm1<br>
-; X64-AVX512VL-NEXT:    vmovaps %ymm0, {{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    vmovdqa %ymm1, {{[0-9]+}}(%rsp)<br>
-; X64-AVX512VL-NEXT:    movq %rbp, %rsp<br>
-; X64-AVX512VL-NEXT:    popq %rbp<br>
-; X64-AVX512VL-NEXT:    vzeroupper<br>
-; X64-AVX512VL-NEXT:    retq<br>
+; X64-LABEL: isel_crash_4q:<br>
+; X64:       ## %bb.0: ## %eintry<br>
+; X64-NEXT:    pushq %rbp<br>
+; X64-NEXT:    .cfi_def_cfa_offset 16<br>
+; X64-NEXT:    .cfi_offset %rbp, -16<br>
+; X64-NEXT:    movq %rsp, %rbp<br>
+; X64-NEXT:    .cfi_def_cfa_register %rbp<br>
+; X64-NEXT:    andq $-32, %rsp<br>
+; X64-NEXT:    subq $128, %rsp<br>
+; X64-NEXT:    vxorps %xmm0, %xmm0, %xmm0<br>
+; X64-NEXT:    vmovaps %ymm0, (%rsp)<br>
+; X64-NEXT:    vbroadcastsd (%rdi), %ymm1<br>
+; X64-NEXT:    vmovaps %ymm0, {{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    vmovaps %ymm1, {{[0-9]+}}(%rsp)<br>
+; X64-NEXT:    movq %rbp, %rsp<br>
+; X64-NEXT:    popq %rbp<br>
+; X64-NEXT:    vzeroupper<br>
+; X64-NEXT:    retq<br>
 eintry:<br>
   %__a.addr.i = alloca <<a href="https://maps.google.com/?q=4+x+i64&entry=gmail&source=g" target="_blank">4 x i64</a>>, align 16<br>
   %__b.addr.i = alloca <<a href="https://maps.google.com/?q=4+x+i64&entry=gmail&source=g" target="_blank">4 x i64</a>>, align 16<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/avx2-vbroadcasti128.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx2-vbroadcasti128.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx2-vbroadcasti128.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/avx2-vbroadcasti128.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/avx2-vbroadcasti128.ll Tue Feb  6 08:14:29 2018<br>
@@ -271,18 +271,16 @@ define <8 x i32> @PR29088(<4 x i32>* %p0<br>
 ; X32:       # %bb.0:<br>
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-NEXT:    vmovaps (%ecx), %xmm0<br>
 ; X32-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X32-NEXT:    vbroadcastf128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X32-NEXT:    vmovaps %ymm1, (%eax)<br>
-; X32-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X32-NEXT:    retl<br>
 ;<br>
 ; X64-LABEL: PR29088:<br>
 ; X64:       # %bb.0:<br>
-; X64-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X64-NEXT:    vbroadcastf128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-NEXT:    vmovaps %ymm1, (%rsi)<br>
-; X64-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-NEXT:    retq<br>
   %ld = load <4 x i32>, <4 x i32>* %p0<br>
   store <8 x float> zeroinitializer, <8 x float>* %p1<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/avx512-vbroadcasti128.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx512-vbroadcasti128.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx512-vbroadcasti128.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/avx512-vbroadcasti128.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/avx512-vbroadcasti128.ll Tue Feb  6 08:14:29 2018<br>
@@ -186,26 +186,23 @@ define <64 x i8> @test_broadcast_16i8_64<br>
 define <8 x i32> @PR29088(<4 x i32>* %p0, <8 x float>* %p1) {<br>
 ; X64-AVX512VL-LABEL: PR29088:<br>
 ; X64-AVX512VL:       ## %bb.0:<br>
-; X64-AVX512VL-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-AVX512VL-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
+; X64-AVX512VL-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-AVX512VL-NEXT:    vmovdqa %ymm1, (%rsi)<br>
-; X64-AVX512VL-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-AVX512VL-NEXT:    retq<br>
 ;<br>
 ; X64-AVX512BWVL-LABEL: PR29088:<br>
 ; X64-AVX512BWVL:       ## %bb.0:<br>
-; X64-AVX512BWVL-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-AVX512BWVL-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
+; X64-AVX512BWVL-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-AVX512BWVL-NEXT:    vmovdqa %ymm1, (%rsi)<br>
-; X64-AVX512BWVL-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-AVX512BWVL-NEXT:    retq<br>
 ;<br>
 ; X64-AVX512DQVL-LABEL: PR29088:<br>
 ; X64-AVX512DQVL:       ## %bb.0:<br>
-; X64-AVX512DQVL-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-AVX512DQVL-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X64-AVX512DQVL-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-AVX512DQVL-NEXT:    vmovaps %ymm1, (%rsi)<br>
-; X64-AVX512DQVL-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-AVX512DQVL-NEXT:    retq<br>
   %ld = load <4 x i32>, <4 x i32>* %p0<br>
   store <8 x float> zeroinitializer, <8 x float>* %p1<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/foldmem_cycle.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/foldmem_cycle.ll?rev=324359&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/foldmem_cycle.ll?rev=324359&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/foldmem_cycle.ll (added)<br>
+++ llvm/trunk/test/CodeGen/X86/foldmem_cycle.ll Tue Feb  6 08:14:29 2018<br>
@@ -0,0 +1,34 @@<br>
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py<br>
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=X64<br>
+<br>
+; The load should not be merged with the and asit causes a cycle in the DAG.<br>
+<br>
+define void @foo() {<br>
+; X64-LABEL: foo:<br>
+; X64:       # %bb.0: # %entry<br>
+; X64-NEXT:    pushq %rbx<br>
+; X64-NEXT:    .cfi_def_cfa_offset 16<br>
+; X64-NEXT:    .cfi_offset %rbx, -16<br>
+; X64-NEXT:    movl (%rax), %ebx<br>
+; X64-NEXT:    callq bar<br>
+; X64-NEXT:    testl %ebx, %eax<br>
+; X64-NEXT:    jne .LBB0_2<br>
+; X64-NEXT:  # %bb.1: # %if.then<br>
+; X64-NEXT:    popq %rbx<br>
+; X64-NEXT:    retq<br>
+; X64-NEXT:  .LBB0_2: # %if.end<br>
+entry:<br>
+  %0 = load i32, i32* undef<br>
+  %call = tail call i32 @bar()<br>
+  %and = and i32 %call, %0<br>
+  %tobool = icmp eq i32 %and, 0<br>
+  br i1 %tobool, label %if.then, label %if.end<br>
+<br>
+if.then:<br>
+  ret void<br>
+<br>
+if.end:<br>
+  unreachable<br>
+}<br>
+<br>
+declare i32 @bar()<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/i256-add.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/i256-add.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/i256-add.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/i256-add.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/i256-add.ll Tue Feb  6 08:14:29 2018<br>
@@ -9,40 +9,30 @@ define void @add(i256* %p, i256* %q) nou<br>
 ; X32-NEXT:    pushl %ebx<br>
 ; X32-NEXT:    pushl %edi<br>
 ; X32-NEXT:    pushl %esi<br>
-; X32-NEXT:    subl $12, %esp<br>
+; X32-NEXT:    subl $8, %esp<br>
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
+; X32-NEXT:    movl 28(%eax), %ecx<br>
+; X32-NEXT:    movl %ecx, {{[0-9]+}}(%esp) # 4-byte Spill<br>
+; X32-NEXT:    movl 24(%eax), %ecx<br>
+; X32-NEXT:    movl %ecx, (%esp) # 4-byte Spill<br>
+; X32-NEXT:    movl 20(%eax), %esi<br>
+; X32-NEXT:    movl 16(%eax), %edi<br>
+; X32-NEXT:    movl 12(%eax), %ebx<br>
+; X32-NEXT:    movl 8(%eax), %ebp<br>
+; X32-NEXT:    movl (%eax), %ecx<br>
+; X32-NEXT:    movl 4(%eax), %edx<br>
 ; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-NEXT:    movl 8(%ecx), %edi<br>
-; X32-NEXT:    movl (%ecx), %edx<br>
-; X32-NEXT:    movl 4(%ecx), %ebx<br>
-; X32-NEXT:    movl 28(%eax), %esi<br>
-; X32-NEXT:    movl %esi, {{[0-9]+}}(%esp) # 4-byte Spill<br>
-; X32-NEXT:    movl 24(%eax), %ebp<br>
-; X32-NEXT:    addl (%eax), %edx<br>
-; X32-NEXT:    movl %edx, {{[0-9]+}}(%esp) # 4-byte Spill<br>
-; X32-NEXT:    adcl 4(%eax), %ebx<br>
-; X32-NEXT:    adcl 8(%eax), %edi<br>
-; X32-NEXT:    movl %edi, (%esp) # 4-byte Spill<br>
-; X32-NEXT:    movl 20(%eax), %edi<br>
-; X32-NEXT:    movl 12(%eax), %edx<br>
-; X32-NEXT:    movl 16(%eax), %esi<br>
-; X32-NEXT:    adcl 12(%ecx), %edx<br>
-; X32-NEXT:    adcl 16(%ecx), %esi<br>
-; X32-NEXT:    adcl 20(%ecx), %edi<br>
-; X32-NEXT:    movl %ebp, %eax<br>
-; X32-NEXT:    adcl 24(%ecx), %eax<br>
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %ebp # 4-byte Reload<br>
-; X32-NEXT:    adcl %ebp, 28(%ecx)<br>
-; X32-NEXT:    movl (%esp), %ebp # 4-byte Reload<br>
-; X32-NEXT:    movl %ebp, 8(%ecx)<br>
-; X32-NEXT:    movl %ebx, 4(%ecx)<br>
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %ebx # 4-byte Reload<br>
-; X32-NEXT:    movl %ebx, (%ecx)<br>
-; X32-NEXT:    movl %edx, 12(%ecx)<br>
-; X32-NEXT:    movl %esi, 16(%ecx)<br>
-; X32-NEXT:    movl %edi, 20(%ecx)<br>
-; X32-NEXT:    movl %eax, 24(%ecx)<br>
-; X32-NEXT:    addl $12, %esp<br>
+; X32-NEXT:    addl %ecx, (%eax)<br>
+; X32-NEXT:    adcl %edx, 4(%eax)<br>
+; X32-NEXT:    adcl %ebp, 8(%eax)<br>
+; X32-NEXT:    adcl %ebx, 12(%eax)<br>
+; X32-NEXT:    adcl %edi, 16(%eax)<br>
+; X32-NEXT:    adcl %esi, 20(%eax)<br>
+; X32-NEXT:    movl (%esp), %ecx # 4-byte Reload<br>
+; X32-NEXT:    adcl %ecx, 24(%eax)<br>
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx # 4-byte Reload<br>
+; X32-NEXT:    adcl %ecx, 28(%eax)<br>
+; X32-NEXT:    addl $8, %esp<br>
 ; X32-NEXT:    popl %esi<br>
 ; X32-NEXT:    popl %edi<br>
 ; X32-NEXT:    popl %ebx<br>
@@ -51,17 +41,14 @@ define void @add(i256* %p, i256* %q) nou<br>
 ;<br>
 ; X64-LABEL: add:<br>
 ; X64:       # %bb.0:<br>
-; X64-NEXT:    movq 16(%rdi), %rax<br>
-; X64-NEXT:    movq (%rdi), %rcx<br>
-; X64-NEXT:    movq 8(%rdi), %rdx<br>
-; X64-NEXT:    movq 24(%rsi), %r8<br>
-; X64-NEXT:    addq (%rsi), %rcx<br>
-; X64-NEXT:    adcq 8(%rsi), %rdx<br>
-; X64-NEXT:    adcq 16(%rsi), %rax<br>
-; X64-NEXT:    adcq %r8, 24(%rdi)<br>
-; X64-NEXT:    movq %rax, 16(%rdi)<br>
-; X64-NEXT:    movq %rdx, 8(%rdi)<br>
-; X64-NEXT:    movq %rcx, (%rdi)<br>
+; X64-NEXT:    movq 24(%rsi), %rax<br>
+; X64-NEXT:    movq 16(%rsi), %rcx<br>
+; X64-NEXT:    movq (%rsi), %rdx<br>
+; X64-NEXT:    movq 8(%rsi), %rsi<br>
+; X64-NEXT:    addq %rdx, (%rdi)<br>
+; X64-NEXT:    adcq %rsi, 8(%rdi)<br>
+; X64-NEXT:    adcq %rcx, 16(%rdi)<br>
+; X64-NEXT:    adcq %rax, 24(%rdi)<br>
 ; X64-NEXT:    retq<br>
   %a = load i256, i256* %p<br>
   %b = load i256, i256* %q<br>
@@ -77,35 +64,28 @@ define void @sub(i256* %p, i256* %q) nou<br>
 ; X32-NEXT:    pushl %edi<br>
 ; X32-NEXT:    pushl %esi<br>
 ; X32-NEXT:    subl $8, %esp<br>
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi<br>
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-NEXT:    movl 16(%ecx), %eax<br>
-; X32-NEXT:    movl 12(%ecx), %edx<br>
-; X32-NEXT:    movl 8(%ecx), %edi<br>
-; X32-NEXT:    movl (%ecx), %ebx<br>
-; X32-NEXT:    movl 4(%ecx), %ebp<br>
-; X32-NEXT:    subl (%esi), %ebx<br>
-; X32-NEXT:    sbbl 4(%esi), %ebp<br>
-; X32-NEXT:    sbbl 8(%esi), %edi<br>
-; X32-NEXT:    sbbl 12(%esi), %edx<br>
-; X32-NEXT:    movl %edx, {{[0-9]+}}(%esp) # 4-byte Spill<br>
-; X32-NEXT:    sbbl 16(%esi), %eax<br>
-; X32-NEXT:    movl %eax, (%esp) # 4-byte Spill<br>
-; X32-NEXT:    movl 20(%ecx), %edx<br>
-; X32-NEXT:    sbbl 20(%esi), %edx<br>
-; X32-NEXT:    movl 24(%ecx), %eax<br>
-; X32-NEXT:    sbbl 24(%esi), %eax<br>
-; X32-NEXT:    movl 28(%esi), %esi<br>
-; X32-NEXT:    sbbl %esi, 28(%ecx)<br>
-; X32-NEXT:    movl %edi, 8(%ecx)<br>
-; X32-NEXT:    movl %ebp, 4(%ecx)<br>
-; X32-NEXT:    movl %ebx, (%ecx)<br>
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %esi # 4-byte Reload<br>
-; X32-NEXT:    movl %esi, 12(%ecx)<br>
-; X32-NEXT:    movl (%esp), %esi # 4-byte Reload<br>
-; X32-NEXT:    movl %esi, 16(%ecx)<br>
-; X32-NEXT:    movl %edx, 20(%ecx)<br>
-; X32-NEXT:    movl %eax, 24(%ecx)<br>
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
+; X32-NEXT:    movl 28(%eax), %ecx<br>
+; X32-NEXT:    movl %ecx, {{[0-9]+}}(%esp) # 4-byte Spill<br>
+; X32-NEXT:    movl 24(%eax), %ecx<br>
+; X32-NEXT:    movl %ecx, (%esp) # 4-byte Spill<br>
+; X32-NEXT:    movl 20(%eax), %esi<br>
+; X32-NEXT:    movl 16(%eax), %edi<br>
+; X32-NEXT:    movl 12(%eax), %ebx<br>
+; X32-NEXT:    movl 8(%eax), %ebp<br>
+; X32-NEXT:    movl (%eax), %ecx<br>
+; X32-NEXT:    movl 4(%eax), %edx<br>
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
+; X32-NEXT:    subl %ecx, (%eax)<br>
+; X32-NEXT:    sbbl %edx, 4(%eax)<br>
+; X32-NEXT:    sbbl %ebp, 8(%eax)<br>
+; X32-NEXT:    sbbl %ebx, 12(%eax)<br>
+; X32-NEXT:    sbbl %edi, 16(%eax)<br>
+; X32-NEXT:    sbbl %esi, 20(%eax)<br>
+; X32-NEXT:    movl (%esp), %ecx # 4-byte Reload<br>
+; X32-NEXT:    sbbl %ecx, 24(%eax)<br>
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx # 4-byte Reload<br>
+; X32-NEXT:    sbbl %ecx, 28(%eax)<br>
 ; X32-NEXT:    addl $8, %esp<br>
 ; X32-NEXT:    popl %esi<br>
 ; X32-NEXT:    popl %edi<br>
@@ -115,17 +95,14 @@ define void @sub(i256* %p, i256* %q) nou<br>
 ;<br>
 ; X64-LABEL: sub:<br>
 ; X64:       # %bb.0:<br>
-; X64-NEXT:    movq 16(%rdi), %rax<br>
-; X64-NEXT:    movq (%rdi), %rcx<br>
-; X64-NEXT:    movq 8(%rdi), %rdx<br>
-; X64-NEXT:    movq 24(%rsi), %r8<br>
-; X64-NEXT:    subq (%rsi), %rcx<br>
-; X64-NEXT:    sbbq 8(%rsi), %rdx<br>
-; X64-NEXT:    sbbq 16(%rsi), %rax<br>
-; X64-NEXT:    sbbq %r8, 24(%rdi)<br>
-; X64-NEXT:    movq %rax, 16(%rdi)<br>
-; X64-NEXT:    movq %rdx, 8(%rdi)<br>
-; X64-NEXT:    movq %rcx, (%rdi)<br>
+; X64-NEXT:    movq 24(%rsi), %rax<br>
+; X64-NEXT:    movq 16(%rsi), %rcx<br>
+; X64-NEXT:    movq (%rsi), %rdx<br>
+; X64-NEXT:    movq 8(%rsi), %rsi<br>
+; X64-NEXT:    subq %rdx, (%rdi)<br>
+; X64-NEXT:    sbbq %rsi, 8(%rdi)<br>
+; X64-NEXT:    sbbq %rcx, 16(%rdi)<br>
+; X64-NEXT:    sbbq %rax, 24(%rdi)<br>
 ; X64-NEXT:    retq<br>
   %a = load i256, i256* %p<br>
   %b = load i256, i256* %q<br>
<br>
Added: llvm/trunk/test/CodeGen/X86/load-op-store-fusion.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/load-op-store-fusion.ll?rev=324359&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/load-op-store-fusion.ll?rev=324359&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/load-op-store-fusion.ll (added)<br>
+++ llvm/trunk/test/CodeGen/X86/load-op-store-fusion.ll Tue Feb  6 08:14:29 2018<br>
@@ -0,0 +1,32 @@<br>
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py<br>
+; RUN: llc < %s -mtriple=i386-unknown | FileCheck %s --check-prefix=X32<br>
+; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s --check-prefix=X64<br>
+<br>
+; This test makes sure we do not merge both load-op-store pairs here as it causes a cycle.<br>
+<br>
+define i8* @fn(i32 %i.015.i,  [64 x i64]* %data.i) {<br>
+; X32-LABEL: fn:<br>
+; X32:       # %bb.0: # %entry<br>
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
+; X32-NEXT:    movl (%ecx,%eax,8), %edx<br>
+; X32-NEXT:    addl $1, %edx<br>
+; X32-NEXT:    adcl $0, 4(%ecx,%eax,8)<br>
+; X32-NEXT:    movl %edx, (%ecx,%eax,8)<br>
+; X32-NEXT:    xorl %eax, %eax<br>
+; X32-NEXT:    retl<br>
+;<br>
+; X64-LABEL: fn:<br>
+; X64:       # %bb.0: # %entry<br>
+; X64-NEXT:    movslq %edi, %rax<br>
+; X64-NEXT:    incq (%rsi,%rax,8)<br>
+; X64-NEXT:    xorl %eax, %eax<br>
+; X64-NEXT:    retq<br>
+entry:<br>
+  %arrayidx.i6 = getelementptr inbounds [64 x i64], [64 x i64]* %data.i, i32 0, i32 %i.015.i<br>
+  %x8 = load volatile i64, i64* %arrayidx.i6, align 8<br>
+  %inc.i7 = add i64 %x8, 1<br>
+  store volatile i64 %inc.i7, i64* %arrayidx.i6, align 8<br>
+  ret i8* null<br>
+}<br>
+<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/masked_memop.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/masked_memop.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/masked_memop.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/masked_memop.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/masked_memop.ll Tue Feb  6 08:14:29 2018<br>
@@ -1264,8 +1264,7 @@ define <8 x double> @load_one_mask_bit_s<br>
 ; AVX-LABEL: load_one_mask_bit_set5:<br>
 ; AVX:       ## %bb.0:<br>
 ; AVX-NEXT:    vextractf128 $1, %ymm1, %xmm2<br>
-; AVX-NEXT:    vmovsd {{.*#+}} xmm3 = mem[0],zero<br>
-; AVX-NEXT:    vmovlhps {{.*#+}} xmm2 = xmm2[0],xmm3[0]<br>
+; AVX-NEXT:    vmovhpd {{.*#+}} xmm2 = xmm2[0],mem[0]<br>
 ; AVX-NEXT:    vinsertf128 $1, %xmm2, %ymm1, %ymm1<br>
 ; AVX-NEXT:    retq<br>
 ;<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/merge-consecutive-stores.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/merge-consecutive-stores.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/merge-consecutive-stores.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/merge-consecutive-stores.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/merge-consecutive-stores.ll Tue Feb  6 08:14:29 2018<br>
@@ -10,12 +10,11 @@ define i32 @foo (i64* %so) nounwind uwta<br>
 ; CHECK-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; CHECK-NEXT:    movl $0, 28(%eax)<br>
 ; CHECK-NEXT:    movl $0, 24(%eax)<br>
-; CHECK-NEXT:    movl 20(%eax), %ecx<br>
-; CHECK-NEXT:    movl $0, 20(%eax)<br>
-; CHECK-NEXT:    xorl %edx, %edx<br>
-; CHECK-NEXT:    cmpl 16(%eax), %edx<br>
+; CHECK-NEXT:    xorl %ecx, %ecx<br>
+; CHECK-NEXT:    cmpl 16(%eax), %ecx<br>
 ; CHECK-NEXT:    movl $0, 16(%eax)<br>
-; CHECK-NEXT:    sbbl %ecx, %edx<br>
+; CHECK-NEXT:    sbbl 20(%eax), %ecx<br>
+; CHECK-NEXT:    movl $0, 20(%eax)<br>
 ; CHECK-NEXT:    setl %al<br>
 ; CHECK-NEXT:    movzbl %al, %eax<br>
 ; CHECK-NEXT:    negl %eax<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/nontemporal.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/nontemporal.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/nontemporal.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/nontemporal.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/nontemporal.ll Tue Feb  6 08:14:29 2018<br>
@@ -13,36 +13,35 @@ define i32 @f(<4 x float> %A, i8* %B, <2<br>
 ; X32-SSE-NEXT:    andl $-16, %esp<br>
 ; X32-SSE-NEXT:    subl $16, %esp<br>
 ; X32-SSE-NEXT:    movsd {{.*#+}} xmm3 = mem[0],zero<br>
-; X32-SSE-NEXT:    movl 12(%ebp), %eax<br>
+; X32-SSE-NEXT:    movl 12(%ebp), %ecx<br>
 ; X32-SSE-NEXT:    movdqa 56(%ebp), %xmm4<br>
 ; X32-SSE-NEXT:    movdqa 40(%ebp), %xmm5<br>
 ; X32-SSE-NEXT:    movdqa 24(%ebp), %xmm6<br>
-; X32-SSE-NEXT:    movl 8(%ebp), %edx<br>
-; X32-SSE-NEXT:    movl 80(%ebp), %ecx<br>
-; X32-SSE-NEXT:    movl (%ecx), %esi<br>
+; X32-SSE-NEXT:    movl 8(%ebp), %esi<br>
+; X32-SSE-NEXT:    movl 80(%ebp), %edx<br>
+; X32-SSE-NEXT:    movl (%edx), %eax<br>
 ; X32-SSE-NEXT:    addps {{\.LCPI.*}}, %xmm0<br>
-; X32-SSE-NEXT:    movntps %xmm0, (%edx)<br>
+; X32-SSE-NEXT:    movntps %xmm0, (%esi)<br>
 ; X32-SSE-NEXT:    paddq {{\.LCPI.*}}, %xmm2<br>
-; X32-SSE-NEXT:    addl (%ecx), %esi<br>
-; X32-SSE-NEXT:    movntdq %xmm2, (%edx)<br>
+; X32-SSE-NEXT:    addl (%edx), %eax<br>
+; X32-SSE-NEXT:    movntdq %xmm2, (%esi)<br>
 ; X32-SSE-NEXT:    addpd {{\.LCPI.*}}, %xmm1<br>
-; X32-SSE-NEXT:    addl (%ecx), %esi<br>
-; X32-SSE-NEXT:    movntpd %xmm1, (%edx)<br>
+; X32-SSE-NEXT:    addl (%edx), %eax<br>
+; X32-SSE-NEXT:    movntpd %xmm1, (%esi)<br>
 ; X32-SSE-NEXT:    paddd {{\.LCPI.*}}, %xmm6<br>
-; X32-SSE-NEXT:    addl (%ecx), %esi<br>
-; X32-SSE-NEXT:    movntdq %xmm6, (%edx)<br>
+; X32-SSE-NEXT:    addl (%edx), %eax<br>
+; X32-SSE-NEXT:    movntdq %xmm6, (%esi)<br>
 ; X32-SSE-NEXT:    paddw {{\.LCPI.*}}, %xmm5<br>
-; X32-SSE-NEXT:    addl (%ecx), %esi<br>
-; X32-SSE-NEXT:    movntdq %xmm5, (%edx)<br>
+; X32-SSE-NEXT:    addl (%edx), %eax<br>
+; X32-SSE-NEXT:    movntdq %xmm5, (%esi)<br>
 ; X32-SSE-NEXT:    paddb {{\.LCPI.*}}, %xmm4<br>
-; X32-SSE-NEXT:    addl (%ecx), %esi<br>
-; X32-SSE-NEXT:    movntdq %xmm4, (%edx)<br>
-; X32-SSE-NEXT:    addl (%ecx), %esi<br>
-; X32-SSE-NEXT:    movntil %eax, (%edx)<br>
-; X32-SSE-NEXT:    movl (%ecx), %eax<br>
-; X32-SSE-NEXT:    addl %esi, %eax<br>
-; X32-SSE-NEXT:    movsd %xmm3, (%edx)<br>
-; X32-SSE-NEXT:    addl (%ecx), %eax<br>
+; X32-SSE-NEXT:    addl (%edx), %eax<br>
+; X32-SSE-NEXT:    movntdq %xmm4, (%esi)<br>
+; X32-SSE-NEXT:    addl (%edx), %eax<br>
+; X32-SSE-NEXT:    movntil %ecx, (%esi)<br>
+; X32-SSE-NEXT:    addl (%edx), %eax<br>
+; X32-SSE-NEXT:    movsd %xmm3, (%esi)<br>
+; X32-SSE-NEXT:    addl (%edx), %eax<br>
 ; X32-SSE-NEXT:    leal -4(%ebp), %esp<br>
 ; X32-SSE-NEXT:    popl %esi<br>
 ; X32-SSE-NEXT:    popl %ebp<br>
@@ -56,36 +55,35 @@ define i32 @f(<4 x float> %A, i8* %B, <2<br>
 ; X32-AVX-NEXT:    andl $-16, %esp<br>
 ; X32-AVX-NEXT:    subl $16, %esp<br>
 ; X32-AVX-NEXT:    vmovsd {{.*#+}} xmm3 = mem[0],zero<br>
-; X32-AVX-NEXT:    movl 12(%ebp), %eax<br>
+; X32-AVX-NEXT:    movl 12(%ebp), %ecx<br>
 ; X32-AVX-NEXT:    vmovdqa 56(%ebp), %xmm4<br>
 ; X32-AVX-NEXT:    vmovdqa 40(%ebp), %xmm5<br>
 ; X32-AVX-NEXT:    vmovdqa 24(%ebp), %xmm6<br>
-; X32-AVX-NEXT:    movl 8(%ebp), %ecx<br>
-; X32-AVX-NEXT:    movl 80(%ebp), %edx<br>
-; X32-AVX-NEXT:    movl (%edx), %esi<br>
+; X32-AVX-NEXT:    movl 8(%ebp), %edx<br>
+; X32-AVX-NEXT:    movl 80(%ebp), %esi<br>
+; X32-AVX-NEXT:    movl (%esi), %eax<br>
 ; X32-AVX-NEXT:    vaddps {{\.LCPI.*}}, %xmm0, %xmm0<br>
-; X32-AVX-NEXT:    vmovntps %xmm0, (%ecx)<br>
+; X32-AVX-NEXT:    vmovntps %xmm0, (%edx)<br>
 ; X32-AVX-NEXT:    vpaddq {{\.LCPI.*}}, %xmm2, %xmm0<br>
-; X32-AVX-NEXT:    addl (%edx), %esi<br>
-; X32-AVX-NEXT:    vmovntdq %xmm0, (%ecx)<br>
+; X32-AVX-NEXT:    addl (%esi), %eax<br>
+; X32-AVX-NEXT:    vmovntdq %xmm0, (%edx)<br>
 ; X32-AVX-NEXT:    vaddpd {{\.LCPI.*}}, %xmm1, %xmm0<br>
-; X32-AVX-NEXT:    addl (%edx), %esi<br>
-; X32-AVX-NEXT:    vmovntpd %xmm0, (%ecx)<br>
+; X32-AVX-NEXT:    addl (%esi), %eax<br>
+; X32-AVX-NEXT:    vmovntpd %xmm0, (%edx)<br>
 ; X32-AVX-NEXT:    vpaddd {{\.LCPI.*}}, %xmm6, %xmm0<br>
-; X32-AVX-NEXT:    addl (%edx), %esi<br>
-; X32-AVX-NEXT:    vmovntdq %xmm0, (%ecx)<br>
+; X32-AVX-NEXT:    addl (%esi), %eax<br>
+; X32-AVX-NEXT:    vmovntdq %xmm0, (%edx)<br>
 ; X32-AVX-NEXT:    vpaddw {{\.LCPI.*}}, %xmm5, %xmm0<br>
-; X32-AVX-NEXT:    addl (%edx), %esi<br>
-; X32-AVX-NEXT:    vmovntdq %xmm0, (%ecx)<br>
+; X32-AVX-NEXT:    addl (%esi), %eax<br>
+; X32-AVX-NEXT:    vmovntdq %xmm0, (%edx)<br>
 ; X32-AVX-NEXT:    vpaddb {{\.LCPI.*}}, %xmm4, %xmm0<br>
-; X32-AVX-NEXT:    addl (%edx), %esi<br>
-; X32-AVX-NEXT:    vmovntdq %xmm0, (%ecx)<br>
-; X32-AVX-NEXT:    addl (%edx), %esi<br>
-; X32-AVX-NEXT:    movntil %eax, (%ecx)<br>
-; X32-AVX-NEXT:    movl (%edx), %eax<br>
-; X32-AVX-NEXT:    addl %esi, %eax<br>
-; X32-AVX-NEXT:    vmovsd %xmm3, (%ecx)<br>
-; X32-AVX-NEXT:    addl (%edx), %eax<br>
+; X32-AVX-NEXT:    addl (%esi), %eax<br>
+; X32-AVX-NEXT:    vmovntdq %xmm0, (%edx)<br>
+; X32-AVX-NEXT:    addl (%esi), %eax<br>
+; X32-AVX-NEXT:    movntil %ecx, (%edx)<br>
+; X32-AVX-NEXT:    addl (%esi), %eax<br>
+; X32-AVX-NEXT:    vmovsd %xmm3, (%edx)<br>
+; X32-AVX-NEXT:    addl (%esi), %eax<br>
 ; X32-AVX-NEXT:    leal -4(%ebp), %esp<br>
 ; X32-AVX-NEXT:    popl %esi<br>
 ; X32-AVX-NEXT:    popl %ebp<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/store_op_load_fold2.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/store_op_load_fold2.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/store_op_load_fold2.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/store_op_load_fold2.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/store_op_load_fold2.ll Tue Feb  6 08:14:29 2018<br>
@@ -17,14 +17,14 @@ cond_true2732.preheader:<br>
         store i64 %<a href="http://tmp2676.us.us" rel="noreferrer" target="_blank">tmp2676.us.us</a>, i64* %tmp2666<br>
         ret i32 0<br>
<br>
-; INTEL:       and     {{e..}}, dword ptr [360]<br>
-; INTEL:       and     dword ptr [356], {{e..}}<br>
-; FIXME:       mov     dword ptr [360], {{e..}}<br>
+; INTEL:       and     {{e..}}, dword ptr [356]<br>
+; INTEL:       and     dword ptr [360], {{e..}}<br>
+; FIXME:       mov     dword ptr [356], {{e..}}<br>
 ; The above line comes out as 'mov 360, eax', but when the register is ecx it works?<br>
<br>
-; ATT:         andl    360, %{{e..}}<br>
-; ATT: andl    %{{e..}}, 356<br>
-; ATT: movl    %{{e..}}, 360<br>
+; ATT:         andl    356, %{{e..}}<br>
+; ATT: andl    %{{e..}}, 360<br>
+; ATT: movl    %{{e..}}, 356<br>
<br>
 }<br>
<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/subvector-broadcast.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/subvector-broadcast.ll?rev=324359&r1=324358&r2=324359&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/subvector-broadcast.ll?rev=324359&r1=324358&r2=324359&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/CodeGen/X86/subvector-broadcast.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/subvector-broadcast.ll Tue Feb  6 08:14:29 2018<br>
@@ -751,72 +751,64 @@ define <8 x i32> @test_broadcast_4i32_8i<br>
 ; X32-AVX:       # %bb.0:<br>
 ; X32-AVX-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-AVX-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-AVX-NEXT:    vmovaps (%ecx), %xmm0<br>
 ; X32-AVX-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X32-AVX-NEXT:    vbroadcastf128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X32-AVX-NEXT:    vmovaps %xmm1, (%eax)<br>
-; X32-AVX-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X32-AVX-NEXT:    retl<br>
 ;<br>
 ; X32-AVX512F-LABEL: test_broadcast_4i32_8i32_chain:<br>
 ; X32-AVX512F:       # %bb.0:<br>
 ; X32-AVX512F-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-AVX512F-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-AVX512F-NEXT:    vmovaps (%ecx), %xmm0<br>
 ; X32-AVX512F-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
+; X32-AVX512F-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X32-AVX512F-NEXT:    vmovdqa %xmm1, (%eax)<br>
-; X32-AVX512F-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X32-AVX512F-NEXT:    retl<br>
 ;<br>
 ; X32-AVX512BW-LABEL: test_broadcast_4i32_8i32_chain:<br>
 ; X32-AVX512BW:       # %bb.0:<br>
 ; X32-AVX512BW-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-AVX512BW-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-AVX512BW-NEXT:    vmovaps (%ecx), %xmm0<br>
 ; X32-AVX512BW-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
+; X32-AVX512BW-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X32-AVX512BW-NEXT:    vmovdqa %xmm1, (%eax)<br>
-; X32-AVX512BW-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X32-AVX512BW-NEXT:    retl<br>
 ;<br>
 ; X32-AVX512DQ-LABEL: test_broadcast_4i32_8i32_chain:<br>
 ; X32-AVX512DQ:       # %bb.0:<br>
 ; X32-AVX512DQ-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-AVX512DQ-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-AVX512DQ-NEXT:    vmovaps (%ecx), %xmm0<br>
 ; X32-AVX512DQ-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X32-AVX512DQ-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X32-AVX512DQ-NEXT:    vmovaps %xmm1, (%eax)<br>
-; X32-AVX512DQ-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X32-AVX512DQ-NEXT:    retl<br>
 ;<br>
 ; X64-AVX-LABEL: test_broadcast_4i32_8i32_chain:<br>
 ; X64-AVX:       # %bb.0:<br>
-; X64-AVX-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-AVX-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X64-AVX-NEXT:    vbroadcastf128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-AVX-NEXT:    vmovaps %xmm1, (%rsi)<br>
-; X64-AVX-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-AVX-NEXT:    retq<br>
 ;<br>
 ; X64-AVX512F-LABEL: test_broadcast_4i32_8i32_chain:<br>
 ; X64-AVX512F:       # %bb.0:<br>
-; X64-AVX512F-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-AVX512F-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
+; X64-AVX512F-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-AVX512F-NEXT:    vmovdqa %xmm1, (%rsi)<br>
-; X64-AVX512F-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-AVX512F-NEXT:    retq<br>
 ;<br>
 ; X64-AVX512BW-LABEL: test_broadcast_4i32_8i32_chain:<br>
 ; X64-AVX512BW:       # %bb.0:<br>
-; X64-AVX512BW-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-AVX512BW-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
+; X64-AVX512BW-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-AVX512BW-NEXT:    vmovdqa %xmm1, (%rsi)<br>
-; X64-AVX512BW-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-AVX512BW-NEXT:    retq<br>
 ;<br>
 ; X64-AVX512DQ-LABEL: test_broadcast_4i32_8i32_chain:<br>
 ; X64-AVX512DQ:       # %bb.0:<br>
-; X64-AVX512DQ-NEXT:    vmovaps (%rdi), %xmm0<br>
 ; X64-AVX512DQ-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X64-AVX512DQ-NEXT:    vbroadcasti128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X64-AVX512DQ-NEXT:    vmovaps %xmm1, (%rsi)<br>
-; X64-AVX512DQ-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %ymm0<br>
 ; X64-AVX512DQ-NEXT:    retq<br>
   %1 = load <4 x i32>, <4 x i32>* %p0<br>
   store <4 x float> zeroinitializer, <4 x float>* %p1<br>
@@ -829,10 +821,9 @@ define <16 x i32> @test_broadcast_4i32_1<br>
 ; X32-AVX:       # %bb.0:<br>
 ; X32-AVX-NEXT:    movl {{[0-9]+}}(%esp), %eax<br>
 ; X32-AVX-NEXT:    movl {{[0-9]+}}(%esp), %ecx<br>
-; X32-AVX-NEXT:    vmovaps (%ecx), %xmm0<br>
 ; X32-AVX-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
+; X32-AVX-NEXT:    vbroadcastf128 {{.*#+}} ymm0 = mem[0,1,0,1]<br>
 ; X32-AVX-NEXT:    vmovaps %xmm1, (%eax)<br>
-; X32-AVX-NEXT:    vinsertf128 $1, %xmm0, %ymm0, %y</blockquote></div></blockquote></div>