Fix bug in ptr+offset decomposition in GatherScatterFlattenOpt

Given IR that encoded computation like "vec(4) + ptr2int(some pointer)",
we'd report that "int2ptr(4)" was the base pointer and the ptr2int 
value was the offset.  This in turn could lead to incorrect code
from LLVM, since we'd end up with GEP instructions where the first
operand was int2ptr(4) and the offset was the original pointer value.
This in turn was sometimes leading to incorrect code and thence a 
failure on the tests/gs-double-improve-multidim.ispc test since LLVM's
memory read/write analysis assumes that nothing after the first operand
of a GEP is actually a pointer.
This commit is contained in:
Matt Pharr
2011-11-28 15:00:41 -08:00
parent 867efc2bce
commit 2a6e3e5fea

36
opt.cpp
View File

@@ -788,6 +788,35 @@ lFlattenInsertChain(llvm::InsertElementInst *ie, int vectorWidth,
}
}
/** Check to make sure that this value is actually a pointer in the end.
We need to make sure that given an expression like vec(offset) +
ptr2int(ptr), lGetBasePointer() doesn't return vec(offset) for the base
pointer such that we then treat ptr2int(ptr) as an offset. This ends
up being important so that we don't generate LLVM GEP instructions like
"gep inttoptr 8, i64 %ptr", which in turn can lead to incorrect code
since LLVM's pointer aliasing analysis assumes that operands after the
first one to a GEP aren't pointers.
*/
static llvm::Value *
lCheckForActualPointer(llvm::Value *v) {
if (v == NULL)
return NULL;
else if (llvm::isa<LLVM_TYPE_CONST llvm::PointerType>(v->getType()))
return v;
else if (llvm::isa<llvm::PtrToIntInst>(v))
return v;
else {
llvm::ConstantExpr *uce =
llvm::dyn_cast<llvm::ConstantExpr>(v);
if (uce != NULL &&
uce->getOpcode() == llvm::Instruction::PtrToInt)
return v;
return NULL;
}
}
/** Given a llvm::Value representing a varying pointer, this function
checks to see if all of the elements of the vector have the same value
(i.e. there's a common base pointer). If so, it returns the common
@@ -813,13 +842,13 @@ lGetBasePointer(llvm::Value *v) {
if (elements[i] != elements[i+1])
return NULL;
return elements[0];
return lCheckForActualPointer(elements[0]);
}
// This case comes up with global/static arrays
llvm::ConstantVector *cv = llvm::dyn_cast<llvm::ConstantVector>(v);
if (cv)
return cv->getSplatValue();
if (cv != NULL)
return lCheckForActualPointer(cv->getSplatValue());
return NULL;
}
@@ -1020,6 +1049,7 @@ GatherScatterFlattenOpt::runOnBasicBlock(llvm::BasicBlock &bb) {
modifiedAny = true;
goto restart;
}
return modifiedAny;
}