From 8ecb7e224316b318dfa25266766e6d136a67b7d9 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Sun, 7 Dec 2014 20:32:11 +0000 Subject: [PATCH] IR: Revert r223618 behaviour of MDNode::concatenate() r223618 including special handling of `MDNode::intersect()`: if the first operand is a self-reference with the same operands you're trying to return, return it instead. Reuse that handling in `MDNode::concatenate()` in the hopes that it fixes a polly test that seems to rely on the old behaviour [1]. [1]: http://lab.llvm.org:8011/builders/polly-amd64-linux/builds/25167 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223619 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/IR/Metadata.cpp | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 70415b01016..a2c7838bb83 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -376,6 +376,25 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) { Store.insert(N); } +/// \brief Get a node, or a self-reference that looks like it. +/// +/// Special handling for finding self-references, for use by \a +/// MDNode::concatenate() and \a MDNode::intersect() to maintain behaviour from +/// when self-referencing nodes were still uniqued. If the first operand has +/// the same operands as \c Ops, return the first operand instead. +static MDNode *getOrSelfReference(LLVMContext &Context, ArrayRef Ops) { + if (!Ops.empty()) + if (MDNode *N = dyn_cast_or_null(Ops[0])) + if (N->getNumOperands() == Ops.size() && N == N->getOperand(0)) { + for (unsigned I = 1, E = Ops.size(); I != E; ++I) + if (Ops[I] != N->getOperand(I)) + return MDNode::get(Context, Ops); + return N; + } + + return MDNode::get(Context, Ops); +} + MDNode *MDNode::concatenate(MDNode *A, MDNode *B) { if (!A) return B; @@ -391,7 +410,9 @@ MDNode *MDNode::concatenate(MDNode *A, MDNode *B) { for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i) Vals[j++] = B->getOperand(i); - return MDNode::get(A->getContext(), Vals); + // FIXME: This preserves long-standing behaviour, but is it really the right + // behaviour? Or was that an unintended side-effect of node uniquing? + return getOrSelfReference(A->getContext(), Vals); } MDNode *MDNode::intersect(MDNode *A, MDNode *B) { @@ -408,19 +429,9 @@ MDNode *MDNode::intersect(MDNode *A, MDNode *B) { } } - // Handle alias scope self-references specially. - // // FIXME: This preserves long-standing behaviour, but is it really the right // behaviour? Or was that an unintended side-effect of node uniquing? - if (!Vals.empty()) - if (MDNode *N = dyn_cast_or_null(Vals[0])) - if (N->getNumOperands() == Vals.size() && N == N->getOperand(0)) { - for (unsigned I = 1, E = Vals.size(); I != E; ++I) - if (Vals[I] != N->getOperand(I)) - return MDNode::get(A->getContext(), Vals); - return N; - } - return MDNode::get(A->getContext(), Vals); + return getOrSelfReference(A->getContext(), Vals); } MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) {