[llvm] r174650 - Identify and simplify idempotent intrinsics. Testcase included.

Nuno Lopes nunoplopes at sapo.pt
Thu Feb 7 12:14:21 PST 2013


Ah, yes, stupid me.
Sorry for the noise, carry on.
Nuno

----- Original Message -----
> Idempotent means that (for unary ops) f(f(x)) = f(x).
>
> This is true of e.g. abs(abs(x)), but not for sqrt(sqrt(x)).
>
> On Feb 7, 2013, at 11:58 AM, Nuno Lopes <nunoplopes at sapo.pt> wrote:
>
>> Wait, aren't all nounwind + readnone functions idempotent?
>> Nuno
>>
>> ----- Original Message -----
>>> Author: milseman
>>> Date: Thu Feb  7 13:26:05 2013
>>> New Revision: 174650
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=174650&view=rev
>>> Log:
>>> Identify and simplify idempotent intrinsics. Test case included.
>>>
>>> Modified:
>>>   llvm/trunk/lib/Analysis/InstructionSimplify.cpp
>>>   llvm/trunk/test/Transforms/InstSimplify/call.ll
>>>
>>> Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
>>> URL: 
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=174650&r1=174649&r2=174650&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Thu Feb  7 13:26:05 
>>> 2013
>>> @@ -2925,6 +2925,37 @@ Value *llvm::SimplifyCmpInst(unsigned Pr
>>>                           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, Ite
>>>  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;
>>>
>>>
>>> Modified: llvm/trunk/test/Transforms/InstSimplify/call.ll
>>> URL: 
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/call.ll?rev=174650&r1=174649&r2=174650&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/test/Transforms/InstSimplify/call.ll (original)
>>> +++ llvm/trunk/test/Transforms/InstSimplify/call.ll Thu Feb  7 13:26:05 
>>> 2013
>>> @@ -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
>>> +}
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits 




More information about the llvm-commits mailing list