+
+ if (Operands.size() != 3)
+ return nullptr;
+
+ if (const ConstantFP *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
+ if (const ConstantFP *Op2 = dyn_cast<ConstantFP>(Operands[1])) {
+ if (const ConstantFP *Op3 = dyn_cast<ConstantFP>(Operands[2])) {
+ switch (IntrinsicID) {
+ default: break;
+ case Intrinsic::fma:
+ case Intrinsic::fmuladd: {
+ APFloat V = Op1->getValueAPF();
+ APFloat::opStatus s = V.fusedMultiplyAdd(Op2->getValueAPF(),
+ Op3->getValueAPF(),
+ APFloat::rmNearestTiesToEven);
+ if (s != APFloat::opInvalidOp)
+ return ConstantFP::get(Ty->getContext(), V);
+
+ return nullptr;
+ }
+ }
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+static Constant *ConstantFoldVectorCall(StringRef Name, unsigned IntrinsicID,
+ VectorType *VTy,
+ ArrayRef<Constant *> Operands,
+ const TargetLibraryInfo *TLI) {
+ SmallVector<Constant *, 4> Result(VTy->getNumElements());
+ SmallVector<Constant *, 4> Lane(Operands.size());
+ Type *Ty = VTy->getElementType();
+
+ for (unsigned I = 0, E = VTy->getNumElements(); I != E; ++I) {
+ // Gather a column of constants.
+ for (unsigned J = 0, JE = Operands.size(); J != JE; ++J) {
+ Constant *Agg = Operands[J]->getAggregateElement(I);
+ if (!Agg)
+ return nullptr;
+
+ Lane[J] = Agg;
+ }
+
+ // Use the regular scalar folding to simplify this column.
+ Constant *Folded = ConstantFoldScalarCall(Name, IntrinsicID, Ty, Lane, TLI);
+ if (!Folded)
+ return nullptr;
+ Result[I] = Folded;
+ }
+
+ return ConstantVector::get(Result);
+}
+
+/// Attempt to constant fold a call to the specified function
+/// with the specified arguments, returning null if unsuccessful.
+Constant *
+llvm::ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands,
+ const TargetLibraryInfo *TLI) {
+ if (!F->hasName())
+ return nullptr;
+ StringRef Name = F->getName();
+
+ Type *Ty = F->getReturnType();
+
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantFoldVectorCall(Name, F->getIntrinsicID(), VTy, Operands, TLI);
+
+ return ConstantFoldScalarCall(Name, F->getIntrinsicID(), Ty, Operands, TLI);