diff options
| author | Michael Ilseman <milseman@apple.com> | 2012-12-12 00:27:46 +0000 | 
|---|---|---|
| committer | Michael Ilseman <milseman@apple.com> | 2012-12-12 00:27:46 +0000 | 
| commit | bb6f691b01310ee83ea985e5116ec0923d5cc42d (patch) | |
| tree | e699c49725c216b59cf3e1665c0ed57fddd6d6e9 /llvm/lib/Analysis | |
| parent | 5cd69b4ce3b752c01e6111c21ad7251669552494 (diff) | |
| download | bcm5719-llvm-bb6f691b01310ee83ea985e5116ec0923d5cc42d.tar.gz bcm5719-llvm-bb6f691b01310ee83ea985e5116ec0923d5cc42d.zip  | |
Added a slew of SimplifyInstruction floating-point optimizations, many of which take advantage of fast-math flags. Test cases included.
  fsub X, +0 ==> X
  fsub X, -0 ==> X, when we know X is not -0
  fsub +/-0.0, (fsub -0.0, X) ==> X
  fsub nsz +/-0.0, (fsub +/-0.0, X) ==> X
  fsub nnan ninf X, X ==> 0.0
  fadd nsz X, 0 ==> X
  fadd [nnan ninf] X, (fsub [nnan ninf] 0, X) ==> 0
    where nnan and ninf have to occur at least once somewhere in this expression
  fmul X, 1.0 ==> X
llvm-svn: 169940
Diffstat (limited to 'llvm/lib/Analysis')
| -rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 119 | 
1 files changed, 109 insertions, 10 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index dd109bde3ac..42e506bbb0c 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -853,6 +853,85 @@ Value *llvm::SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,                             RecursionLimit);  } +/// Given operands for an FAdd, see if we can fold the result.  If not, this +/// returns null. +static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, +                              const Query &Q, unsigned MaxRecurse) { +  if (Constant *CLHS = dyn_cast<Constant>(Op0)) { +    if (Constant *CRHS = dyn_cast<Constant>(Op1)) { +      Constant *Ops[] = { CLHS, CRHS }; +      return ConstantFoldInstOperands(Instruction::FAdd, CLHS->getType(), +                                      Ops, Q.TD, Q.TLI); +    } + +    // Canonicalize the constant to the RHS. +    std::swap(Op0, Op1); +  } + +  // fadd X, -0 ==> X +  if (match(Op1, m_NegZero())) +    return Op0; + +  // fadd X, 0 ==> X, when we know X is not -0 +  if (match(Op1, m_Zero()) && +      (FMF.noSignedZeros() || CannotBeNegativeZero(Op0))) +    return Op0; + +  // fadd [nnan ninf] X, (fsub [nnan ninf] 0, X) ==> 0 +  //   where nnan and ninf have to occur at least once somewhere in this +  //   expression +  Value *SubOp = 0; +  if (match(Op1, m_FSub(m_AnyZero(), m_Specific(Op0)))) +    SubOp = Op1; +  else if (match(Op0, m_FSub(m_AnyZero(), m_Specific(Op1)))) +    SubOp = Op0; +  if (SubOp) { +    Instruction *FSub = cast<Instruction>(SubOp); +    if ((FMF.noNaNs() || FSub->hasNoNaNs()) && +        (FMF.noInfs() || FSub->hasNoInfs())) +      return Constant::getNullValue(Op0->getType()); +  } + +  return 0; +} + +/// Given operands for an FSub, see if we can fold the result.  If not, this +/// returns null. +static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, +                              const Query &Q, unsigned MaxRecurse) { +  if (Constant *CLHS = dyn_cast<Constant>(Op0)) { +    if (Constant *CRHS = dyn_cast<Constant>(Op1)) { +      Constant *Ops[] = { CLHS, CRHS }; +      return ConstantFoldInstOperands(Instruction::FSub, CLHS->getType(), +                                      Ops, Q.TD, Q.TLI); +    } +  } + +  // fsub X, 0 ==> X +  if (match(Op1, m_Zero())) +    return Op0; + +  // fsub X, -0 ==> X, when we know X is not -0 +  if (match(Op1, m_NegZero()) && +      (FMF.noSignedZeros() || CannotBeNegativeZero(Op0))) +    return Op0; + +  // fsub 0, (fsub -0.0, X) ==> X +  Value *X; +  if (match(Op0, m_AnyZero())) { +    if (match(Op1, m_FSub(m_NegZero(), m_Value(X)))) +      return X; +    if (FMF.noSignedZeros() && match(Op1, m_FSub(m_AnyZero(), m_Value(X)))) +      return X; +  } + +  // fsub nnan ninf x, x ==> 0.0 +  if (FMF.noNaNs() && FMF.noInfs() && Op0 == Op1) +    return Constant::getNullValue(Op0->getType()); + +  return 0; +} +  /// Given the operands for an FMul, see if we can fold the result  static Value *SimplifyFMulInst(Value *Op0, Value *Op1,                                 FastMathFlags FMF, @@ -864,19 +943,19 @@ static Value *SimplifyFMulInst(Value *Op0, Value *Op1,        return ConstantFoldInstOperands(Instruction::FMul, CLHS->getType(),                                        Ops, Q.TD, Q.TLI);      } - } - // Check for some fast-math optimizations - if (FMF.noNaNs()) { -   if (FMF.noSignedZeros()) { -     // fmul N S 0, x ==> 0 -     if (match(Op0, m_Zero())) -       return Op0; -     if (match(Op1, m_Zero())) -       return Op1; -   } +    // Canonicalize the constant to the RHS. +    std::swap(Op0, Op1);   } + // fmul X, 1.0 ==> X + if (match(Op1, m_FPOne())) +   return Op0; + + // fmul nnan nsz X, 0 ==> 0 + if (FMF.noNaNs() && FMF.noSignedZeros() && match(Op1, m_AnyZero())) +   return Op1; +   return 0;  } @@ -945,6 +1024,18 @@ static Value *SimplifyMulInst(Value *Op0, Value *Op1, const Query &Q,    return 0;  } +Value *llvm::SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF, +                             const DataLayout *TD, const TargetLibraryInfo *TLI, +                             const DominatorTree *DT) { +  return ::SimplifyFAddInst(Op0, Op1, FMF, Query (TD, TLI, DT), RecursionLimit); +} + +Value *llvm::SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF, +                             const DataLayout *TD, const TargetLibraryInfo *TLI, +                             const DominatorTree *DT) { +  return ::SimplifyFSubInst(Op0, Op1, FMF, Query (TD, TLI, DT), RecursionLimit); +} +  Value *llvm::SimplifyFMulInst(Value *Op0, Value *Op1,                                FastMathFlags FMF,                                const DataLayout *TD, @@ -2789,12 +2880,20 @@ Value *llvm::SimplifyInstruction(Instruction *I, const DataLayout *TD,    default:      Result = ConstantFoldInstruction(I, TD, TLI);      break; +  case Instruction::FAdd: +    Result = SimplifyFAddInst(I->getOperand(0), I->getOperand(1), +                              I->getFastMathFlags(), TD, TLI, DT); +    break;    case Instruction::Add:      Result = SimplifyAddInst(I->getOperand(0), I->getOperand(1),                               cast<BinaryOperator>(I)->hasNoSignedWrap(),                               cast<BinaryOperator>(I)->hasNoUnsignedWrap(),                               TD, TLI, DT);      break; +  case Instruction::FSub: +    Result = SimplifyFSubInst(I->getOperand(0), I->getOperand(1), +                              I->getFastMathFlags(), TD, TLI, DT); +    break;    case Instruction::Sub:      Result = SimplifySubInst(I->getOperand(0), I->getOperand(1),                               cast<BinaryOperator>(I)->hasNoSignedWrap(),  | 

