Move the Metadata merging methods from GVN and make them public in MDNode.

There are other passes, BBVectorize specifically, that also need some of
this functionality.

llvm-svn: 158605
This commit is contained in:
Hal Finkel 2012-06-16 20:33:37 +00:00
parent f70bea93e2
commit 16ddd4b66b
3 changed files with 158 additions and 153 deletions

View File

@ -165,6 +165,11 @@ public:
static bool classof(const Value *V) {
return V->getValueID() == MDNodeVal;
}
/// Methods for metadata merging.
static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B);
static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B);
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
private:
// destroy - Delete this node. Only when there are no uses.
void destroy();

View File

@ -42,7 +42,6 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/PatternMatch.h"
@ -1736,155 +1735,6 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
return true;
}
static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B) {
if (!A || !B)
return NULL;
if (A == B)
return A;
SmallVector<MDNode *, 4> PathA;
MDNode *T = A;
while (T) {
PathA.push_back(T);
T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0;
}
SmallVector<MDNode *, 4> PathB;
T = B;
while (T) {
PathB.push_back(T);
T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0;
}
int IA = PathA.size() - 1;
int IB = PathB.size() - 1;
MDNode *Ret = 0;
while (IA >= 0 && IB >=0) {
if (PathA[IA] == PathB[IB])
Ret = PathA[IA];
else
break;
--IA;
--IB;
}
return Ret;
}
static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B) {
if (!A || !B)
return NULL;
APFloat AVal = cast<ConstantFP>(A->getOperand(0))->getValueAPF();
APFloat BVal = cast<ConstantFP>(B->getOperand(0))->getValueAPF();
if (AVal.compare(BVal) == APFloat::cmpLessThan)
return A;
return B;
}
static bool isContiguous(const ConstantRange &A, const ConstantRange &B) {
return A.getUpper() == B.getLower() || A.getLower() == B.getUpper();
}
static bool canBeMerged(const ConstantRange &A, const ConstantRange &B) {
return !A.intersectWith(B).isEmptySet() || isContiguous(A, B);
}
static bool tryMergeRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low,
ConstantInt *High) {
ConstantRange NewRange(Low->getValue(), High->getValue());
unsigned Size = EndPoints.size();
APInt LB = cast<ConstantInt>(EndPoints[Size - 2])->getValue();
APInt LE = cast<ConstantInt>(EndPoints[Size - 1])->getValue();
ConstantRange LastRange(LB, LE);
if (canBeMerged(NewRange, LastRange)) {
ConstantRange Union = LastRange.unionWith(NewRange);
Type *Ty = High->getType();
EndPoints[Size - 2] = ConstantInt::get(Ty, Union.getLower());
EndPoints[Size - 1] = ConstantInt::get(Ty, Union.getUpper());
return true;
}
return false;
}
static void addRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low,
ConstantInt *High) {
if (!EndPoints.empty())
if (tryMergeRange(EndPoints, Low, High))
return;
EndPoints.push_back(Low);
EndPoints.push_back(High);
}
static MDNode *getMostGenericRange(MDNode *A, MDNode *B) {
// Given two ranges, we want to compute the union of the ranges. This
// is slightly complitade by having to combine the intervals and merge
// the ones that overlap.
if (!A || !B)
return NULL;
if (A == B)
return A;
// First, walk both lists in older of the lower boundary of each interval.
// At each step, try to merge the new interval to the last one we adedd.
SmallVector<Value*, 4> EndPoints;
int AI = 0;
int BI = 0;
int AN = A->getNumOperands() / 2;
int BN = B->getNumOperands() / 2;
while (AI < AN && BI < BN) {
ConstantInt *ALow = cast<ConstantInt>(A->getOperand(2 * AI));
ConstantInt *BLow = cast<ConstantInt>(B->getOperand(2 * BI));
if (ALow->getValue().slt(BLow->getValue())) {
addRange(EndPoints, ALow, cast<ConstantInt>(A->getOperand(2 * AI + 1)));
++AI;
} else {
addRange(EndPoints, BLow, cast<ConstantInt>(B->getOperand(2 * BI + 1)));
++BI;
}
}
while (AI < AN) {
addRange(EndPoints, cast<ConstantInt>(A->getOperand(2 * AI)),
cast<ConstantInt>(A->getOperand(2 * AI + 1)));
++AI;
}
while (BI < BN) {
addRange(EndPoints, cast<ConstantInt>(B->getOperand(2 * BI)),
cast<ConstantInt>(B->getOperand(2 * BI + 1)));
++BI;
}
// If we have more than 2 ranges (4 endpoints) we have to try to merge
// the last and first ones.
unsigned Size = EndPoints.size();
if (Size > 4) {
ConstantInt *FB = cast<ConstantInt>(EndPoints[0]);
ConstantInt *FE = cast<ConstantInt>(EndPoints[1]);
if (tryMergeRange(EndPoints, FB, FE)) {
for (unsigned i = 0; i < Size - 2; ++i) {
EndPoints[i] = EndPoints[i + 2];
}
EndPoints.resize(Size - 2);
}
}
// If in the end we have a single range, it is possible that it is now the
// full range. Just drop the metadata in that case.
if (EndPoints.size() == 2) {
ConstantRange Range(cast<ConstantInt>(EndPoints[0])->getValue(),
cast<ConstantInt>(EndPoints[1])->getValue());
if (Range.isFullSet())
return NULL;
}
return MDNode::get(A->getContext(), EndPoints);
}
static void patchReplacementInstruction(Value *Repl, Instruction *I) {
// Patch the replacement so that it is not more restrictive than the value
// being replaced.
@ -1911,16 +1761,16 @@ static void patchReplacementInstruction(Value *Repl, Instruction *I) {
case LLVMContext::MD_dbg:
llvm_unreachable("getAllMetadataOtherThanDebugLoc returned a MD_dbg");
case LLVMContext::MD_tbaa:
ReplInst->setMetadata(Kind, getMostGenericTBAA(IMD, ReplMD));
ReplInst->setMetadata(Kind, MDNode::getMostGenericTBAA(IMD, ReplMD));
break;
case LLVMContext::MD_range:
ReplInst->setMetadata(Kind, getMostGenericRange(IMD, ReplMD));
ReplInst->setMetadata(Kind, MDNode::getMostGenericRange(IMD, ReplMD));
break;
case LLVMContext::MD_prof:
llvm_unreachable("MD_prof in a non terminator instruction");
break;
case LLVMContext::MD_fpmath:
ReplInst->setMetadata(Kind, getMostGenericFPMath(IMD, ReplMD));
ReplInst->setMetadata(Kind, MDNode::getMostGenericFPMath(IMD, ReplMD));
break;
}
}

View File

@ -21,6 +21,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/STLExtras.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/ValueHandle.h"
using namespace llvm;
@ -401,6 +402,155 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) {
}
}
MDNode *MDNode::getMostGenericTBAA(MDNode *A, MDNode *B) {
if (!A || !B)
return NULL;
if (A == B)
return A;
SmallVector<MDNode *, 4> PathA;
MDNode *T = A;
while (T) {
PathA.push_back(T);
T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0;
}
SmallVector<MDNode *, 4> PathB;
T = B;
while (T) {
PathB.push_back(T);
T = T->getNumOperands() >= 2 ? cast_or_null<MDNode>(T->getOperand(1)) : 0;
}
int IA = PathA.size() - 1;
int IB = PathB.size() - 1;
MDNode *Ret = 0;
while (IA >= 0 && IB >=0) {
if (PathA[IA] == PathB[IB])
Ret = PathA[IA];
else
break;
--IA;
--IB;
}
return Ret;
}
MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) {
if (!A || !B)
return NULL;
APFloat AVal = cast<ConstantFP>(A->getOperand(0))->getValueAPF();
APFloat BVal = cast<ConstantFP>(B->getOperand(0))->getValueAPF();
if (AVal.compare(BVal) == APFloat::cmpLessThan)
return A;
return B;
}
static bool isContiguous(const ConstantRange &A, const ConstantRange &B) {
return A.getUpper() == B.getLower() || A.getLower() == B.getUpper();
}
static bool canBeMerged(const ConstantRange &A, const ConstantRange &B) {
return !A.intersectWith(B).isEmptySet() || isContiguous(A, B);
}
static bool tryMergeRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low,
ConstantInt *High) {
ConstantRange NewRange(Low->getValue(), High->getValue());
unsigned Size = EndPoints.size();
APInt LB = cast<ConstantInt>(EndPoints[Size - 2])->getValue();
APInt LE = cast<ConstantInt>(EndPoints[Size - 1])->getValue();
ConstantRange LastRange(LB, LE);
if (canBeMerged(NewRange, LastRange)) {
ConstantRange Union = LastRange.unionWith(NewRange);
Type *Ty = High->getType();
EndPoints[Size - 2] = ConstantInt::get(Ty, Union.getLower());
EndPoints[Size - 1] = ConstantInt::get(Ty, Union.getUpper());
return true;
}
return false;
}
static void addRange(SmallVector<Value*, 4> &EndPoints, ConstantInt *Low,
ConstantInt *High) {
if (!EndPoints.empty())
if (tryMergeRange(EndPoints, Low, High))
return;
EndPoints.push_back(Low);
EndPoints.push_back(High);
}
MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) {
// Given two ranges, we want to compute the union of the ranges. This
// is slightly complitade by having to combine the intervals and merge
// the ones that overlap.
if (!A || !B)
return NULL;
if (A == B)
return A;
// First, walk both lists in older of the lower boundary of each interval.
// At each step, try to merge the new interval to the last one we adedd.
SmallVector<Value*, 4> EndPoints;
int AI = 0;
int BI = 0;
int AN = A->getNumOperands() / 2;
int BN = B->getNumOperands() / 2;
while (AI < AN && BI < BN) {
ConstantInt *ALow = cast<ConstantInt>(A->getOperand(2 * AI));
ConstantInt *BLow = cast<ConstantInt>(B->getOperand(2 * BI));
if (ALow->getValue().slt(BLow->getValue())) {
addRange(EndPoints, ALow, cast<ConstantInt>(A->getOperand(2 * AI + 1)));
++AI;
} else {
addRange(EndPoints, BLow, cast<ConstantInt>(B->getOperand(2 * BI + 1)));
++BI;
}
}
while (AI < AN) {
addRange(EndPoints, cast<ConstantInt>(A->getOperand(2 * AI)),
cast<ConstantInt>(A->getOperand(2 * AI + 1)));
++AI;
}
while (BI < BN) {
addRange(EndPoints, cast<ConstantInt>(B->getOperand(2 * BI)),
cast<ConstantInt>(B->getOperand(2 * BI + 1)));
++BI;
}
// If we have more than 2 ranges (4 endpoints) we have to try to merge
// the last and first ones.
unsigned Size = EndPoints.size();
if (Size > 4) {
ConstantInt *FB = cast<ConstantInt>(EndPoints[0]);
ConstantInt *FE = cast<ConstantInt>(EndPoints[1]);
if (tryMergeRange(EndPoints, FB, FE)) {
for (unsigned i = 0; i < Size - 2; ++i) {
EndPoints[i] = EndPoints[i + 2];
}
EndPoints.resize(Size - 2);
}
}
// If in the end we have a single range, it is possible that it is now the
// full range. Just drop the metadata in that case.
if (EndPoints.size() == 2) {
ConstantRange Range(cast<ConstantInt>(EndPoints[0])->getValue(),
cast<ConstantInt>(EndPoints[1])->getValue());
if (Range.isFullSet())
return NULL;
}
return MDNode::get(A->getContext(), EndPoints);
}
//===----------------------------------------------------------------------===//
// NamedMDNode implementation.
//