summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Analysis/InstructionSimplify.h4
-rw-r--r--lib/Analysis/InstructionSimplify.cpp37
-rw-r--r--test/Transforms/InstSimplify/call.ll52
3 files changed, 83 insertions, 10 deletions
diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h
index dd643a0469..e70bfe2860 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 f0696f070d..e1207f1e47 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 0000000000..1a8d0c25bd
--- /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
+}