forked from OSchip/llvm-project
fix PR8932, a case where arg promotion could infinitely promote.
llvm-svn: 123574
This commit is contained in:
parent
ed1fb92cfe
commit
e5f8de8639
|
@ -135,47 +135,74 @@ CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) {
|
||||||
if (PointerArgs.empty()) return 0;
|
if (PointerArgs.empty()) return 0;
|
||||||
|
|
||||||
// Second check: make sure that all callers are direct callers. We can't
|
// Second check: make sure that all callers are direct callers. We can't
|
||||||
// transform functions that have indirect callers.
|
// transform functions that have indirect callers. Also see if the function
|
||||||
if (F->hasAddressTaken())
|
// is self-recursive.
|
||||||
return 0;
|
bool isSelfRecursive = false;
|
||||||
|
for (Value::use_iterator UI = F->use_begin(), E = F->use_end();
|
||||||
|
UI != E; ++UI) {
|
||||||
|
CallSite CS(*UI);
|
||||||
|
// Must be a direct call.
|
||||||
|
if (CS.getInstruction() == 0 || !CS.isCallee(UI)) return 0;
|
||||||
|
|
||||||
|
if (CS.getInstruction()->getParent()->getParent() == F)
|
||||||
|
isSelfRecursive = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check to see which arguments are promotable. If an argument is promotable,
|
// Check to see which arguments are promotable. If an argument is promotable,
|
||||||
// add it to ArgsToPromote.
|
// add it to ArgsToPromote.
|
||||||
SmallPtrSet<Argument*, 8> ArgsToPromote;
|
SmallPtrSet<Argument*, 8> ArgsToPromote;
|
||||||
SmallPtrSet<Argument*, 8> ByValArgsToTransform;
|
SmallPtrSet<Argument*, 8> ByValArgsToTransform;
|
||||||
for (unsigned i = 0; i != PointerArgs.size(); ++i) {
|
for (unsigned i = 0; i != PointerArgs.size(); ++i) {
|
||||||
bool isByVal = F->paramHasAttr(PointerArgs[i].second+1, Attribute::ByVal);
|
bool isByVal = F->paramHasAttr(PointerArgs[i].second+1, Attribute::ByVal);
|
||||||
|
Argument *PtrArg = PointerArgs[i].first;
|
||||||
|
const Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType();
|
||||||
|
|
||||||
// If this is a byval argument, and if the aggregate type is small, just
|
// If this is a byval argument, and if the aggregate type is small, just
|
||||||
// pass the elements, which is always safe.
|
// pass the elements, which is always safe.
|
||||||
Argument *PtrArg = PointerArgs[i].first;
|
|
||||||
if (isByVal) {
|
if (isByVal) {
|
||||||
const Type *AgTy = cast<PointerType>(PtrArg->getType())->getElementType();
|
|
||||||
if (const StructType *STy = dyn_cast<StructType>(AgTy)) {
|
if (const StructType *STy = dyn_cast<StructType>(AgTy)) {
|
||||||
if (maxElements > 0 && STy->getNumElements() > maxElements) {
|
if (maxElements > 0 && STy->getNumElements() > maxElements) {
|
||||||
DEBUG(dbgs() << "argpromotion disable promoting argument '"
|
DEBUG(dbgs() << "argpromotion disable promoting argument '"
|
||||||
<< PtrArg->getName() << "' because it would require adding more"
|
<< PtrArg->getName() << "' because it would require adding more"
|
||||||
<< " than " << maxElements << " arguments to the function.\n");
|
<< " than " << maxElements << " arguments to the function.\n");
|
||||||
} else {
|
continue;
|
||||||
// If all the elements are single-value types, we can promote it.
|
}
|
||||||
bool AllSimple = true;
|
|
||||||
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
|
// If all the elements are single-value types, we can promote it.
|
||||||
if (!STy->getElementType(i)->isSingleValueType()) {
|
bool AllSimple = true;
|
||||||
AllSimple = false;
|
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
|
||||||
break;
|
if (!STy->getElementType(i)->isSingleValueType()) {
|
||||||
}
|
AllSimple = false;
|
||||||
|
break;
|
||||||
// Safe to transform, don't even bother trying to "promote" it.
|
|
||||||
// Passing the elements as a scalar will allow scalarrepl to hack on
|
|
||||||
// the new alloca we introduce.
|
|
||||||
if (AllSimple) {
|
|
||||||
ByValArgsToTransform.insert(PtrArg);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Safe to transform, don't even bother trying to "promote" it.
|
||||||
|
// Passing the elements as a scalar will allow scalarrepl to hack on
|
||||||
|
// the new alloca we introduce.
|
||||||
|
if (AllSimple) {
|
||||||
|
ByValArgsToTransform.insert(PtrArg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the argument is a recursive type and we're in a recursive
|
||||||
|
// function, we could end up infinitely peeling the function argument.
|
||||||
|
if (isSelfRecursive) {
|
||||||
|
if (const StructType *STy = dyn_cast<StructType>(AgTy)) {
|
||||||
|
bool RecursiveType = false;
|
||||||
|
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
|
||||||
|
if (STy->getElementType(i) == PtrArg->getType()) {
|
||||||
|
RecursiveType = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (RecursiveType)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Otherwise, see if we can promote the pointer to its value.
|
// Otherwise, see if we can promote the pointer to its value.
|
||||||
if (isSafeToPromoteArgument(PtrArg, isByVal))
|
if (isSafeToPromoteArgument(PtrArg, isByVal))
|
||||||
ArgsToPromote.insert(PtrArg);
|
ArgsToPromote.insert(PtrArg);
|
||||||
|
@ -188,9 +215,9 @@ CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) {
|
||||||
return DoPromotion(F, ArgsToPromote, ByValArgsToTransform);
|
return DoPromotion(F, ArgsToPromote, ByValArgsToTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AllCalleesPassInValidPointerForArgument - Return true if we can prove that
|
/// AllCallersPassInValidPointerForArgument - Return true if we can prove that
|
||||||
/// all callees pass in a valid pointer for the specified function argument.
|
/// all callees pass in a valid pointer for the specified function argument.
|
||||||
static bool AllCalleesPassInValidPointerForArgument(Argument *Arg) {
|
static bool AllCallersPassInValidPointerForArgument(Argument *Arg) {
|
||||||
Function *Callee = Arg->getParent();
|
Function *Callee = Arg->getParent();
|
||||||
|
|
||||||
unsigned ArgNo = std::distance(Callee->arg_begin(),
|
unsigned ArgNo = std::distance(Callee->arg_begin(),
|
||||||
|
@ -310,7 +337,7 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg, bool isByVal) const {
|
||||||
GEPIndicesSet ToPromote;
|
GEPIndicesSet ToPromote;
|
||||||
|
|
||||||
// If the pointer is always valid, any load with first index 0 is valid.
|
// If the pointer is always valid, any load with first index 0 is valid.
|
||||||
if (isByVal || AllCalleesPassInValidPointerForArgument(Arg))
|
if (isByVal || AllCallersPassInValidPointerForArgument(Arg))
|
||||||
SafeToUnconditionallyLoad.insert(IndicesVector(1, 0));
|
SafeToUnconditionallyLoad.insert(IndicesVector(1, 0));
|
||||||
|
|
||||||
// First, iterate the entry block and mark loads of (geps of) arguments as
|
// First, iterate the entry block and mark loads of (geps of) arguments as
|
||||||
|
|
|
@ -36,3 +36,24 @@ entry:
|
||||||
ret i1 undef
|
ret i1 undef
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
; PR8932 - infinite promotion.
|
||||||
|
%0 = type { %0* }
|
||||||
|
|
||||||
|
define i32 @test2(i32 %a) {
|
||||||
|
init:
|
||||||
|
%0 = alloca %0
|
||||||
|
%1 = alloca %0
|
||||||
|
%2 = call i32 @"clay_assign(Chain, Chain)"(%0* %0, %0* %1)
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
||||||
|
define internal i32 @"clay_assign(Chain, Chain)"(%0* %c, %0* %d) {
|
||||||
|
init:
|
||||||
|
%0 = getelementptr %0* %d, i32 0, i32 0
|
||||||
|
%1 = load %0** %0
|
||||||
|
%2 = getelementptr %0* %c, i32 0, i32 0
|
||||||
|
%3 = load %0** %2
|
||||||
|
%4 = call i32 @"clay_assign(Chain, Chain)"(%0* %3, %0* %1)
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue