aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Ilseman <milseman@apple.com>2013-02-07 19:26:05 +0000
committerMichael Ilseman <milseman@apple.com>2013-02-07 19:26:05 +0000
commitf89de816ae5cf2d0dad7869882dd626532b934ef (patch)
tree770282708d5bbb6a827369708c27a9e96736472e
parent96a6555b5706af59e408bb190c3685f0f15bc2a9 (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.cpp36
-rw-r--r--test/Transforms/InstSimplify/call.ll51
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
+}