[PATCH] RemapValue() assert during type legalisation

Hal Finkel hfinkel at anl.gov
Mon Jul 8 08:56:32 PDT 2013


Richard,

I've just opened http://llvm.org/bugs/show_bug.cgi?id=16562 -- and thanks to Duncan for pointing out that this is a duplicate of this bug (and, indeed, fixed by your patch). So now we have a PPC test case too.

+  /// NeWNodes must not appear as targets of ReplacedValues.
(I assume that you meant to write NewNodes not NeWNodes)

FWIW, this does seem reasonable to me. Owen?

 -Hal

----- Original Message -----
> In this testcase, lovingly reduced from a large llvmpipe one, we
> abort
> during type legalisation in DAGTypeLegalizer::RemapValue():
> 
> void DAGTypeLegalizer::RemapValue(SDValue &N) {
>   DenseMap<SDValue, SDValue>::iterator I = ReplacedValues.find(N);
>   if (I != ReplacedValues.end()) {
>     // Use path compression to speed up future lookups if values get
>     multiply
>     // replaced with other values.
>     RemapValue(I->second);
>     N = I->second;
>     assert(N.getNode()->getNodeId() != NewNode && "Mapped to new
>     node!");
>   }
> }
> 
> What seems to be happening is that for one particular node
> replacement in
> DAGTypeLegalizer::ReplaceValueWith():
> 
>   DAG.ReplaceAllUsesOfValueWith(From, To);
> 
> there are two nodes N1 and N2 whose operands are CSEd, but which
> themselves
> remain unique.  These nodes are marked "new" and are added to the
> NodesToAnalyze worklist:
> 
>     virtual void NodeUpdated(SDNode *N) {
>       // Node updates can mean pretty much anything.  It is possible
>       that an
>       // operand was set to something already processed (f.e.) in
>       which case
>       // this node could become ready.  Recompute its flags.
>       assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess &&
>              N->getNodeId() != DAGTypeLegalizer::Processed &&
>              "Invalid node ID for RAUW deletion!");
>       N->setNodeId(DAGTypeLegalizer::NewNode);
>       NodesToAnalyze.insert(N);
>     }
> 
> As it happens, N1 is the target of a ReplacedValues replacement.
> 
> Later during this same replacement, there is a node N3 that is CSEd
> to N4.
> N4 is a NewNode at address A, and the previous (deleted) incarnation
> of
> the node at address A is still mapped by ReplacedValues.  So when
> NodeUpdateListener::NodeDeleted() sees the N3->N4 replacement,
> it indirectly calls ExpungeNode(N4) to flush out the stale data.
> However, ExpungeNode calls:
> 
>   RemapValue(I->second);
> 
> on _all_ entries in ReplacedValues, including the one that maps to
> N1,
> even though that entry is not related to A.  (Which is fair enough.
> It can't really know in advance which are related to A and which
> aren't.)
> We then assert because N1 was marked NeWNode before being added to
> the
> worklist, but hasn't been processed yet.
> 
> Question is, what's the right fix?  The comment at the top of the
> file says:
> 
>   // The final node obtained by mapping by ReplacedValues is not
>   marked NewNode.
> 
> but it also says:
> 
>   // Note that these invariants may not hold momentarily when
>   processing a node:
> 
> which seems to be the case here.  I'm not sure whether the assert has
> really found a bug or not.
> 
> The patch below avoids asserting for nodes in the ReplaceValueWith()
> worklist, but at the cost of making the worklist a member of
> DAGTypeLegalizer.
> 
> I made the test force s390x-linux-gnu because the test won't fail on
> targets where the vector types are legal.  The test also seems very
> sensitive to the order of node reuse.
> 
> What do you think?  Is this the right fix, or is the assert expected
> to hold even in this situation?
> 
> Thanks,
> Richard
> 
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-commits mailing list