[flang-commits] [flang] a9e1d2e - [flang] Add PowerPC vec_add, vec_and, vec_mul, vec_sub and vec_xor intrinsics
Kelvin Li via flang-commits
flang-commits at lists.llvm.org
Tue Jun 13 13:06:53 PDT 2023
Author: Kelvin Li
Date: 2023-06-13T16:05:21-04:00
New Revision: a9e1d2e760b502fb31ad522b0885a2150f008e86
URL: https://github.com/llvm/llvm-project/commit/a9e1d2e760b502fb31ad522b0885a2150f008e86
DIFF: https://github.com/llvm/llvm-project/commit/a9e1d2e760b502fb31ad522b0885a2150f008e86.diff
LOG: [flang] Add PowerPC vec_add, vec_and, vec_mul, vec_sub and vec_xor intrinsics
Differential Revision: https://reviews.llvm.org/D151857
Added:
flang/test/Lower/PowerPC/ppc-intrinsics.f90
flang/test/Lower/PowerPC/ppc-vec_add-and-mul-sub-xor.f90
flang/test/Lower/PowerPC/ppc-vector-types.f90
flang/test/Semantics/PowerPC/ppc-vector-types01.f90
flang/test/Semantics/PowerPC/ppc-vector-types02.f90
flang/test/Semantics/PowerPC/ppc-vector-types03.f90
Modified:
flang/include/flang/Evaluate/target.h
flang/include/flang/Optimizer/Builder/IntrinsicCall.h
flang/include/flang/Optimizer/Dialect/FIROps.td
flang/lib/Evaluate/target.cpp
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/Optimizer/Builder/IntrinsicCall.cpp
flang/lib/Optimizer/CodeGen/CMakeLists.txt
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/lib/Optimizer/Dialect/FIROps.cpp
flang/lib/Semantics/resolve-names.cpp
flang/lib/Semantics/semantics.cpp
flang/module/__fortran_ppc_intrinsics.f90
flang/tools/bbc/bbc.cpp
flang/tools/f18/CMakeLists.txt
Removed:
flang/test/Lower/ppc-intrinsics.f90
flang/test/Lower/ppc-vector-types.f90
flang/test/Semantics/ppc-vector-types01.f90
flang/test/Semantics/ppc-vector-types02.f90
################################################################################
diff --git a/flang/include/flang/Evaluate/target.h b/flang/include/flang/Evaluate/target.h
index bcf9d83100b18..80deac5952301 100644
--- a/flang/include/flang/Evaluate/target.h
+++ b/flang/include/flang/Evaluate/target.h
@@ -91,11 +91,15 @@ class TargetCharacteristics {
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
index 348b354a5fefb..db08fbfe5469d 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -88,6 +88,10 @@ enum class LowerIntrinsicArgAs {
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 @@ struct IntrinsicLibrary {
mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args);
+ template <VecOp>
+ fir::ExtendedValue
+ genVecAddAndMulSubXor(mlir::Type resultType,
+ llvm::ArrayRef<fir::ExtendedValue> args);
+
/// Define the
diff erent 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
index a6a19d41e99ce..c9d68f1e1cf90 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -2610,6 +2610,7 @@ def fir_ConvertOp : fir_OneResultOp<"convert", [NoMemoryEffect]> {
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
index b678f283c55ef..98925b2be617e 100644
--- a/flang/lib/Evaluate/target.cpp
+++ b/flang/lib/Evaluate/target.cpp
@@ -102,6 +102,8 @@ void TargetCharacteristics::set_isBigEndian(bool isBig) {
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
index 55fe9890be2aa..610f60c5899bb 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1107,6 +1107,9 @@ void CompilerInvocation::setSemanticsOpts(
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
index 384d8e9ad56ef..f595bbeac1935 100644
--- 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 @@ static bool isStaticallyPresent(const fir::ExtendedValue &exv) {
return !isStaticallyAbsent(exv);
}
+//===----------------------------------------------------------------------===//
+// Helper functions for argument handling in vector intrinsics.
+//===----------------------------------------------------------------------===//
+static mlir::Type getConvertedElementType(mlir::MLIRContext *context,
+ mlir::Type eleTy) {
+ if (eleTy.isa<mlir::IntegerType>() && !eleTy.isSignlessInteger()) {
+ const auto intTy{eleTy.dyn_cast<mlir::IntegerType>()};
+ 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<mlir::Float32Type>(eleTy); }
+
+ bool isFloat64() { return mlir::isa<mlir::Float64Type>(eleTy); }
+
+ bool isFloat() { return isFloat32() || isFloat64(); }
+};
+
+static llvm::SmallVector<mlir::Value>
+getBasesForArgs(llvm::ArrayRef<fir::ExtendedValue> args) {
+ llvm::SmallVector<mlir::Value, 4> baseVec;
+ for (auto arg : args)
+ baseVec.push_back(getBase(arg));
+ return baseVec;
+}
+
+static llvm::SmallVector<mlir::Type>
+getTypesForArgs(llvm::ArrayRef<mlir::Value> args) {
+ llvm::SmallVector<mlir::Type, 4> 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<fir::VectorType>());
+ VecTypeInfo vecTyInfo;
+ vecTyInfo.eleTy = firTy.dyn_cast<fir::VectorType>().getEleTy();
+ vecTyInfo.len = firTy.dyn_cast<fir::VectorType>().getLen();
+ return vecTyInfo;
+}
+
+static VecTypeInfo getVecTypeFromFir(mlir::Value firVec) {
+ return getVecTypeFromFirType(firVec.getType());
+}
+
+// Converts array of fir vectors to mlir vectors.
+static llvm::SmallVector<mlir::Value>
+convertVecArgs(fir::FirOpBuilder &builder, mlir::Location loc,
+ VecTypeInfo vecTyInfo, llvm::SmallVector<mlir::Value> args) {
+ llvm::SmallVector<mlir::Value, 4> 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 @@ static constexpr IntrinsicHandler ppcHandlers[]{
&I::genMtfsf<true>,
{{{"bf", asValue}, {"i", asValue}}},
/*isElemental=*/false},
+ {"__ppc_vec_add",
+ &I::genVecAddAndMulSubXor<VecOp::Add>,
+ {{{"arg1", asValue}, {"arg2", asValue}}},
+ /*isElemental=*/true},
+ {"__ppc_vec_and",
+ &I::genVecAddAndMulSubXor<VecOp::And>,
+ {{{"arg1", asValue}, {"arg2", asValue}}},
+ /*isElemental=*/true},
+ {"__ppc_vec_mul",
+ &I::genVecAddAndMulSubXor<VecOp::Mul>,
+ {{{"arg1", asValue}, {"arg2", asValue}}},
+ /*isElemental=*/true},
+ {"__ppc_vec_sub",
+ &I::genVecAddAndMulSubXor<VecOp::Sub>,
+ {{{"arg1", asValue}, {"arg2", asValue}}},
+ /*isElemental=*/true},
+ {"__ppc_vec_xor",
+ &I::genVecAddAndMulSubXor<VecOp::Xor>,
+ {{{"arg1", asValue}, {"arg2", asValue}}},
+ /*isElemental=*/true},
};
static const IntrinsicHandler *findIntrinsicHandler(llvm::StringRef name) {
@@ -4505,6 +4604,73 @@ mlir::Value IntrinsicLibrary::genTrailz(mlir::Type resultType,
return builder.createConvert(loc, resultType, result);
}
+// VEC_ADD, VEC_AND, VEC_SUB, VEC_MUL, VEC_XOR
+template <VecOp vop>
+fir::ExtendedValue IntrinsicLibrary::genVecAddAndMulSubXor(
+ mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args) {
+ assert(args.size() == 2);
+ auto argBases{getBasesForArgs(args)};
+ auto argsTy{getTypesForArgs(argBases)};
+ assert(argsTy[0].isa<fir::VectorType>() && argsTy[1].isa<fir::VectorType>());
+
+ auto vecTyInfo{getVecTypeFromFir(argBases[0])};
+
+ const auto isInteger{vecTyInfo.eleTy.isa<mlir::IntegerType>()};
+ const auto isFloat{vecTyInfo.eleTy.isa<mlir::FloatType>()};
+ 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<mlir::arith::AddIOp>(loc, vargs[0], vargs[1]);
+ else if (isFloat)
+ r = builder.create<mlir::arith::AddFOp>(loc, vargs[0], vargs[1]);
+ break;
+ case VecOp::Mul:
+ if (isInteger)
+ r = builder.create<mlir::arith::MulIOp>(loc, vargs[0], vargs[1]);
+ else if (isFloat)
+ r = builder.create<mlir::arith::MulFOp>(loc, vargs[0], vargs[1]);
+ break;
+ case VecOp::Sub:
+ if (isInteger)
+ r = builder.create<mlir::arith::SubIOp>(loc, vargs[0], vargs[1]);
+ else if (isFloat)
+ r = builder.create<mlir::arith::SubFOp>(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<mlir::FloatType>().getWidth()};
+ auto ftype{builder.getIntegerType(wd)};
+ auto bcVecTy{mlir::VectorType::get(vecTyInfo.len, ftype)};
+ arg1 = builder.create<mlir::vector::BitCastOp>(loc, bcVecTy, vargs[0]);
+ arg2 = builder.create<mlir::vector::BitCastOp>(loc, bcVecTy, vargs[1]);
+ }
+ if (vop == VecOp::And)
+ r = builder.create<mlir::arith::AndIOp>(loc, arg1, arg2);
+ else if (vop == VecOp::Xor)
+ r = builder.create<mlir::arith::XOrIOp>(loc, arg1, arg2);
+
+ if (isFloat)
+ r = builder.create<mlir::vector::BitCastOp>(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
index 016544ef870a5..0b2e3943c1068 100644
--- a/flang/lib/Optimizer/CodeGen/CMakeLists.txt
+++ b/flang/lib/Optimizer/CodeGen/CMakeLists.txt
@@ -27,6 +27,7 @@ add_flang_library(FIRCodeGen
MLIRBuiltinToLLVMIRTranslation
MLIRLLVMToLLVMIRTranslation
MLIRTargetLLVMIRExport
+ MLIRVectorToLLVM
LINK_COMPONENTS
AsmParser
diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp
index f3565c04abcb8..2e207a9caab4d 100644
--- 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 @@ class FIRToLLVMLowering
// to Libm.
mlir::populateMathToLibmConversionPatterns(pattern);
mlir::populateComplexToLLVMConversionPatterns(typeConverter, pattern);
+ mlir::populateVectorToLLVMConversionPatterns(typeConverter, pattern);
mlir::ConversionTarget target{*context};
target.addLegalDialect<mlir::LLVM::LLVMDialect>();
// 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
index cad27cf703bc1..e796f2c385d95 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -943,6 +943,59 @@ bool fir::ConvertOp::isPointerCompatible(mlir::Type ty) {
fir::TypeDescType>();
}
+static std::optional<mlir::Type> getVectorElementType(mlir::Type ty) {
+ if (mlir::isa<fir::VectorType>(ty)) {
+ auto elemTy = mlir::dyn_cast<fir::VectorType>(ty).getEleTy();
+
+ // fir.vector<4:ui32> is converted to mlir.vector<4xi32>
+ if (elemTy.isUnsignedInteger()) {
+ elemTy = mlir::IntegerType::get(
+ ty.getContext(),
+ mlir::dyn_cast<mlir::IntegerType>(elemTy).getWidth());
+ }
+ return elemTy;
+ } else if (mlir::isa<mlir::VectorType>(ty))
+ return mlir::dyn_cast<mlir::VectorType>(ty).getElementType();
+
+ return std::nullopt;
+}
+
+static std::optional<uint64_t> getVectorLen(mlir::Type ty) {
+ if (mlir::isa<fir::VectorType>(ty))
+ return mlir::dyn_cast<fir::VectorType>(ty).getLen();
+ else if (mlir::isa<mlir::VectorType>(ty)) {
+ // fir.vector only supports 1-D vector
+ if (mlir::dyn_cast<mlir::VectorType>(ty).getNumScalableDims() == 0)
+ return mlir::dyn_cast<mlir::VectorType>(ty).getShape()[0];
+ }
+
+ return std::nullopt;
+}
+
+bool fir::ConvertOp::areVectorsCompatible(mlir::Type inTy, mlir::Type outTy) {
+ if (!(mlir::isa<fir::VectorType>(inTy) &&
+ mlir::isa<mlir::VectorType>(outTy)) &&
+ !(mlir::isa<mlir::VectorType>(inTy) && mlir::isa<fir::VectorType>(outTy)))
+ return false;
+
+ // Only support integer, unsigned and real vector
+ // Both vectors must have the same element type
+ std::optional<mlir::Type> inElemTy = getVectorElementType(inTy);
+ std::optional<mlir::Type> 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<uint64_t> inLen = getVectorLen(inTy);
+ std::optional<uint64_t> 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 @@ bool fir::ConvertOp::canBeConverted(mlir::Type inType, mlir::Type outType) {
(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<BoxType>());
+ (fir::isPolymorphicType(inType) && outType.isa<BoxType>()) ||
+ areVectorsCompatible(inType, outType);
}
mlir::LogicalResult fir::ConvertOp::verify() {
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 0df8a5765124b..45d94313f2321 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -4849,6 +4849,13 @@ int DeclarationVisitor::GetVectorElementKind(
}
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
index 7f2f64ecb1bd1..428dadb539e8f 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -513,19 +513,21 @@ bool Semantics::Perform() {
if (frontModule &&
(std::get<parser::Statement<parser::ModuleStmt>>(frontModule->value().t)
.statement.v.source == "__fortran_builtins" ||
- std::get<parser::Statement<parser::ModuleStmt>>(
- frontModule->value().t)
- .statement.v.source == "__fortran_ppc_intrinsics" ||
std::get<parser::Statement<parser::ModuleStmt>>(
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<parser::Statement<parser::ModuleStmt>>(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
index 906aba701ec37..bcaef97422bd2 100644
--- a/flang/module/__fortran_ppc_intrinsics.f90
+++ b/flang/module/__fortran_ppc_intrinsics.f90
@@ -18,6 +18,37 @@ end function func_r4r4r4r4
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 function func_r8r8i
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
similarity index 100%
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
index 0000000000000..d6ce91e067a8b
--- /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<!fir.vector<4:f32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:f32>>
+! 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<contract> : vector<4xf32>
+! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<4xf32>) -> !fir.vector<4:f32>
+
+! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr<vector<4xf32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xf32>>
+! CHECK-LLVMIR: %{{[0-9]}} = llvm.fadd %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath<contract>} : 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<!fir.vector<2:f64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:f64>>
+! 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<contract> : vector<2xf64>
+! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsum]] : (vector<2xf64>) -> !fir.vector<2:f64>
+
+! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr<vector<2xf64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xf64>>
+! CHECK-LLVMIR: %{{[0-9]}} = llvm.fadd %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath<contract>} : 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<!fir.vector<16:i8>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<16:i8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:i16>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<8:i16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:i32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:i32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:i64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:i64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<16:ui8>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<16:ui8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:ui16>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<8:ui16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:ui32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:ui32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:ui64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:ui64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<4:f32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:f32>>
+! 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<contract> : vector<4xf32>
+! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<4xf32>) -> !fir.vector<4:f32>
+
+! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr<vector<4xf32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xf32>>
+! CHECK-LLVMIR: %{{[0-9]}} = llvm.fmul %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath<contract>} : 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<!fir.vector<2:f64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:f64>>
+! 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<contract> : vector<2xf64>
+! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vmul]] : (vector<2xf64>) -> !fir.vector<2:f64>
+
+! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr<vector<2xf64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xf64>>
+! CHECK-LLVMIR: %{{[0-9]}} = llvm.fmul %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath<contract>} : 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<!fir.vector<16:i8>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<16:i8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:i16>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<8:i16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:i32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:i32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:i64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:i64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<16:ui8>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<16:ui8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:ui16>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<8:ui16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:ui32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:ui32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:ui64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:ui64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<4:f32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:f32>>
+! 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<contract> : vector<4xf32>
+! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<4xf32>) -> !fir.vector<4:f32>
+
+! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr<vector<4xf32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xf32>>
+! CHECK-LLVMIR: %{{[0-9]}} = llvm.fsub %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath<contract>} : 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<!fir.vector<2:f64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:f64>>
+! 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<contract> : vector<2xf64>
+! CHECK-FIR: %{{[0-9]}} = fir.convert %[[vsub]] : (vector<2xf64>) -> !fir.vector<2:f64>
+
+! CHECK-LLVMIR: %[[x:.*]] = llvm.load %arg0 : !llvm.ptr<vector<2xf64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xf64>>
+! CHECK-LLVMIR: %{{[0-9]}} = llvm.fsub %[[x]], %[[y]] {fastmathFlags = #llvm.fastmath<contract>} : 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<!fir.vector<16:i8>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<16:i8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:i16>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<8:i16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:i32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:i32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:i64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:i64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<16:ui8>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<16:ui8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:ui16>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<8:ui16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:ui32>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<4:ui32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:ui64>>
+! CHECK-FIR: %[[y:.*]] = fir.load %arg1 : !fir.ref<!fir.vector<2:ui64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[y:.*]] = llvm.load %arg1 : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<16:i8>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<16:i8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:i16>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<8:i16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:i32>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<4:i32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:i64>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<2:i64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<16:ui8>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<16:ui8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:ui16>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<8:ui16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:ui32>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<4:ui32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:ui64>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<2:ui64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<4:f32>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<4:f32>>
+! 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<vector<4xf32>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<4xf32>>
+! 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<!fir.vector<2:f64>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<2:f64>>
+! 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<vector<2xf64>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<2xf64>>
+! 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<!fir.vector<16:i8>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<16:i8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:i16>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<8:i16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:i32>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<4:i32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:i64>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<2:i64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<16:ui8>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<16:ui8>>
+! 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<vector<16xi8>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<16xi8>>
+! 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<!fir.vector<8:ui16>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<8:ui16>>
+! 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<vector<8xi16>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<8xi16>>
+! 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<!fir.vector<4:ui32>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<4:ui32>>
+! 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<vector<4xi32>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<4xi32>>
+! 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<!fir.vector<2:ui64>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<2:ui64>>
+! 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<vector<2xi64>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<2xi64>>
+! 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<!fir.vector<4:f32>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<4:f32>>
+! 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<vector<4xf32>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<4xf32>>
+! 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<!fir.vector<2:f64>>
+! CHECK-FIR: %[[arg2:.*]] = fir.load %{{.*}} : !fir.ref<!fir.vector<2:f64>>
+! 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<vector<2xf64>>
+! CHECK-LLVMIR: %[[arg2:.*]] = llvm.load %{{.*}} : !llvm.ptr<vector<2xf64>>
+! 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
similarity index 100%
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
similarity index 100%
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
similarity index 100%
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
index 0000000000000..516b5eeb01d3a
--- /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
index f00b2189242f0..6c17ab9ad3125 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -421,6 +421,8 @@ int main(int argc, char **argv) {
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
index d4e882d3e4ec5..7a22bbef555d7 100644
--- a/flang/tools/f18/CMakeLists.txt
+++ b/flang/tools/f18/CMakeLists.txt
@@ -44,9 +44,16 @@ if (NOT CMAKE_CROSSCOMPILING)
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}
)
More information about the flang-commits
mailing list