diff --git a/flang/include/flang/Evaluate/target.h b/flang/include/flang/Evaluate/target.h --- a/flang/include/flang/Evaluate/target.h +++ b/flang/include/flang/Evaluate/target.h @@ -91,11 +91,15 @@ return *this; } + bool isPPC() const { return isPPC_; } + void set_isPPC(bool isPPC = false); + private: static constexpr int maxKind{32}; std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind]{}; std::uint8_t align_[common::TypeCategory_enumSize][maxKind]{}; bool isBigEndian_{false}; + bool isPPC_{false}; bool areSubnormalsFlushedToZero_{false}; Rounding roundingMode_{defaultRounding}; std::size_t procedurePointerByteSize_{8}; diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -88,6 +88,10 @@ Inquired }; +/// Enums used to templatize vector intrinsic function generators. Enum does +/// not contain every vector intrinsic, only intrinsics that share generators. +enum class VecOp { Add, And, Mul, Sub, Xor }; + /// Define how a given intrinsic argument must be lowered. struct ArgLoweringRule { LowerIntrinsicArgAs lowerAs; @@ -335,6 +339,11 @@ mlir::Type resultType, llvm::ArrayRef args); + template + fir::ExtendedValue + genVecAddAndMulSubXor(mlir::Type resultType, + llvm::ArrayRef args); + /// Define the different FIR generators that can be mapped to intrinsic to /// generate the related code. using ElementalGenerator = decltype(&IntrinsicLibrary::genAbs); diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -2610,6 +2610,7 @@ static bool isFloatCompatible(mlir::Type ty); static bool isPointerCompatible(mlir::Type ty); static bool canBeConverted(mlir::Type inType, mlir::Type outType); + static bool areVectorsCompatible(mlir::Type inTy, mlir::Type outTy); }]; let hasCanonicalizer = 1; } diff --git a/flang/lib/Evaluate/target.cpp b/flang/lib/Evaluate/target.cpp --- a/flang/lib/Evaluate/target.cpp +++ b/flang/lib/Evaluate/target.cpp @@ -102,6 +102,8 @@ isBigEndian_ = isBig; } +void TargetCharacteristics::set_isPPC(bool isPowerPC) { isPPC_ = isPowerPC; } + void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes) { areSubnormalsFlushedToZero_ = yes; } diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -1107,6 +1107,9 @@ semanticsContext->targetCharacteristics() .set_compilerOptionsString(allCompilerInvocOpts) .set_compilerVersionString(version); + + if (targetTriple.isPPC()) + semanticsContext->targetCharacteristics().set_isPPC(true); } /// Set \p loweringOptions controlling lowering behavior based diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -41,6 +41,7 @@ #include "mlir/Dialect/Complex/IR/Complex.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/Math/IR/Math.h" +#include "mlir/Dialect/Vector/IR/VectorOps.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" @@ -88,6 +89,84 @@ return !isStaticallyAbsent(exv); } +//===----------------------------------------------------------------------===// +// Helper functions for argument handling in vector intrinsics. +//===----------------------------------------------------------------------===// +static mlir::Type getConvertedElementType(mlir::MLIRContext *context, + mlir::Type eleTy) { + if (eleTy.isa() && !eleTy.isSignlessInteger()) { + const auto intTy{eleTy.dyn_cast()}; + auto newEleTy{mlir::IntegerType::get(context, intTy.getWidth())}; + return newEleTy; + } + return eleTy; +} + +// Wrapper struct to encapsulate information for a vector type. Preserves +// sign of eleTy if eleTy is signed/unsigned integer. Helps with vector type +// conversions. +struct VecTypeInfo { + mlir::Type eleTy; + uint64_t len; + + mlir::Type toFirVectorType() { return fir::VectorType::get(len, eleTy); } + + // We need a builder to do the signless element conversion. + mlir::Type toMlirVectorType(mlir::MLIRContext *context) { + // Will convert to eleTy to signless int if eleTy is signed/unsigned int. + auto convEleTy{getConvertedElementType(context, eleTy)}; + return mlir::VectorType::get(len, convEleTy); + } + + bool isFloat32() { return mlir::isa(eleTy); } + + bool isFloat64() { return mlir::isa(eleTy); } + + bool isFloat() { return isFloat32() || isFloat64(); } +}; + +static llvm::SmallVector +getBasesForArgs(llvm::ArrayRef args) { + llvm::SmallVector baseVec; + for (auto arg : args) + baseVec.push_back(getBase(arg)); + return baseVec; +} + +static llvm::SmallVector +getTypesForArgs(llvm::ArrayRef args) { + llvm::SmallVector typeVec; + for (auto arg : args) + typeVec.push_back(arg.getType()); + return typeVec; +} + +// Returns a VecTypeInfo with element type and length of given fir vector type. +// Preserves signness of fir vector type if element type of integer. +static VecTypeInfo getVecTypeFromFirType(mlir::Type firTy) { + assert(firTy.isa()); + VecTypeInfo vecTyInfo; + vecTyInfo.eleTy = firTy.dyn_cast().getEleTy(); + vecTyInfo.len = firTy.dyn_cast().getLen(); + return vecTyInfo; +} + +static VecTypeInfo getVecTypeFromFir(mlir::Value firVec) { + return getVecTypeFromFirType(firVec.getType()); +} + +// Converts array of fir vectors to mlir vectors. +static llvm::SmallVector +convertVecArgs(fir::FirOpBuilder &builder, mlir::Location loc, + VecTypeInfo vecTyInfo, llvm::SmallVector args) { + llvm::SmallVector newArgs; + auto ty{vecTyInfo.toMlirVectorType(builder.getContext())}; + assert(ty && "unknown mlir vector type"); + for (size_t i = 0; i < args.size(); i++) + newArgs.push_back(builder.createConvert(loc, ty, args[i])); + return newArgs; +} + constexpr auto asValue = fir::LowerIntrinsicArgAs::Value; constexpr auto asAddr = fir::LowerIntrinsicArgAs::Addr; constexpr auto asBox = fir::LowerIntrinsicArgAs::Box; @@ -531,6 +610,26 @@ &I::genMtfsf, {{{"bf", asValue}, {"i", asValue}}}, /*isElemental=*/false}, + {"__ppc_vec_add", + &I::genVecAddAndMulSubXor, + {{{"arg1", asValue}, {"arg2", asValue}}}, + /*isElemental=*/true}, + {"__ppc_vec_and", + &I::genVecAddAndMulSubXor, + {{{"arg1", asValue}, {"arg2", asValue}}}, + /*isElemental=*/true}, + {"__ppc_vec_mul", + &I::genVecAddAndMulSubXor, + {{{"arg1", asValue}, {"arg2", asValue}}}, + /*isElemental=*/true}, + {"__ppc_vec_sub", + &I::genVecAddAndMulSubXor, + {{{"arg1", asValue}, {"arg2", asValue}}}, + /*isElemental=*/true}, + {"__ppc_vec_xor", + &I::genVecAddAndMulSubXor, + {{{"arg1", asValue}, {"arg2", asValue}}}, + /*isElemental=*/true}, }; static const IntrinsicHandler *findIntrinsicHandler(llvm::StringRef name) { @@ -4505,6 +4604,73 @@ return builder.createConvert(loc, resultType, result); } +// VEC_ADD, VEC_AND, VEC_SUB, VEC_MUL, VEC_XOR +template +fir::ExtendedValue IntrinsicLibrary::genVecAddAndMulSubXor( + mlir::Type resultType, llvm::ArrayRef args) { + assert(args.size() == 2); + auto argBases{getBasesForArgs(args)}; + auto argsTy{getTypesForArgs(argBases)}; + assert(argsTy[0].isa() && argsTy[1].isa()); + + auto vecTyInfo{getVecTypeFromFir(argBases[0])}; + + const auto isInteger{vecTyInfo.eleTy.isa()}; + const auto isFloat{vecTyInfo.eleTy.isa()}; + assert((isInteger || isFloat) && "unknown vector type"); + + auto vargs{convertVecArgs(builder, loc, vecTyInfo, argBases)}; + + mlir::Value r{nullptr}; + switch (vop) { + case VecOp::Add: + if (isInteger) + r = builder.create(loc, vargs[0], vargs[1]); + else if (isFloat) + r = builder.create(loc, vargs[0], vargs[1]); + break; + case VecOp::Mul: + if (isInteger) + r = builder.create(loc, vargs[0], vargs[1]); + else if (isFloat) + r = builder.create(loc, vargs[0], vargs[1]); + break; + case VecOp::Sub: + if (isInteger) + r = builder.create(loc, vargs[0], vargs[1]); + else if (isFloat) + r = builder.create(loc, vargs[0], vargs[1]); + break; + case VecOp::And: + case VecOp::Xor: { + mlir::Value arg1{nullptr}; + mlir::Value arg2{nullptr}; + if (isInteger) { + arg1 = vargs[0]; + arg2 = vargs[1]; + } else if (isFloat) { + // bitcast the arguments to integer + auto wd{vecTyInfo.eleTy.dyn_cast().getWidth()}; + auto ftype{builder.getIntegerType(wd)}; + auto bcVecTy{mlir::VectorType::get(vecTyInfo.len, ftype)}; + arg1 = builder.create(loc, bcVecTy, vargs[0]); + arg2 = builder.create(loc, bcVecTy, vargs[1]); + } + if (vop == VecOp::And) + r = builder.create(loc, arg1, arg2); + else if (vop == VecOp::Xor) + r = builder.create(loc, arg1, arg2); + + if (isFloat) + r = builder.create(loc, vargs[0].getType(), r); + + break; + } + } + + return builder.createConvert(loc, argsTy[0], r); +} + static bool hasDefaultLowerBound(const fir::ExtendedValue &exv) { return exv.match( [](const fir::ArrayBoxValue &arr) { return arr.getLBounds().empty(); }, diff --git a/flang/lib/Optimizer/CodeGen/CMakeLists.txt b/flang/lib/Optimizer/CodeGen/CMakeLists.txt --- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt +++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt @@ -27,6 +27,7 @@ MLIRBuiltinToLLVMIRTranslation MLIRLLVMToLLVMIRTranslation MLIRTargetLLVMIRExport + MLIRVectorToLLVM LINK_COMPONENTS AsmParser diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -33,6 +33,7 @@ #include "mlir/Conversion/MathToLibm/MathToLibm.h" #include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h" #include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h" +#include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" @@ -3697,6 +3698,7 @@ // to Libm. mlir::populateMathToLibmConversionPatterns(pattern); mlir::populateComplexToLLVMConversionPatterns(typeConverter, pattern); + mlir::populateVectorToLLVMConversionPatterns(typeConverter, pattern); mlir::ConversionTarget target{*context}; target.addLegalDialect(); // The OpenMP dialect is legal for Operations without regions, for those diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -943,6 +943,59 @@ fir::TypeDescType>(); } +static std::optional getVectorElementType(mlir::Type ty) { + if (mlir::isa(ty)) { + auto elemTy = mlir::dyn_cast(ty).getEleTy(); + + // fir.vector<4:ui32> is converted to mlir.vector<4xi32> + if (elemTy.isUnsignedInteger()) { + elemTy = mlir::IntegerType::get( + ty.getContext(), + mlir::dyn_cast(elemTy).getWidth()); + } + return elemTy; + } else if (mlir::isa(ty)) + return mlir::dyn_cast(ty).getElementType(); + + return std::nullopt; +} + +static std::optional getVectorLen(mlir::Type ty) { + if (mlir::isa(ty)) + return mlir::dyn_cast(ty).getLen(); + else if (mlir::isa(ty)) { + // fir.vector only supports 1-D vector + if (mlir::dyn_cast(ty).getNumScalableDims() == 0) + return mlir::dyn_cast(ty).getShape()[0]; + } + + return std::nullopt; +} + +bool fir::ConvertOp::areVectorsCompatible(mlir::Type inTy, mlir::Type outTy) { + if (!(mlir::isa(inTy) && + mlir::isa(outTy)) && + !(mlir::isa(inTy) && mlir::isa(outTy))) + return false; + + // Only support integer, unsigned and real vector + // Both vectors must have the same element type + std::optional inElemTy = getVectorElementType(inTy); + std::optional outElemTy = getVectorElementType(outTy); + if (!inElemTy.has_value() || !outElemTy.has_value() || + inElemTy.value() != outElemTy.value()) + return false; + + // Both vectors must have the same number of elements + std::optional inLen = getVectorLen(inTy); + std::optional outLen = getVectorLen(outTy); + if (!inLen.has_value() || !outLen.has_value() || + inLen.value() != outLen.value()) + return false; + + return true; +} + bool fir::ConvertOp::canBeConverted(mlir::Type inType, mlir::Type outType) { if (inType == outType) return true; @@ -958,7 +1011,8 @@ (fir::isa_complex(inType) && fir::isa_complex(outType)) || (fir::isBoxedRecordType(inType) && fir::isPolymorphicType(outType)) || (fir::isPolymorphicType(inType) && fir::isPolymorphicType(outType)) || - (fir::isPolymorphicType(inType) && outType.isa()); + (fir::isPolymorphicType(inType) && outType.isa()) || + areVectorsCompatible(inType, outType); } mlir::LogicalResult fir::ConvertOp::verify() { diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -4849,6 +4849,13 @@ } bool DeclarationVisitor::Pre(const parser::VectorTypeSpec &) { + // PowerPC vector types are allowed only on Power architectures. + if (!currScope().context().targetCharacteristics().isPPC()) { + Say(currStmtSource().value(), + "Vector type is only supported for PowerPC"_err_en_US); + isVectorType_ = false; + return false; + } isVectorType_ = true; return true; } diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp --- a/flang/lib/Semantics/semantics.cpp +++ b/flang/lib/Semantics/semantics.cpp @@ -513,19 +513,21 @@ if (frontModule && (std::get>(frontModule->value().t) .statement.v.source == "__fortran_builtins" || - std::get>( - frontModule->value().t) - .statement.v.source == "__fortran_ppc_intrinsics" || std::get>( frontModule->value().t) .statement.v.source == "__fortran_ppc_types")) { // Don't try to read the builtins module when we're actually building it. + } else if (frontModule && + std::get>(frontModule->value().t) + .statement.v.source == "__fortran_ppc_intrinsics") { + // The derived type definition for the vectors is needed. + context_.UsePPCFortranBuiltinTypesModule(); } else { context_.UseFortranBuiltinsModule(); llvm::Triple targetTriple{llvm::Triple( llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()))}; // Only use __Fortran_PPC_intrinsics module when targetting PowerPC arch - if (targetTriple.isPPC()) { + if (context_.targetCharacteristics().isPPC()) { context_.UsePPCFortranBuiltinTypesModule(); context_.UsePPCFortranBuiltinsModule(); } diff --git a/flang/module/__fortran_ppc_intrinsics.f90 b/flang/module/__fortran_ppc_intrinsics.f90 --- a/flang/module/__fortran_ppc_intrinsics.f90 +++ b/flang/module/__fortran_ppc_intrinsics.f90 @@ -18,6 +18,37 @@ elemental real(8) function func_r8r8r8r8(a, x, y) real(8), intent(in) :: a, x, y end function func_r8r8r8r8 + +!-------------------- +! Vector intrinsic +!-------------------- +!! ================ 2 arguments function interface ================ +! vector(i) function f(vector(i), vector(i)) +#define ELEM_FUNC_VIVIVI(VKIND) \ + elemental vector(integer(VKIND)) function elem_func_vi##VKIND##vi##VKIND##vi##VKIND(arg1, arg2); \ + vector(integer(VKIND)), intent(in) :: arg1, arg2; \ + end function ; + +! vector(u) function f(vector(u), vector(u)) +#define ELEM_FUNC_VUVUVU(VKIND) \ + elemental vector(unsigned(VKIND)) function elem_func_vu##VKIND##vu##VKIND##vu##VKIND(arg1, arg2); \ + vector(unsigned(VKIND)), intent(in) :: arg1, arg2; \ + end function ; + +! vector(r) function f(vector(r), vector(r)) +#define ELEM_FUNC_VRVRVR(VKIND) \ + elemental vector(real(VKIND)) function elem_func_vr##VKIND##vr##VKIND##vr##VKIND(arg1, arg2); \ + vector(real(VKIND)), intent(in) :: arg1, arg2; \ + end function ; + + ELEM_FUNC_VIVIVI(1) ELEM_FUNC_VIVIVI(2) ELEM_FUNC_VIVIVI(4) ELEM_FUNC_VIVIVI(8) + ELEM_FUNC_VUVUVU(1) ELEM_FUNC_VUVUVU(2) ELEM_FUNC_VUVUVU(4) ELEM_FUNC_VUVUVU(8) + ELEM_FUNC_VRVRVR(4) ELEM_FUNC_VRVRVR(8) + +#undef ELEM_FUNC_VRVRVR +#undef ELEM_FUNC_VUVUVU +#undef ELEM_FUNC_VIVIVI + end interface procedure(func_r4r4r4r4) :: __ppc_fmadd_r4 @@ -174,4 +205,80 @@ end subroutine __ppc_mtfsfi end interface mtfsfi public :: mtfsfi + +!--------------------------------- +! vector function(vector, vector) +!--------------------------------- +#define VI_VI_VI(NAME, VKIND) __ppc_##NAME##_vi##VKIND##vi##VKIND##vi##VKIND +#define VU_VU_VU(NAME, VKIND) __ppc_##NAME##_vu##VKIND##vu##VKIND##vu##VKIND +#define VR_VR_VR(NAME, VKIND) __ppc_##NAME##_vr##VKIND##vr##VKIND##vr##VKIND + +#define VEC_VI_VI_VI(NAME, VKIND) \ + procedure(elem_func_vi##VKIND##vi##VKIND##vi##VKIND) :: VI_VI_VI(NAME, VKIND); +#define VEC_VU_VU_VU(NAME, VKIND) \ + procedure(elem_func_vu##VKIND##vu##VKIND##vu##VKIND) :: VU_VU_VU(NAME, VKIND); +#define VEC_VR_VR_VR(NAME, VKIND) \ + procedure(elem_func_vr##VKIND##vr##VKIND##vr##VKIND) :: VR_VR_VR(NAME, VKIND); + +! vec_add + VEC_VI_VI_VI(vec_add,1) VEC_VI_VI_VI(vec_add,2) VEC_VI_VI_VI(vec_add,4) VEC_VI_VI_VI(vec_add,8) + VEC_VU_VU_VU(vec_add,1) VEC_VU_VU_VU(vec_add,2) VEC_VU_VU_VU(vec_add,4) VEC_VU_VU_VU(vec_add,8) + VEC_VR_VR_VR(vec_add,4) VEC_VR_VR_VR(vec_add,8) + interface vec_add + procedure :: VI_VI_VI(vec_add,1), VI_VI_VI(vec_add,2), VI_VI_VI(vec_add,4), VI_VI_VI(vec_add,8) + procedure :: VU_VU_VU(vec_add,1), VU_VU_VU(vec_add,2), VU_VU_VU(vec_add,4), VU_VU_VU(vec_add,8) + procedure :: VR_VR_VR(vec_add,4), VR_VR_VR(vec_add,8) + end interface vec_add + public :: vec_add + +! vec_and + VEC_VI_VI_VI(vec_and,1) VEC_VI_VI_VI(vec_and,2) VEC_VI_VI_VI(vec_and,4) VEC_VI_VI_VI(vec_and,8) + VEC_VU_VU_VU(vec_and,1) VEC_VU_VU_VU(vec_and,2) VEC_VU_VU_VU(vec_and,4) VEC_VU_VU_VU(vec_and,8) + VEC_VR_VR_VR(vec_and,4) VEC_VR_VR_VR(vec_and,8) + interface vec_and + procedure :: VI_VI_VI(vec_and,1), VI_VI_VI(vec_and,2), VI_VI_VI(vec_and,4), VI_VI_VI(vec_and,8) + procedure :: VU_VU_VU(vec_and,1), VU_VU_VU(vec_and,2), VU_VU_VU(vec_and,4), VU_VU_VU(vec_and,8) + procedure :: VR_VR_VR(vec_and,4), VR_VR_VR(vec_and,8) + end interface vec_and + public :: vec_and + +! vec_mul + VEC_VI_VI_VI(vec_mul,1) VEC_VI_VI_VI(vec_mul,2) VEC_VI_VI_VI(vec_mul,4) VEC_VI_VI_VI(vec_mul,8) + VEC_VU_VU_VU(vec_mul,1) VEC_VU_VU_VU(vec_mul,2) VEC_VU_VU_VU(vec_mul,4) VEC_VU_VU_VU(vec_mul,8) + VEC_VR_VR_VR(vec_mul,4) VEC_VR_VR_VR(vec_mul,8) + interface vec_mul + procedure :: VI_VI_VI(vec_mul,1), VI_VI_VI(vec_mul,2), VI_VI_VI(vec_mul,4), VI_VI_VI(vec_mul,8) + procedure :: VU_VU_VU(vec_mul,1), VU_VU_VU(vec_mul,2), VU_VU_VU(vec_mul,4), VU_VU_VU(vec_mul,8) + procedure :: VR_VR_VR(vec_mul,4), VR_VR_VR(vec_mul,8) + end interface vec_mul + public :: vec_mul + +! vec_sub + VEC_VI_VI_VI(vec_sub,1) VEC_VI_VI_VI(vec_sub,2) VEC_VI_VI_VI(vec_sub,4) VEC_VI_VI_VI(vec_sub,8) + VEC_VU_VU_VU(vec_sub,1) VEC_VU_VU_VU(vec_sub,2) VEC_VU_VU_VU(vec_sub,4) VEC_VU_VU_VU(vec_sub,8) + VEC_VR_VR_VR(vec_sub,4) VEC_VR_VR_VR(vec_sub,8) + interface vec_sub + procedure :: VI_VI_VI(vec_sub,1), VI_VI_VI(vec_sub,2), VI_VI_VI(vec_sub,4), VI_VI_VI(vec_sub,8) + procedure :: VU_VU_VU(vec_sub,1), VU_VU_VU(vec_sub,2), VU_VU_VU(vec_sub,4), VU_VU_VU(vec_sub,8) + procedure :: VR_VR_VR(vec_sub,4), VR_VR_VR(vec_sub,8) + end interface vec_sub + public :: vec_sub + +! vec_xor + VEC_VI_VI_VI(vec_xor,1) VEC_VI_VI_VI(vec_xor,2) VEC_VI_VI_VI(vec_xor,4) VEC_VI_VI_VI(vec_xor,8) + VEC_VU_VU_VU(vec_xor,1) VEC_VU_VU_VU(vec_xor,2) VEC_VU_VU_VU(vec_xor,4) VEC_VU_VU_VU(vec_xor,8) + VEC_VR_VR_VR(vec_xor,4) VEC_VR_VR_VR(vec_xor,8) + interface vec_xor + procedure :: VI_VI_VI(vec_xor,1), VI_VI_VI(vec_xor,2), VI_VI_VI(vec_xor,4), VI_VI_VI(vec_xor,8) + procedure :: VU_VU_VU(vec_xor,1), VU_VU_VU(vec_xor,2), VU_VU_VU(vec_xor,4), VU_VU_VU(vec_xor,8) + procedure :: VR_VR_VR(vec_xor,4), VR_VR_VR(vec_xor,8) + end interface vec_xor + public :: vec_xor + +#undef VEC_VR_VR_VR +#undef VEC_VU_VU_VU +#undef VEC_VI_VI_VI +#undef VR_VR_VR +#undef VU_VU_VU +#undef VI_VI_VI end module __Fortran_PPC_intrinsics diff --git a/flang/test/Lower/ppc-intrinsics.f90 b/flang/test/Lower/PowerPC/ppc-intrinsics.f90 rename from flang/test/Lower/ppc-intrinsics.f90 rename to flang/test/Lower/PowerPC/ppc-intrinsics.f90 diff --git a/flang/test/Lower/PowerPC/ppc-vec_add-and-mul-sub-xor.f90 b/flang/test/Lower/PowerPC/ppc-vec_add-and-mul-sub-xor.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/PowerPC/ppc-vec_add-and-mul-sub-xor.f90 @@ -0,0 +1,1055 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck --check-prefixes="CHECK-FIR" %s +! RUN: %flang_fc1 -emit-fir %s -o - | fir-opt --fir-to-llvm-ir | FileCheck --check-prefixes="CHECK-LLVMIR" %s +! RUN: %flang_fc1 -emit-llvm %s -o - | FileCheck --check-prefixes="CHECK" %s +! REQUIRES: target=powerpc{{.*}} + +! vec_add + +! CHECK-LABEL: vec_add_testf32 +subroutine vec_add_testf32(x, y) + vector(real(4)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[vsum:.*]] = arith.addf %[[vx]], %[[vy]] fastmath : vector<4xf32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<4xf32>) -> !fir.vector<4:f32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.fadd %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath} : vector<4xf32> + +! CHECK: %[[x:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = fadd contract <4 x float> %[[x]], %[[y]] +end subroutine vec_add_testf32 + +! CHECK-LABEL: vec_add_testf64 +subroutine vec_add_testf64(x, y) + vector(real(8)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[vsum:.*]] = arith.addf %[[vx]], %[[vy]] fastmath : vector<2xf64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<2xf64>) -> !fir.vector<2:f64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.fadd %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath} : vector<2xf64> + +! CHECK: %[[x:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = fadd contract <2 x double> %[[x]], %[[y]] +end subroutine vec_add_testf64 + +! CHECK-LABEL: vec_add_testi8 +subroutine vec_add_testi8(x, y) + vector(integer(1)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[vsum:.*]] = arith.addi %[[vx]], %[[vy]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<16xi8>) -> !fir.vector<16:i8> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.add %[[x]], %[[y]] : vector<16xi8> + +! CHECK: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = add <16 x i8> %[[x]], %[[y]] +end subroutine vec_add_testi8 + +! CHECK-LABEL: vec_add_testi16 +subroutine vec_add_testi16(x, y) + vector(integer(2)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[vsum:.*]] = arith.addi %[[vx]], %[[vy]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<8xi16>) -> !fir.vector<8:i16> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.add %[[x]], %[[y]] : vector<8xi16> + +! CHECK: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = add <8 x i16> %[[x]], %[[y]] +end subroutine vec_add_testi16 + +! CHECK-LABEL: vec_add_testi32 +subroutine vec_add_testi32(x, y) + vector(integer(4)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[vsum:.*]] = arith.addi %[[vx]], %[[vy]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<4xi32>) -> !fir.vector<4:i32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.add %[[x]], %[[y]] : vector<4xi32> + +! CHECK: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = add <4 x i32> %[[x]], %[[y]] +end subroutine vec_add_testi32 + +! CHECK-LABEL: vec_add_testi64 +subroutine vec_add_testi64(x, y) + vector(integer(8)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[vsum:.*]] = arith.addi %[[vx]], %[[vy]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<2xi64>) -> !fir.vector<2:i64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.add %[[x]], %[[y]] : vector<2xi64> + +! CHECK: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = add <2 x i64> %[[x]], %[[y]] +end subroutine vec_add_testi64 + +! CHECK-LABEL: vec_add_testui8 +subroutine vec_add_testui8(x, y) + vector(unsigned(1)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[vsum:.*]] = arith.addi %[[vx]], %[[vy]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<16xi8>) -> !fir.vector<16:ui8> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.add %[[x]], %[[y]] : vector<16xi8> + +! CHECK: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = add <16 x i8> %[[x]], %[[y]] +end subroutine vec_add_testui8 + +! CHECK-LABEL: vec_add_testui16 +subroutine vec_add_testui16(x, y) + vector(unsigned(2)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[vsum:.*]] = arith.addi %[[vx]], %[[vy]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<8xi16>) -> !fir.vector<8:ui16> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.add %[[x]], %[[y]] : vector<8xi16> + +! CHECK: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = add <8 x i16> %[[x]], %[[y]] +end subroutine vec_add_testui16 + +! CHECK-LABEL: vec_add_testui32 +subroutine vec_add_testui32(x, y) + vector(unsigned(4)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[vsum:.*]] = arith.addi %[[vx]], %[[vy]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<4xi32>) -> !fir.vector<4:ui32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.add %[[x]], %[[y]] : vector<4xi32> + +! CHECK: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = add <4 x i32> %[[x]], %[[y]] +end subroutine vec_add_testui32 + +! CHECK-LABEL: vec_add_testui64 +subroutine vec_add_testui64(x, y) + vector(unsigned(8)) :: vsum, x, y + vsum = vec_add(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[vsum:.*]] = arith.addi %[[vx]], %[[vy]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<2xi64>) -> !fir.vector<2:ui64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.add %[[x]], %[[y]] : vector<2xi64> + +! CHECK: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = add <2 x i64> %[[x]], %[[y]] +end subroutine vec_add_testui64 + +! vec_mul + +! CHECK-LABEL: vec_mul_testf32 +subroutine vec_mul_testf32(x, y) + vector(real(4)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[vmul:.*]] = arith.mulf %[[vx]], %[[vy]] fastmath : vector<4xf32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<4xf32>) -> !fir.vector<4:f32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.fmul %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath} : vector<4xf32> + +! CHECK: %[[x:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = fmul contract <4 x float> %[[x]], %[[y]] +end subroutine vec_mul_testf32 + +! CHECK-LABEL: vec_mul_testf64 +subroutine vec_mul_testf64(x, y) + vector(real(8)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[vmul:.*]] = arith.mulf %[[vx]], %[[vy]] fastmath : vector<2xf64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<2xf64>) -> !fir.vector<2:f64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.fmul %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath} : vector<2xf64> + +! CHECK: %[[x:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = fmul contract <2 x double> %[[x]], %[[y]] +end subroutine vec_mul_testf64 + +! CHECK-LABEL: vec_mul_testi8 +subroutine vec_mul_testi8(x, y) + vector(integer(1)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[vmul:.*]] = arith.muli %[[vx]], %[[vy]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<16xi8>) -> !fir.vector<16:i8> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.mul %[[x]], %[[y]] : vector<16xi8> + +! CHECK: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = mul <16 x i8> %[[x]], %[[y]] +end subroutine vec_mul_testi8 + +! CHECK-LABEL: vec_mul_testi16 +subroutine vec_mul_testi16(x, y) + vector(integer(2)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[vmul:.*]] = arith.muli %[[vx]], %[[vy]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<8xi16>) -> !fir.vector<8:i16> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.mul %[[x]], %[[y]] : vector<8xi16> + +! CHECK: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = mul <8 x i16> %[[x]], %[[y]] +end subroutine vec_mul_testi16 + +! CHECK-LABEL: vec_mul_testi32 +subroutine vec_mul_testi32(x, y) + vector(integer(4)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[vmul:.*]] = arith.muli %[[vx]], %[[vy]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<4xi32>) -> !fir.vector<4:i32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.mul %[[x]], %[[y]] : vector<4xi32> + +! CHECK: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = mul <4 x i32> %[[x]], %[[y]] +end subroutine vec_mul_testi32 + +! CHECK-LABEL: vec_mul_testi64 +subroutine vec_mul_testi64(x, y) + vector(integer(8)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[vmul:.*]] = arith.muli %[[vx]], %[[vy]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<2xi64>) -> !fir.vector<2:i64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.mul %[[x]], %[[y]] : vector<2xi64> + +! CHECK: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = mul <2 x i64> %[[x]], %[[y]] +end subroutine vec_mul_testi64 + +! CHECK-LABEL: vec_mul_testui8 +subroutine vec_mul_testui8(x, y) + vector(unsigned(1)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[vmul:.*]] = arith.muli %[[vx]], %[[vy]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<16xi8>) -> !fir.vector<16:ui8> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.mul %[[x]], %[[y]] : vector<16xi8> + +! CHECK: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = mul <16 x i8> %[[x]], %[[y]] +end subroutine vec_mul_testui8 + +! CHECK-LABEL: vec_mul_testui16 +subroutine vec_mul_testui16(x, y) + vector(unsigned(2)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[vmul:.*]] = arith.muli %[[vx]], %[[vy]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<8xi16>) -> !fir.vector<8:ui16> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.mul %[[x]], %[[y]] : vector<8xi16> + +! CHECK: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = mul <8 x i16> %[[x]], %[[y]] +end subroutine vec_mul_testui16 + +! CHECK-LABEL: vec_mul_testui32 +subroutine vec_mul_testui32(x, y) + vector(unsigned(4)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[vmul:.*]] = arith.muli %[[vx]], %[[vy]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<4xi32>) -> !fir.vector<4:ui32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.mul %[[x]], %[[y]] : vector<4xi32> + +! CHECK: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = mul <4 x i32> %[[x]], %[[y]] +end subroutine vec_mul_testui32 + +! CHECK-LABEL: vec_mul_testui64 +subroutine vec_mul_testui64(x, y) + vector(unsigned(8)) :: vmul, x, y + vmul = vec_mul(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[vmul:.*]] = arith.muli %[[vx]], %[[vy]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<2xi64>) -> !fir.vector<2:ui64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.mul %[[x]], %[[y]] : vector<2xi64> + +! CHECK: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = mul <2 x i64> %[[x]], %[[y]] +end subroutine vec_mul_testui64 + +! vec_sub + +! CHECK-LABEL: vec_sub_testf32 +subroutine vec_sub_testf32(x, y) + vector(real(4)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[vsub:.*]] = arith.subf %[[vx]], %[[vy]] fastmath : vector<4xf32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<4xf32>) -> !fir.vector<4:f32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.fsub %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath} : vector<4xf32> + +! CHECK: %[[x:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x float>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = fsub contract <4 x float> %[[x]], %[[y]] +end subroutine vec_sub_testf32 + +! CHECK-LABEL: vec_sub_testf64 +subroutine vec_sub_testf64(x, y) + vector(real(8)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[vsub:.*]] = arith.subf %[[vx]], %[[vy]] fastmath : vector<2xf64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<2xf64>) -> !fir.vector<2:f64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.fsub %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath} : vector<2xf64> + +! CHECK: %[[x:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x double>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = fsub contract <2 x double> %[[x]], %[[y]] +end subroutine vec_sub_testf64 + +! CHECK-LABEL: vec_sub_testi8 +subroutine vec_sub_testi8(x, y) + vector(integer(1)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[vsub:.*]] = arith.subi %[[vx]], %[[vy]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<16xi8>) -> !fir.vector<16:i8> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.sub %[[x]], %[[y]] : vector<16xi8> + +! CHECK: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = sub <16 x i8> %[[x]], %[[y]] +end subroutine vec_sub_testi8 + +! CHECK-LABEL: vec_sub_testi16 +subroutine vec_sub_testi16(x, y) + vector(integer(2)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[vsub:.*]] = arith.subi %[[vx]], %[[vy]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<8xi16>) -> !fir.vector<8:i16> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.sub %[[x]], %[[y]] : vector<8xi16> + +! CHECK: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = sub <8 x i16> %[[x]], %[[y]] +end subroutine vec_sub_testi16 + +! CHECK-LABEL: vec_sub_testi32 +subroutine vec_sub_testi32(x, y) + vector(integer(4)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[vsub:.*]] = arith.subi %[[vx]], %[[vy]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<4xi32>) -> !fir.vector<4:i32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.sub %[[x]], %[[y]] : vector<4xi32> + +! CHECK: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = sub <4 x i32> %[[x]], %[[y]] +end subroutine vec_sub_testi32 + +! CHECK-LABEL: vec_sub_testi64 +subroutine vec_sub_testi64(x, y) + vector(integer(8)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[vsub:.*]] = arith.subi %[[vx]], %[[vy]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<2xi64>) -> !fir.vector<2:i64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.sub %[[x]], %[[y]] : vector<2xi64> + +! CHECK: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = sub <2 x i64> %[[x]], %[[y]] +end subroutine vec_sub_testi64 + +! CHECK-LABEL: vec_sub_testui8 +subroutine vec_sub_testui8(x, y) + vector(unsigned(1)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[vsub:.*]] = arith.subi %[[vx]], %[[vy]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<16xi8>) -> !fir.vector<16:ui8> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.sub %[[x]], %[[y]] : vector<16xi8> + +! CHECK: %[[x:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <16 x i8>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = sub <16 x i8> %[[x]], %[[y]] +end subroutine vec_sub_testui8 + +! CHECK-LABEL: vec_sub_testui16 +subroutine vec_sub_testui16(x, y) + vector(unsigned(2)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[vsub:.*]] = arith.subi %[[vx]], %[[vy]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<8xi16>) -> !fir.vector<8:ui16> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.sub %[[x]], %[[y]] : vector<8xi16> + +! CHECK: %[[x:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <8 x i16>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = sub <8 x i16> %[[x]], %[[y]] +end subroutine vec_sub_testui16 + +! CHECK-LABEL: vec_sub_testui32 +subroutine vec_sub_testui32(x, y) + vector(unsigned(4)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[vsub:.*]] = arith.subi %[[vx]], %[[vy]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<4xi32>) -> !fir.vector<4:ui32> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.sub %[[x]], %[[y]] : vector<4xi32> + +! CHECK: %[[x:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <4 x i32>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = sub <4 x i32> %[[x]], %[[y]] +end subroutine vec_sub_testui32 + +! CHECK-LABEL: vec_sub_testui64 +subroutine vec_sub_testui64(x, y) + vector(unsigned(8)) :: vsub, x, y + vsub = vec_sub(x, y) +! CHECK-FIR: %[[x:.*]] = fir.load %arg0 : !fir.ref> +! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref> +! CHECK-FIR: %[[vx:.*]] = fir.convert %[[x]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[vy:.*]] = fir.convert %[[y]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[vsub:.*]] = arith.subi %[[vx]], %[[vy]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<2xi64>) -> !fir.vector<2:ui64> + +! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr> +! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]}} = llvm.sub %[[x]], %[[y]] : vector<2xi64> + +! CHECK: %[[x:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %[[y:.*]] = load <2 x i64>, ptr %{{[0-9]}}, align 16 +! CHECK: %{{[0-9]}} = sub <2 x i64> %[[x]], %[[y]] +end subroutine vec_sub_testui64 + +!---------------------- +! vec_and +!---------------------- + +! CHECK-LABEL: vec_and_test_i8 +subroutine vec_and_test_i8(arg1, arg2) + vector(integer(1)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[varg1]], %[[varg2]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<16xi8>) -> !fir.vector<16:i8> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.and %[[arg1]], %[[arg2]] : vector<16xi8> + +! CHECK: %[[arg1:.*]] = load <16 x i8>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <16 x i8>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = and <16 x i8> %[[arg1]], %[[arg2]] +end subroutine vec_and_test_i8 + +! CHECK-LABEL: vec_and_test_i16 +subroutine vec_and_test_i16(arg1, arg2) + vector(integer(2)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[varg1]], %[[varg2]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<8xi16>) -> !fir.vector<8:i16> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.and %[[arg1]], %[[arg2]] : vector<8xi16> + +! CHECK: %[[arg1:.*]] = load <8 x i16>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <8 x i16>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = and <8 x i16> %[[arg1]], %[[arg2]] +end subroutine vec_and_test_i16 + +! CHECK-LABEL: vec_and_test_i32 +subroutine vec_and_test_i32(arg1, arg2) + vector(integer(4)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[varg1]], %[[varg2]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<4xi32>) -> !fir.vector<4:i32> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.and %[[arg1]], %[[arg2]] : vector<4xi32> + +! CHECK: %[[arg1:.*]] = load <4 x i32>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <4 x i32>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = and <4 x i32> %[[arg1]], %[[arg2]] +end subroutine vec_and_test_i32 + +! CHECK-LABEL: vec_and_test_i64 +subroutine vec_and_test_i64(arg1, arg2) + vector(integer(8)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[varg1]], %[[varg2]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<2xi64>) -> !fir.vector<2:i64> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.and %[[arg1]], %[[arg2]] : vector<2xi64> + +! CHECK: %[[arg1:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = and <2 x i64> %[[arg1]], %[[arg2]] +end subroutine vec_and_test_i64 + +! CHECK-LABEL: vec_and_test_u8 +subroutine vec_and_test_u8(arg1, arg2) + vector(unsigned(1)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[varg1]], %[[varg2]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<16xi8>) -> !fir.vector<16:ui8> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.and %[[arg1]], %[[arg2]] : vector<16xi8> + +! CHECK: %[[arg1:.*]] = load <16 x i8>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <16 x i8>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = and <16 x i8> %[[arg1]], %[[arg2]] +end subroutine vec_and_test_u8 + +! CHECK-LABEL: vec_and_test_u16 +subroutine vec_and_test_u16(arg1, arg2) + vector(unsigned(2)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[varg1]], %[[varg2]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<8xi16>) -> !fir.vector<8:ui16> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.and %[[arg1]], %[[arg2]] : vector<8xi16> + +! CHECK: %[[arg1:.*]] = load <8 x i16>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <8 x i16>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = and <8 x i16> %[[arg1]], %[[arg2]] +end subroutine vec_and_test_u16 + +! CHECK-LABEL: vec_and_test_u32 +subroutine vec_and_test_u32(arg1, arg2) + vector(unsigned(4)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[varg1]], %[[varg2]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<4xi32>) -> !fir.vector<4:ui32> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.and %[[arg1]], %[[arg2]] : vector<4xi32> + +! CHECK: %[[arg1:.*]] = load <4 x i32>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <4 x i32>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = and <4 x i32> %[[arg1]], %[[arg2]] +end subroutine vec_and_test_u32 + +! CHECK-LABEL: vec_and_test_u64 +subroutine vec_and_test_u64(arg1, arg2) + vector(unsigned(8)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[varg1]], %[[varg2]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<2xi64>) -> !fir.vector<2:ui64> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.and %[[arg1]], %[[arg2]] : vector<2xi64> + +! CHECK: %[[arg1:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = and <2 x i64> %[[arg1]], %[[arg2]] +end subroutine vec_and_test_u64 + +! CHECK-LABEL: vec_and_testf32 +subroutine vec_and_testf32(arg1, arg2) + vector(real(4)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[bc1:.*]] = vector.bitcast %[[varg1]] : vector<4xf32> to vector<4xi32> +! CHECK-FIR: %[[bc2:.*]] = vector.bitcast %[[varg2]] : vector<4xf32> to vector<4xi32> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[bc1]], %[[bc2]] : vector<4xi32> +! CHECK-FIR: %[[vr:.*]] = vector.bitcast %[[r]] : vector<4xi32> to vector<4xf32> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[vr]] : (vector<4xf32>) -> !fir.vector<4:f32> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[bc1:.*]] = llvm.bitcast %[[arg1]] : vector<4xf32> to vector<4xi32> +! CHECK-LLVMIR: %[[bc2:.*]] = llvm.bitcast %[[arg2]] : vector<4xf32> to vector<4xi32> +! CHECK-LLVMIR: %[[r:.*]] = llvm.and %[[bc1]], %[[bc2]] : vector<4xi32> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.bitcast %[[r]] : vector<4xi32> to vector<4xf32> + +! CHECK: %[[arg1:.*]] = load <4 x float>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <4 x float>, ptr %{{.*}}, align 16 +! CHECK: %[[bc1:.*]] = bitcast <4 x float> %[[arg1]] to <4 x i32> +! CHECK: %[[bc2:.*]] = bitcast <4 x float> %[[arg2]] to <4 x i32> +! CHECK: %[[r:.*]] = and <4 x i32> %[[bc1]], %[[bc2]] +! CHECK: %{{[0-9]+}} = bitcast <4 x i32> %[[r]] to <4 x float> +end subroutine vec_and_testf32 + +! CHECK-LABEL: vec_and_testf64 +subroutine vec_and_testf64(arg1, arg2) + vector(real(8)) :: r, arg1, arg2 + r = vec_and(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[bc1:.*]] = vector.bitcast %[[varg1]] : vector<2xf64> to vector<2xi64> +! CHECK-FIR: %[[bc2:.*]] = vector.bitcast %[[varg2]] : vector<2xf64> to vector<2xi64> +! CHECK-FIR: %[[r:.*]] = arith.andi %[[bc1]], %[[bc2]] : vector<2xi64> +! CHECK-FIR: %[[vr:.*]] = vector.bitcast %[[r]] : vector<2xi64> to vector<2xf64> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[vr]] : (vector<2xf64>) -> !fir.vector<2:f64> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[bc1:.*]] = llvm.bitcast %[[arg1]] : vector<2xf64> to vector<2xi64> +! CHECK-LLVMIR: %[[bc2:.*]] = llvm.bitcast %[[arg2]] : vector<2xf64> to vector<2xi64> +! CHECK-LLVMIR: %[[r:.*]] = llvm.and %[[bc1]], %[[bc2]] : vector<2xi64> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.bitcast %[[r]] : vector<2xi64> to vector<2xf64> + +! CHECK: %[[arg1:.*]] = load <2 x double>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <2 x double>, ptr %{{.*}}, align 16 +! CHECK: %[[bc1:.*]] = bitcast <2 x double> %[[arg1]] to <2 x i64> +! CHECK: %[[bc2:.*]] = bitcast <2 x double> %[[arg2]] to <2 x i64> +! CHECK: %[[r:.*]] = and <2 x i64> %[[bc1]], %[[bc2]] +! CHECK: %{{[0-9]+}} = bitcast <2 x i64> %[[r]] to <2 x double> +end subroutine vec_and_testf64 + +!---------------------- +! vec_xor +!---------------------- + +! CHECK-LABEL: vec_xor_test_i8 +subroutine vec_xor_test_i8(arg1, arg2) + vector(integer(1)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<16:i8>) -> vector<16xi8> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[varg1]], %[[varg2]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<16xi8>) -> !fir.vector<16:i8> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.xor %[[arg1]], %[[arg2]] : vector<16xi8> + +! CHECK: %[[arg1:.*]] = load <16 x i8>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <16 x i8>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = xor <16 x i8> %[[arg1]], %[[arg2]] +end subroutine vec_xor_test_i8 + +! CHECK-LABEL: vec_xor_test_i16 +subroutine vec_xor_test_i16(arg1, arg2) + vector(integer(2)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<8:i16>) -> vector<8xi16> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[varg1]], %[[varg2]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<8xi16>) -> !fir.vector<8:i16> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.xor %[[arg1]], %[[arg2]] : vector<8xi16> + +! CHECK: %[[arg1:.*]] = load <8 x i16>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <8 x i16>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = xor <8 x i16> %[[arg1]], %[[arg2]] +end subroutine vec_xor_test_i16 + +! CHECK-LABEL: vec_xor_test_i32 +subroutine vec_xor_test_i32(arg1, arg2) + vector(integer(4)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<4:i32>) -> vector<4xi32> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[varg1]], %[[varg2]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<4xi32>) -> !fir.vector<4:i32> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.xor %[[arg1]], %[[arg2]] : vector<4xi32> + +! CHECK: %[[arg1:.*]] = load <4 x i32>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <4 x i32>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = xor <4 x i32> %[[arg1]], %[[arg2]] +end subroutine vec_xor_test_i32 + +! CHECK-LABEL: vec_xor_test_i64 +subroutine vec_xor_test_i64(arg1, arg2) + vector(integer(8)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<2:i64>) -> vector<2xi64> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[varg1]], %[[varg2]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<2xi64>) -> !fir.vector<2:i64> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.xor %[[arg1]], %[[arg2]] : vector<2xi64> + +! CHECK: %[[arg1:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = xor <2 x i64> %[[arg1]], %[[arg2]] +end subroutine vec_xor_test_i64 + +! CHECK-LABEL: vec_xor_test_u8 +subroutine vec_xor_test_u8(arg1, arg2) + vector(unsigned(1)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<16:ui8>) -> vector<16xi8> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[varg1]], %[[varg2]] : vector<16xi8> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<16xi8>) -> !fir.vector<16:ui8> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.xor %[[arg1]], %[[arg2]] : vector<16xi8> + +! CHECK: %[[arg1:.*]] = load <16 x i8>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <16 x i8>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = xor <16 x i8> %[[arg1]], %[[arg2]] +end subroutine vec_xor_test_u8 + +! CHECK-LABEL: vec_xor_test_u16 +subroutine vec_xor_test_u16(arg1, arg2) + vector(unsigned(2)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<8:ui16>) -> vector<8xi16> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[varg1]], %[[varg2]] : vector<8xi16> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<8xi16>) -> !fir.vector<8:ui16> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.xor %[[arg1]], %[[arg2]] : vector<8xi16> + +! CHECK: %[[arg1:.*]] = load <8 x i16>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <8 x i16>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = xor <8 x i16> %[[arg1]], %[[arg2]] +end subroutine vec_xor_test_u16 + +! CHECK-LABEL: vec_xor_test_u32 +subroutine vec_xor_test_u32(arg1, arg2) + vector(unsigned(4)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<4:ui32>) -> vector<4xi32> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[varg1]], %[[varg2]] : vector<4xi32> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<4xi32>) -> !fir.vector<4:ui32> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.xor %[[arg1]], %[[arg2]] : vector<4xi32> + +! CHECK: %[[arg1:.*]] = load <4 x i32>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <4 x i32>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = xor <4 x i32> %[[arg1]], %[[arg2]] +end subroutine vec_xor_test_u32 + +! CHECK-LABEL: vec_xor_test_u64 +subroutine vec_xor_test_u64(arg1, arg2) + vector(unsigned(8)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<2:ui64>) -> vector<2xi64> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[varg1]], %[[varg2]] : vector<2xi64> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[r]] : (vector<2xi64>) -> !fir.vector<2:ui64> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.xor %[[arg1]], %[[arg2]] : vector<2xi64> + +! CHECK: %[[arg1:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <2 x i64>, ptr %{{.*}}, align 16 +! CHECK: %{{[0-9]+}} = xor <2 x i64> %[[arg1]], %[[arg2]] +end subroutine vec_xor_test_u64 + +! CHECK-LABEL: vec_xor_testf32 +subroutine vec_xor_testf32(arg1, arg2) + vector(real(4)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<4:f32>) -> vector<4xf32> +! CHECK-FIR: %[[bc1:.*]] = vector.bitcast %[[varg1]] : vector<4xf32> to vector<4xi32> +! CHECK-FIR: %[[bc2:.*]] = vector.bitcast %[[varg2]] : vector<4xf32> to vector<4xi32> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[bc1]], %[[bc2]] : vector<4xi32> +! CHECK-FIR: %[[vr:.*]] = vector.bitcast %[[r]] : vector<4xi32> to vector<4xf32> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[vr]] : (vector<4xf32>) -> !fir.vector<4:f32> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[bc1:.*]] = llvm.bitcast %[[arg1]] : vector<4xf32> to vector<4xi32> +! CHECK-LLVMIR: %[[bc2:.*]] = llvm.bitcast %[[arg2]] : vector<4xf32> to vector<4xi32> +! CHECK-LLVMIR: %[[r:.*]] = llvm.xor %[[bc1]], %[[bc2]] : vector<4xi32> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.bitcast %[[r]] : vector<4xi32> to vector<4xf32> + +! CHECK: %[[arg1:.*]] = load <4 x float>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <4 x float>, ptr %{{.*}}, align 16 +! CHECK: %[[bc1:.*]] = bitcast <4 x float> %[[arg1]] to <4 x i32> +! CHECK: %[[bc2:.*]] = bitcast <4 x float> %[[arg2]] to <4 x i32> +! CHECK: %[[r:.*]] = xor <4 x i32> %[[bc1]], %[[bc2]] +! CHECK: %{{[0-9]+}} = bitcast <4 x i32> %[[r]] to <4 x float> +end subroutine vec_xor_testf32 + +! CHECK-LABEL: vec_xor_testf64 +subroutine vec_xor_testf64(arg1, arg2) + vector(real(8)) :: r, arg1, arg2 + r = vec_xor(arg1, arg2) +! CHECK-FIR: %[[arg1:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref> +! CHECK-FIR: %[[varg1:.*]] = fir.convert %[[arg1]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[varg2:.*]] = fir.convert %[[arg2]] : (!fir.vector<2:f64>) -> vector<2xf64> +! CHECK-FIR: %[[bc1:.*]] = vector.bitcast %[[varg1]] : vector<2xf64> to vector<2xi64> +! CHECK-FIR: %[[bc2:.*]] = vector.bitcast %[[varg2]] : vector<2xf64> to vector<2xi64> +! CHECK-FIR: %[[r:.*]] = arith.xori %[[bc1]], %[[bc2]] : vector<2xi64> +! CHECK-FIR: %[[vr:.*]] = vector.bitcast %[[r]] : vector<2xi64> to vector<2xf64> +! CHECK-FIR: %{{[0-9]+}} = fir.convert %[[vr]] : (vector<2xf64>) -> !fir.vector<2:f64> + +! CHECK-LLVMIR: %[[arg1:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr> +! CHECK-LLVMIR: %[[bc1:.*]] = llvm.bitcast %[[arg1]] : vector<2xf64> to vector<2xi64> +! CHECK-LLVMIR: %[[bc2:.*]] = llvm.bitcast %[[arg2]] : vector<2xf64> to vector<2xi64> +! CHECK-LLVMIR: %[[r:.*]] = llvm.xor %[[bc1]], %[[bc2]] : vector<2xi64> +! CHECK-LLVMIR: %{{[0-9]+}} = llvm.bitcast %[[r]] : vector<2xi64> to vector<2xf64> + +! CHECK: %[[arg1:.*]] = load <2 x double>, ptr %{{.*}}, align 16 +! CHECK: %[[arg2:.*]] = load <2 x double>, ptr %{{.*}}, align 16 +! CHECK: %[[bc1:.*]] = bitcast <2 x double> %[[arg1]] to <2 x i64> +! CHECK: %[[bc2:.*]] = bitcast <2 x double> %[[arg2]] to <2 x i64> +! CHECK: %[[r:.*]] = xor <2 x i64> %[[bc1]], %[[bc2]] +! CHECK: %{{[0-9]+}} = bitcast <2 x i64> %[[r]] to <2 x double> +end subroutine vec_xor_testf64 + diff --git a/flang/test/Lower/ppc-vector-types.f90 b/flang/test/Lower/PowerPC/ppc-vector-types.f90 rename from flang/test/Lower/ppc-vector-types.f90 rename to flang/test/Lower/PowerPC/ppc-vector-types.f90 diff --git a/flang/test/Semantics/ppc-vector-types01.f90 b/flang/test/Semantics/PowerPC/ppc-vector-types01.f90 rename from flang/test/Semantics/ppc-vector-types01.f90 rename to flang/test/Semantics/PowerPC/ppc-vector-types01.f90 diff --git a/flang/test/Semantics/ppc-vector-types02.f90 b/flang/test/Semantics/PowerPC/ppc-vector-types02.f90 rename from flang/test/Semantics/ppc-vector-types02.f90 rename to flang/test/Semantics/PowerPC/ppc-vector-types02.f90 diff --git a/flang/test/Semantics/PowerPC/ppc-vector-types03.f90 b/flang/test/Semantics/PowerPC/ppc-vector-types03.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/PowerPC/ppc-vector-types03.f90 @@ -0,0 +1,21 @@ +! RUN: %python %S/../test_errors.py %s %flang_fc1 +! REQUIRES: target=aarch64{{.*}} || target=arm{{.*}} || target=x86{{.*}} + +program ppc_vec_types04 + implicit none +!ERROR: Vector type is only supported for PowerPC +!ERROR: No explicit type declared for 'vi' + vector(integer(4)) :: vi +!ERROR: Vector type is only supported for PowerPC +!ERROR: No explicit type declared for 'vr' + vector(real(8)) :: vr +!ERROR: Vector type is only supported for PowerPC +!ERROR: No explicit type declared for 'vu' + vector(unsigned(2)) :: vu +!ERROR: Vector type is only supported for PowerPC +!ERROR: No explicit type declared for 'vp' + __vector_pair :: vp +!ERROR: Vector type is only supported for PowerPC +!ERROR: No explicit type declared for 'vq' + __vector_quad :: vq +end program ppc_vec_types04 diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp --- a/flang/tools/bbc/bbc.cpp +++ b/flang/tools/bbc/bbc.cpp @@ -421,6 +421,8 @@ semanticsContext.targetCharacteristics().DisableType( Fortran::common::TypeCategory::Real, /*kind=*/10); } + if (targetTriple.isPPC()) + semanticsContext.targetCharacteristics().set_isPPC(true); return mlir::failed(convertFortranSourceToMLIR( inputFilename, options, programPrefix, semanticsContext, passPipe)); diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt --- a/flang/tools/f18/CMakeLists.txt +++ b/flang/tools/f18/CMakeLists.txt @@ -44,9 +44,16 @@ set(depends ${FLANG_INTRINSIC_MODULES_DIR}/__fortran_ieee_exceptions.mod) endif() endif() + + # The module contains PPC vector types that needs the PPC target. + set(opts "") + if(${filename} STREQUAL "__fortran_ppc_intrinsics") + set(opts "--target=ppc64le") + endif() + add_custom_command(OUTPUT ${base}.mod COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR} - COMMAND flang-new -fc1 -cpp -fsyntax-only -module-dir ${FLANG_INTRINSIC_MODULES_DIR} + COMMAND flang-new -cpp -fsyntax-only ${opts} -module-dir ${FLANG_INTRINSIC_MODULES_DIR} ${FLANG_SOURCE_DIR}/module/${filename}.f90 DEPENDS flang-new ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${depends} )