diff options
| author | Cameron McInally <cameron.mcinally@nyu.edu> | 2019-05-05 16:07:09 +0000 | 
|---|---|---|
| committer | Cameron McInally <cameron.mcinally@nyu.edu> | 2019-05-05 16:07:09 +0000 | 
| commit | 1d0c845d9dce577c2ef14cd7d5fcf0b9c17f9ed2 (patch) | |
| tree | bc2a42daa117355c7d3a43a82ce69c34ea357883 /llvm/lib/IR | |
| parent | 70ee2def906e928624f59611c3de732fe121b8a4 (diff) | |
| download | bcm5719-llvm-1d0c845d9dce577c2ef14cd7d5fcf0b9c17f9ed2.tar.gz bcm5719-llvm-1d0c845d9dce577c2ef14cd7d5fcf0b9c17f9ed2.zip  | |
Add FNeg IR constant folding support
llvm-svn: 359982
Diffstat (limited to 'llvm/lib/IR')
| -rw-r--r-- | llvm/lib/IR/ConstantFold.cpp | 46 | ||||
| -rw-r--r-- | llvm/lib/IR/ConstantFold.h | 1 | ||||
| -rw-r--r-- | llvm/lib/IR/Constants.cpp | 10 | 
3 files changed, 53 insertions, 4 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 1dfd5284a97..835fbb3443b 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -918,6 +918,52 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,    return ConstantVector::get(Result);  } +Constant *llvm::ConstantFoldUnaryInstruction(unsigned Opcode, Constant *C) { +  assert(Instruction::isUnaryOp(Opcode) && "Non-unary instruction detected"); + +  // Handle scalar UndefValue. Vectors are always evaluated per element. +  bool HasScalarUndef = !C->getType()->isVectorTy() && isa<UndefValue>(C); + +  if (HasScalarUndef) { +    switch (static_cast<Instruction::UnaryOps>(Opcode)) { +    case Instruction::FNeg: +      return C; // -undef -> undef +    case Instruction::UnaryOpsEnd: +      llvm_unreachable("Invalid UnaryOp"); +    } +  } + +  // Constant should not be UndefValue, unless these are vector constants. +  assert(!HasScalarUndef && "Unexpected UndefValue"); +  // We only have FP UnaryOps right now. +  assert(!isa<ConstantInt>(C) && "Unexpected Integer UnaryOp"); + +  if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) { +    const APFloat &CV = CFP->getValueAPF(); +    switch (Opcode) { +    default: +      break; +    case Instruction::FNeg: +      return ConstantFP::get(C->getContext(), neg(CV)); +    } +  } else if (VectorType *VTy = dyn_cast<VectorType>(C->getType())) { +    // Fold each element and create a vector constant from those constants. +    SmallVector<Constant*, 16> Result; +    Type *Ty = IntegerType::get(VTy->getContext(), 32); +    for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) { +      Constant *ExtractIdx = ConstantInt::get(Ty, i); +      Constant *Elt = ConstantExpr::getExtractElement(C, ExtractIdx); + +      Result.push_back(ConstantExpr::get(Opcode, Elt)); +    } + +    return ConstantVector::get(Result); +  } + +  // We don't know how to fold this. +  return nullptr; +} +  Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,                                                Constant *C2) {    assert(Instruction::isBinaryOp(Opcode) && "Non-binary instruction detected"); diff --git a/llvm/lib/IR/ConstantFold.h b/llvm/lib/IR/ConstantFold.h index b57153bf00b..9ad6e14e9e4 100644 --- a/llvm/lib/IR/ConstantFold.h +++ b/llvm/lib/IR/ConstantFold.h @@ -43,6 +43,7 @@ template <typename T> class ArrayRef;                                                  ArrayRef<unsigned> Idxs);    Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,                                                 ArrayRef<unsigned> Idxs); +  Constant *ConstantFoldUnaryInstruction(unsigned Opcode, Constant *V);    Constant *ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1,                                            Constant *V2);    Constant *ConstantFoldCompareInstruction(unsigned short predicate, diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 00c722651ed..5545eb46686 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -1830,7 +1830,8 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C, unsigned Flags,    }  #endif -  // TODO: Try to constant fold operation. +  if (Constant *FC = ConstantFoldUnaryInstruction(Opcode, C)) +    return FC;    if (OnlyIfReducedTy == C->getType())      return nullptr; @@ -1909,7 +1910,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,  #endif    if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2)) -    return FC;          // Fold a few common cases. +    return FC;    if (OnlyIfReducedTy == C1->getType())      return nullptr; @@ -2235,7 +2236,7 @@ Constant *ConstantExpr::getNeg(Constant *C, bool HasNUW, bool HasNSW) {  Constant *ConstantExpr::getFNeg(Constant *C) {    assert(C->getType()->isFPOrFPVectorTy() &&           "Cannot FNEG a non-floating-point value!"); -  return getFSub(ConstantFP::getZeroValueForNegation(C->getType()), C); +  return get(Instruction::FNeg, C);  }  Constant *ConstantExpr::getNot(Constant *C) { @@ -3024,7 +3025,8 @@ Instruction *ConstantExpr::getAsInstruction() {    case Instruction::FCmp:      return CmpInst::Create((Instruction::OtherOps)getOpcode(),                             (CmpInst::Predicate)getPredicate(), Ops[0], Ops[1]); - +  case Instruction::FNeg: +    return UnaryOperator::Create((Instruction::UnaryOps)getOpcode(), Ops[0]);    default:      assert(getNumOperands() == 2 && "Must be binary operator?");      BinaryOperator *BO =  | 

