[llvm-commits] [llvm] r169025 - /llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Michael Ilseman milseman at apple.com
Fri Nov 30 14:03:02 PST 2012


Pedro, you can take a look at PatternMatch.h to see many pattern matching utilities that can make some of these checks easier. Must of the other code in InstCombine takes advantage of them.

For example, InstCombineMulDivRem.cpp:37 is able to match many levels deep in one expression.

On Nov 30, 2012, at 11:43 AM, Matt Beaumont-Gay <matthewbg at google.com> wrote:

> On Fri, Nov 30, 2012 at 11:09 AM, Pedro Artigas <partigas at apple.com> wrote:
>> Author: partigas
>> Date: Fri Nov 30 13:09:41 2012
>> New Revision: 169025
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=169025&view=rev
>> Log:
>> Add fast math inst combine X*log2(Y*0.5)-->X*log2(Y)-X
>> 
>> reviewed by Michael Ilseman <milseman at apple.com>
>> 
>> 
>> Modified:
>>    llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
>> 
>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp?rev=169025&r1=169024&r2=169025&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (original)
>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp Fri Nov 30 13:09:41 2012
>> @@ -284,6 +284,83 @@
>>     if (Value *Op1v = dyn_castFNegVal(Op1))
>>       return BinaryOperator::CreateFMul(Op0v, Op1v);
>> 
>> +  // Under unsafe algebra do:
>> +  // X * log2(0.5*Y) = X*log2(Y) - X
>> +  if (I.hasUnsafeAlgebra()) {
>> +    Value *OpX = NULL;
>> +    Value *OpY = NULL;
>> +    IntrinsicInst *Log2;
>> +    if (Op0->hasOneUse()) {
>> +      if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op0)) {
>> +        if (II->getIntrinsicID() == Intrinsic::log2 &&
>> +            II->hasUnsafeAlgebra())
>> +        {
>> +          Log2 = II;
>> +          Value *OpLog2Of = II->getArgOperand(0);
>> +          if (OpLog2Of->hasOneUse()) {
>> +            if (Instruction *I = dyn_cast<Instruction>(OpLog2Of)) {
>> +              if (I->getOpcode() == Instruction::FMul &&
>> +                  I->hasUnsafeAlgebra())
>> +              {
>> +                ConstantFP *CFP = dyn_cast<ConstantFP>(I->getOperand(0));
>> +                if (CFP && CFP->isExactlyValue(0.5)) {
> 
> This is, if I count correctly, eight levels of nested 'if'. Can some
> of these conditions be inverted to simplify things?
> http://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code
> 
>> +                  OpY = I->getOperand(1);
>> +                  OpX = Op1;
>> +                } else {
>> +                  CFP = dyn_cast<ConstantFP>(I->getOperand(1));
>> +                  if (CFP && CFP->isExactlyValue(0.5)) {
>> +                    OpY = I->getOperand(0);
>> +                    OpX = Op1;
>> +                  }
>> +                }
>> +              }
>> +            }
>> +          }
>> +        }
>> +      }
>> +    }
>> +    if (Op1->hasOneUse()) {
>> +      if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Op1)) {
>> +        if (II->getIntrinsicID() == Intrinsic::log2 &&
>> +            II->hasUnsafeAlgebra())
>> +        {
>> +          Log2 = II;
>> +          Value *OpLog2Of = II->getArgOperand(0);
>> +          if (OpLog2Of->hasOneUse()) {
>> +            if (Instruction *I = dyn_cast<Instruction>(OpLog2Of)) {
>> +              if (I->getOpcode() == Instruction::FMul &&
>> +                  I->hasUnsafeAlgebra())
>> +              {
>> +                ConstantFP *CFP = dyn_cast<ConstantFP>(I->getOperand(0));
>> +                if (CFP && CFP->isExactlyValue(0.5)) {
>> +                  OpY = I->getOperand(1);
>> +                  OpX = Op0;
>> +                } else {
>> +                  CFP = dyn_cast<ConstantFP>(I->getOperand(1));
>> +                  if (CFP && CFP->isExactlyValue(0.5)) {
>> +                    OpY = I->getOperand(0);
>> +                    OpX = Op0;
>> +                  }
>> +                }
>> +              }
>> +            }
>> +          }
>> +        }
>> +      }
>> +    }
>> +    // if pattern detected emit alternate sequence
>> +    if (OpX && OpY) {
>> +      Log2->setArgOperand(0, OpY);
>> +      Value *FMulVal = Builder->CreateFMul(OpX, Log2);
>> +      Instruction *FMul = dyn_cast<Instruction>(FMulVal);
>> +      assert(FMul && "Must be instruction as Log2 is instruction");
>> +      FMul->copyFastMathFlags(Log2);
>> +      Instruction *FSub = BinaryOperator::CreateFSub(FMulVal, OpX);
>> +      FSub->copyFastMathFlags(Log2);
>> +      return FSub;
>> +    }
>> +  }
>> +
>>   return Changed ? &I : 0;
>> }
>> 
>> 
>> 
>> _______________________________________________
>> 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