forked from OSchip/llvm-project
Reland "Revert "[InstCombine] when calling conventions are compatible, don't convert the call to undef idiom""
This reverts commita3fabc79ae
(relandsf4d682d6ce
with fix for the compile-time regression issue).
This commit is contained in:
parent
c2ad7c2370
commit
c5fda0e662
|
@ -192,6 +192,11 @@ public:
|
|||
/// vector functions.
|
||||
void getWidestVF(StringRef ScalarF, ElementCount &FixedVF,
|
||||
ElementCount &Scalable) const;
|
||||
|
||||
/// Returns true if call site / callee has cdecl-compatible calling
|
||||
/// conventions.
|
||||
static bool isCallingConvCCompatible(CallBase *CI);
|
||||
static bool isCallingConvCCompatible(Function *Callee);
|
||||
};
|
||||
|
||||
/// Provides information about what library functions are available for
|
||||
|
|
|
@ -65,6 +65,49 @@ static bool hasBcmp(const Triple &TT) {
|
|||
return TT.isOSFreeBSD() || TT.isOSSolaris();
|
||||
}
|
||||
|
||||
static bool isCallingConvCCompatible(CallingConv::ID CC, StringRef TT,
|
||||
FunctionType *FuncTy) {
|
||||
switch (CC) {
|
||||
default:
|
||||
return false;
|
||||
case llvm::CallingConv::C:
|
||||
return true;
|
||||
case llvm::CallingConv::ARM_APCS:
|
||||
case llvm::CallingConv::ARM_AAPCS:
|
||||
case llvm::CallingConv::ARM_AAPCS_VFP: {
|
||||
|
||||
// The iOS ABI diverges from the standard in some cases, so for now don't
|
||||
// try to simplify those calls.
|
||||
if (Triple(TT).isiOS())
|
||||
return false;
|
||||
|
||||
if (!FuncTy->getReturnType()->isPointerTy() &&
|
||||
!FuncTy->getReturnType()->isIntegerTy() &&
|
||||
!FuncTy->getReturnType()->isVoidTy())
|
||||
return false;
|
||||
|
||||
for (auto *Param : FuncTy->params()) {
|
||||
if (!Param->isPointerTy() && !Param->isIntegerTy())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TargetLibraryInfoImpl::isCallingConvCCompatible(CallBase *CI) {
|
||||
return ::isCallingConvCCompatible(CI->getCallingConv(),
|
||||
CI->getModule()->getTargetTriple(),
|
||||
CI->getFunctionType());
|
||||
}
|
||||
|
||||
bool TargetLibraryInfoImpl::isCallingConvCCompatible(Function *F) {
|
||||
return ::isCallingConvCCompatible(F->getCallingConv(),
|
||||
F->getParent()->getTargetTriple(),
|
||||
F->getFunctionType());
|
||||
}
|
||||
|
||||
/// Initialize the set of available library functions based on the specified
|
||||
/// target triple. This should be carefully written so that a missing target
|
||||
/// triple gets a sane set of defaults.
|
||||
|
|
|
@ -2158,9 +2158,14 @@ Instruction *InstCombinerImpl::visitCallBase(CallBase &Call) {
|
|||
return &Call;
|
||||
}
|
||||
|
||||
// If the call and callee calling conventions don't match, this call must
|
||||
// be unreachable, as the call is undefined.
|
||||
if (CalleeF->getCallingConv() != Call.getCallingConv() &&
|
||||
// If the call and callee calling conventions don't match, and neither one
|
||||
// of the calling conventions is compatible with C calling convention
|
||||
// this call must be unreachable, as the call is undefined.
|
||||
if ((CalleeF->getCallingConv() != Call.getCallingConv() &&
|
||||
!(CalleeF->getCallingConv() == llvm::CallingConv::C &&
|
||||
TargetLibraryInfoImpl::isCallingConvCCompatible(&Call)) &&
|
||||
!(Call.getCallingConv() == llvm::CallingConv::C &&
|
||||
TargetLibraryInfoImpl::isCallingConvCCompatible(CalleeF))) &&
|
||||
// Only do this for calls to a function with a body. A prototype may
|
||||
// not actually end up matching the implementation's calling conv for a
|
||||
// variety of reasons (e.g. it may be written in assembly).
|
||||
|
|
|
@ -56,38 +56,6 @@ static bool ignoreCallingConv(LibFunc Func) {
|
|||
Func == LibFunc_llabs || Func == LibFunc_strlen;
|
||||
}
|
||||
|
||||
static bool isCallingConvCCompatible(CallInst *CI) {
|
||||
switch(CI->getCallingConv()) {
|
||||
default:
|
||||
return false;
|
||||
case llvm::CallingConv::C:
|
||||
return true;
|
||||
case llvm::CallingConv::ARM_APCS:
|
||||
case llvm::CallingConv::ARM_AAPCS:
|
||||
case llvm::CallingConv::ARM_AAPCS_VFP: {
|
||||
|
||||
// The iOS ABI diverges from the standard in some cases, so for now don't
|
||||
// try to simplify those calls.
|
||||
if (Triple(CI->getModule()->getTargetTriple()).isiOS())
|
||||
return false;
|
||||
|
||||
auto *FuncTy = CI->getFunctionType();
|
||||
|
||||
if (!FuncTy->getReturnType()->isPointerTy() &&
|
||||
!FuncTy->getReturnType()->isIntegerTy() &&
|
||||
!FuncTy->getReturnType()->isVoidTy())
|
||||
return false;
|
||||
|
||||
for (auto Param : FuncTy->params()) {
|
||||
if (!Param->isPointerTy() && !Param->isIntegerTy())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Return true if it is only used in equality comparisons with With.
|
||||
static bool isOnlyUsedInEqualityComparison(Value *V, Value *With) {
|
||||
for (User *U : V->users()) {
|
||||
|
@ -2862,9 +2830,10 @@ Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI,
|
|||
// Check for string/memory library functions.
|
||||
if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) {
|
||||
// Make sure we never change the calling convention.
|
||||
assert((ignoreCallingConv(Func) ||
|
||||
isCallingConvCCompatible(CI)) &&
|
||||
"Optimizing string/memory libcall would change the calling convention");
|
||||
assert(
|
||||
(ignoreCallingConv(Func) ||
|
||||
TargetLibraryInfoImpl::isCallingConvCCompatible(CI)) &&
|
||||
"Optimizing string/memory libcall would change the calling convention");
|
||||
switch (Func) {
|
||||
case LibFunc_strcat:
|
||||
return optimizeStrCat(CI, Builder);
|
||||
|
@ -3048,7 +3017,7 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) {
|
|||
|
||||
LibFunc Func;
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
bool isCallingConvC = isCallingConvCCompatible(CI);
|
||||
bool IsCallingConvC = TargetLibraryInfoImpl::isCallingConvCCompatible(CI);
|
||||
|
||||
SmallVector<OperandBundleDef, 2> OpBundles;
|
||||
CI->getOperandBundlesAsDefs(OpBundles);
|
||||
|
@ -3066,7 +3035,7 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) {
|
|||
|
||||
// First, check for intrinsics.
|
||||
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
|
||||
if (!isCallingConvC)
|
||||
if (!IsCallingConvC)
|
||||
return nullptr;
|
||||
// The FP intrinsics have corresponding constrained versions so we don't
|
||||
// need to check for the StrictFP attribute here.
|
||||
|
@ -3119,7 +3088,7 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) {
|
|||
// Then check for known library functions.
|
||||
if (TLI->getLibFunc(*Callee, Func) && TLI->has(Func)) {
|
||||
// We never change the calling convention.
|
||||
if (!ignoreCallingConv(Func) && !isCallingConvC)
|
||||
if (!ignoreCallingConv(Func) && !IsCallingConvC)
|
||||
return nullptr;
|
||||
if (Value *V = optimizeStringMemoryLibCall(CI, Builder))
|
||||
return V;
|
||||
|
@ -3503,7 +3472,7 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI,
|
|||
|
||||
LibFunc Func;
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
bool isCallingConvC = isCallingConvCCompatible(CI);
|
||||
bool IsCallingConvC = TargetLibraryInfoImpl::isCallingConvCCompatible(CI);
|
||||
|
||||
SmallVector<OperandBundleDef, 2> OpBundles;
|
||||
CI->getOperandBundlesAsDefs(OpBundles);
|
||||
|
@ -3517,7 +3486,7 @@ Value *FortifiedLibCallSimplifier::optimizeCall(CallInst *CI,
|
|||
return nullptr;
|
||||
|
||||
// We never change the calling convention.
|
||||
if (!ignoreCallingConv(Func) && !isCallingConvC)
|
||||
if (!ignoreCallingConv(Func) && !IsCallingConvC)
|
||||
return nullptr;
|
||||
|
||||
switch (Func) {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
; Verify that a cdecl-compatible calling convention does not trigger emitting
|
||||
; unreachable idom `store i1 true, i1* undef`.
|
||||
|
||||
define arm_aapcs_vfpcc i8 @bar(i8* %0) {
|
||||
; CHECK-LABEL: @bar(
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = load i8, i8* [[TMP0:%.*]], align 1
|
||||
; CHECK-NEXT: ret i8 [[TMP2]]
|
||||
;
|
||||
%2 = load i8, i8* %0, align 1
|
||||
ret i8 %2
|
||||
}
|
||||
|
||||
define dso_local arm_aapcs_vfpcc i8 @foo(i8* %0) {
|
||||
; CHECK-LABEL: @foo(
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call i8 @bar(i8* [[TMP0:%.*]])
|
||||
; CHECK-NEXT: ret i8 [[TMP2]]
|
||||
;
|
||||
%2 = call i8 @bar(i8* %0)
|
||||
ret i8 %2
|
||||
}
|
Loading…
Reference in New Issue