mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 11:02:04 +08:00
[flang] Add -fcomplex-arithmetic= option and select complex division algorithm (#146641)
This patch adds an option to select the method for computing complex number division. It uses `LoweringOptions` to determine whether to lower complex division to a runtime function call or to MLIR's `complex.div`, and `CodeGenOptions` to select the computation algorithm for `complex.div`. The available option values and their corresponding algorithms are as follows: - `full`: Lower to a runtime function call. (Default behavior) - `improved`: Lower to `complex.div` and expand to Smith's algorithm. - `basic`: Lower to `complex.div` and expand to the algebraic algorithm. See also the discussion in the following discourse post: https://discourse.llvm.org/t/optimization-of-complex-number-division/83468 --------- Co-authored-by: Tarun Prabhu <tarunprabhu@gmail.com>
This commit is contained in:
committed by
GitHub
parent
bccd34f323
commit
c9900015a9
@@ -283,6 +283,12 @@ StringRef parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
|
||||
StringRef parseMRecipOption(clang::DiagnosticsEngine &Diags,
|
||||
const llvm::opt::ArgList &Args);
|
||||
|
||||
// Convert ComplexRangeKind to a string that can be passed as a frontend option.
|
||||
std::string complexRangeKindToStr(LangOptions::ComplexRangeKind Range);
|
||||
|
||||
// Render a frontend option corresponding to ComplexRangeKind.
|
||||
std::string renderComplexRangeOption(LangOptions::ComplexRangeKind Range);
|
||||
|
||||
} // end namespace tools
|
||||
} // end namespace driver
|
||||
} // end namespace clang
|
||||
|
||||
@@ -1023,12 +1023,13 @@ defm offload_uniform_block : BoolFOption<"offload-uniform-block",
|
||||
BothFlags<[], [ClangOption], " that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)">>;
|
||||
|
||||
def fcomplex_arithmetic_EQ : Joined<["-"], "fcomplex-arithmetic=">, Group<f_Group>,
|
||||
Visibility<[ClangOption, CC1Option]>,
|
||||
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
|
||||
Values<"full,improved,promoted,basic">, NormalizedValuesScope<"LangOptions">,
|
||||
NormalizedValues<["CX_Full", "CX_Improved", "CX_Promoted", "CX_Basic"]>;
|
||||
NormalizedValues<["CX_Full", "CX_Improved", "CX_Promoted", "CX_Basic"]>,
|
||||
HelpText<"Controls the calculation methods of complex number multiplication and division.">;
|
||||
|
||||
def complex_range_EQ : Joined<["-"], "complex-range=">, Group<f_Group>,
|
||||
Visibility<[CC1Option]>,
|
||||
Visibility<[CC1Option, FC1Option]>,
|
||||
Values<"full,improved,promoted,basic">, NormalizedValuesScope<"LangOptions">,
|
||||
NormalizedValues<["CX_Full", "CX_Improved", "CX_Promoted", "CX_Basic"]>,
|
||||
MarshallingInfoEnum<LangOpts<"ComplexRange">, "CX_Full">;
|
||||
|
||||
@@ -2750,29 +2750,10 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
|
||||
}
|
||||
}
|
||||
|
||||
static std::string ComplexRangeKindToStr(LangOptions::ComplexRangeKind Range) {
|
||||
switch (Range) {
|
||||
case LangOptions::ComplexRangeKind::CX_Full:
|
||||
return "full";
|
||||
break;
|
||||
case LangOptions::ComplexRangeKind::CX_Basic:
|
||||
return "basic";
|
||||
break;
|
||||
case LangOptions::ComplexRangeKind::CX_Improved:
|
||||
return "improved";
|
||||
break;
|
||||
case LangOptions::ComplexRangeKind::CX_Promoted:
|
||||
return "promoted";
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static std::string ComplexArithmeticStr(LangOptions::ComplexRangeKind Range) {
|
||||
return (Range == LangOptions::ComplexRangeKind::CX_None)
|
||||
? ""
|
||||
: "-fcomplex-arithmetic=" + ComplexRangeKindToStr(Range);
|
||||
: "-fcomplex-arithmetic=" + complexRangeKindToStr(Range);
|
||||
}
|
||||
|
||||
static void EmitComplexRangeDiag(const Driver &D, std::string str1,
|
||||
@@ -2782,14 +2763,6 @@ static void EmitComplexRangeDiag(const Driver &D, std::string str1,
|
||||
}
|
||||
}
|
||||
|
||||
static std::string
|
||||
RenderComplexRangeOption(LangOptions::ComplexRangeKind Range) {
|
||||
std::string ComplexRangeStr = ComplexRangeKindToStr(Range);
|
||||
if (!ComplexRangeStr.empty())
|
||||
return "-complex-range=" + ComplexRangeStr;
|
||||
return ComplexRangeStr;
|
||||
}
|
||||
|
||||
static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
|
||||
bool OFastEnabled, const ArgList &Args,
|
||||
ArgStringList &CmdArgs,
|
||||
@@ -2922,7 +2895,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
|
||||
case options::OPT_fcx_limited_range:
|
||||
if (GccRangeComplexOption.empty()) {
|
||||
if (Range != LangOptions::ComplexRangeKind::CX_Basic)
|
||||
EmitComplexRangeDiag(D, RenderComplexRangeOption(Range),
|
||||
EmitComplexRangeDiag(D, renderComplexRangeOption(Range),
|
||||
"-fcx-limited-range");
|
||||
} else {
|
||||
if (GccRangeComplexOption != "-fno-cx-limited-range")
|
||||
@@ -2934,7 +2907,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
|
||||
break;
|
||||
case options::OPT_fno_cx_limited_range:
|
||||
if (GccRangeComplexOption.empty()) {
|
||||
EmitComplexRangeDiag(D, RenderComplexRangeOption(Range),
|
||||
EmitComplexRangeDiag(D, renderComplexRangeOption(Range),
|
||||
"-fno-cx-limited-range");
|
||||
} else {
|
||||
if (GccRangeComplexOption != "-fcx-limited-range" &&
|
||||
@@ -2948,7 +2921,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
|
||||
break;
|
||||
case options::OPT_fcx_fortran_rules:
|
||||
if (GccRangeComplexOption.empty())
|
||||
EmitComplexRangeDiag(D, RenderComplexRangeOption(Range),
|
||||
EmitComplexRangeDiag(D, renderComplexRangeOption(Range),
|
||||
"-fcx-fortran-rules");
|
||||
else
|
||||
EmitComplexRangeDiag(D, GccRangeComplexOption, "-fcx-fortran-rules");
|
||||
@@ -2958,7 +2931,7 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
|
||||
break;
|
||||
case options::OPT_fno_cx_fortran_rules:
|
||||
if (GccRangeComplexOption.empty()) {
|
||||
EmitComplexRangeDiag(D, RenderComplexRangeOption(Range),
|
||||
EmitComplexRangeDiag(D, renderComplexRangeOption(Range),
|
||||
"-fno-cx-fortran-rules");
|
||||
} else {
|
||||
if (GccRangeComplexOption != "-fno-cx-limited-range")
|
||||
@@ -3426,12 +3399,12 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
|
||||
CmdArgs.push_back("-fno-strict-float-cast-overflow");
|
||||
|
||||
if (Range != LangOptions::ComplexRangeKind::CX_None)
|
||||
ComplexRangeStr = RenderComplexRangeOption(Range);
|
||||
ComplexRangeStr = renderComplexRangeOption(Range);
|
||||
if (!ComplexRangeStr.empty()) {
|
||||
CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr));
|
||||
if (Args.hasArg(options::OPT_fcomplex_arithmetic_EQ))
|
||||
CmdArgs.push_back(Args.MakeArgString("-fcomplex-arithmetic=" +
|
||||
ComplexRangeKindToStr(Range)));
|
||||
complexRangeKindToStr(Range)));
|
||||
}
|
||||
if (Args.hasArg(options::OPT_fcx_limited_range))
|
||||
CmdArgs.push_back("-fcx-limited-range");
|
||||
|
||||
@@ -3420,3 +3420,30 @@ StringRef tools::parseMRecipOption(clang::DiagnosticsEngine &Diags,
|
||||
|
||||
return Out;
|
||||
}
|
||||
|
||||
std::string tools::complexRangeKindToStr(LangOptions::ComplexRangeKind Range) {
|
||||
switch (Range) {
|
||||
case LangOptions::ComplexRangeKind::CX_Full:
|
||||
return "full";
|
||||
break;
|
||||
case LangOptions::ComplexRangeKind::CX_Basic:
|
||||
return "basic";
|
||||
break;
|
||||
case LangOptions::ComplexRangeKind::CX_Improved:
|
||||
return "improved";
|
||||
break;
|
||||
case LangOptions::ComplexRangeKind::CX_Promoted:
|
||||
return "promoted";
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
tools::renderComplexRangeOption(LangOptionsBase::ComplexRangeKind Range) {
|
||||
std::string ComplexRangeStr = complexRangeKindToStr(Range);
|
||||
if (!ComplexRangeStr.empty())
|
||||
return "-complex-range=" + ComplexRangeStr;
|
||||
return ComplexRangeStr;
|
||||
}
|
||||
|
||||
@@ -612,6 +612,8 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
|
||||
bool AssociativeMath = false;
|
||||
bool ReciprocalMath = false;
|
||||
|
||||
LangOptions::ComplexRangeKind Range = LangOptions::ComplexRangeKind::CX_None;
|
||||
|
||||
if (const Arg *A = Args.getLastArg(options::OPT_ffp_contract)) {
|
||||
const StringRef Val = A->getValue();
|
||||
if (Val == "fast" || Val == "off") {
|
||||
@@ -636,6 +638,20 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
|
||||
default:
|
||||
continue;
|
||||
|
||||
case options::OPT_fcomplex_arithmetic_EQ: {
|
||||
StringRef Val = A->getValue();
|
||||
if (Val == "full")
|
||||
Range = LangOptions::ComplexRangeKind::CX_Full;
|
||||
else if (Val == "improved")
|
||||
Range = LangOptions::ComplexRangeKind::CX_Improved;
|
||||
else if (Val == "basic")
|
||||
Range = LangOptions::ComplexRangeKind::CX_Basic;
|
||||
else {
|
||||
D.Diag(diag::err_drv_unsupported_option_argument)
|
||||
<< A->getSpelling() << Val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case options::OPT_fhonor_infinities:
|
||||
HonorINFs = true;
|
||||
break;
|
||||
@@ -706,6 +722,13 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
|
||||
if (!Recip.empty())
|
||||
CmdArgs.push_back(Args.MakeArgString("-mrecip=" + Recip));
|
||||
|
||||
if (Range != LangOptions::ComplexRangeKind::CX_None) {
|
||||
std::string ComplexRangeStr = renderComplexRangeOption(Range);
|
||||
CmdArgs.push_back(Args.MakeArgString(ComplexRangeStr));
|
||||
CmdArgs.push_back(Args.MakeArgString("-fcomplex-arithmetic=" +
|
||||
complexRangeKindToStr(Range)));
|
||||
}
|
||||
|
||||
if (!HonorINFs && !HonorNaNs && AssociativeMath && ReciprocalMath &&
|
||||
ApproxFunc && !SignedZeros &&
|
||||
(FPContract == "fast" || FPContract.empty())) {
|
||||
|
||||
@@ -74,4 +74,26 @@ The ComplexToStandard dialect does still call into libm for some floating
|
||||
point math operations, however these don't have the same ABI issues as the
|
||||
complex libm functions.
|
||||
|
||||
The flang driver option `-fcomplex-arithmetic=` allows you to select whether
|
||||
complex number division is lowered to function calls or to the `complex.div`
|
||||
operation in the MLIR complex dialect. To avoid the ABI issues mentioned above,
|
||||
the choice of function calls or the `complex.div` operation is made during the
|
||||
lowering phase. The behavior of this option is as follows:
|
||||
|
||||
- `basic`: Lowers to `complex.div` and is converted to algebraic formulas. No
|
||||
special handling to avoid overflow. NaN and infinite values are not handled.
|
||||
- `improved`: Lowers to `complex.div` and is converted to Smith's algorithm. See
|
||||
SMITH, R. L. Algorithm 116: Complex division. Commun. ACM 5, 8 (1962). This
|
||||
value offers improved handling for overflow in intermediate calculations, but
|
||||
overflow may occur. NaN and infinite values are handled.
|
||||
- `full`: Lowers to a call to runtime library functions. Overflow and non-finite
|
||||
values are handled by the library implementation. This is the default value.
|
||||
|
||||
While [the same option in clang][2] allows specifying `promoted`, this is not
|
||||
implemented in Flang. Also, in the case of `improved`, clang does not handle NaN
|
||||
and infinite values, but Flang does. These behavioral differences arise because
|
||||
the transformation of complex division calculations depends on the implementation
|
||||
of ComplexToStandard, which may change in the future.
|
||||
|
||||
[1]: https://discourse.llvm.org/t/rfc-change-lowering-of-fortran-math-intrinsics/63971
|
||||
[2]: https://clang.llvm.org/docs/UsersManual.html#cmdoption-fcomplex-arithmetic
|
||||
|
||||
@@ -52,6 +52,7 @@ ENUM_CODEGENOPT(RelocationModel, llvm::Reloc::Model, 3, llvm::Reloc::PIC_) ///<
|
||||
ENUM_CODEGENOPT(DebugInfo, llvm::codegenoptions::DebugInfoKind, 4, llvm::codegenoptions::NoDebugInfo) ///< Level of debug info to generate
|
||||
ENUM_CODEGENOPT(VecLib, llvm::driver::VectorLibrary, 4, llvm::driver::VectorLibrary::NoLibrary) ///< Vector functions library to use
|
||||
ENUM_CODEGENOPT(FramePointer, llvm::FramePointerKind, 2, llvm::FramePointerKind::None) ///< Enable the usage of frame pointers
|
||||
ENUM_CODEGENOPT(ComplexRange, ComplexRangeKind, 3, ComplexRangeKind::CX_Full) ///< Method for calculating complex number division
|
||||
|
||||
ENUM_CODEGENOPT(DoConcurrentMapping, DoConcurrentMappingKind, 2, DoConcurrentMappingKind::DCMK_None) ///< Map `do concurrent` to OpenMP
|
||||
|
||||
|
||||
@@ -192,6 +192,31 @@ public:
|
||||
return getProfileUse() == llvm::driver::ProfileCSIRInstr;
|
||||
}
|
||||
|
||||
/// Controls the various implementations for complex division.
|
||||
enum ComplexRangeKind {
|
||||
/// Implementation of complex division using a call to runtime library
|
||||
/// functions. Overflow and non-finite values are handled by the library
|
||||
/// implementation. This is the default value.
|
||||
CX_Full,
|
||||
|
||||
/// Implementation of complex division offering an improved handling
|
||||
/// for overflow in intermediate calculations. Overflow and non-finite
|
||||
/// values are handled by MLIR's implementation of "complex.div", but this
|
||||
/// may change in the future.
|
||||
CX_Improved,
|
||||
|
||||
/// Implementation of complex division using algebraic formulas at source
|
||||
/// precision. No special handling to avoid overflow. NaN and infinite
|
||||
/// values are not handled.
|
||||
CX_Basic,
|
||||
|
||||
/// No range rule is enabled.
|
||||
CX_None
|
||||
|
||||
/// TODO: Implemention of other values as needed. In Clang, "CX_Promoted"
|
||||
/// is implemented. (See clang/Basic/LangOptions.h)
|
||||
};
|
||||
|
||||
// Define accessors/mutators for code generation options of enumeration type.
|
||||
#define CODEGENOPT(Name, Bits, Default)
|
||||
#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \
|
||||
|
||||
@@ -70,5 +70,9 @@ ENUM_LOWERINGOPT(CUDARuntimeCheck, unsigned, 1, 0)
|
||||
/// derived types defined in other compilation units.
|
||||
ENUM_LOWERINGOPT(SkipExternalRttiDefinition, unsigned, 1, 0)
|
||||
|
||||
/// If true, convert complex number division to runtime on the frontend.
|
||||
/// If false, lower to the complex dialect of MLIR.
|
||||
/// On by default.
|
||||
ENUM_LOWERINGOPT(ComplexDivisionToRuntime, unsigned, 1, 1)
|
||||
#undef LOWERINGOPT
|
||||
#undef ENUM_LOWERINGOPT
|
||||
|
||||
@@ -609,6 +609,17 @@ public:
|
||||
return integerOverflowFlags;
|
||||
}
|
||||
|
||||
/// Set ComplexDivisionToRuntimeFlag value. If set to true, complex number
|
||||
/// division is lowered to a runtime function by this builder.
|
||||
void setComplexDivisionToRuntimeFlag(bool flag) {
|
||||
complexDivisionToRuntimeFlag = flag;
|
||||
}
|
||||
|
||||
/// Get current ComplexDivisionToRuntimeFlag value.
|
||||
bool getComplexDivisionToRuntimeFlag() const {
|
||||
return complexDivisionToRuntimeFlag;
|
||||
}
|
||||
|
||||
/// Dump the current function. (debug)
|
||||
LLVM_DUMP_METHOD void dumpFunc();
|
||||
|
||||
@@ -673,6 +684,10 @@ private:
|
||||
/// mlir::arith::IntegerOverflowFlagsAttr.
|
||||
mlir::arith::IntegerOverflowFlags integerOverflowFlags{};
|
||||
|
||||
/// Flag to control whether complex number division is lowered to a runtime
|
||||
/// function or to the MLIR complex dialect.
|
||||
bool complexDivisionToRuntimeFlag = true;
|
||||
|
||||
/// fir::GlobalOp and func::FuncOp symbol table to speed-up
|
||||
/// lookups.
|
||||
mlir::SymbolTable *symbolTable = nullptr;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef FORTRAN_OPTIMIZER_CODEGEN_CODEGEN_H
|
||||
#define FORTRAN_OPTIMIZER_CODEGEN_CODEGEN_H
|
||||
|
||||
#include "flang/Frontend/CodeGenOptions.h"
|
||||
#include "mlir/IR/BuiltinOps.h"
|
||||
#include "mlir/Pass/Pass.h"
|
||||
#include "mlir/Pass/PassRegistry.h"
|
||||
@@ -58,6 +59,11 @@ struct FIRToLLVMPassOptions {
|
||||
// the name of the global variable corresponding to a derived
|
||||
// type's descriptor.
|
||||
bool typeDescriptorsRenamedForAssembly = false;
|
||||
|
||||
// Specify the calculation method for complex number division used by the
|
||||
// Conversion pass of the MLIR complex dialect.
|
||||
Fortran::frontend::CodeGenOptions::ComplexRangeKind ComplexRange =
|
||||
Fortran::frontend::CodeGenOptions::ComplexRangeKind::CX_Full;
|
||||
};
|
||||
|
||||
/// Convert FIR to the LLVM IR dialect with default options.
|
||||
|
||||
@@ -140,6 +140,9 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
|
||||
std::string InstrumentFunctionExit =
|
||||
""; ///< Name of the instrument-function that is called on each
|
||||
///< function-exit
|
||||
Fortran::frontend::CodeGenOptions::ComplexRangeKind ComplexRange =
|
||||
Fortran::frontend::CodeGenOptions::ComplexRangeKind::
|
||||
CX_Full; ///< Method for calculating complex number division
|
||||
};
|
||||
|
||||
struct OffloadModuleOpts {
|
||||
|
||||
@@ -485,6 +485,21 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
|
||||
}
|
||||
|
||||
parseDoConcurrentMapping(opts, args, diags);
|
||||
|
||||
if (const llvm::opt::Arg *arg =
|
||||
args.getLastArg(clang::driver::options::OPT_complex_range_EQ)) {
|
||||
llvm::StringRef argValue = llvm::StringRef(arg->getValue());
|
||||
if (argValue == "full") {
|
||||
opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Full);
|
||||
} else if (argValue == "improved") {
|
||||
opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Improved);
|
||||
} else if (argValue == "basic") {
|
||||
opts.setComplexRange(CodeGenOptions::ComplexRangeKind::CX_Basic);
|
||||
} else {
|
||||
diags.Report(clang::diag::err_drv_invalid_value)
|
||||
<< arg->getAsString(args) << arg->getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses all target input arguments and populates the target
|
||||
@@ -1812,4 +1827,10 @@ void CompilerInvocation::setLoweringOptions() {
|
||||
.setNoSignedZeros(langOptions.NoSignedZeros)
|
||||
.setAssociativeMath(langOptions.AssociativeMath)
|
||||
.setReciprocalMath(langOptions.ReciprocalMath);
|
||||
|
||||
if (codegenOpts.getComplexRange() ==
|
||||
CodeGenOptions::ComplexRangeKind::CX_Improved ||
|
||||
codegenOpts.getComplexRange() ==
|
||||
CodeGenOptions::ComplexRangeKind::CX_Basic)
|
||||
loweringOpts.setComplexDivisionToRuntime(false);
|
||||
}
|
||||
|
||||
@@ -750,6 +750,8 @@ void CodeGenAction::generateLLVMIR() {
|
||||
if (ci.getInvocation().getLoweringOpts().getIntegerWrapAround())
|
||||
config.NSWOnLoopVarInc = false;
|
||||
|
||||
config.ComplexRange = opts.getComplexRange();
|
||||
|
||||
// Create the pass pipeline
|
||||
fir::createMLIRToLLVMPassPipeline(pm, config, getCurrentFile());
|
||||
(void)mlir::applyPassManagerCLOptions(pm);
|
||||
|
||||
@@ -5749,6 +5749,8 @@ private:
|
||||
builder =
|
||||
new fir::FirOpBuilder(func, bridge.getKindMap(), &mlirSymbolTable);
|
||||
assert(builder && "FirOpBuilder did not instantiate");
|
||||
builder->setComplexDivisionToRuntimeFlag(
|
||||
bridge.getLoweringOptions().getComplexDivisionToRuntime());
|
||||
builder->setFastMathFlags(bridge.getLoweringOptions().getMathOptions());
|
||||
builder->setInsertionPointToStart(&func.front());
|
||||
if (funit.parent.isA<Fortran::lower::pft::FunctionLikeUnit>()) {
|
||||
|
||||
@@ -1066,8 +1066,17 @@ struct BinaryOp<Fortran::evaluate::Divide<
|
||||
mlir::Type ty = Fortran::lower::getFIRType(
|
||||
builder.getContext(), Fortran::common::TypeCategory::Complex, KIND,
|
||||
/*params=*/{});
|
||||
return hlfir::EntityWithAttributes{
|
||||
fir::genDivC(builder, loc, ty, lhs, rhs)};
|
||||
|
||||
// TODO: Ideally, complex number division operations should always be
|
||||
// lowered to MLIR. However, converting them to the runtime via MLIR causes
|
||||
// ABI issues.
|
||||
if (builder.getComplexDivisionToRuntimeFlag()) {
|
||||
return hlfir::EntityWithAttributes{
|
||||
fir::genDivC(builder, loc, ty, lhs, rhs)};
|
||||
} else {
|
||||
return hlfir::EntityWithAttributes{
|
||||
builder.create<mlir::complex::DivOp>(loc, lhs, rhs)};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4162,7 +4162,20 @@ public:
|
||||
mathToFuncsOptions.minWidthOfFPowIExponent = 33;
|
||||
mathConvertionPM.addPass(
|
||||
mlir::createConvertMathToFuncs(mathToFuncsOptions));
|
||||
mathConvertionPM.addPass(mlir::createConvertComplexToStandardPass());
|
||||
|
||||
mlir::ConvertComplexToStandardPassOptions complexToStandardOptions{};
|
||||
if (options.ComplexRange ==
|
||||
Fortran::frontend::CodeGenOptions::ComplexRangeKind::CX_Basic) {
|
||||
complexToStandardOptions.complexRange =
|
||||
mlir::complex::ComplexRangeFlags::basic;
|
||||
} else if (options.ComplexRange == Fortran::frontend::CodeGenOptions::
|
||||
ComplexRangeKind::CX_Improved) {
|
||||
complexToStandardOptions.complexRange =
|
||||
mlir::complex::ComplexRangeFlags::improved;
|
||||
}
|
||||
mathConvertionPM.addPass(
|
||||
mlir::createConvertComplexToStandardPass(complexToStandardOptions));
|
||||
|
||||
// Convert Math dialect operations into LLVM dialect operations.
|
||||
// There is no way to prefer MathToLLVM patterns over MathToLibm
|
||||
// patterns (applied below), so we have to run MathToLLVM conversion here.
|
||||
|
||||
@@ -113,6 +113,7 @@ void addFIRToLLVMPass(mlir::PassManager &pm,
|
||||
options.forceUnifiedTBAATree = useOldAliasTags;
|
||||
options.typeDescriptorsRenamedForAssembly =
|
||||
!disableCompilerGeneratedNamesConversion;
|
||||
options.ComplexRange = config.ComplexRange;
|
||||
addPassConditionally(pm, disableFirToLlvmIr,
|
||||
[&]() { return fir::createFIRToLLVMPass(options); });
|
||||
// The dialect conversion framework may leave dead unrealized_conversion_cast
|
||||
|
||||
23
flang/test/Driver/complex-range.f90
Normal file
23
flang/test/Driver/complex-range.f90
Normal file
@@ -0,0 +1,23 @@
|
||||
! Test range options for complex multiplication and division.
|
||||
|
||||
! RUN: %flang -### -c %s 2>&1 \
|
||||
! RUN: | FileCheck %s --check-prefix=RANGE
|
||||
|
||||
! RUN: %flang -### -fcomplex-arithmetic=full -c %s 2>&1 \
|
||||
! RUN: | FileCheck %s --check-prefix=FULL
|
||||
|
||||
! RUN: %flang -### -fcomplex-arithmetic=improved -c %s 2>&1 \
|
||||
! RUN: | FileCheck %s --check-prefix=IMPRVD
|
||||
|
||||
! RUN: %flang -### -fcomplex-arithmetic=basic -c %s 2>&1 \
|
||||
! RUN: | FileCheck %s --check-prefix=BASIC
|
||||
|
||||
! RUN: not %flang -### -fcomplex-arithmetic=foo -c %s 2>&1 \
|
||||
! RUN: | FileCheck %s --check-prefix=ERR
|
||||
|
||||
! RANGE-NOT: -complex-range=
|
||||
! FULL: -complex-range=full
|
||||
! IMPRVD: -complex-range=improved
|
||||
! BASIC: -complex-range=basic
|
||||
|
||||
! ERR: error: unsupported argument 'foo' to option '-fcomplex-arithmetic='
|
||||
131
flang/test/Integration/complex-div-to-llvm-kind10.f90
Normal file
131
flang/test/Integration/complex-div-to-llvm-kind10.f90
Normal file
@@ -0,0 +1,131 @@
|
||||
! Test lowering complex division to llvm ir according to options
|
||||
|
||||
! REQUIRES: target=x86_64{{.*}}
|
||||
! RUN: %flang -fcomplex-arithmetic=improved -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: %flang -fcomplex-arithmetic=basic -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
|
||||
|
||||
! CHECK-LABEL: @div_test_extended
|
||||
! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]])
|
||||
! CHECK: %[[LOAD_LHS:.*]] = load { x86_fp80, x86_fp80 }, ptr %[[LHS]], align 16
|
||||
! CHECK: %[[LOAD_RHS:.*]] = load { x86_fp80, x86_fp80 }, ptr %[[RHS]], align 16
|
||||
! CHECK: %[[LHS_REAL:.*]] = extractvalue { x86_fp80, x86_fp80 } %[[LOAD_LHS]], 0
|
||||
! CHECK: %[[LHS_IMAG:.*]] = extractvalue { x86_fp80, x86_fp80 } %[[LOAD_LHS]], 1
|
||||
! CHECK: %[[RHS_REAL:.*]] = extractvalue { x86_fp80, x86_fp80 } %[[LOAD_RHS]], 0
|
||||
! CHECK: %[[RHS_IMAG:.*]] = extractvalue { x86_fp80, x86_fp80 } %[[LOAD_RHS]], 1
|
||||
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_RATIO:.*]] = fdiv contract x86_fp80 %[[RHS_REAL]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract x86_fp80 %[[RHS_REAL_IMAG_RATIO]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_DENOM:.*]] = fadd contract x86_fp80 %[[RHS_IMAG]], %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract x86_fp80 %[[LHS_REAL]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_1:.*]] = fadd contract x86_fp80 %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_1:.*]] = fdiv contract x86_fp80 %[[REAL_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract x86_fp80 %[[LHS_IMAG]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_1:.*]] = fsub contract x86_fp80 %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_1:.*]] = fdiv contract x86_fp80 %[[IMAG_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_RATIO:.*]] = fdiv contract x86_fp80 %[[RHS_IMAG]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract x86_fp80 %[[RHS_IMAG_REAL_RATIO]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_DENOM:.*]] = fadd contract x86_fp80 %[[RHS_REAL]], %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract x86_fp80 %[[LHS_IMAG]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_2:.*]] = fadd contract x86_fp80 %[[LHS_REAL]], %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_REAL_2:.*]] = fdiv contract x86_fp80 %[[REAL_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract x86_fp80 %[[LHS_REAL]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_2:.*]] = fsub contract x86_fp80 %[[LHS_IMAG]], %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_IMAG_2:.*]] = fdiv contract x86_fp80 %[[IMAG_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
|
||||
! Case 1. Zero denominator, numerator contains at most one NaN value.
|
||||
! IMPRVD: %[[RHS_REAL_ABS:.*]] = call contract x86_fp80 @llvm.fabs.f80(x86_fp80 %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_REAL_ABS_IS_ZERO:.*]] = fcmp oeq x86_fp80 %[[RHS_REAL_ABS]], 0xK00000000000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_ABS:.*]] = call contract x86_fp80 @llvm.fabs.f80(x86_fp80 %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_IMAG_ABS_IS_ZERO:.*]] = fcmp oeq x86_fp80 %[[RHS_IMAG_ABS]], 0xK00000000000000000000
|
||||
! IMPRVD: %[[LHS_REAL_IS_NOT_NAN:.*]] = fcmp ord x86_fp80 %[[LHS_REAL]], 0xK00000000000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_IS_NOT_NAN:.*]] = fcmp ord x86_fp80 %[[LHS_IMAG]], 0xK00000000000000000000
|
||||
! IMPRVD: %[[LHS_CONTAINS_NOT_NAN_VALUE:.*]] = or i1 %[[LHS_REAL_IS_NOT_NAN]], %[[LHS_IMAG_IS_NOT_NAN]]
|
||||
! IMPRVD: %[[RHS_IS_ZERO:.*]] = and i1 %[[RHS_REAL_ABS_IS_ZERO]], %[[RHS_IMAG_ABS_IS_ZERO]]
|
||||
! IMPRVD: %[[RESULT_IS_INFINITY:.*]] = and i1 %[[LHS_CONTAINS_NOT_NAN_VALUE]], %[[RHS_IS_ZERO]]
|
||||
! IMPRVD: %[[INF_WITH_SIGN_OF_RHS_REAL:.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 0xK7FFF8000000000000000, x86_fp80 %[[RHS_REAL]])
|
||||
! IMPRVD: %[[INFINITY_RESULT_REAL:.*]] = fmul contract x86_fp80 %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[INFINITY_RESULT_IMAG:.*]] = fmul contract x86_fp80 %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_IMAG]]
|
||||
|
||||
! Case 2. Infinite numerator, finite denominator.
|
||||
! IMPRVD: %[[RHS_REAL_FINITE:.*]] = fcmp one x86_fp80 %[[RHS_REAL_ABS]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_FINITE:.*]] = fcmp one x86_fp80 %[[RHS_IMAG_ABS]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[RHS_IS_FINITE:.*]] = and i1 %[[RHS_REAL_FINITE]], %[[RHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_ABS:.*]] = call contract x86_fp80 @llvm.fabs.f80(x86_fp80 %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_REAL_INFINITE:.*]] = fcmp oeq x86_fp80 %[[LHS_REAL_ABS]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_ABS:.*]] = call contract x86_fp80 @llvm.fabs.f80(x86_fp80 %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_IMAG_INFINITE:.*]] = fcmp oeq x86_fp80 %[[LHS_IMAG_ABS]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[LHS_IS_INFINITE:.*]] = or i1 %[[LHS_REAL_INFINITE]], %[[LHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[INF_NUM_FINITE_DENOM:.*]] = and i1 %[[LHS_IS_INFINITE]], %[[RHS_IS_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF:.*]] = select i1 %[[LHS_REAL_INFINITE]], x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK00000000000000000000
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN:.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 %[[LHS_REAL_IS_INF]], x86_fp80 %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF:.*]] = select i1 %[[LHS_IMAG_INFINITE]], x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK00000000000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN:.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 %[[LHS_IMAG_IS_INF]], x86_fp80 %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract x86_fp80 %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract x86_fp80 %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_1:.*]] = fadd contract x86_fp80 %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_3:.*]] = fmul contract x86_fp80 %[[INF_MULTIPLICATOR_1]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract x86_fp80 %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract x86_fp80 %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_2:.*]] = fsub contract x86_fp80 %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_IMAG_3:.*]] = fmul contract x86_fp80 %[[INF_MULTIPLICATOR_2]], 0xK7FFF8000000000000000
|
||||
|
||||
! Case 3. Finite numerator, infinite denominator.
|
||||
! IMPRVD: %[[LHS_REAL_FINITE:.*]] = fcmp one x86_fp80 %[[LHS_REAL_ABS]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_FINITE:.*]] = fcmp one x86_fp80 %[[LHS_IMAG_ABS]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[LHS_IS_FINITE:.*]] = and i1 %[[LHS_REAL_FINITE]], %[[LHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_INFINITE:.*]] = fcmp oeq x86_fp80 %[[RHS_REAL_ABS]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_INFINITE:.*]] = fcmp oeq x86_fp80 %[[RHS_IMAG_ABS]], 0xK7FFF8000000000000000
|
||||
! IMPRVD: %[[RHS_IS_INFINITE:.*]] = or i1 %[[RHS_REAL_INFINITE]], %[[RHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[FINITE_NUM_INFINITE_DENOM:.*]] = and i1 %[[LHS_IS_FINITE]], %[[RHS_IS_INFINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF:.*]] = select i1 %[[RHS_REAL_INFINITE]], x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK00000000000000000000
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN:.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 %[[RHS_REAL_IS_INF]], x86_fp80 %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF:.*]] = select i1 %[[RHS_IMAG_INFINITE]], x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK00000000000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN:.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 %[[RHS_IMAG_IS_INF]], x86_fp80 %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract x86_fp80 %[[LHS_REAL]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract x86_fp80 %[[LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_1:.*]] = fadd contract x86_fp80 %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_4:.*]] = fmul contract x86_fp80 %[[ZERO_MULTIPLICATOR_1]], 0xK00000000000000000000
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract x86_fp80 %[[LHS_IMAG]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract x86_fp80 %[[LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_2:.*]] = fsub contract x86_fp80 %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_4:.*]] = fmul contract x86_fp80 %[[ZERO_MULTIPLICATOR_2]], 0xK00000000000000000000
|
||||
|
||||
! IMPRVD: %[[REAL_ABS_SMALLER_THAN_IMAG_ABS:.*]] = fcmp olt x86_fp80 %[[RHS_REAL_ABS]], %[[RHS_IMAG_ABS]]
|
||||
! IMPRVD: %[[RESULT_REAL:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], x86_fp80 %[[RESULT_REAL_1]], x86_fp80 %[[RESULT_REAL_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], x86_fp80 %[[RESULT_IMAG_1]], x86_fp80 %[[RESULT_IMAG_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], x86_fp80 %[[RESULT_REAL_4]], x86_fp80 %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], x86_fp80 %[[RESULT_IMAG_4]], x86_fp80 %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], x86_fp80 %[[RESULT_REAL_3]], x86_fp80 %[[RESULT_REAL_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], x86_fp80 %[[RESULT_IMAG_3]], x86_fp80 %[[RESULT_IMAG_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], x86_fp80 %[[INFINITY_RESULT_REAL]], x86_fp80 %[[RESULT_REAL_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], x86_fp80 %[[INFINITY_RESULT_IMAG]], x86_fp80 %[[RESULT_IMAG_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_IS_NAN:.*]] = fcmp uno x86_fp80 %[[RESULT_REAL]], 0xK00000000000000000000
|
||||
! IMPRVD: %[[RESULT_IMAG_IS_NAN:.*]] = fcmp uno x86_fp80 %[[RESULT_IMAG]], 0xK00000000000000000000
|
||||
! IMPRVD: %[[RESULT_IS_NAN:.*]] = and i1 %[[RESULT_REAL_IS_NAN]], %[[RESULT_IMAG_IS_NAN]]
|
||||
! IMPRVD: %[[RESULT_REAL_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], x86_fp80 %[[RESULT_REAL_SPECIAL_CASE_1]], x86_fp80 %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], x86_fp80 %[[RESULT_IMAG_SPECIAL_CASE_1]], x86_fp80 %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_1:.*]] = insertvalue { x86_fp80, x86_fp80 } poison, x86_fp80 %[[RESULT_REAL_WITH_SPECIAL_CASES]], 0
|
||||
! IMPRVD: %[[RESULT_2:.*]] = insertvalue { x86_fp80, x86_fp80 } %[[RESULT_1]], x86_fp80 %[[RESULT_IMAG_WITH_SPECIAL_CASES]], 1
|
||||
! IMPRVD: store { x86_fp80, x86_fp80 } %[[RESULT_2]], ptr %[[RET]], align 16
|
||||
|
||||
! BASIC-DAG: %[[RHS_REAL_SQ:.*]] = fmul contract x86_fp80 %[[RHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[RHS_IMAG_SQ:.*]] = fmul contract x86_fp80 %[[RHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[SQ_NORM:.*]] = fadd contract x86_fp80 %[[RHS_REAL_SQ]], %[[RHS_IMAG_SQ]]
|
||||
! BASIC-DAG: %[[REAL_TMP_0:.*]] = fmul contract x86_fp80 %[[LHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[REAL_TMP_1:.*]] = fmul contract x86_fp80 %[[LHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[REAL_TMP_2:.*]] = fadd contract x86_fp80 %[[REAL_TMP_0]], %[[REAL_TMP_1]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_0:.*]] = fmul contract x86_fp80 %[[LHS_IMAG]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_1:.*]] = fmul contract x86_fp80 %[[LHS_REAL]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[IMAG_TMP_2:.*]] = fsub contract x86_fp80 %[[IMAG_TMP_0]], %[[IMAG_TMP_1]]
|
||||
! BASIC: %[[REAL:.*]] = fdiv contract x86_fp80 %[[REAL_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[IMAG:.*]] = fdiv contract x86_fp80 %[[IMAG_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[RESULT_1:.*]] = insertvalue { x86_fp80, x86_fp80 } poison, x86_fp80 %[[REAL]], 0
|
||||
! BASIC: %[[RESULT_2:.*]] = insertvalue { x86_fp80, x86_fp80 } %[[RESULT_1]], x86_fp80 %[[IMAG]], 1
|
||||
! BASIC: store { x86_fp80, x86_fp80 } %[[RESULT_2]], ptr %[[RET]], align 16
|
||||
|
||||
! CHECK: ret void
|
||||
subroutine div_test_extended(a,b,c)
|
||||
complex(kind=10) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_extended
|
||||
131
flang/test/Integration/complex-div-to-llvm-kind16.f90
Normal file
131
flang/test/Integration/complex-div-to-llvm-kind16.f90
Normal file
@@ -0,0 +1,131 @@
|
||||
! Test lowering complex division to llvm ir according to options
|
||||
|
||||
! REQUIRES: flang-supports-f128-math
|
||||
! RUN: %flang -fcomplex-arithmetic=improved -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: %flang -fcomplex-arithmetic=basic -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
|
||||
|
||||
! CHECK-LABEL: @div_test_quad
|
||||
! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]])
|
||||
! CHECK: %[[LOAD_LHS:.*]] = load { fp128, fp128 }, ptr %[[LHS]], align 16
|
||||
! CHECK: %[[LOAD_RHS:.*]] = load { fp128, fp128 }, ptr %[[RHS]], align 16
|
||||
! CHECK: %[[LHS_REAL:.*]] = extractvalue { fp128, fp128 } %[[LOAD_LHS]], 0
|
||||
! CHECK: %[[LHS_IMAG:.*]] = extractvalue { fp128, fp128 } %[[LOAD_LHS]], 1
|
||||
! CHECK: %[[RHS_REAL:.*]] = extractvalue { fp128, fp128 } %[[LOAD_RHS]], 0
|
||||
! CHECK: %[[RHS_IMAG:.*]] = extractvalue { fp128, fp128 } %[[LOAD_RHS]], 1
|
||||
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_RATIO:.*]] = fdiv contract fp128 %[[RHS_REAL]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract fp128 %[[RHS_REAL_IMAG_RATIO]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_DENOM:.*]] = fadd contract fp128 %[[RHS_IMAG]], %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract fp128 %[[LHS_REAL]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_1:.*]] = fadd contract fp128 %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_1:.*]] = fdiv contract fp128 %[[REAL_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract fp128 %[[LHS_IMAG]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_1:.*]] = fsub contract fp128 %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_1:.*]] = fdiv contract fp128 %[[IMAG_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_RATIO:.*]] = fdiv contract fp128 %[[RHS_IMAG]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract fp128 %[[RHS_IMAG_REAL_RATIO]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_DENOM:.*]] = fadd contract fp128 %[[RHS_REAL]], %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract fp128 %[[LHS_IMAG]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_2:.*]] = fadd contract fp128 %[[LHS_REAL]], %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_REAL_2:.*]] = fdiv contract fp128 %[[REAL_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract fp128 %[[LHS_REAL]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_2:.*]] = fsub contract fp128 %[[LHS_IMAG]], %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_IMAG_2:.*]] = fdiv contract fp128 %[[IMAG_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
|
||||
! Case 1. Zero denominator, numerator contains at most one NaN value.
|
||||
! IMPRVD: %[[RHS_REAL_ABS:.*]] = call contract fp128 @llvm.fabs.f128(fp128 %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_REAL_ABS_IS_ZERO:.*]] = fcmp oeq fp128 %[[RHS_REAL_ABS]], 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_ABS:.*]] = call contract fp128 @llvm.fabs.f128(fp128 %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_IMAG_ABS_IS_ZERO:.*]] = fcmp oeq fp128 %[[RHS_IMAG_ABS]], 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[LHS_REAL_IS_NOT_NAN:.*]] = fcmp ord fp128 %[[LHS_REAL]], 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_IS_NOT_NAN:.*]] = fcmp ord fp128 %[[LHS_IMAG]], 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[LHS_CONTAINS_NOT_NAN_VALUE:.*]] = or i1 %[[LHS_REAL_IS_NOT_NAN]], %[[LHS_IMAG_IS_NOT_NAN]]
|
||||
! IMPRVD: %[[RHS_IS_ZERO:.*]] = and i1 %[[RHS_REAL_ABS_IS_ZERO]], %[[RHS_IMAG_ABS_IS_ZERO]]
|
||||
! IMPRVD: %[[RESULT_IS_INFINITY:.*]] = and i1 %[[LHS_CONTAINS_NOT_NAN_VALUE]], %[[RHS_IS_ZERO]]
|
||||
! IMPRVD: %[[INF_WITH_SIGN_OF_RHS_REAL:.*]] = call fp128 @llvm.copysign.f128(fp128 0xL00000000000000007FFF000000000000, fp128 %[[RHS_REAL]])
|
||||
! IMPRVD: %[[INFINITY_RESULT_REAL:.*]] = fmul contract fp128 %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[INFINITY_RESULT_IMAG:.*]] = fmul contract fp128 %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_IMAG]]
|
||||
|
||||
! Case 2. Infinite numerator, finite denominator.
|
||||
! IMPRVD: %[[RHS_REAL_FINITE:.*]] = fcmp one fp128 %[[RHS_REAL_ABS]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_FINITE:.*]] = fcmp one fp128 %[[RHS_IMAG_ABS]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[RHS_IS_FINITE:.*]] = and i1 %[[RHS_REAL_FINITE]], %[[RHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_ABS:.*]] = call contract fp128 @llvm.fabs.f128(fp128 %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_REAL_INFINITE:.*]] = fcmp oeq fp128 %[[LHS_REAL_ABS]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_ABS:.*]] = call contract fp128 @llvm.fabs.f128(fp128 %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_IMAG_INFINITE:.*]] = fcmp oeq fp128 %[[LHS_IMAG_ABS]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[LHS_IS_INFINITE:.*]] = or i1 %[[LHS_REAL_INFINITE]], %[[LHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[INF_NUM_FINITE_DENOM:.*]] = and i1 %[[LHS_IS_INFINITE]], %[[RHS_IS_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF:.*]] = select i1 %[[LHS_REAL_INFINITE]], fp128 0xL00000000000000003FFF000000000000, fp128 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN:.*]] = call fp128 @llvm.copysign.f128(fp128 %[[LHS_REAL_IS_INF]], fp128 %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF:.*]] = select i1 %[[LHS_IMAG_INFINITE]], fp128 0xL00000000000000003FFF000000000000, fp128 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN:.*]] = call fp128 @llvm.copysign.f128(fp128 %[[LHS_IMAG_IS_INF]], fp128 %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract fp128 %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract fp128 %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_1:.*]] = fadd contract fp128 %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_3:.*]] = fmul contract fp128 %[[INF_MULTIPLICATOR_1]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract fp128 %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract fp128 %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_2:.*]] = fsub contract fp128 %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_IMAG_3:.*]] = fmul contract fp128 %[[INF_MULTIPLICATOR_2]], 0xL00000000000000007FFF000000000000
|
||||
|
||||
! Case 3. Finite numerator, infinite denominator.
|
||||
! IMPRVD: %[[LHS_REAL_FINITE:.*]] = fcmp one fp128 %[[LHS_REAL_ABS]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_FINITE:.*]] = fcmp one fp128 %[[LHS_IMAG_ABS]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[LHS_IS_FINITE:.*]] = and i1 %[[LHS_REAL_FINITE]], %[[LHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_INFINITE:.*]] = fcmp oeq fp128 %[[RHS_REAL_ABS]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_INFINITE:.*]] = fcmp oeq fp128 %[[RHS_IMAG_ABS]], 0xL00000000000000007FFF000000000000
|
||||
! IMPRVD: %[[RHS_IS_INFINITE:.*]] = or i1 %[[RHS_REAL_INFINITE]], %[[RHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[FINITE_NUM_INFINITE_DENOM:.*]] = and i1 %[[LHS_IS_FINITE]], %[[RHS_IS_INFINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF:.*]] = select i1 %[[RHS_REAL_INFINITE]], fp128 0xL00000000000000003FFF000000000000, fp128 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN:.*]] = call fp128 @llvm.copysign.f128(fp128 %[[RHS_REAL_IS_INF]], fp128 %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF:.*]] = select i1 %[[RHS_IMAG_INFINITE]], fp128 0xL00000000000000003FFF000000000000, fp128 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN:.*]] = call fp128 @llvm.copysign.f128(fp128 %[[RHS_IMAG_IS_INF]], fp128 %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract fp128 %[[LHS_REAL]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract fp128 %[[LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_1:.*]] = fadd contract fp128 %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_4:.*]] = fmul contract fp128 %[[ZERO_MULTIPLICATOR_1]], 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract fp128 %[[LHS_IMAG]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract fp128 %[[LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_2:.*]] = fsub contract fp128 %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_4:.*]] = fmul contract fp128 %[[ZERO_MULTIPLICATOR_2]], 0xL00000000000000000000000000000000
|
||||
|
||||
! IMPRVD: %[[REAL_ABS_SMALLER_THAN_IMAG_ABS:.*]] = fcmp olt fp128 %[[RHS_REAL_ABS]], %[[RHS_IMAG_ABS]]
|
||||
! IMPRVD: %[[RESULT_REAL:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], fp128 %[[RESULT_REAL_1]], fp128 %[[RESULT_REAL_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], fp128 %[[RESULT_IMAG_1]], fp128 %[[RESULT_IMAG_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], fp128 %[[RESULT_REAL_4]], fp128 %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], fp128 %[[RESULT_IMAG_4]], fp128 %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], fp128 %[[RESULT_REAL_3]], fp128 %[[RESULT_REAL_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], fp128 %[[RESULT_IMAG_3]], fp128 %[[RESULT_IMAG_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], fp128 %[[INFINITY_RESULT_REAL]], fp128 %[[RESULT_REAL_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], fp128 %[[INFINITY_RESULT_IMAG]], fp128 %[[RESULT_IMAG_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_IS_NAN:.*]] = fcmp uno fp128 %[[RESULT_REAL]], 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[RESULT_IMAG_IS_NAN:.*]] = fcmp uno fp128 %[[RESULT_IMAG]], 0xL00000000000000000000000000000000
|
||||
! IMPRVD: %[[RESULT_IS_NAN:.*]] = and i1 %[[RESULT_REAL_IS_NAN]], %[[RESULT_IMAG_IS_NAN]]
|
||||
! IMPRVD: %[[RESULT_REAL_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], fp128 %[[RESULT_REAL_SPECIAL_CASE_1]], fp128 %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], fp128 %[[RESULT_IMAG_SPECIAL_CASE_1]], fp128 %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_1:.*]] = insertvalue { fp128, fp128 } poison, fp128 %[[RESULT_REAL_WITH_SPECIAL_CASES]], 0
|
||||
! IMPRVD: %[[RESULT_2:.*]] = insertvalue { fp128, fp128 } %[[RESULT_1]], fp128 %[[RESULT_IMAG_WITH_SPECIAL_CASES]], 1
|
||||
! IMPRVD: store { fp128, fp128 } %[[RESULT_2]], ptr %[[RET]], align 16
|
||||
|
||||
! BASIC-DAG: %[[RHS_REAL_SQ:.*]] = fmul contract fp128 %[[RHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[RHS_IMAG_SQ:.*]] = fmul contract fp128 %[[RHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[SQ_NORM:.*]] = fadd contract fp128 %[[RHS_REAL_SQ]], %[[RHS_IMAG_SQ]]
|
||||
! BASIC-DAG: %[[REAL_TMP_0:.*]] = fmul contract fp128 %[[LHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[REAL_TMP_1:.*]] = fmul contract fp128 %[[LHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[REAL_TMP_2:.*]] = fadd contract fp128 %[[REAL_TMP_0]], %[[REAL_TMP_1]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_0:.*]] = fmul contract fp128 %[[LHS_IMAG]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_1:.*]] = fmul contract fp128 %[[LHS_REAL]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[IMAG_TMP_2:.*]] = fsub contract fp128 %[[IMAG_TMP_0]], %[[IMAG_TMP_1]]
|
||||
! BASIC: %[[REAL:.*]] = fdiv contract fp128 %[[REAL_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[IMAG:.*]] = fdiv contract fp128 %[[IMAG_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[RESULT_1:.*]] = insertvalue { fp128, fp128 } poison, fp128 %[[REAL]], 0
|
||||
! BASIC: %[[RESULT_2:.*]] = insertvalue { fp128, fp128 } %[[RESULT_1]], fp128 %[[IMAG]], 1
|
||||
! BASIC: store { fp128, fp128 } %[[RESULT_2]], ptr %[[RET]], align 16
|
||||
|
||||
! CHECK: ret void
|
||||
subroutine div_test_quad(a,b,c)
|
||||
complex(kind=16) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_quad
|
||||
508
flang/test/Integration/complex-div-to-llvm.f90
Normal file
508
flang/test/Integration/complex-div-to-llvm.f90
Normal file
@@ -0,0 +1,508 @@
|
||||
! Test lowering complex division to llvm ir according to options
|
||||
|
||||
! RUN: %flang -fcomplex-arithmetic=improved -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: %flang -fcomplex-arithmetic=basic -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
|
||||
|
||||
! CHECK-LABEL: @div_test_half
|
||||
! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]])
|
||||
! CHECK: %[[LOAD_LHS:.*]] = load { half, half }, ptr %[[LHS]], align 2
|
||||
! CHECK: %[[LOAD_RHS:.*]] = load { half, half }, ptr %[[RHS]], align 2
|
||||
! CHECK: %[[LHS_REAL:.*]] = extractvalue { half, half } %[[LOAD_LHS]], 0
|
||||
! CHECK: %[[LHS_IMAG:.*]] = extractvalue { half, half } %[[LOAD_LHS]], 1
|
||||
! CHECK: %[[RHS_REAL:.*]] = extractvalue { half, half } %[[LOAD_RHS]], 0
|
||||
! CHECK: %[[RHS_IMAG:.*]] = extractvalue { half, half } %[[LOAD_RHS]], 1
|
||||
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_RATIO:.*]] = fdiv contract half %[[RHS_REAL]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract half %[[RHS_REAL_IMAG_RATIO]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_DENOM:.*]] = fadd contract half %[[RHS_IMAG]], %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract half %[[LHS_REAL]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_1:.*]] = fadd contract half %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_1:.*]] = fdiv contract half %[[REAL_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract half %[[LHS_IMAG]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_1:.*]] = fsub contract half %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_1:.*]] = fdiv contract half %[[IMAG_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_RATIO:.*]] = fdiv contract half %[[RHS_IMAG]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract half %[[RHS_IMAG_REAL_RATIO]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_DENOM:.*]] = fadd contract half %[[RHS_REAL]], %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract half %[[LHS_IMAG]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_2:.*]] = fadd contract half %[[LHS_REAL]], %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_REAL_2:.*]] = fdiv contract half %[[REAL_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract half %[[LHS_REAL]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_2:.*]] = fsub contract half %[[LHS_IMAG]], %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_IMAG_2:.*]] = fdiv contract half %[[IMAG_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
|
||||
! Case 1. Zero denominator, numerator contains at most one NaN value.
|
||||
! IMPRVD: %[[RHS_REAL_ABS:.*]] = call contract half @llvm.fabs.f16(half %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_REAL_ABS_IS_ZERO:.*]] = fcmp oeq half %[[RHS_REAL_ABS]], 0xH0000
|
||||
! IMPRVD: %[[RHS_IMAG_ABS:.*]] = call contract half @llvm.fabs.f16(half %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_IMAG_ABS_IS_ZERO:.*]] = fcmp oeq half %[[RHS_IMAG_ABS]], 0xH0000
|
||||
! IMPRVD: %[[LHS_REAL_IS_NOT_NAN:.*]] = fcmp ord half %[[LHS_REAL]], 0xH0000
|
||||
! IMPRVD: %[[LHS_IMAG_IS_NOT_NAN:.*]] = fcmp ord half %[[LHS_IMAG]], 0xH0000
|
||||
! IMPRVD: %[[LHS_CONTAINS_NOT_NAN_VALUE:.*]] = or i1 %[[LHS_REAL_IS_NOT_NAN]], %[[LHS_IMAG_IS_NOT_NAN]]
|
||||
! IMPRVD: %[[RHS_IS_ZERO:.*]] = and i1 %[[RHS_REAL_ABS_IS_ZERO]], %[[RHS_IMAG_ABS_IS_ZERO]]
|
||||
! IMPRVD: %[[RESULT_IS_INFINITY:.*]] = and i1 %[[LHS_CONTAINS_NOT_NAN_VALUE]], %[[RHS_IS_ZERO]]
|
||||
! IMPRVD: %[[INF_WITH_SIGN_OF_RHS_REAL:.*]] = call half @llvm.copysign.f16(half 0xH7C00, half %[[RHS_REAL]])
|
||||
! IMPRVD: %[[INFINITY_RESULT_REAL:.*]] = fmul contract half %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[INFINITY_RESULT_IMAG:.*]] = fmul contract half %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_IMAG]]
|
||||
|
||||
! Case 2. Infinite numerator, finite denominator.
|
||||
! IMPRVD: %[[RHS_REAL_FINITE:.*]] = fcmp one half %[[RHS_REAL_ABS]], 0xH7C00
|
||||
! IMPRVD: %[[RHS_IMAG_FINITE:.*]] = fcmp one half %[[RHS_IMAG_ABS]], 0xH7C00
|
||||
! IMPRVD: %[[RHS_IS_FINITE:.*]] = and i1 %[[RHS_REAL_FINITE]], %[[RHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_ABS:.*]] = call contract half @llvm.fabs.f16(half %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_REAL_INFINITE:.*]] = fcmp oeq half %[[LHS_REAL_ABS]], 0xH7C00
|
||||
! IMPRVD: %[[LHS_IMAG_ABS:.*]] = call contract half @llvm.fabs.f16(half %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_IMAG_INFINITE:.*]] = fcmp oeq half %[[LHS_IMAG_ABS]], 0xH7C00
|
||||
! IMPRVD: %[[LHS_IS_INFINITE:.*]] = or i1 %[[LHS_REAL_INFINITE]], %[[LHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[INF_NUM_FINITE_DENOM:.*]] = and i1 %[[LHS_IS_INFINITE]], %[[RHS_IS_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF:.*]] = select i1 %[[LHS_REAL_INFINITE]], half 0xH3C00, half 0xH0000
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN:.*]] = call half @llvm.copysign.f16(half %[[LHS_REAL_IS_INF]], half %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF:.*]] = select i1 %[[LHS_IMAG_INFINITE]], half 0xH3C00, half 0xH0000
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN:.*]] = call half @llvm.copysign.f16(half %[[LHS_IMAG_IS_INF]], half %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract half %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract half %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_1:.*]] = fadd contract half %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_3:.*]] = fmul contract half %[[INF_MULTIPLICATOR_1]], 0xH7C00
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract half %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract half %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_2:.*]] = fsub contract half %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_IMAG_3:.*]] = fmul contract half %[[INF_MULTIPLICATOR_2]], 0xH7C00
|
||||
|
||||
! Case 3. Finite numerator, infinite denominator.
|
||||
! IMPRVD: %[[LHS_REAL_FINITE:.*]] = fcmp one half %[[LHS_REAL_ABS]], 0xH7C00
|
||||
! IMPRVD: %[[LHS_IMAG_FINITE:.*]] = fcmp one half %[[LHS_IMAG_ABS]], 0xH7C00
|
||||
! IMPRVD: %[[LHS_IS_FINITE:.*]] = and i1 %[[LHS_REAL_FINITE]], %[[LHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_INFINITE:.*]] = fcmp oeq half %[[RHS_REAL_ABS]], 0xH7C00
|
||||
! IMPRVD: %[[RHS_IMAG_INFINITE:.*]] = fcmp oeq half %[[RHS_IMAG_ABS]], 0xH7C00
|
||||
! IMPRVD: %[[RHS_IS_INFINITE:.*]] = or i1 %[[RHS_REAL_INFINITE]], %[[RHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[FINITE_NUM_INFINITE_DENOM:.*]] = and i1 %[[LHS_IS_FINITE]], %[[RHS_IS_INFINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF:.*]] = select i1 %[[RHS_REAL_INFINITE]], half 0xH3C00, half 0xH0000
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN:.*]] = call half @llvm.copysign.f16(half %[[RHS_REAL_IS_INF]], half %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF:.*]] = select i1 %[[RHS_IMAG_INFINITE]], half 0xH3C00, half 0xH0000
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN:.*]] = call half @llvm.copysign.f16(half %[[RHS_IMAG_IS_INF]], half %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract half %[[LHS_REAL]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract half %[[LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_1:.*]] = fadd contract half %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_4:.*]] = fmul contract half %[[ZERO_MULTIPLICATOR_1]], 0xH0000
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract half %[[LHS_IMAG]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract half %[[LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_2:.*]] = fsub contract half %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_4:.*]] = fmul contract half %[[ZERO_MULTIPLICATOR_2]], 0xH0000
|
||||
|
||||
! IMPRVD: %[[REAL_ABS_SMALLER_THAN_IMAG_ABS:.*]] = fcmp olt half %[[RHS_REAL_ABS]], %[[RHS_IMAG_ABS]]
|
||||
! IMPRVD: %[[RESULT_REAL:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], half %[[RESULT_REAL_1]], half %[[RESULT_REAL_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], half %[[RESULT_IMAG_1]], half %[[RESULT_IMAG_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], half %[[RESULT_REAL_4]], half %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], half %[[RESULT_IMAG_4]], half %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], half %[[RESULT_REAL_3]], half %[[RESULT_REAL_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], half %[[RESULT_IMAG_3]], half %[[RESULT_IMAG_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], half %[[INFINITY_RESULT_REAL]], half %[[RESULT_REAL_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], half %[[INFINITY_RESULT_IMAG]], half %[[RESULT_IMAG_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_IS_NAN:.*]] = fcmp uno half %[[RESULT_REAL]], 0xH0000
|
||||
! IMPRVD: %[[RESULT_IMAG_IS_NAN:.*]] = fcmp uno half %[[RESULT_IMAG]], 0xH0000
|
||||
! IMPRVD: %[[RESULT_IS_NAN:.*]] = and i1 %[[RESULT_REAL_IS_NAN]], %[[RESULT_IMAG_IS_NAN]]
|
||||
! IMPRVD: %[[RESULT_REAL_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], half %[[RESULT_REAL_SPECIAL_CASE_1]], half %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], half %[[RESULT_IMAG_SPECIAL_CASE_1]], half %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_1:.*]] = insertvalue { half, half } poison, half %[[RESULT_REAL_WITH_SPECIAL_CASES]], 0
|
||||
! IMPRVD: %[[RESULT_2:.*]] = insertvalue { half, half } %[[RESULT_1]], half %[[RESULT_IMAG_WITH_SPECIAL_CASES]], 1
|
||||
! IMPRVD: store { half, half } %[[RESULT_2]], ptr %[[RET]], align 2
|
||||
|
||||
! BASIC-DAG: %[[RHS_REAL_SQ:.*]] = fmul contract half %[[RHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[RHS_IMAG_SQ:.*]] = fmul contract half %[[RHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[SQ_NORM:.*]] = fadd contract half %[[RHS_REAL_SQ]], %[[RHS_IMAG_SQ]]
|
||||
! BASIC-DAG: %[[REAL_TMP_0:.*]] = fmul contract half %[[LHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[REAL_TMP_1:.*]] = fmul contract half %[[LHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[REAL_TMP_2:.*]] = fadd contract half %[[REAL_TMP_0]], %[[REAL_TMP_1]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_0:.*]] = fmul contract half %[[LHS_IMAG]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_1:.*]] = fmul contract half %[[LHS_REAL]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[IMAG_TMP_2:.*]] = fsub contract half %[[IMAG_TMP_0]], %[[IMAG_TMP_1]]
|
||||
! BASIC: %[[REAL:.*]] = fdiv contract half %[[REAL_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[IMAG:.*]] = fdiv contract half %[[IMAG_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[RESULT_1:.*]] = insertvalue { half, half } poison, half %[[REAL]], 0
|
||||
! BASIC: %[[RESULT_2:.*]] = insertvalue { half, half } %[[RESULT_1]], half %[[IMAG]], 1
|
||||
! BASIC: store { half, half } %[[RESULT_2]], ptr %[[RET]], align 2
|
||||
|
||||
! CHECK: ret void
|
||||
subroutine div_test_half(a,b,c)
|
||||
complex(kind=2) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_half
|
||||
|
||||
|
||||
! CHECK-LABEL: @div_test_bfloat
|
||||
! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]])
|
||||
! CHECK: %[[LOAD_LHS:.*]] = load { bfloat, bfloat }, ptr %[[LHS]], align 2
|
||||
! CHECK: %[[LOAD_RHS:.*]] = load { bfloat, bfloat }, ptr %[[RHS]], align 2
|
||||
! CHECK: %[[LHS_REAL:.*]] = extractvalue { bfloat, bfloat } %[[LOAD_LHS]], 0
|
||||
! CHECK: %[[LHS_IMAG:.*]] = extractvalue { bfloat, bfloat } %[[LOAD_LHS]], 1
|
||||
! CHECK: %[[RHS_REAL:.*]] = extractvalue { bfloat, bfloat } %[[LOAD_RHS]], 0
|
||||
! CHECK: %[[RHS_IMAG:.*]] = extractvalue { bfloat, bfloat } %[[LOAD_RHS]], 1
|
||||
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_RATIO:.*]] = fdiv contract bfloat %[[RHS_REAL]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract bfloat %[[RHS_REAL_IMAG_RATIO]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_DENOM:.*]] = fadd contract bfloat %[[RHS_IMAG]], %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract bfloat %[[LHS_REAL]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_1:.*]] = fadd contract bfloat %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_1:.*]] = fdiv contract bfloat %[[REAL_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract bfloat %[[LHS_IMAG]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_1:.*]] = fsub contract bfloat %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_1:.*]] = fdiv contract bfloat %[[IMAG_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_RATIO:.*]] = fdiv contract bfloat %[[RHS_IMAG]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract bfloat %[[RHS_IMAG_REAL_RATIO]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_DENOM:.*]] = fadd contract bfloat %[[RHS_REAL]], %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract bfloat %[[LHS_IMAG]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_2:.*]] = fadd contract bfloat %[[LHS_REAL]], %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_REAL_2:.*]] = fdiv contract bfloat %[[REAL_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract bfloat %[[LHS_REAL]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_2:.*]] = fsub contract bfloat %[[LHS_IMAG]], %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_IMAG_2:.*]] = fdiv contract bfloat %[[IMAG_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
|
||||
! Case 1. Zero denominator, numerator contains at most one NaN value.
|
||||
! IMPRVD: %[[RHS_REAL_ABS:.*]] = call contract bfloat @llvm.fabs.bf16(bfloat %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_REAL_ABS_IS_ZERO:.*]] = fcmp oeq bfloat %[[RHS_REAL_ABS]], 0xR0000
|
||||
! IMPRVD: %[[RHS_IMAG_ABS:.*]] = call contract bfloat @llvm.fabs.bf16(bfloat %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_IMAG_ABS_IS_ZERO:.*]] = fcmp oeq bfloat %[[RHS_IMAG_ABS]], 0xR0000
|
||||
! IMPRVD: %[[LHS_REAL_IS_NOT_NAN:.*]] = fcmp ord bfloat %[[LHS_REAL]], 0xR0000
|
||||
! IMPRVD: %[[LHS_IMAG_IS_NOT_NAN:.*]] = fcmp ord bfloat %[[LHS_IMAG]], 0xR0000
|
||||
! IMPRVD: %[[LHS_CONTAINS_NOT_NAN_VALUE:.*]] = or i1 %[[LHS_REAL_IS_NOT_NAN]], %[[LHS_IMAG_IS_NOT_NAN]]
|
||||
! IMPRVD: %[[RHS_IS_ZERO:.*]] = and i1 %[[RHS_REAL_ABS_IS_ZERO]], %[[RHS_IMAG_ABS_IS_ZERO]]
|
||||
! IMPRVD: %[[RESULT_IS_INFINITY:.*]] = and i1 %[[LHS_CONTAINS_NOT_NAN_VALUE]], %[[RHS_IS_ZERO]]
|
||||
! IMPRVD: %[[INF_WITH_SIGN_OF_RHS_REAL:.*]] = call bfloat @llvm.copysign.bf16(bfloat 0xR7F80, bfloat %[[RHS_REAL]])
|
||||
! IMPRVD: %[[INFINITY_RESULT_REAL:.*]] = fmul contract bfloat %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[INFINITY_RESULT_IMAG:.*]] = fmul contract bfloat %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_IMAG]]
|
||||
|
||||
! Case 2. Infinite numerator, finite denominator.
|
||||
! IMPRVD: %[[RHS_REAL_FINITE:.*]] = fcmp one bfloat %[[RHS_REAL_ABS]], 0xR7F80
|
||||
! IMPRVD: %[[RHS_IMAG_FINITE:.*]] = fcmp one bfloat %[[RHS_IMAG_ABS]], 0xR7F80
|
||||
! IMPRVD: %[[RHS_IS_FINITE:.*]] = and i1 %[[RHS_REAL_FINITE]], %[[RHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_ABS:.*]] = call contract bfloat @llvm.fabs.bf16(bfloat %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_REAL_INFINITE:.*]] = fcmp oeq bfloat %[[LHS_REAL_ABS]], 0xR7F80
|
||||
! IMPRVD: %[[LHS_IMAG_ABS:.*]] = call contract bfloat @llvm.fabs.bf16(bfloat %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_IMAG_INFINITE:.*]] = fcmp oeq bfloat %[[LHS_IMAG_ABS]], 0xR7F80
|
||||
! IMPRVD: %[[LHS_IS_INFINITE:.*]] = or i1 %[[LHS_REAL_INFINITE]], %[[LHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[INF_NUM_FINITE_DENOM:.*]] = and i1 %[[LHS_IS_INFINITE]], %[[RHS_IS_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF:.*]] = select i1 %[[LHS_REAL_INFINITE]], bfloat 0xR3F80, bfloat 0xR0000
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN:.*]] = call bfloat @llvm.copysign.bf16(bfloat %[[LHS_REAL_IS_INF]], bfloat %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF:.*]] = select i1 %[[LHS_IMAG_INFINITE]], bfloat 0xR3F80, bfloat 0xR0000
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN:.*]] = call bfloat @llvm.copysign.bf16(bfloat %[[LHS_IMAG_IS_INF]], bfloat %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract bfloat %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract bfloat %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_1:.*]] = fadd contract bfloat %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_3:.*]] = fmul contract bfloat %[[INF_MULTIPLICATOR_1]], 0xR7F80
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract bfloat %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract bfloat %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_2:.*]] = fsub contract bfloat %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_IMAG_3:.*]] = fmul contract bfloat %[[INF_MULTIPLICATOR_2]], 0xR7F80
|
||||
|
||||
! Case 3. Finite numerator, infinite denominator.
|
||||
! IMPRVD: %[[LHS_REAL_FINITE:.*]] = fcmp one bfloat %[[LHS_REAL_ABS]], 0xR7F80
|
||||
! IMPRVD: %[[LHS_IMAG_FINITE:.*]] = fcmp one bfloat %[[LHS_IMAG_ABS]], 0xR7F80
|
||||
! IMPRVD: %[[LHS_IS_FINITE:.*]] = and i1 %[[LHS_REAL_FINITE]], %[[LHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_INFINITE:.*]] = fcmp oeq bfloat %[[RHS_REAL_ABS]], 0xR7F80
|
||||
! IMPRVD: %[[RHS_IMAG_INFINITE:.*]] = fcmp oeq bfloat %[[RHS_IMAG_ABS]], 0xR7F80
|
||||
! IMPRVD: %[[RHS_IS_INFINITE:.*]] = or i1 %[[RHS_REAL_INFINITE]], %[[RHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[FINITE_NUM_INFINITE_DENOM:.*]] = and i1 %[[LHS_IS_FINITE]], %[[RHS_IS_INFINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF:.*]] = select i1 %[[RHS_REAL_INFINITE]], bfloat 0xR3F80, bfloat 0xR0000
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN:.*]] = call bfloat @llvm.copysign.bf16(bfloat %[[RHS_REAL_IS_INF]], bfloat %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF:.*]] = select i1 %[[RHS_IMAG_INFINITE]], bfloat 0xR3F80, bfloat 0xR0000
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN:.*]] = call bfloat @llvm.copysign.bf16(bfloat %[[RHS_IMAG_IS_INF]], bfloat %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract bfloat %[[LHS_REAL]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract bfloat %[[LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_1:.*]] = fadd contract bfloat %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_4:.*]] = fmul contract bfloat %[[ZERO_MULTIPLICATOR_1]], 0xR0000
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract bfloat %[[LHS_IMAG]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract bfloat %[[LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_2:.*]] = fsub contract bfloat %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_4:.*]] = fmul contract bfloat %[[ZERO_MULTIPLICATOR_2]], 0xR0000
|
||||
|
||||
! IMPRVD: %[[REAL_ABS_SMALLER_THAN_IMAG_ABS:.*]] = fcmp olt bfloat %[[RHS_REAL_ABS]], %[[RHS_IMAG_ABS]]
|
||||
! IMPRVD: %[[RESULT_REAL:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], bfloat %[[RESULT_REAL_1]], bfloat %[[RESULT_REAL_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], bfloat %[[RESULT_IMAG_1]], bfloat %[[RESULT_IMAG_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], bfloat %[[RESULT_REAL_4]], bfloat %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], bfloat %[[RESULT_IMAG_4]], bfloat %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], bfloat %[[RESULT_REAL_3]], bfloat %[[RESULT_REAL_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], bfloat %[[RESULT_IMAG_3]], bfloat %[[RESULT_IMAG_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], bfloat %[[INFINITY_RESULT_REAL]], bfloat %[[RESULT_REAL_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], bfloat %[[INFINITY_RESULT_IMAG]], bfloat %[[RESULT_IMAG_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_IS_NAN:.*]] = fcmp uno bfloat %[[RESULT_REAL]], 0xR0000
|
||||
! IMPRVD: %[[RESULT_IMAG_IS_NAN:.*]] = fcmp uno bfloat %[[RESULT_IMAG]], 0xR0000
|
||||
! IMPRVD: %[[RESULT_IS_NAN:.*]] = and i1 %[[RESULT_REAL_IS_NAN]], %[[RESULT_IMAG_IS_NAN]]
|
||||
! IMPRVD: %[[RESULT_REAL_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], bfloat %[[RESULT_REAL_SPECIAL_CASE_1]], bfloat %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], bfloat %[[RESULT_IMAG_SPECIAL_CASE_1]], bfloat %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_1:.*]] = insertvalue { bfloat, bfloat } poison, bfloat %[[RESULT_REAL_WITH_SPECIAL_CASES]], 0
|
||||
! IMPRVD: %[[RESULT_2:.*]] = insertvalue { bfloat, bfloat } %[[RESULT_1]], bfloat %[[RESULT_IMAG_WITH_SPECIAL_CASES]], 1
|
||||
! IMPRVD: store { bfloat, bfloat } %[[RESULT_2]], ptr %[[RET]], align 2
|
||||
|
||||
! BASIC-DAG: %[[RHS_REAL_SQ:.*]] = fmul contract bfloat %[[RHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[RHS_IMAG_SQ:.*]] = fmul contract bfloat %[[RHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[SQ_NORM:.*]] = fadd contract bfloat %[[RHS_REAL_SQ]], %[[RHS_IMAG_SQ]]
|
||||
! BASIC-DAG: %[[REAL_TMP_0:.*]] = fmul contract bfloat %[[LHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[REAL_TMP_1:.*]] = fmul contract bfloat %[[LHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[REAL_TMP_2:.*]] = fadd contract bfloat %[[REAL_TMP_0]], %[[REAL_TMP_1]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_0:.*]] = fmul contract bfloat %[[LHS_IMAG]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_1:.*]] = fmul contract bfloat %[[LHS_REAL]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[IMAG_TMP_2:.*]] = fsub contract bfloat %[[IMAG_TMP_0]], %[[IMAG_TMP_1]]
|
||||
! BASIC: %[[REAL:.*]] = fdiv contract bfloat %[[REAL_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[IMAG:.*]] = fdiv contract bfloat %[[IMAG_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[RESULT_1:.*]] = insertvalue { bfloat, bfloat } poison, bfloat %[[REAL]], 0
|
||||
! BASIC: %[[RESULT_2:.*]] = insertvalue { bfloat, bfloat } %[[RESULT_1]], bfloat %[[IMAG]], 1
|
||||
! BASIC: store { bfloat, bfloat } %[[RESULT_2]], ptr %[[RET]], align 2
|
||||
|
||||
! CHECK: ret void
|
||||
subroutine div_test_bfloat(a,b,c)
|
||||
complex(kind=3) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_bfloat
|
||||
|
||||
|
||||
! CHECK-LABEL: @div_test_single
|
||||
! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]])
|
||||
! CHECK: %[[LOAD_LHS:.*]] = load { float, float }, ptr %[[LHS]], align 4
|
||||
! CHECK: %[[LOAD_RHS:.*]] = load { float, float }, ptr %[[RHS]], align 4
|
||||
! CHECK: %[[LHS_REAL:.*]] = extractvalue { float, float } %[[LOAD_LHS]], 0
|
||||
! CHECK: %[[LHS_IMAG:.*]] = extractvalue { float, float } %[[LOAD_LHS]], 1
|
||||
! CHECK: %[[RHS_REAL:.*]] = extractvalue { float, float } %[[LOAD_RHS]], 0
|
||||
! CHECK: %[[RHS_IMAG:.*]] = extractvalue { float, float } %[[LOAD_RHS]], 1
|
||||
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_RATIO:.*]] = fdiv contract float %[[RHS_REAL]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract float %[[RHS_REAL_IMAG_RATIO]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_DENOM:.*]] = fadd contract float %[[RHS_IMAG]], %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract float %[[LHS_REAL]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_1:.*]] = fadd contract float %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_1:.*]] = fdiv contract float %[[REAL_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract float %[[LHS_IMAG]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_1:.*]] = fsub contract float %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_1:.*]] = fdiv contract float %[[IMAG_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_RATIO:.*]] = fdiv contract float %[[RHS_IMAG]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract float %[[RHS_IMAG_REAL_RATIO]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_DENOM:.*]] = fadd contract float %[[RHS_REAL]], %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract float %[[LHS_IMAG]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_2:.*]] = fadd contract float %[[LHS_REAL]], %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_REAL_2:.*]] = fdiv contract float %[[REAL_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract float %[[LHS_REAL]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_2:.*]] = fsub contract float %[[LHS_IMAG]], %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_IMAG_2:.*]] = fdiv contract float %[[IMAG_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
|
||||
! Case 1. Zero denominator, numerator contains at most one NaN value.
|
||||
! IMPRVD: %[[RHS_REAL_ABS:.*]] = call contract float @llvm.fabs.f32(float %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_REAL_ABS_IS_ZERO:.*]] = fcmp oeq float %[[RHS_REAL_ABS]], 0.000000e+00
|
||||
! IMPRVD: %[[RHS_IMAG_ABS:.*]] = call contract float @llvm.fabs.f32(float %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_IMAG_ABS_IS_ZERO:.*]] = fcmp oeq float %[[RHS_IMAG_ABS]], 0.000000e+00
|
||||
! IMPRVD: %[[LHS_REAL_IS_NOT_NAN:.*]] = fcmp ord float %[[LHS_REAL]], 0.000000e+00
|
||||
! IMPRVD: %[[LHS_IMAG_IS_NOT_NAN:.*]] = fcmp ord float %[[LHS_IMAG]], 0.000000e+00
|
||||
! IMPRVD: %[[LHS_CONTAINS_NOT_NAN_VALUE:.*]] = or i1 %[[LHS_REAL_IS_NOT_NAN]], %[[LHS_IMAG_IS_NOT_NAN]]
|
||||
! IMPRVD: %[[RHS_IS_ZERO:.*]] = and i1 %[[RHS_REAL_ABS_IS_ZERO]], %[[RHS_IMAG_ABS_IS_ZERO]]
|
||||
! IMPRVD: %[[RESULT_IS_INFINITY:.*]] = and i1 %[[LHS_CONTAINS_NOT_NAN_VALUE]], %[[RHS_IS_ZERO]]
|
||||
! IMPRVD: %[[INF_WITH_SIGN_OF_RHS_REAL:.*]] = call float @llvm.copysign.f32(float 0x7FF0000000000000, float %[[RHS_REAL]])
|
||||
! IMPRVD: %[[INFINITY_RESULT_REAL:.*]] = fmul contract float %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[INFINITY_RESULT_IMAG:.*]] = fmul contract float %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_IMAG]]
|
||||
|
||||
! Case 2. Infinite numerator, finite denominator.
|
||||
! IMPRVD: %[[RHS_REAL_FINITE:.*]] = fcmp one float %[[RHS_REAL_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_FINITE:.*]] = fcmp one float %[[RHS_IMAG_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[RHS_IS_FINITE:.*]] = and i1 %[[RHS_REAL_FINITE]], %[[RHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_ABS:.*]] = call contract float @llvm.fabs.f32(float %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_REAL_INFINITE:.*]] = fcmp oeq float %[[LHS_REAL_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_ABS:.*]] = call contract float @llvm.fabs.f32(float %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_IMAG_INFINITE:.*]] = fcmp oeq float %[[LHS_IMAG_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_IS_INFINITE:.*]] = or i1 %[[LHS_REAL_INFINITE]], %[[LHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[INF_NUM_FINITE_DENOM:.*]] = and i1 %[[LHS_IS_INFINITE]], %[[RHS_IS_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF:.*]] = select i1 %[[LHS_REAL_INFINITE]], float 1.000000e+00, float 0.000000e+00
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN:.*]] = call float @llvm.copysign.f32(float %[[LHS_REAL_IS_INF]], float %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF:.*]] = select i1 %[[LHS_IMAG_INFINITE]], float 1.000000e+00, float 0.000000e+00
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN:.*]] = call float @llvm.copysign.f32(float %[[LHS_IMAG_IS_INF]], float %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract float %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract float %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_1:.*]] = fadd contract float %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_3:.*]] = fmul contract float %[[INF_MULTIPLICATOR_1]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract float %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract float %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_2:.*]] = fsub contract float %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_IMAG_3:.*]] = fmul contract float %[[INF_MULTIPLICATOR_2]], 0x7FF0000000000000
|
||||
|
||||
! Case 3. Finite numerator, infinite denominator.
|
||||
! IMPRVD: %[[LHS_REAL_FINITE:.*]] = fcmp one float %[[LHS_REAL_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_FINITE:.*]] = fcmp one float %[[LHS_IMAG_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_IS_FINITE:.*]] = and i1 %[[LHS_REAL_FINITE]], %[[LHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_INFINITE:.*]] = fcmp oeq float %[[RHS_REAL_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_INFINITE:.*]] = fcmp oeq float %[[RHS_IMAG_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[RHS_IS_INFINITE:.*]] = or i1 %[[RHS_REAL_INFINITE]], %[[RHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[FINITE_NUM_INFINITE_DENOM:.*]] = and i1 %[[LHS_IS_FINITE]], %[[RHS_IS_INFINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF:.*]] = select i1 %[[RHS_REAL_INFINITE]], float 1.000000e+00, float 0.000000e+00
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN:.*]] = call float @llvm.copysign.f32(float %[[RHS_REAL_IS_INF]], float %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF:.*]] = select i1 %[[RHS_IMAG_INFINITE]], float 1.000000e+00, float 0.000000e+00
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN:.*]] = call float @llvm.copysign.f32(float %[[RHS_IMAG_IS_INF]], float %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract float %[[LHS_REAL]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract float %[[LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_1:.*]] = fadd contract float %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_4:.*]] = fmul contract float %[[ZERO_MULTIPLICATOR_1]], 0.000000e+00
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract float %[[LHS_IMAG]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract float %[[LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_2:.*]] = fsub contract float %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_4:.*]] = fmul contract float %[[ZERO_MULTIPLICATOR_2]], 0.000000e+00
|
||||
|
||||
! IMPRVD: %[[REAL_ABS_SMALLER_THAN_IMAG_ABS:.*]] = fcmp olt float %[[RHS_REAL_ABS]], %[[RHS_IMAG_ABS]]
|
||||
! IMPRVD: %[[RESULT_REAL:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], float %[[RESULT_REAL_1]], float %[[RESULT_REAL_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], float %[[RESULT_IMAG_1]], float %[[RESULT_IMAG_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], float %[[RESULT_REAL_4]], float %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], float %[[RESULT_IMAG_4]], float %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], float %[[RESULT_REAL_3]], float %[[RESULT_REAL_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], float %[[RESULT_IMAG_3]], float %[[RESULT_IMAG_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], float %[[INFINITY_RESULT_REAL]], float %[[RESULT_REAL_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], float %[[INFINITY_RESULT_IMAG]], float %[[RESULT_IMAG_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_IS_NAN:.*]] = fcmp uno float %[[RESULT_REAL]], 0.000000e+00
|
||||
! IMPRVD: %[[RESULT_IMAG_IS_NAN:.*]] = fcmp uno float %[[RESULT_IMAG]], 0.000000e+00
|
||||
! IMPRVD: %[[RESULT_IS_NAN:.*]] = and i1 %[[RESULT_REAL_IS_NAN]], %[[RESULT_IMAG_IS_NAN]]
|
||||
! IMPRVD: %[[RESULT_REAL_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], float %[[RESULT_REAL_SPECIAL_CASE_1]], float %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], float %[[RESULT_IMAG_SPECIAL_CASE_1]], float %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_1:.*]] = insertvalue { float, float } poison, float %[[RESULT_REAL_WITH_SPECIAL_CASES]], 0
|
||||
! IMPRVD: %[[RESULT_2:.*]] = insertvalue { float, float } %[[RESULT_1]], float %[[RESULT_IMAG_WITH_SPECIAL_CASES]], 1
|
||||
! IMPRVD: store { float, float } %[[RESULT_2]], ptr %[[RET]], align 4
|
||||
|
||||
! BASIC-DAG: %[[RHS_REAL_SQ:.*]] = fmul contract float %[[RHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[RHS_IMAG_SQ:.*]] = fmul contract float %[[RHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[SQ_NORM:.*]] = fadd contract float %[[RHS_REAL_SQ]], %[[RHS_IMAG_SQ]]
|
||||
! BASIC-DAG: %[[REAL_TMP_0:.*]] = fmul contract float %[[LHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[REAL_TMP_1:.*]] = fmul contract float %[[LHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[REAL_TMP_2:.*]] = fadd contract float %[[REAL_TMP_0]], %[[REAL_TMP_1]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_0:.*]] = fmul contract float %[[LHS_IMAG]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_1:.*]] = fmul contract float %[[LHS_REAL]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[IMAG_TMP_2:.*]] = fsub contract float %[[IMAG_TMP_0]], %[[IMAG_TMP_1]]
|
||||
! BASIC: %[[REAL:.*]] = fdiv contract float %[[REAL_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[IMAG:.*]] = fdiv contract float %[[IMAG_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[RESULT_1:.*]] = insertvalue { float, float } poison, float %[[REAL]], 0
|
||||
! BASIC: %[[RESULT_2:.*]] = insertvalue { float, float } %[[RESULT_1]], float %[[IMAG]], 1
|
||||
! BASIC: store { float, float } %[[RESULT_2]], ptr %[[RET]], align 4
|
||||
|
||||
! CHECK: ret void
|
||||
subroutine div_test_single(a,b,c)
|
||||
complex(kind=4) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_single
|
||||
|
||||
|
||||
! CHECK-LABEL: @div_test_double
|
||||
! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]])
|
||||
! CHECK: %[[LOAD_LHS:.*]] = load { double, double }, ptr %[[LHS]], align 8
|
||||
! CHECK: %[[LOAD_RHS:.*]] = load { double, double }, ptr %[[RHS]], align 8
|
||||
! CHECK: %[[LHS_REAL:.*]] = extractvalue { double, double } %[[LOAD_LHS]], 0
|
||||
! CHECK: %[[LHS_IMAG:.*]] = extractvalue { double, double } %[[LOAD_LHS]], 1
|
||||
! CHECK: %[[RHS_REAL:.*]] = extractvalue { double, double } %[[LOAD_RHS]], 0
|
||||
! CHECK: %[[RHS_IMAG:.*]] = extractvalue { double, double } %[[LOAD_RHS]], 1
|
||||
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_RATIO:.*]] = fdiv contract double %[[RHS_REAL]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract double %[[RHS_REAL_IMAG_RATIO]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_REAL_IMAG_DENOM:.*]] = fadd contract double %[[RHS_IMAG]], %[[RHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract double %[[LHS_REAL]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_1:.*]] = fadd contract double %[[LHS_REAL_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_1:.*]] = fdiv contract double %[[REAL_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO:.*]] = fmul contract double %[[LHS_IMAG]], %[[RHS_REAL_IMAG_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_1:.*]] = fsub contract double %[[LHS_IMAG_TIMES_RHS_REAL_IMAG_RATIO]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_1:.*]] = fdiv contract double %[[IMAG_NUMERATOR_1]], %[[RHS_REAL_IMAG_DENOM]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_RATIO:.*]] = fdiv contract double %[[RHS_IMAG]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract double %[[RHS_IMAG_REAL_RATIO]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[RHS_IMAG_REAL_DENOM:.*]] = fadd contract double %[[RHS_REAL]], %[[RHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract double %[[LHS_IMAG]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[REAL_NUMERATOR_2:.*]] = fadd contract double %[[LHS_REAL]], %[[LHS_IMAG_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_REAL_2:.*]] = fdiv contract double %[[REAL_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
! IMPRVD: %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO:.*]] = fmul contract double %[[LHS_REAL]], %[[RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[IMAG_NUMERATOR_2:.*]] = fsub contract double %[[LHS_IMAG]], %[[LHS_REAL_TIMES_RHS_IMAG_REAL_RATIO]]
|
||||
! IMPRVD: %[[RESULT_IMAG_2:.*]] = fdiv contract double %[[IMAG_NUMERATOR_2]], %[[RHS_IMAG_REAL_DENOM]]
|
||||
|
||||
! Case 1. Zero denominator, numerator contains at most one NaN value.
|
||||
! IMPRVD: %[[RHS_REAL_ABS:.*]] = call contract double @llvm.fabs.f64(double %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_REAL_ABS_IS_ZERO:.*]] = fcmp oeq double %[[RHS_REAL_ABS]], 0.000000e+00
|
||||
! IMPRVD: %[[RHS_IMAG_ABS:.*]] = call contract double @llvm.fabs.f64(double %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_IMAG_ABS_IS_ZERO:.*]] = fcmp oeq double %[[RHS_IMAG_ABS]], 0.000000e+00
|
||||
! IMPRVD: %[[LHS_REAL_IS_NOT_NAN:.*]] = fcmp ord double %[[LHS_REAL]], 0.000000e+00
|
||||
! IMPRVD: %[[LHS_IMAG_IS_NOT_NAN:.*]] = fcmp ord double %[[LHS_IMAG]], 0.000000e+00
|
||||
! IMPRVD: %[[LHS_CONTAINS_NOT_NAN_VALUE:.*]] = or i1 %[[LHS_REAL_IS_NOT_NAN]], %[[LHS_IMAG_IS_NOT_NAN]]
|
||||
! IMPRVD: %[[RHS_IS_ZERO:.*]] = and i1 %[[RHS_REAL_ABS_IS_ZERO]], %[[RHS_IMAG_ABS_IS_ZERO]]
|
||||
! IMPRVD: %[[RESULT_IS_INFINITY:.*]] = and i1 %[[LHS_CONTAINS_NOT_NAN_VALUE]], %[[RHS_IS_ZERO]]
|
||||
! IMPRVD: %[[INF_WITH_SIGN_OF_RHS_REAL:.*]] = call double @llvm.copysign.f64(double 0x7FF0000000000000, double %[[RHS_REAL]])
|
||||
! IMPRVD: %[[INFINITY_RESULT_REAL:.*]] = fmul contract double %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_REAL]]
|
||||
! IMPRVD: %[[INFINITY_RESULT_IMAG:.*]] = fmul contract double %[[INF_WITH_SIGN_OF_RHS_REAL]], %[[LHS_IMAG]]
|
||||
|
||||
! Case 2. Infinite numerator, finite denominator.
|
||||
! IMPRVD: %[[RHS_REAL_FINITE:.*]] = fcmp one double %[[RHS_REAL_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_FINITE:.*]] = fcmp one double %[[RHS_IMAG_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[RHS_IS_FINITE:.*]] = and i1 %[[RHS_REAL_FINITE]], %[[RHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_ABS:.*]] = call contract double @llvm.fabs.f64(double %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_REAL_INFINITE:.*]] = fcmp oeq double %[[LHS_REAL_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_ABS:.*]] = call contract double @llvm.fabs.f64(double %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_IMAG_INFINITE:.*]] = fcmp oeq double %[[LHS_IMAG_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_IS_INFINITE:.*]] = or i1 %[[LHS_REAL_INFINITE]], %[[LHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[INF_NUM_FINITE_DENOM:.*]] = and i1 %[[LHS_IS_INFINITE]], %[[RHS_IS_FINITE]]
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF:.*]] = select i1 %[[LHS_REAL_INFINITE]], double 1.000000e+00, double 0.000000e+00
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN:.*]] = call double @llvm.copysign.f64(double %[[LHS_REAL_IS_INF]], double %[[LHS_REAL]])
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF:.*]] = select i1 %[[LHS_IMAG_INFINITE]], double 1.000000e+00, double 0.000000e+00
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN:.*]] = call double @llvm.copysign.f64(double %[[LHS_IMAG_IS_INF]], double %[[LHS_IMAG]])
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract double %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract double %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_1:.*]] = fadd contract double %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_3:.*]] = fmul contract double %[[INF_MULTIPLICATOR_1]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG:.*]] = fmul contract double %[[LHS_REAL_IS_INF_WITH_SIGN]], %[[RHS_IMAG]]
|
||||
! IMPRVD: %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL:.*]] = fmul contract double %[[LHS_IMAG_IS_INF_WITH_SIGN]], %[[RHS_REAL]]
|
||||
! IMPRVD: %[[INF_MULTIPLICATOR_2:.*]] = fsub contract double %[[LHS_IMAG_IS_INF_WITH_SIGN_TIMES_RHS_REAL]], %[[LHS_REAL_IS_INF_WITH_SIGN_TIMES_RHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_IMAG_3:.*]] = fmul contract double %[[INF_MULTIPLICATOR_2]], 0x7FF0000000000000
|
||||
|
||||
! Case 3. Finite numerator, infinite denominator.
|
||||
! IMPRVD: %[[LHS_REAL_FINITE:.*]] = fcmp one double %[[LHS_REAL_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_IMAG_FINITE:.*]] = fcmp one double %[[LHS_IMAG_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[LHS_IS_FINITE:.*]] = and i1 %[[LHS_REAL_FINITE]], %[[LHS_IMAG_FINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_INFINITE:.*]] = fcmp oeq double %[[RHS_REAL_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[RHS_IMAG_INFINITE:.*]] = fcmp oeq double %[[RHS_IMAG_ABS]], 0x7FF0000000000000
|
||||
! IMPRVD: %[[RHS_IS_INFINITE:.*]] = or i1 %[[RHS_REAL_INFINITE]], %[[RHS_IMAG_INFINITE]]
|
||||
! IMPRVD: %[[FINITE_NUM_INFINITE_DENOM:.*]] = and i1 %[[LHS_IS_FINITE]], %[[RHS_IS_INFINITE]]
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF:.*]] = select i1 %[[RHS_REAL_INFINITE]], double 1.000000e+00, double 0.000000e+00
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN:.*]] = call double @llvm.copysign.f64(double %[[RHS_REAL_IS_INF]], double %[[RHS_REAL]])
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF:.*]] = select i1 %[[RHS_IMAG_INFINITE]], double 1.000000e+00, double 0.000000e+00
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN:.*]] = call double @llvm.copysign.f64(double %[[RHS_IMAG_IS_INF]], double %[[RHS_IMAG]])
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract double %[[LHS_REAL]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract double %[[LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_1:.*]] = fadd contract double %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_4:.*]] = fmul contract double %[[ZERO_MULTIPLICATOR_1]], 0.000000e+00
|
||||
! IMPRVD: %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG:.*]] = fmul contract double %[[LHS_IMAG]], %[[RHS_REAL_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL:.*]] = fmul contract double %[[LHS_REAL]], %[[RHS_IMAG_IS_INF_WITH_SIGN]]
|
||||
! IMPRVD: %[[ZERO_MULTIPLICATOR_2:.*]] = fsub contract double %[[RHS_REAL_IS_INF_WITH_SIGN_TIMES_LHS_IMAG]], %[[RHS_IMAG_IS_INF_WITH_SIGN_TIMES_LHS_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_4:.*]] = fmul contract double %[[ZERO_MULTIPLICATOR_2]], 0.000000e+00
|
||||
|
||||
! IMPRVD: %[[REAL_ABS_SMALLER_THAN_IMAG_ABS:.*]] = fcmp olt double %[[RHS_REAL_ABS]], %[[RHS_IMAG_ABS]]
|
||||
! IMPRVD: %[[RESULT_REAL:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], double %[[RESULT_REAL_1]], double %[[RESULT_REAL_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG:.*]] = select i1 %[[REAL_ABS_SMALLER_THAN_IMAG_ABS]], double %[[RESULT_IMAG_1]], double %[[RESULT_IMAG_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], double %[[RESULT_REAL_4]], double %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_3:.*]] = select i1 %[[FINITE_NUM_INFINITE_DENOM]], double %[[RESULT_IMAG_4]], double %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], double %[[RESULT_REAL_3]], double %[[RESULT_REAL_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_2:.*]] = select i1 %[[INF_NUM_FINITE_DENOM]], double %[[RESULT_IMAG_3]], double %[[RESULT_IMAG_SPECIAL_CASE_3]]
|
||||
! IMPRVD: %[[RESULT_REAL_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], double %[[INFINITY_RESULT_REAL]], double %[[RESULT_REAL_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_IMAG_SPECIAL_CASE_1:.*]] = select i1 %[[RESULT_IS_INFINITY]], double %[[INFINITY_RESULT_IMAG]], double %[[RESULT_IMAG_SPECIAL_CASE_2]]
|
||||
! IMPRVD: %[[RESULT_REAL_IS_NAN:.*]] = fcmp uno double %[[RESULT_REAL]], 0.000000e+00
|
||||
! IMPRVD: %[[RESULT_IMAG_IS_NAN:.*]] = fcmp uno double %[[RESULT_IMAG]], 0.000000e+00
|
||||
! IMPRVD: %[[RESULT_IS_NAN:.*]] = and i1 %[[RESULT_REAL_IS_NAN]], %[[RESULT_IMAG_IS_NAN]]
|
||||
! IMPRVD: %[[RESULT_REAL_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], double %[[RESULT_REAL_SPECIAL_CASE_1]], double %[[RESULT_REAL]]
|
||||
! IMPRVD: %[[RESULT_IMAG_WITH_SPECIAL_CASES:.*]] = select i1 %[[RESULT_IS_NAN]], double %[[RESULT_IMAG_SPECIAL_CASE_1]], double %[[RESULT_IMAG]]
|
||||
! IMPRVD: %[[RESULT_1:.*]] = insertvalue { double, double } poison, double %[[RESULT_REAL_WITH_SPECIAL_CASES]], 0
|
||||
! IMPRVD: %[[RESULT_2:.*]] = insertvalue { double, double } %[[RESULT_1]], double %[[RESULT_IMAG_WITH_SPECIAL_CASES]], 1
|
||||
! IMPRVD: store { double, double } %[[RESULT_2]], ptr %[[RET]], align 8
|
||||
|
||||
! BASIC-DAG: %[[RHS_REAL_SQ:.*]] = fmul contract double %[[RHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[RHS_IMAG_SQ:.*]] = fmul contract double %[[RHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[SQ_NORM:.*]] = fadd contract double %[[RHS_REAL_SQ]], %[[RHS_IMAG_SQ]]
|
||||
! BASIC-DAG: %[[REAL_TMP_0:.*]] = fmul contract double %[[LHS_REAL]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[REAL_TMP_1:.*]] = fmul contract double %[[LHS_IMAG]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[REAL_TMP_2:.*]] = fadd contract double %[[REAL_TMP_0]], %[[REAL_TMP_1]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_0:.*]] = fmul contract double %[[LHS_IMAG]], %[[RHS_REAL]]
|
||||
! BASIC-DAG: %[[IMAG_TMP_1:.*]] = fmul contract double %[[LHS_REAL]], %[[RHS_IMAG]]
|
||||
! BASIC: %[[IMAG_TMP_2:.*]] = fsub contract double %[[IMAG_TMP_0]], %[[IMAG_TMP_1]]
|
||||
! BASIC: %[[REAL:.*]] = fdiv contract double %[[REAL_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[IMAG:.*]] = fdiv contract double %[[IMAG_TMP_2]], %[[SQ_NORM]]
|
||||
! BASIC: %[[RESULT_1:.*]] = insertvalue { double, double } poison, double %[[REAL]], 0
|
||||
! BASIC: %[[RESULT_2:.*]] = insertvalue { double, double } %[[RESULT_1]], double %[[IMAG]], 1
|
||||
! BASIC: store { double, double } %[[RESULT_2]], ptr %[[RET]], align 8
|
||||
|
||||
! CHECK: ret void
|
||||
subroutine div_test_double(a,b,c)
|
||||
complex(kind=8) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_double
|
||||
34
flang/test/Lower/HLFIR/complex-div-to-hlfir-kind10.f90
Normal file
34
flang/test/Lower/HLFIR/complex-div-to-hlfir-kind10.f90
Normal file
@@ -0,0 +1,34 @@
|
||||
! Test lowering of complex division according to options
|
||||
|
||||
! REQUIRES: target=x86_64{{.*}}
|
||||
! RUN: bbc -complex-range=full -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,FULL
|
||||
! RUN: bbc -complex-range=improved -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: bbc -complex-range=basic -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
! RUN: %flang_fc1 -complex-range=full -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,FULL
|
||||
! RUN: %flang_fc1 -complex-range=improved -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: %flang_fc1 -complex-range=basic -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
|
||||
! CHECK-LABEL: @_QPdiv_test_extended
|
||||
! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f80>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f80>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f80>> {{.*}})
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_extendedEa"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>)
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_extendedEb"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>)
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_extendedEc"} : (!fir.ref<complex<f80>>, !fir.dscope) -> (!fir.ref<complex<f80>>, !fir.ref<complex<f80>>)
|
||||
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f80>>
|
||||
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f80>>
|
||||
|
||||
! FULL: %[[VAL_9:.*]] = fir.extract_value %[[VAL_7]], [0 : index] : (complex<f80>) -> f80
|
||||
! FULL: %[[VAL_10:.*]] = fir.extract_value %[[VAL_7]], [1 : index] : (complex<f80>) -> f80
|
||||
! FULL: %[[VAL_11:.*]] = fir.extract_value %[[VAL_8]], [0 : index] : (complex<f80>) -> f80
|
||||
! FULL: %[[VAL_12:.*]] = fir.extract_value %[[VAL_8]], [1 : index] : (complex<f80>) -> f80
|
||||
! FULL: %[[VAL_RET:.*]] = fir.call @__divxc3(%[[VAL_9]], %[[VAL_10]], %[[VAL_11]], %[[VAL_12]]) fastmath<contract> : (f80, f80, f80, f80) -> complex<f80>
|
||||
|
||||
! IMPRVD: %[[VAL_RET:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f80>
|
||||
! BASIC: %[[VAL_RET:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f80>
|
||||
|
||||
! CHECK: hlfir.assign %[[VAL_RET]] to %[[VAL_4]]#0 : complex<f80>, !fir.ref<complex<f80>>
|
||||
! CHECK: return
|
||||
subroutine div_test_extended(a,b,c)
|
||||
complex(kind=10) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_extended
|
||||
35
flang/test/Lower/HLFIR/complex-div-to-hlfir-kind16.f90
Normal file
35
flang/test/Lower/HLFIR/complex-div-to-hlfir-kind16.f90
Normal file
@@ -0,0 +1,35 @@
|
||||
! Test lowering of complex division according to options
|
||||
|
||||
! REQUIRES: flang-supports-f128-math
|
||||
! RUN: bbc -complex-range=full -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,FULL
|
||||
! RUN: bbc -complex-range=improved -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: bbc -complex-range=basic -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
! RUN: %flang_fc1 -complex-range=full -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,FULL
|
||||
! RUN: %flang_fc1 -complex-range=improved -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: %flang_fc1 -complex-range=basic -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
|
||||
|
||||
! CHECK-LABEL: @_QPdiv_test_quad
|
||||
! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f128>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f128>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f128>> {{.*}})
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_quadEa"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>)
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_quadEb"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>)
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_quadEc"} : (!fir.ref<complex<f128>>, !fir.dscope) -> (!fir.ref<complex<f128>>, !fir.ref<complex<f128>>)
|
||||
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f128>>
|
||||
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f128>>
|
||||
|
||||
! FULL: %[[VAL_9:.*]] = fir.extract_value %[[VAL_7]], [0 : index] : (complex<f128>) -> f128
|
||||
! FULL: %[[VAL_10:.*]] = fir.extract_value %[[VAL_7]], [1 : index] : (complex<f128>) -> f128
|
||||
! FULL: %[[VAL_11:.*]] = fir.extract_value %[[VAL_8]], [0 : index] : (complex<f128>) -> f128
|
||||
! FULL: %[[VAL_12:.*]] = fir.extract_value %[[VAL_8]], [1 : index] : (complex<f128>) -> f128
|
||||
! FULL: %[[VAL_RET:.*]] = fir.call @__divtc3(%[[VAL_9]], %[[VAL_10]], %[[VAL_11]], %[[VAL_12]]) fastmath<contract> : (f128, f128, f128, f128) -> complex<f128>
|
||||
|
||||
! IMPRVD: %[[VAL_RET:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f128>
|
||||
! BASIC: %[[VAL_RET:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f128>
|
||||
|
||||
! CHECK: hlfir.assign %[[VAL_RET]] to %[[VAL_4]]#0 : complex<f128>, !fir.ref<complex<f128>>
|
||||
! CHECK: return
|
||||
subroutine div_test_quad(a,b,c)
|
||||
complex(kind=16) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_quad
|
||||
94
flang/test/Lower/HLFIR/complex-div-to-hlfir.f90
Normal file
94
flang/test/Lower/HLFIR/complex-div-to-hlfir.f90
Normal file
@@ -0,0 +1,94 @@
|
||||
! Test lowering of complex division according to options
|
||||
|
||||
! RUN: bbc -complex-range=full -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,FULL
|
||||
! RUN: bbc -complex-range=improved -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: bbc -complex-range=basic -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
! RUN: %flang_fc1 -complex-range=full -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,FULL
|
||||
! RUN: %flang_fc1 -complex-range=improved -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD
|
||||
! RUN: %flang_fc1 -complex-range=basic -emit-hlfir %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC
|
||||
|
||||
|
||||
! CHECK-LABEL: @_QPdiv_test_half
|
||||
! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f16>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f16>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f16>> {{.*}})
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_halfEa"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>)
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_halfEb"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>)
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_halfEc"} : (!fir.ref<complex<f16>>, !fir.dscope) -> (!fir.ref<complex<f16>>, !fir.ref<complex<f16>>)
|
||||
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f16>>
|
||||
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f16>>
|
||||
! CHECK: %[[VAL_9:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f16>
|
||||
! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : complex<f16>, !fir.ref<complex<f16>>
|
||||
! CHECK: return
|
||||
subroutine div_test_half(a,b,c)
|
||||
complex(kind=2) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_half
|
||||
|
||||
|
||||
! CHECK-LABEL: @_QPdiv_test_bfloat
|
||||
! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<bf16>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<bf16>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<bf16>> {{.*}})
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_bfloatEa"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>)
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_bfloatEb"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>)
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_bfloatEc"} : (!fir.ref<complex<bf16>>, !fir.dscope) -> (!fir.ref<complex<bf16>>, !fir.ref<complex<bf16>>)
|
||||
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<bf16>>
|
||||
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<bf16>>
|
||||
! CHECK: %[[VAL_9:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<bf16>
|
||||
! CHECK: hlfir.assign %[[VAL_9]] to %[[VAL_4]]#0 : complex<bf16>, !fir.ref<complex<bf16>>
|
||||
! CHECK: return
|
||||
subroutine div_test_bfloat(a,b,c)
|
||||
complex(kind=3) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_bfloat
|
||||
|
||||
|
||||
! CHECK-LABEL: @_QPdiv_test_single
|
||||
! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f32>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f32>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f32>> {{.*}})
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_singleEa"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>)
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_singleEb"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>)
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_singleEc"} : (!fir.ref<complex<f32>>, !fir.dscope) -> (!fir.ref<complex<f32>>, !fir.ref<complex<f32>>)
|
||||
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f32>>
|
||||
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f32>>
|
||||
|
||||
! FULL: %[[VAL_9:.*]] = fir.extract_value %[[VAL_7]], [0 : index] : (complex<f32>) -> f32
|
||||
! FULL: %[[VAL_10:.*]] = fir.extract_value %[[VAL_7]], [1 : index] : (complex<f32>) -> f32
|
||||
! FULL: %[[VAL_11:.*]] = fir.extract_value %[[VAL_8]], [0 : index] : (complex<f32>) -> f32
|
||||
! FULL: %[[VAL_12:.*]] = fir.extract_value %[[VAL_8]], [1 : index] : (complex<f32>) -> f32
|
||||
! FULL: %[[VAL_RET:.*]] = fir.call @__divsc3(%[[VAL_9]], %[[VAL_10]], %[[VAL_11]], %[[VAL_12]]) fastmath<contract> : (f32, f32, f32, f32) -> complex<f32>
|
||||
|
||||
! IMPRVD: %[[VAL_RET:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f32>
|
||||
! BASIC: %[[VAL_RET:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f32>
|
||||
|
||||
! CHECK: hlfir.assign %[[VAL_RET]] to %[[VAL_4]]#0 : complex<f32>, !fir.ref<complex<f32>>
|
||||
! CHECK: return
|
||||
subroutine div_test_single(a,b,c)
|
||||
complex(kind=4) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_single
|
||||
|
||||
|
||||
! CHECK-LABEL: @_QPdiv_test_double
|
||||
! CHECK-SAME: %[[REF_0:.*]]: !fir.ref<complex<f64>> {{.*}}, %[[REF_1:.*]]: !fir.ref<complex<f64>> {{.*}}, %[[REF_2:.*]]: !fir.ref<complex<f64>> {{.*}})
|
||||
! CHECK: %[[VAL_3:.*]] = fir.dummy_scope : !fir.dscope
|
||||
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[REF_0]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_doubleEa"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>)
|
||||
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[REF_1]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_doubleEb"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>)
|
||||
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[REF_2]] dummy_scope %[[VAL_3]] {uniq_name = "_QFdiv_test_doubleEc"} : (!fir.ref<complex<f64>>, !fir.dscope) -> (!fir.ref<complex<f64>>, !fir.ref<complex<f64>>)
|
||||
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<complex<f64>>
|
||||
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<complex<f64>>
|
||||
|
||||
! FULL: %[[VAL_9:.*]] = fir.extract_value %[[VAL_7]], [0 : index] : (complex<f64>) -> f64
|
||||
! FULL: %[[VAL_10:.*]] = fir.extract_value %[[VAL_7]], [1 : index] : (complex<f64>) -> f64
|
||||
! FULL: %[[VAL_11:.*]] = fir.extract_value %[[VAL_8]], [0 : index] : (complex<f64>) -> f64
|
||||
! FULL: %[[VAL_12:.*]] = fir.extract_value %[[VAL_8]], [1 : index] : (complex<f64>) -> f64
|
||||
! FULL: %[[VAL_RET:.*]] = fir.call @__divdc3(%[[VAL_9]], %[[VAL_10]], %[[VAL_11]], %[[VAL_12]]) fastmath<contract> : (f64, f64, f64, f64) -> complex<f64>
|
||||
|
||||
! IMPRVD: %[[VAL_RET:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f64>
|
||||
! BASIC: %[[VAL_RET:.*]] = complex.div %[[VAL_7]], %[[VAL_8]] fastmath<contract> : complex<f64>
|
||||
|
||||
! CHECK: hlfir.assign %[[VAL_RET]] to %[[VAL_4]]#0 : complex<f64>, !fir.ref<complex<f64>>
|
||||
! CHECK: return
|
||||
subroutine div_test_double(a,b,c)
|
||||
complex(kind=8) :: a, b, c
|
||||
a = b / c
|
||||
end subroutine div_test_double
|
||||
@@ -281,6 +281,12 @@ static llvm::cl::opt<bool>
|
||||
"leading dimension will be repacked"),
|
||||
llvm::cl::init(true));
|
||||
|
||||
static llvm::cl::opt<std::string> complexRange(
|
||||
"complex-range",
|
||||
llvm::cl::desc("Controls the various implementations for complex "
|
||||
"multiplication and division [full|improved|basic]"),
|
||||
llvm::cl::init(""));
|
||||
|
||||
#define FLANG_EXCLUDE_CODEGEN
|
||||
#include "flang/Optimizer/Passes/CommandLineOpts.h"
|
||||
#include "flang/Optimizer/Passes/Pipelines.h"
|
||||
@@ -442,6 +448,8 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
|
||||
loweringOptions.setSkipExternalRttiDefinition(skipExternalRttiDefinition);
|
||||
if (enableCUDA)
|
||||
loweringOptions.setCUDARuntimeCheck(true);
|
||||
if (complexRange == "improved" || complexRange == "basic")
|
||||
loweringOptions.setComplexDivisionToRuntime(false);
|
||||
std::vector<Fortran::lower::EnvironmentDefault> envDefaults = {};
|
||||
Fortran::frontend::TargetOptions targetOpts;
|
||||
Fortran::frontend::CodeGenOptions cgOpts;
|
||||
|
||||
Reference in New Issue
Block a user