Update GVN to support vectors of pointers.

GVN will now generate ptrtoint instructions for vectors of pointers.
Fixes PR14166.

llvm-svn: 166624
This commit is contained in:
Hal Finkel 2012-10-24 21:22:30 +00:00
parent 30cc37ae2b
commit 69b07a2c3a
2 changed files with 57 additions and 20 deletions

View File

@ -746,6 +746,15 @@ static bool CanCoerceMustAliasedValueToLoad(Value *StoredVal,
return true;
}
/// Wrap TD.getIntPtrType, but return a vector type for vector inputs.
static Type *getIntPtrType(Type *Ty, const DataLayout &TD) {
Type *ITy = TD.getIntPtrType(Ty);
if (Ty->isVectorTy()) {
ITy = VectorType::get(ITy, Ty->getVectorNumElements());
}
return ITy;
}
/// CoerceAvailableValueToLoadType - If we saw a store of a value to memory, and
/// then a load from a must-aliased pointer of a different type, try to coerce
@ -769,24 +778,25 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal,
// If the store and reload are the same size, we can always reuse it.
if (StoreSize == LoadSize) {
// Pointer to Pointer -> use bitcast.
if (StoredValTy->isPointerTy() && LoadedTy->isPointerTy())
if (StoredValTy->getScalarType()->isPointerTy() &&
LoadedTy->getScalarType()->isPointerTy())
return new BitCastInst(StoredVal, LoadedTy, "", InsertPt);
// Convert source pointers to integers, which can be bitcast.
if (StoredValTy->isPointerTy()) {
StoredValTy = TD.getIntPtrType(StoredValTy);
if (StoredValTy->getScalarType()->isPointerTy()) {
StoredValTy = getIntPtrType(StoredValTy, TD);
StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt);
}
Type *TypeToCastTo = LoadedTy;
if (TypeToCastTo->isPointerTy())
TypeToCastTo = TD.getIntPtrType(StoredValTy);
if (TypeToCastTo->getScalarType()->isPointerTy())
TypeToCastTo = getIntPtrType(StoredValTy, TD);
if (StoredValTy != TypeToCastTo)
StoredVal = new BitCastInst(StoredVal, TypeToCastTo, "", InsertPt);
// Cast to pointer if the load needs a pointer type.
if (LoadedTy->isPointerTy())
if (LoadedTy->getScalarType()->isPointerTy())
StoredVal = new IntToPtrInst(StoredVal, LoadedTy, "", InsertPt);
return StoredVal;
@ -798,8 +808,8 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal,
assert(StoreSize >= LoadSize && "CanCoerceMustAliasedValueToLoad fail");
// Convert source pointers to integers, which can be manipulated.
if (StoredValTy->isPointerTy()) {
StoredValTy = TD.getIntPtrType(StoredValTy);
if (StoredValTy->getScalarType()->isPointerTy()) {
StoredValTy = getIntPtrType(StoredValTy, TD);
StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt);
}
@ -824,7 +834,7 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal,
return StoredVal;
// If the result is a pointer, inttoptr.
if (LoadedTy->isPointerTy())
if (LoadedTy->getScalarType()->isPointerTy())
return new IntToPtrInst(StoredVal, LoadedTy, "inttoptr", InsertPt);
// Otherwise, bitcast.
@ -1019,9 +1029,9 @@ static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset,
// Compute which bits of the stored value are being used by the load. Convert
// to an integer type to start with.
if (SrcVal->getType()->isPointerTy())
if (SrcVal->getType()->getScalarType()->isPointerTy())
SrcVal = Builder.CreatePtrToInt(SrcVal,
TD.getIntPtrType(SrcVal->getType()));
getIntPtrType(SrcVal->getType(), TD));
if (!SrcVal->getType()->isIntegerTy())
SrcVal = Builder.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize*8));
@ -1302,7 +1312,7 @@ static Value *ConstructSSAForLoadSet(LoadInst *LI,
Value *V = SSAUpdate.GetValueInMiddleOfBlock(LI->getParent());
// If new PHI nodes were created, notify alias analysis.
if (V->getType()->isPointerTy()) {
if (V->getType()->getScalarType()->isPointerTy()) {
AliasAnalysis *AA = gvn.getAliasAnalysis();
for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i)
@ -1499,7 +1509,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
if (isa<PHINode>(V))
V->takeName(LI);
if (V->getType()->isPointerTy())
if (V->getType()->getScalarType()->isPointerTy())
MD->invalidateCachedPointerInfo(V);
markInstructionForDeletion(LI);
++NumGVNLoad;
@ -1731,7 +1741,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
LI->replaceAllUsesWith(V);
if (isa<PHINode>(V))
V->takeName(LI);
if (V->getType()->isPointerTy())
if (V->getType()->getScalarType()->isPointerTy())
MD->invalidateCachedPointerInfo(V);
markInstructionForDeletion(LI);
++NumPRELoad;
@ -1858,7 +1868,7 @@ bool GVN::processLoad(LoadInst *L) {
// Replace the load!
L->replaceAllUsesWith(AvailVal);
if (AvailVal->getType()->isPointerTy())
if (AvailVal->getType()->getScalarType()->isPointerTy())
MD->invalidateCachedPointerInfo(AvailVal);
markInstructionForDeletion(L);
++NumGVNLoad;
@ -1915,7 +1925,7 @@ bool GVN::processLoad(LoadInst *L) {
// Remove it!
L->replaceAllUsesWith(StoredVal);
if (StoredVal->getType()->isPointerTy())
if (StoredVal->getType()->getScalarType()->isPointerTy())
MD->invalidateCachedPointerInfo(StoredVal);
markInstructionForDeletion(L);
++NumGVNLoad;
@ -1944,7 +1954,7 @@ bool GVN::processLoad(LoadInst *L) {
// Remove it!
patchAndReplaceAllUsesWith(AvailableVal, L);
if (DepLI->getType()->isPointerTy())
if (DepLI->getType()->getScalarType()->isPointerTy())
MD->invalidateCachedPointerInfo(DepLI);
markInstructionForDeletion(L);
++NumGVNLoad;
@ -2185,7 +2195,7 @@ bool GVN::processInstruction(Instruction *I) {
// "%z = and i32 %x, %y" becomes "%z = and i32 %x, %x" which we now simplify.
if (Value *V = SimplifyInstruction(I, TD, TLI, DT)) {
I->replaceAllUsesWith(V);
if (MD && V->getType()->isPointerTy())
if (MD && V->getType()->getScalarType()->isPointerTy())
MD->invalidateCachedPointerInfo(V);
markInstructionForDeletion(I);
++NumGVNSimpl;
@ -2285,7 +2295,7 @@ bool GVN::processInstruction(Instruction *I) {
// Remove it!
patchAndReplaceAllUsesWith(repl, I);
if (MD && repl->getType()->isPointerTy())
if (MD && repl->getType()->getScalarType()->isPointerTy())
MD->invalidateCachedPointerInfo(repl);
markInstructionForDeletion(I);
return true;
@ -2533,7 +2543,7 @@ bool GVN::performPRE(Function &F) {
addToLeaderTable(ValNo, Phi, CurrentBlock);
Phi->setDebugLoc(CurInst->getDebugLoc());
CurInst->replaceAllUsesWith(Phi);
if (Phi->getType()->isPointerTy()) {
if (Phi->getType()->getScalarType()->isPointerTy()) {
// Because we have added a PHI-use of the pointer value, it has now
// "escaped" from alias analysis' perspective. We need to inform
// AA of this.

View File

@ -0,0 +1,27 @@
; RUN: opt -gvn -S < %s | FileCheck %s
target datalayout = "e-p:32:32:32"
target triple = "i386-pc-linux-gnu"
define <2 x i32> @test1() {
%v1 = alloca <2 x i32>
call void @anything(<2 x i32>* %v1)
%v2 = load <2 x i32>* %v1
%v3 = inttoptr <2 x i32> %v2 to <2 x i8*>
%v4 = bitcast <2 x i32>* %v1 to <2 x i8*>*
store <2 x i8*> %v3, <2 x i8*>* %v4
%v5 = load <2 x i32>* %v1
ret <2 x i32> %v5
; CHECK: @test1
; CHECK: %v1 = alloca <2 x i32>
; CHECK: call void @anything(<2 x i32>* %v1)
; CHECK: %v2 = load <2 x i32>* %v1
; CHECK: %v3 = inttoptr <2 x i32> %v2 to <2 x i8*>
; CHECK: %v4 = bitcast <2 x i32>* %v1 to <2 x i8*>*
; CHECK: store <2 x i8*> %v3, <2 x i8*>* %v4
; CHECK: %1 = ptrtoint <2 x i8*> %v3 to <2 x i32>
; CHECK: %2 = bitcast <2 x i32> %1 to i64
; CHECK: %3 = bitcast i64 %2 to <2 x i32>
; CHECK: ret <2 x i32> %3
}
declare void @anything(<2 x i32>*)