[llvm-commits] [llvm] r54786 - in /llvm/trunk: lib/Transforms/Scalar/LoopStrengthReduce.cpp test/Transforms/LoopStrengthReduce/2008-08-14-ShadowIV.ll

Daniel Dunbar daniel at zuster.org
Thu Aug 14 21:09:27 PDT 2008


I can't really speak to the legality because I'm not familiar with what the 
standard says w.r.t. floating point transformations. My assumption has 
always been that the compiler was restricted from doing anything this 
aggressive. Actually I didn't even think the compiler was allowed to 
reassociate ((x + 1.) + 1.) for some FP x, within a single statement. I'd 
love to know kind of flexibility is actually allowed though.

> In your second example, 9907199999999999 is out of range of  
> representable unsigneds, so this patch shouldn't cause a problem.  I think it's "safe"


Yes, this is true. Although I think it is more complicated than just the bits
in the mantissa exceeding the bits of the type, because really the issue is
whether the mantissa has enough bits to represent '1', which will vary depending
on the exponent. However, it may be that cases where that is not true (for
double) would already have roundoff errors.

Of course, if this transformation induced
--
double d = 9907199999999999;
for (unsigned i=0; i<someLargeN; ++i)
  foo(d + (double) i);
--
to transform to
--
double d = 9907199999999999;
for (unsigned i=0; i<someLargeN; ++i, ++d)
  foo(d);
--
the issue would still occur, but that is more the fault of folding the cast into the add.

It also seems to me that there is potential for
--
for (unsigned i=~4; i!=4, ++i)
    foo((double) i);
--
to be transformed to something completely different, but I don't
understand all of the machinery in this crazy "back-end" world. :)

 - Daniel


----- Original Message ----
From: Dale Johannesen <dalej at apple.com>
To: Commit Messages and Patches for LLVM <llvm-commits at cs.uiuc.edu>
Sent: Thursday, August 14, 2008 7:54:39 PM
Subject: Re: [llvm-commits] [llvm] r54786 - in /llvm/trunk: lib/Transforms/Scalar/LoopStrengthReduce.cpp test/Transforms/LoopStrengthReduce/2008-08-14-ShadowIV.ll

Yeah, I looked at this for a while, but eventually concluded all the  
cases
where the behavior changes are undefined behavior in the standards.
I might have missed something, and there's an argument for not changing
the behavior anyway.

In your second example, 9907199999999999 is out of range of  
representable
unsigneds, so this patch shouldn't cause a problem.  I think it's "safe"
provided the FP type has enough mantissa bits to represent all possible
values of the int type.  Thus for 32-bit ints I think this is OK for  
double
and long double, but could change the behavior for some cases involving
float overflow.  Maybe put the insufficient-bits case under -ffast-math?

This does come up in SPEC IIRC.

On Aug 14, 2008, at 7:07 PM, Daniel Dunbar wrote:

> I'm seeing a lot of test-suite failures which I isolated to this  
> commit.
> In particular, in SingleSource/UnitTests/Vector, sse.expandfft,  
> see.stepfft,
> sumarray, and sumarray-dbl are failing.
>
>
>
> +      /* If shadow use is a int->float cast then insert a second IV
> +         to elminate this cast.
> +
> +           for (unsigned i = 0; i < n; ++i)
> +             foo((double)i);
> +
> +         is trnasformed into
> +
> +           double d = 0.0;
> +           for (unsigned i = 0; i < n; ++i, ++d)
> +             foo(d);
> +      */
>
> If this is really the transformation how can this be legal?
>  16777216.0f + 1.0f == 16777216.0f
> and
>  9007199999999999.0 + 1.0 == 9007199999999999.0
> on my machine, for example.
>
> - Daniel
>
> ----- Original Message ----
> From: Devang Patel <dpatel at apple.com>
> To: llvm-commits at cs.uiuc.edu
> Sent: Thursday, August 14, 2008 1:58:31 PM
> Subject: [llvm-commits] [llvm] r54786 - in /llvm/trunk: lib/ 
> Transforms/Scalar/LoopStrengthReduce.cpp test/Transforms/ 
> LoopStrengthReduce/2008-08-14-ShadowIV.ll
>
> Author: dpatel
> Date: Thu Aug 14 15:58:31 2008
> New Revision: 54786
>
> URL: http://llvm.org/viewvc/llvm-project?rev=54786&view=rev
> Log:
> If IV is used in a int-to-float cast inside the loop then try to  
> eliminate the cast opeation.
>
> Added:
>    llvm/trunk/test/Transforms/LoopStrengthReduce/2008-08-14- 
> ShadowIV.ll
> Modified:
>    llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
>
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=54786&r1=54785&r2=54786&view=diff
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Thu Aug  
> 14 15:58:31 2008
> @@ -45,6 +45,7 @@
> STATISTIC(NumInserted,    "Number of PHIs inserted");
> STATISTIC(NumVariable,    "Number of PHIs with variable strides");
> STATISTIC(NumEliminated , "Number of strides eliminated");
> +STATISTIC(NumShadow , "Number of Shdow IVs optimized");
>
> namespace {
>
> @@ -177,6 +178,10 @@
>                                   IVStrideUse* &CondUse,
>                                   const SCEVHandle* &CondStride);
>     void OptimizeIndvars(Loop *L);
> +
> +    /// OptimizeShadowIV - If IV is used in a int-to-float cast
> +    /// inside the loop then try to eliminate the cast opeation.
> +    void OptimizeShadowIV(Loop *L);
>     bool FindIVUserForCond(ICmpInst *Cond, IVStrideUse *&CondUse,
>                        const SCEVHandle *&CondStride);
>     bool RequiresTypeConversion(const Type *Ty, const Type *NewTy);
> @@ -1689,12 +1694,108 @@
>   return Cond;
> }
>
> +/// OptimizeShadowIV - If IV is used in a int-to-float cast
> +/// inside the loop then try to eliminate the cast opeation.
> +void LoopStrengthReduce::OptimizeShadowIV(Loop *L) {
> +
> +  for (unsigned Stride = 0, e = StrideOrder.size(); Stride != e;
> +       ++Stride) {
> +    std::map<SCEVHandle, IVUsersOfOneStride>::iterator SI =
> +      IVUsesByStride.find(StrideOrder[Stride]);
> +    assert(SI != IVUsesByStride.end() && "Stride doesn't exist!");
> +
> +    for (std::vector<IVStrideUse>::iterator UI = SI- 
> >second.Users.begin(),
> +           E = SI->second.Users.end(); UI != E; /* empty */) {
> +      std::vector<IVStrideUse>::iterator CandidateUI = UI;
> +      UI++;
> +      Instruction *ShadowUse = CandidateUI->User;
> +      const Type *DestTy = NULL;
> +
> +      /* If shadow use is a int->float cast then insert a second IV
> +         to elminate this cast.
> +
> +           for (unsigned i = 0; i < n; ++i)
> +             foo((double)i);
> +
> +         is trnasformed into
> +
> +           double d = 0.0;
> +           for (unsigned i = 0; i < n; ++i, ++d)
> +             foo(d);
> +      */
> +      UIToFPInst *UCast = dyn_cast<UIToFPInst>(CandidateUI->User);
> +      if (UCast)
> +        DestTy = UCast->getDestTy();
> +      else {
> +        SIToFPInst *SCast = dyn_cast<SIToFPInst>(CandidateUI->User);
> +        if (!SCast) continue;
> +        DestTy = SCast->getDestTy();
> +      }
> +
> +      PHINode *PH = dyn_cast<PHINode>(ShadowUse->getOperand(0));
> +      if (!PH) continue;
> +      if (PH->getNumIncomingValues() != 2) continue;
> +
> +      unsigned Entry, Latch;
> +      if (PH->getIncomingBlock(0) == L->getLoopPreheader()) {
> +        Entry = 0;
> +        Latch = 1;
> +      } else {
> +        Entry = 1;
> +        Latch = 0;
> +      }
> +
> +      ConstantInt *Init = dyn_cast<ConstantInt>(PH- 
> >getIncomingValue(Entry));
> +      if (!Init) continue;
> +      ConstantFP *NewInit = ConstantFP::get(DestTy, Init- 
> >getZExtValue());
> +
> +      BinaryOperator *Incr =
> +        dyn_cast<BinaryOperator>(PH->getIncomingValue(Latch));
> +      if (!Incr) continue;
> +      if (Incr->getOpcode() != Instruction::Add
> +          && Incr->getOpcode() != Instruction::Sub)
> +        continue;
> +
> +      /* Initialize new IV, double d = 0.0 in above example. */
> +      ConstantInt *C = NULL;
> +      if (Incr->getOperand(0) == PH)
> +        C = dyn_cast<ConstantInt>(Incr->getOperand(1));
> +      else if (Incr->getOperand(1) == PH)
> +        C = dyn_cast<ConstantInt>(Incr->getOperand(0));
> +      else
> +        continue;
> +
> +      if (!C) continue;
> +
> +      /* create new icnrement. '++d' in above example. */
> +      ConstantFP *CFP = ConstantFP::get(DestTy, C->getZExtValue());
> +      BinaryOperator *NewIncr =
> +        BinaryOperator::Create(Incr->getOpcode(),
> +                               NewInit, CFP, "IV.S.next.", Incr);
> +
> +      /* Add new PHINode. */
> +      PHINode *NewPH = PHINode::Create(DestTy, "IV.S.", PH);
> +      NewPH->addIncoming(NewInit, PH->getIncomingBlock(Entry));
> +      NewPH->addIncoming(NewIncr, PH->getIncomingBlock(Latch));
> +
> +      /* Remove cast operation */
> +      ShadowUse->replaceAllUsesWith(NewPH);
> +      ShadowUse->eraseFromParent();
> +      SI->second.Users.erase(CandidateUI);
> +      NumShadow++;
> +      break;
> +    }
> +  }
> +}
> +
> // OptimizeIndvars - Now that IVUsesByStride is set up with all of  
> the indvar
> // uses in the loop, look to see if we can eliminate some, in favor  
> of using
> // common indvars for the different uses.
> void LoopStrengthReduce::OptimizeIndvars(Loop *L) {
>   // TODO: implement optzns here.
>
> +  OptimizeShadowIV(L);
> +
>   // Finally, get the terminating condition for the loop if  
> possible.  If we
>   // can, we want to change it to use a post-incremented version of  
> its
>   // induction variable, to allow coalescing the live ranges for the  
> IV into
>
> Added: llvm/trunk/test/Transforms/LoopStrengthReduce/2008-08-14- 
> ShadowIV.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/2008-08-14-ShadowIV.ll?rev=54786&view=auto
>
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> = 
> ======================================================================
> --- llvm/trunk/test/Transforms/LoopStrengthReduce/2008-08-14- 
> ShadowIV.ll (added)
> +++ llvm/trunk/test/Transforms/LoopStrengthReduce/2008-08-14- 
> ShadowIV.ll Thu Aug 14 15:58:31 2008
> @@ -0,0 +1,27 @@
> +; RUN: llvm-as < %s | opt -loop-reduce | llvm-dis | grep "phi double"
> +
> +define void @foobar(i32 %n) nounwind {
> +entry:
> +    icmp eq i32 %n, 0        ; <i1>:0 [#uses=2]
> +    br i1 %0, label %return, label %bb.nph
> +
> +bb.nph:        ; preds = %entry
> +    %umax = select i1 %0, i32 1, i32 %n        ; <i32> [#uses=1]
> +    br label %bb
> +
> +bb:        ; preds = %bb, %bb.nph
> +    %i.03 = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb ]        ;  
> <i32> [#uses=3]
> +    tail call void @bar( i32 %i.03 ) nounwind
> +    uitofp i32 %i.03 to double        ; <double>:1 [#uses=1]
> +    tail call void @foo( double %1 ) nounwind
> +    %indvar.next = add i32 %i.03, 1        ; <i32> [#uses=2]
> +    %exitcond = icmp eq i32 %indvar.next, %umax        ; <i1>  
> [#uses=1]
> +    br i1 %exitcond, label %return, label %bb
> +
> +oreturn:        ; preds = %bb, %entry
> +    ret void
> +}
> +
> +declare void @bar(i32)
> +
> +declare void @foo(double)
>
>
> _______________________________________________
> 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

_______________________________________________
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