diff options
-rw-r--r-- | include/llvm/Analysis/InstructionSimplify.h | 4 | ||||
-rw-r--r-- | lib/Analysis/InstructionSimplify.cpp | 37 | ||||
-rw-r--r-- | test/Transforms/InstSimplify/call.ll | 52 |
3 files changed, 83 insertions, 10 deletions
diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index dd643a0..e70bfe2 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -211,7 +211,7 @@ namespace llvm { /// the result. /// /// If this call could not be simplified returns null. - Value *SimplifyCall(Value *F, User::op_iterator ArgBegin, + Value *SimplifyCall(Value *V, User::op_iterator ArgBegin, User::op_iterator ArgEnd, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); @@ -220,7 +220,7 @@ namespace llvm { /// result. /// /// If this call could not be simplified returns null. - Value *SimplifyCall(Value *F, ArrayRef<Value *> Args, + Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0, const DominatorTree *DT = 0); diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index f0696f0..e1207f1 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -2870,32 +2870,53 @@ Value *llvm::SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, } template <typename IterTy> -static Value *SimplifyCall(Value *F, IterTy ArgBegin, IterTy ArgEnd, +static Value *SimplifyIntrinsic(Intrinsic::ID IID, IterTy ArgBegin, IterTy ArgEnd, + const Query &Q, unsigned MaxRecurse) { +} + +template <typename IterTy> +static Value *SimplifyCall(Value *V, IterTy ArgBegin, IterTy ArgEnd, const Query &Q, unsigned MaxRecurse) { - Type *Ty = F->getType(); + Type *Ty = V->getType(); if (PointerType *PTy = dyn_cast<PointerType>(Ty)) Ty = PTy->getElementType(); FunctionType *FTy = cast<FunctionType>(Ty); // call undef -> undef - if (isa<UndefValue>(F)) + if (isa<UndefValue>(V)) return UndefValue::get(FTy->getReturnType()); - return 0; + Function *F = dyn_cast<Function>(V); + if (!F) + return 0; + + if (!canConstantFoldCallTo(F)) + return 0; + + SmallVector<Constant *, 4> ConstantArgs; + ConstantArgs.reserve(ArgEnd - ArgBegin); + for (IterTy I = ArgBegin, E = ArgEnd; I != E; ++I) { + Constant *C = dyn_cast<Constant>(*I); + if (!C) + return 0; + ConstantArgs.push_back(C); + } + + return ConstantFoldCall(F, ConstantArgs, Q.TLI); } -Value *llvm::SimplifyCall(Value *F, User::op_iterator ArgBegin, +Value *llvm::SimplifyCall(Value *V, User::op_iterator ArgBegin, User::op_iterator ArgEnd, const DataLayout *TD, const TargetLibraryInfo *TLI, const DominatorTree *DT) { - return ::SimplifyCall(F, ArgBegin, ArgEnd, Query(TD, TLI, DT), + return ::SimplifyCall(V, ArgBegin, ArgEnd, Query(TD, TLI, DT), RecursionLimit); } -Value *llvm::SimplifyCall(Value *F, ArrayRef<Value *> Args, +Value *llvm::SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout *TD, const TargetLibraryInfo *TLI, const DominatorTree *DT) { - return ::SimplifyCall(F, Args.begin(), Args.end(), Query(TD, TLI, DT), + return ::SimplifyCall(V, Args.begin(), Args.end(), Query(TD, TLI, DT), RecursionLimit); } diff --git a/test/Transforms/InstSimplify/call.ll b/test/Transforms/InstSimplify/call.ll new file mode 100644 index 0000000..1a8d0c2 --- /dev/null +++ b/test/Transforms/InstSimplify/call.ll @@ -0,0 +1,52 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +declare {i8, i1} @llvm.uadd.with.overflow.i8(i8 %a, i8 %b) + +define i1 @test_uadd1() { +; CHECK: @test_uadd1 + %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 3) + %overflow = extractvalue {i8, i1} %x, 1 + ret i1 %overflow +; CHECK-NEXT: ret i1 true +} + +define i8 @test_uadd2() { +; CHECK: @test_uadd2 + %x = call {i8, i1} @llvm.uadd.with.overflow.i8(i8 254, i8 44) + %result = extractvalue {i8, i1} %x, 0 + ret i8 %result +; CHECK-NEXT: ret i8 42 +} + +declare i256 @llvm.cttz.i256(i256 %src, i1 %is_zero_undef) + +define i256 @test_cttz() { +; CHECK: @test_cttz + %x = call i256 @llvm.cttz.i256(i256 10, i1 false) + ret i256 %x +; CHECK-NEXT: ret i256 1 +} + +declare i256 @llvm.ctpop.i256(i256 %src) + +define i256 @test_ctpop() { +; CHECK: @test_ctpop + %x = call i256 @llvm.ctpop.i256(i256 10) + ret i256 %x +; CHECK-NEXT: ret i256 2 +} + +; Test a non-intrinsic that we know about as a library call. +declare float @fabs(float %x) + +define float @test_fabs_libcall() { +; CHECK: @test_fabs_libcall + + %x = call float @fabs(float -42.0) +; This is still a real function call, so instsimplify won't nuke it -- other +; passes have to do that. +; CHECK-NEXT: call float @fabs + + ret float %x +; CHECK-NEXT: ret float 4.2{{0+}}e+01 +} |