diff options
author | Michael Ilseman <milseman@apple.com> | 2013-02-07 19:26:05 +0000 |
---|---|---|
committer | Michael Ilseman <milseman@apple.com> | 2013-02-07 19:26:05 +0000 |
commit | f89de816ae5cf2d0dad7869882dd626532b934ef (patch) | |
tree | 770282708d5bbb6a827369708c27a9e96736472e | |
parent | 96a6555b5706af59e408bb190c3685f0f15bc2a9 (diff) |
Identify and simplify idempotent intrinsics. Test case included.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174650 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Analysis/InstructionSimplify.cpp | 36 | ||||
-rw-r--r-- | test/Transforms/InstSimplify/call.ll | 51 |
2 files changed, 87 insertions, 0 deletions
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 34ff64d900..4a3c74e9db 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -2925,6 +2925,37 @@ Value *llvm::SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, RecursionLimit); } +static bool IsIdempotent(Intrinsic::ID ID) { + switch (ID) { + default: return false; + + // Unary idempotent: f(f(x)) = f(x) + case Intrinsic::fabs: + case Intrinsic::floor: + case Intrinsic::ceil: + case Intrinsic::trunc: + case Intrinsic::rint: + case Intrinsic::nearbyint: + return true; + } +} + +template <typename IterTy> +static Value *SimplifyIntrinsic(Intrinsic::ID IID, IterTy ArgBegin, IterTy ArgEnd, + const Query &Q, unsigned MaxRecurse) { + // Perform idempotent optimizations + if (!IsIdempotent(IID)) + return 0; + + // Unary Ops + if (std::distance(ArgBegin, ArgEnd) == 1) + if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(*ArgBegin)) + if (II->getIntrinsicID() == IID) + return II; + + return 0; +} + template <typename IterTy> static Value *SimplifyCall(Value *V, IterTy ArgBegin, IterTy ArgEnd, const Query &Q, unsigned MaxRecurse) { @@ -2941,6 +2972,11 @@ static Value *SimplifyCall(Value *V, IterTy ArgBegin, IterTy ArgEnd, if (!F) return 0; + if (unsigned IID = F->getIntrinsicID()) + if (Value *Ret = + SimplifyIntrinsic((Intrinsic::ID) IID, ArgBegin, ArgEnd, Q, MaxRecurse)) + return Ret; + if (!canConstantFoldCallTo(F)) return 0; diff --git a/test/Transforms/InstSimplify/call.ll b/test/Transforms/InstSimplify/call.ll index 1a8d0c25bd..cf2f847676 100644 --- a/test/Transforms/InstSimplify/call.ll +++ b/test/Transforms/InstSimplify/call.ll @@ -50,3 +50,54 @@ define float @test_fabs_libcall() { ret float %x ; CHECK-NEXT: ret float 4.2{{0+}}e+01 } + + +declare float @llvm.fabs.f32(float) nounwind readnone +declare float @llvm.floor.f32(float) nounwind readnone +declare float @llvm.ceil.f32(float) nounwind readnone +declare float @llvm.trunc.f32(float) nounwind readnone +declare float @llvm.rint.f32(float) nounwind readnone +declare float @llvm.nearbyint.f32(float) nounwind readnone + +; Test idempotent intrinsics +define float @test_idempotence(float %a) { +; CHECK: @test_idempotence + +; CHECK: fabs +; CHECK-NOT: fabs + %a0 = call float @llvm.fabs.f32(float %a) + %a1 = call float @llvm.fabs.f32(float %a0) + +; CHECK: floor +; CHECK-NOT: floor + %b0 = call float @llvm.floor.f32(float %a) + %b1 = call float @llvm.floor.f32(float %b0) + +; CHECK: ceil +; CHECK-NOT: ceil + %c0 = call float @llvm.ceil.f32(float %a) + %c1 = call float @llvm.ceil.f32(float %c0) + +; CHECK: trunc +; CHECK-NOT: trunc + %d0 = call float @llvm.trunc.f32(float %a) + %d1 = call float @llvm.trunc.f32(float %d0) + +; CHECK: rint +; CHECK-NOT: rint + %e0 = call float @llvm.rint.f32(float %a) + %e1 = call float @llvm.rint.f32(float %e0) + +; CHECK: nearbyint +; CHECK-NOT: nearbyint + %f0 = call float @llvm.nearbyint.f32(float %a) + %f1 = call float @llvm.nearbyint.f32(float %f0) + + %r0 = fadd float %a1, %b1 + %r1 = fadd float %r0, %c1 + %r2 = fadd float %r1, %d1 + %r3 = fadd float %r2, %e1 + %r4 = fadd float %r3, %f1 + + ret float %r4 +} |