[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