forked from OSchip/llvm-project
[InstSimplify] Don't constant fold or DCE calls that are marked nobuiltin
Differential Revision: https://reviews.llvm.org/D33737 llvm-svn: 305132
This commit is contained in:
parent
dd96270472
commit
647025f9e1
|
@ -31,6 +31,7 @@ class DataLayout;
|
|||
class Function;
|
||||
class GlobalValue;
|
||||
class Instruction;
|
||||
class ImmutableCallSite;
|
||||
class TargetLibraryInfo;
|
||||
class Type;
|
||||
|
||||
|
@ -125,11 +126,12 @@ Constant *ConstantFoldLoadThroughGEPIndices(Constant *C,
|
|||
|
||||
/// canConstantFoldCallTo - Return true if its even possible to fold a call to
|
||||
/// the specified function.
|
||||
bool canConstantFoldCallTo(const Function *F);
|
||||
bool canConstantFoldCallTo(ImmutableCallSite CS, const Function *F);
|
||||
|
||||
/// ConstantFoldCall - Attempt to constant fold a call to the specified function
|
||||
/// with the specified arguments, returning null if unsuccessful.
|
||||
Constant *ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
|
||||
Constant *ConstantFoldCall(ImmutableCallSite CS, Function *F,
|
||||
ArrayRef<Constant *> Operands,
|
||||
const TargetLibraryInfo *TLI = nullptr);
|
||||
|
||||
/// \brief Check whether the given call has no side-effects.
|
||||
|
|
|
@ -41,6 +41,7 @@ template <class T> class ArrayRef;
|
|||
class AssumptionCache;
|
||||
class DominatorTree;
|
||||
class Instruction;
|
||||
class ImmutableCallSite;
|
||||
class DataLayout;
|
||||
class FastMathFlags;
|
||||
struct LoopStandardAnalysisResults;
|
||||
|
@ -194,11 +195,12 @@ Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
|
|||
|
||||
/// Given a function and iterators over arguments, fold the result or return
|
||||
/// null.
|
||||
Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
|
||||
Value *SimplifyCall(ImmutableCallSite CS, Value *V, User::op_iterator ArgBegin,
|
||||
User::op_iterator ArgEnd, const SimplifyQuery &Q);
|
||||
|
||||
/// Given a function and set of arguments, fold the result or return null.
|
||||
Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const SimplifyQuery &Q);
|
||||
Value *SimplifyCall(ImmutableCallSite CS, Value *V, ArrayRef<Value *> Args,
|
||||
const SimplifyQuery &Q);
|
||||
|
||||
/// See if we can compute a simplified version of this instruction. If not,
|
||||
/// return null.
|
||||
|
|
|
@ -1015,9 +1015,11 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
|
|||
case Instruction::ICmp:
|
||||
case Instruction::FCmp: llvm_unreachable("Invalid for compares");
|
||||
case Instruction::Call:
|
||||
if (auto *F = dyn_cast<Function>(Ops.back()))
|
||||
if (canConstantFoldCallTo(F))
|
||||
return ConstantFoldCall(F, Ops.slice(0, Ops.size() - 1), TLI);
|
||||
if (auto *F = dyn_cast<Function>(Ops.back())) {
|
||||
ImmutableCallSite CS(cast<CallInst>(InstOrCE));
|
||||
if (canConstantFoldCallTo(CS, F))
|
||||
return ConstantFoldCall(CS, F, Ops.slice(0, Ops.size() - 1), TLI);
|
||||
}
|
||||
return nullptr;
|
||||
case Instruction::Select:
|
||||
return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
|
||||
|
@ -1356,7 +1358,9 @@ llvm::ConstantFoldLoadThroughGEPIndices(Constant *C,
|
|||
// Constant Folding for Calls
|
||||
//
|
||||
|
||||
bool llvm::canConstantFoldCallTo(const Function *F) {
|
||||
bool llvm::canConstantFoldCallTo(ImmutableCallSite CS, const Function *F) {
|
||||
if (CS.isNoBuiltin())
|
||||
return false;
|
||||
switch (F->getIntrinsicID()) {
|
||||
case Intrinsic::fabs:
|
||||
case Intrinsic::minnum:
|
||||
|
@ -2059,8 +2063,11 @@ Constant *ConstantFoldVectorCall(StringRef Name, unsigned IntrinsicID,
|
|||
} // end anonymous namespace
|
||||
|
||||
Constant *
|
||||
llvm::ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
|
||||
llvm::ConstantFoldCall(ImmutableCallSite CS, Function *F,
|
||||
ArrayRef<Constant *> Operands,
|
||||
const TargetLibraryInfo *TLI) {
|
||||
if (CS.isNoBuiltin())
|
||||
return nullptr;
|
||||
if (!F->hasName())
|
||||
return nullptr;
|
||||
StringRef Name = F->getName();
|
||||
|
@ -2077,6 +2084,8 @@ llvm::ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
|
|||
bool llvm::isMathLibCallNoop(CallSite CS, const TargetLibraryInfo *TLI) {
|
||||
// FIXME: Refactor this code; this duplicates logic in LibCallsShrinkWrap
|
||||
// (and to some extent ConstantFoldScalarCall).
|
||||
if (CS.isNoBuiltin())
|
||||
return false;
|
||||
Function *F = CS.getCalledFunction();
|
||||
if (!F)
|
||||
return false;
|
||||
|
|
|
@ -869,7 +869,7 @@ bool CallAnalyzer::simplifyCallSite(Function *F, CallSite CS) {
|
|||
// because we have to continually rebuild the argument list even when no
|
||||
// simplifications can be performed. Until that is fixed with remapping
|
||||
// inside of instsimplify, directly constant fold calls here.
|
||||
if (!canConstantFoldCallTo(F))
|
||||
if (!canConstantFoldCallTo(CS, F))
|
||||
return false;
|
||||
|
||||
// Try to re-map the arguments to constants.
|
||||
|
@ -885,7 +885,7 @@ bool CallAnalyzer::simplifyCallSite(Function *F, CallSite CS) {
|
|||
|
||||
ConstantArgs.push_back(C);
|
||||
}
|
||||
if (Constant *C = ConstantFoldCall(F, ConstantArgs)) {
|
||||
if (Constant *C = ConstantFoldCall(CS, F, ConstantArgs)) {
|
||||
SimplifiedValues[CS.getInstruction()] = C;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -4473,8 +4473,9 @@ static Value *SimplifyIntrinsic(Function *F, IterTy ArgBegin, IterTy ArgEnd,
|
|||
}
|
||||
|
||||
template <typename IterTy>
|
||||
static Value *SimplifyCall(Value *V, IterTy ArgBegin, IterTy ArgEnd,
|
||||
const SimplifyQuery &Q, unsigned MaxRecurse) {
|
||||
static Value *SimplifyCall(ImmutableCallSite CS, Value *V, IterTy ArgBegin,
|
||||
IterTy ArgEnd, const SimplifyQuery &Q,
|
||||
unsigned MaxRecurse) {
|
||||
Type *Ty = V->getType();
|
||||
if (PointerType *PTy = dyn_cast<PointerType>(Ty))
|
||||
Ty = PTy->getElementType();
|
||||
|
@ -4493,7 +4494,7 @@ static Value *SimplifyCall(Value *V, IterTy ArgBegin, IterTy ArgEnd,
|
|||
if (Value *Ret = SimplifyIntrinsic(F, ArgBegin, ArgEnd, Q, MaxRecurse))
|
||||
return Ret;
|
||||
|
||||
if (!canConstantFoldCallTo(F))
|
||||
if (!canConstantFoldCallTo(CS, F))
|
||||
return nullptr;
|
||||
|
||||
SmallVector<Constant *, 4> ConstantArgs;
|
||||
|
@ -4505,17 +4506,18 @@ static Value *SimplifyCall(Value *V, IterTy ArgBegin, IterTy ArgEnd,
|
|||
ConstantArgs.push_back(C);
|
||||
}
|
||||
|
||||
return ConstantFoldCall(F, ConstantArgs, Q.TLI);
|
||||
return ConstantFoldCall(CS, F, ConstantArgs, Q.TLI);
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyCall(Value *V, User::op_iterator ArgBegin,
|
||||
User::op_iterator ArgEnd, const SimplifyQuery &Q) {
|
||||
return ::SimplifyCall(V, ArgBegin, ArgEnd, Q, RecursionLimit);
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyCall(Value *V, ArrayRef<Value *> Args,
|
||||
Value *llvm::SimplifyCall(ImmutableCallSite CS, Value *V,
|
||||
User::op_iterator ArgBegin, User::op_iterator ArgEnd,
|
||||
const SimplifyQuery &Q) {
|
||||
return ::SimplifyCall(V, Args.begin(), Args.end(), Q, RecursionLimit);
|
||||
return ::SimplifyCall(CS, V, ArgBegin, ArgEnd, Q, RecursionLimit);
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyCall(ImmutableCallSite CS, Value *V,
|
||||
ArrayRef<Value *> Args, const SimplifyQuery &Q) {
|
||||
return ::SimplifyCall(CS, V, Args.begin(), Args.end(), Q, RecursionLimit);
|
||||
}
|
||||
|
||||
/// See if we can compute a simplified version of this instruction.
|
||||
|
@ -4646,7 +4648,8 @@ Value *llvm::SimplifyInstruction(Instruction *I, const SimplifyQuery &SQ,
|
|||
break;
|
||||
case Instruction::Call: {
|
||||
CallSite CS(cast<CallInst>(I));
|
||||
Result = SimplifyCall(CS.getCalledValue(), CS.arg_begin(), CS.arg_end(), Q);
|
||||
Result = SimplifyCall(CS, CS.getCalledValue(), CS.arg_begin(), CS.arg_end(),
|
||||
Q);
|
||||
break;
|
||||
}
|
||||
#define HANDLE_CAST_INST(num, opc, clas) case Instruction::opc:
|
||||
|
|
|
@ -6793,7 +6793,7 @@ static bool CanConstantFold(const Instruction *I) {
|
|||
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(I))
|
||||
if (const Function *F = CI->getCalledFunction())
|
||||
return canConstantFoldCallTo(F);
|
||||
return canConstantFoldCallTo(CI, F);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1814,8 +1814,8 @@ Instruction *InstCombiner::visitVACopyInst(VACopyInst &I) {
|
|||
/// lifting.
|
||||
Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
||||
auto Args = CI.arg_operands();
|
||||
if (Value *V = SimplifyCall(CI.getCalledValue(), Args.begin(), Args.end(),
|
||||
SQ.getWithInstruction(&CI)))
|
||||
if (Value *V = SimplifyCall(&CI, CI.getCalledValue(), Args.begin(),
|
||||
Args.end(), SQ.getWithInstruction(&CI)))
|
||||
return replaceInstUsesWith(CI, V);
|
||||
|
||||
if (isFreeCall(&CI, &TLI))
|
||||
|
|
|
@ -1117,7 +1117,7 @@ CallOverdefined:
|
|||
// Otherwise, if we have a single return value case, and if the function is
|
||||
// a declaration, maybe we can constant fold it.
|
||||
if (F && F->isDeclaration() && !I->getType()->isStructTy() &&
|
||||
canConstantFoldCallTo(F)) {
|
||||
canConstantFoldCallTo(CS, F)) {
|
||||
|
||||
SmallVector<Constant*, 8> Operands;
|
||||
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
|
||||
|
@ -1137,7 +1137,7 @@ CallOverdefined:
|
|||
|
||||
// If we can constant fold this, mark the result of the call as a
|
||||
// constant.
|
||||
if (Constant *C = ConstantFoldCall(F, Operands, TLI)) {
|
||||
if (Constant *C = ConstantFoldCall(CS, F, Operands, TLI)) {
|
||||
// call -> undef.
|
||||
if (isa<UndefValue>(C))
|
||||
return;
|
||||
|
|
|
@ -439,7 +439,7 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst,
|
|||
|
||||
if (Callee->isDeclaration()) {
|
||||
// If this is a function we can constant fold, do it.
|
||||
if (Constant *C = ConstantFoldCall(Callee, Formals, TLI)) {
|
||||
if (Constant *C = ConstantFoldCall(CS, Callee, Formals, TLI)) {
|
||||
InstResult = C;
|
||||
DEBUG(dbgs() << "Constant folded function call. Result: " <<
|
||||
*InstResult << "\n");
|
||||
|
|
|
@ -72,6 +72,10 @@ entry:
|
|||
; CHECK-NEXT: %cos2 = call double @cos(double 0x7FF0000000000000)
|
||||
%cos2 = call double @cos(double 0x7FF0000000000000)
|
||||
|
||||
; cos(0) nobuiltin may have side effects
|
||||
; CHECK-NEXT: %cos3 = call double @cos(double 0.000000e+00)
|
||||
%cos3 = call double @cos(double 0.000000e+00) nobuiltin
|
||||
|
||||
; pow(0, 1) is 0
|
||||
%pow1 = call double @pow(double 0x7FF0000000000000, double 1.000000e+00)
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
|
||||
declare double @acos(double)
|
||||
|
||||
; Check that functions without any function attributes are simplified.
|
||||
|
||||
define double @test_simplify_acos() {
|
||||
; CHECK-LABEL: @test_simplify_acos
|
||||
%pi = call double @acos(double -1.000000e+00)
|
||||
; CHECK-NOT: call double @acos
|
||||
; CHECK: ret double 0x400921FB54442D18
|
||||
ret double %pi
|
||||
}
|
||||
|
||||
define double @test_acos_nobuiltin() {
|
||||
; CHECK-LABEL: @test_acos_nobuiltin
|
||||
%pi = call double @acos(double -1.000000e+00) nobuiltin
|
||||
; CHECK: call double @acos(double -1.000000e+00)
|
||||
ret double %pi
|
||||
}
|
Loading…
Reference in New Issue