diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -1624,6 +1624,43 @@ Value *CreateNAryOp(unsigned Opc, ArrayRef Ops, const Twine &Name = "", MDNode *FPMathTag = nullptr); + /// Construct a complex value out of a pair of real and imaginary values. + /// The resulting value will be a vector, with lane 0 being the real value and + /// lane 1 being the complex value. + /// Either the \p Real or \p Imag parameter may be null, if the input is a + /// pure real or pure imaginary number. + Value *CreateComplexValue(Value *Real, Value *Imag, const Twine &Name = "") { + Type *ScalarTy = (Real ? Real : Imag)->getType(); + assert(ScalarTy->isFloatingPointTy() && + "Only floating-point types may be complex values."); + Type *ComplexTy = FixedVectorType::get(ScalarTy, 2); + Value *Base = PoisonValue::get(ComplexTy); + if (Real) + Base = CreateInsertElement(Base, Real, uint64_t(0), Name); + if (Imag) + Base = CreateInsertElement(Base, Imag, uint64_t(1), Name); + return Base; + } + + /// Construct a complex multiply operation, setting fast-math flags and the + /// complex-range attribute as appropriate. + Value *CreateComplexMul(Value *L, Value *R, bool CxLimitedRange, + const Twine &Name = ""); + + /// Construct a complex divide operation, setting fast-math flags and the + /// complex-range attribute as appropriate. + /// The complex-range attribute is set from the \p IgnoreNaNs and + /// \p DisableScaling as follows: + /// + /// \p IgnoreNans | \p DisableScaling | complex-range value + /// ------------- | ----------------- | ------------------- + /// false | false | full + /// false | true | (illegal combination) + /// true | false | no-nan + /// true | true | limited + Value *CreateComplexDiv(Value *L, Value *R, bool IgnoreNaNs, + bool DisableScaling = false, const Twine &Name = ""); + //===--------------------------------------------------------------------===// // Instruction creation methods: Memory Instructions //===--------------------------------------------------------------------===// diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -988,6 +988,38 @@ return C; } +Value *IRBuilderBase::CreateComplexMul(Value *L, Value *R, bool CxLimitedRange, + const Twine &Name) { + CallInst *Result = CreateBinaryIntrinsic(Intrinsic::experimental_complex_fmul, + L, R, nullptr, Name); + Result->setFastMathFlags(FMF); + AttributeList Attrs = Result->getAttributes(); + StringRef Range = + (CxLimitedRange || FMF.noNaNs() || FMF.noInfs()) ? "limited" : "full"; + Attrs = Attrs.addFnAttribute(getContext(), "complex-range", Range); + Result->setAttributes(Attrs); + return Result; +} + +Value *IRBuilderBase::CreateComplexDiv(Value *L, Value *R, bool IgnoreNaNs, + bool DisableScaling, const Twine &Name) { + CallInst *Result = CreateBinaryIntrinsic(Intrinsic::experimental_complex_fdiv, + L, R, nullptr, Name); + Result->setFastMathFlags(FMF); + AttributeList Attrs = Result->getAttributes(); + StringRef Range = "full"; + if (DisableScaling) { + assert(IgnoreNaNs && + "complex division DisableScaling should imply IgnoreNaNs"); + Range = "limited"; + } else if (IgnoreNaNs || FMF.noNaNs() || FMF.noInfs()) { + Range = "no-nan"; + } + Attrs = Attrs.addFnAttribute(getContext(), "complex-range", Range); + Result->setAttributes(Attrs); + return Result; +} + Value *IRBuilderBase::CreateSelect(Value *C, Value *True, Value *False, const Twine &Name, Instruction *MDFrom) { if (auto *V = Folder.FoldSelect(C, True, False))