This is an archive of the discontinued LLVM Phabricator instance.

[DAGCombiner] Don't add volatile or indexed stores to ChainedStores
ClosedPublic

Authored by flyingforyou on Jan 22 2016, 3:45 AM.

Details

Summary

findBetterNeighborChains does not handle indexed stores.
However, it did not check when adding stores to ChainedStores.

Diff Detail

Repository
rL LLVM

Event Timeline

flyingforyou retitled this revision from to [DAGCombiner] Check store node's value count before replaceStoreChain.
flyingforyou updated this object.
flyingforyou added a reviewer: arsenm.
flyingforyou added a subscriber: llvm-commits.

It's unclear to me what problem this patch is trying to solve. Can you provide additional details?

Also, please include a test case. In many cases that makes understanding the problem much easier.

Thanks for comment Chad.

I respect your opinion. But I couldn't add testcase for this patch.
Because it's about assert.

So, I want to explain more about this.

for (StoreSDNode *ChainedStore : ChainedStores) {
  // If ChainedStore has more than one value, we don't try replaceStoreChain.
  // replaceStoreChain uses CombineTo, which only consider Chain only.
  if (ChainedStore->getNumValues() != 1)
    continue;

  SDValue Chain = ChainedStore->getChain();
  SDValue BetterChain = FindBetterChain(ChainedStore, Chain);

  if (Chain != BetterChain) {
    MadeChange = true;
    BetterChains.push_back(std::make_pair(ChainedStore, BetterChain));
  }
}

// Do all replacements after finding the replacements to make to avoid making
// the chains more complicated by introducing new TokenFactors.
for (auto Replacement : BetterChains)
  replaceStoreChain(Replacement.first, Replacement.second);

When you see inside of for loop, ChainedStore is added to BetterChains.
After this, replaceStoreChain get ChainedStore for first parameter.

SDValue DAGCombiner::replaceStoreChain(StoreSDNode *ST, SDValue BetterChain) {
  SDLoc SL(ST);
  SDValue ReplStore;

  // Replace the chain to avoid dependency.
  if (ST->isTruncatingStore()) {
    ReplStore = DAG.getTruncStore(BetterChain, SL, ST->getValue(),
                                  ST->getBasePtr(), ST->getMemoryVT(),
                                  ST->getMemOperand());
  } else {
    ReplStore = DAG.getStore(BetterChain, SL, ST->getValue(), ST->getBasePtr(),
                             ST->getMemOperand());
  }

  // Create token to keep both nodes around.
  SDValue Token = DAG.getNode(ISD::TokenFactor, SL,
                              MVT::Other, ST->getChain(), ReplStore);

  // Make sure the new and old chains are cleaned up.
  AddToWorklist(Token.getNode());

  // Don't add users to work list.
  return CombineTo(ST, Token, false);
}

Inside of replaceStoreChain, ChainedStore will be passed to CombineTo's first parameter.
And Token which is CombineTo's second paratemter only can be combined with same type node.

SDValue DAGCombiner::CombineTo(SDNode *N, const SDValue *To, unsigned NumTo,
                               bool AddTo) {
  assert(N->getNumValues() == NumTo && "Broken CombineTo call!");
  ++NodesCombined;
  DEBUG(dbgs() << "\nReplacing.1 ";
        N->dump(&DAG);
        dbgs() << "\nWith: ";
        To[0].getNode()->dump(&DAG);
        dbgs() << " and " << NumTo-1 << " other values\n");
  for (unsigned i = 0, e = NumTo; i != e; ++i)
    assert((!To[i].getNode() ||
            N->getValueType(i) == To[i].getValueType()) &&
           "Cannot combine value to value of different type!");

  WorklistRemover DeadNodes(*this);
  DAG.ReplaceAllUsesWith(N, To);
  if (AddTo) {
    // Push the new nodes and any users onto the worklist
    for (unsigned i = 0, e = NumTo; i != e; ++i) {
      if (To[i].getNode()) {
        AddToWorklist(To[i].getNode());
        AddUsersToWorklist(To[i].getNode());
      }
    }
  }

  // Finally, if the node is now dead, remove it from the graph.  The node
  // may not be dead if the replacement process recursively simplified to
  // something else needing this node.
  if (N->use_empty())
    deleteAndRecombine(N);
  return SDValue(N, 0);
}

There is a assert check assert(N->getNumValues() == NumTo && "Broken CombineTo call!");.
When we call CombineTo(ST, Token, false), this is changed likes below.

/// Replaces all uses of the results of one DAG node with new values.
SDValue CombineTo(SDNode *N, SDValue Res, bool AddTo = true) {
  return CombineTo(N, &Res, 1, AddTo);
}

That means NumTo is always 1. This is why I added check code likes below.

if (ChainedStore->getNumValues() != 1)
  continue;

Junmo.

arsenm edited edge metadata.Jan 22 2016, 11:23 PM
arsenm added a subscriber: arsenm.

Here is a reduced testcase. I’ll try to look at this later

This isn't exactly the right way to fix this. The problem is this is trying to perform this for an indexed store, which was supposed to be skipped, so it should never end up in the ChainedStores list.

The loop in findBetterNeighborChains is supposed to mirror the logic in getStoreMergeAndAliasCandidates (and will hopefully eventually replace it), but it looks like it will add ChainedStores even for indexed. The first loop here is what should be fixed

flyingforyou retitled this revision from [DAGCombiner] Check store node's value count before replaceStoreChain to [DAGCombiner] Don't add volatile or indexed stores to ChainedStores.
flyingforyou updated this object.
flyingforyou edited edge metadata.

Addressed Matt's comments.

Chad, there are several examples about crash. Sorry for misunderstanding.

Junmo.

I'll defer to Matt's judgement since he has a far better understanding of the problem then I.

zzheng added a subscriber: zzheng.Jan 25 2016, 4:46 PM

Isn't this trying to solve the same problem as http://reviews.llvm.org/D15348?

apazos edited edge metadata.Jan 25 2016, 4:50 PM

Yes, it looks like the issue in http://reviews.llvm.org/D15348. Matt can you try your reduced test with that on-going review?

Hi Ana.

I am amazed that your first approch is almost same with my first patch.
But the last patch is extending replaceStoreChain. (This is not what I am doing in this patch.)

What is the proper decision about this patch? (Transfer the test case, Abandon?)
Let me know, please.

Junmo.

Yes, it looks like the issue in http://reviews.llvm.org/D15348. Matt can you try your reduced test with that on-going review?

I don't think that patch will fix this bug. It will fix the assertion, but I think this problem uncovers one that will also effect volatiles. You can probably produce a testcase derived from this one which will break volatile handling

Can you try to come up with a volatile testcase that hits this problem?

lib/CodeGen/SelectionDAG/DAGCombiner.cpp
14763–14765 ↗(On Diff #45841)

We might as well fully break out of the loop here. This is just going to now reach the next iteration and then break the other place this was checked

The fix I have is to allow forming store chains that can contain stores with pre/post increment. So the check for STn->isUnindexed can be removed from Junmo's patch since his is a more restrictive solution. Let's see if Junmo can create a test for the Volatile case only.

flyingforyou edited edge metadata.

Addressed Matt's comments.

Junmo, if my patch goes in, do you still need the check STn->isIndexed()? I hope to have mine merged soon.

flyingforyou marked an inline comment as done.Jan 26 2016, 7:40 PM

Junmo, if my patch goes in, do you still need the check STn->isIndexed()? I hope to have mine merged soon.

Ana, I want to hear about opinion from Matt.
I don't want to disturb your effort in D15348. But the first test-case was made by Matt. And this commit's first reviewer is also Matt.

So, it's belong to him. Matt, could you give me a opinion about this change, please?

Junmo.

arsenm accepted this revision.Jan 27 2016, 5:32 PM
arsenm edited edge metadata.

LGTM

This revision is now accepted and ready to land.Jan 27 2016, 5:32 PM

Does the test need check lines? I would kind of expect an invalid merging to occur before with the volatile

Crash occurs before merging in testcase.

Thanks for reviewing Matt.

This revision was automatically updated to reflect the committed changes.

Ana.

Please, feel free to remove STn->isIndexed(), when your patch is ready. I still think your patch is also good.

Thanks,
Junmo.