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

Benjamin Kramer benny.kra at gmail.com
Thu Feb 7 12:02:28 PST 2013


On 07.02.2013, at 20:58, Nuno Lopes <nunoplopes at sapo.pt> wrote:

> Wait, aren't all nounwind + readnone functions idempotent?

int foo(int x) {
  return x + 1;
}

that's nounwind + readnone, but not idempotent.

- Ben

> 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 
> 
> _______________________________________________
> 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