瀏覽代碼

[spirv] Translate more instrinsic functions (#537)

Using GLSL 450 extended instruction set to translate some HLSL
intrinsic functions.
Ehsan 8 年之前
父節點
當前提交
ff65329ee2
共有 36 個文件被更改,包括 1873 次插入34 次删除
  1. 69 1
      docs/SPIR-V.rst
  2. 12 0
      tools/clang/include/clang/SPIRV/ModuleBuilder.h
  3. 15 15
      tools/clang/include/clang/SPIRV/Structure.h
  4. 19 1
      tools/clang/lib/SPIRV/ModuleBuilder.cpp
  5. 124 8
      tools/clang/lib/SPIRV/SPIRVEmitter.cpp
  6. 21 4
      tools/clang/lib/SPIRV/SPIRVEmitter.h
  7. 5 5
      tools/clang/lib/SPIRV/Structure.cpp
  8. 10 0
      tools/clang/lib/SPIRV/TypeTranslator.cpp
  9. 79 0
      tools/clang/test/CodeGenSPIRV/intrinsics.abs.hlsl
  10. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.acos.hlsl
  11. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.asin.hlsl
  12. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.atan.hlsl
  13. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.ceil.hlsl
  14. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.cos.hlsl
  15. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.cosh.hlsl
  16. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.degrees.hlsl
  17. 17 0
      tools/clang/test/CodeGenSPIRV/intrinsics.determinant.hlsl
  18. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.exp.hlsl
  19. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.exp2.hlsl
  20. 51 0
      tools/clang/test/CodeGenSPIRV/intrinsics.floatsign.hlsl
  21. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.floor.hlsl
  22. 60 0
      tools/clang/test/CodeGenSPIRV/intrinsics.intsign.hlsl
  23. 28 0
      tools/clang/test/CodeGenSPIRV/intrinsics.length.hlsl
  24. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.log.hlsl
  25. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.log2.hlsl
  26. 32 0
      tools/clang/test/CodeGenSPIRV/intrinsics.normalize.hlsl
  27. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.radians.hlsl
  28. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.round.hlsl
  29. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.rsqrt.hlsl
  30. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.sin.hlsl
  31. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.sinh.hlsl
  32. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.sqrt.hlsl
  33. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.tan.hlsl
  34. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.tanh.hlsl
  35. 62 0
      tools/clang/test/CodeGenSPIRV/intrinsics.trunc.hlsl
  36. 29 0
      tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

+ 69 - 1
docs/SPIR-V.rst

@@ -460,7 +460,75 @@ Intrinsic functions
 
 
 The following intrinsic HLSL functions are currently supported:
 The following intrinsic HLSL functions are currently supported:
 
 
-- `dot` : performs dot product of two vectors, each containing floats or integers. If the two parameters are vectors of floats, we use SPIR-V's OpDot instruction to perform the translation. If the two parameters are vectors of integers, we multiply corresponding vector elementes using OpIMul and accumulate the results using OpIAdd to compute the dot product.
+- ``dot`` : performs dot product of two vectors, each containing floats or integers. If the two parameters are vectors of floats, we use SPIR-V's OpDot instruction to perform the translation. If the two parameters are vectors of integers, we multiply corresponding vector elementes using OpIMul and accumulate the results using OpIAdd to compute the dot product.
+
+- ``all``: returns true if all components of the given scalar, vector, or matrix are true. Performs conversions to boolean where necessary. Uses SPIR-V ``OpAll`` for scalar arguments and vector arguments. For matrix arguments, performs ``OpAll`` on each row, and then again on the vector containing the results of all rows.
+
+- ``any``: returns true if any component of the given scalar, vector, or matrix is true. Performs conversions to boolean where necessary. Uses SPIR-V ``OpAny`` for scalar arguments and vector arguments. For matrix arguments, performs ``OpAny`` on each row, and then again on the vector containing the results of all rows.
+
+- ``asfloat``: converts the component type of a scalar/vector/matrix from float, uint, or int into float. Uses ``OpBitcast``. This method currently does not support taking non-float matrix arguments.
+
+- ``asint``: converts the component type of a scalar/vector/matrix from float or uint into int. Uses ``OpBitcast``. This method currently does not support conversion into integer matrices.
+
+- ``asuint``: converts the component type of a scalar/vector/matrix from float or int into uint. Uses ``OpBitcast``. This method currently does not support conversion into unsigned integer matrices.
+
+- Using SPIR-V Extended Instructions for GLSL: the following intrinsic HLSL functions are translated using their equivalent instruction in the GLSL extended instruction set.
+
++-----------------------------+-----------------------------------------------------+
+|   HLSL intrinsic function   |               GLSL Extended Instruction             |
++-----------------------------+-----------------------------------------------------+
+|        ``abs``              |   ``SAbs`` for ints, and ``FAbs`` for floats        |
++-----------------------------+-----------------------------------------------------+
+|        ``acos``             |                       ``Acos``                      |
++-----------------------------+-----------------------------------------------------+
+|        ``asin``             |                       ``Asin``                      |
++-----------------------------+-----------------------------------------------------+
+|        ``atan``             |                       ``Atan``                      |
++-----------------------------+-----------------------------------------------------+
+|        ``ceil``             |                       ``Ceil``                      |
++-----------------------------+-----------------------------------------------------+
+|        ``cos``              |                       ``Cos``                       |
++-----------------------------+-----------------------------------------------------+
+|        ``cosh``             |                       ``Cosh``                      |
++-----------------------------+-----------------------------------------------------+
+|       ``degrees``           |                      ``Degrees``                    |
++-----------------------------+-----------------------------------------------------+
+|       ``radians``           |                      ``Radian``                     |
++-----------------------------+-----------------------------------------------------+
+|    ``determinant``          |                   ``Determinant``                   |
++-----------------------------+-----------------------------------------------------+
+|        ``exp``              |                       ``Exp``                       |
++-----------------------------+-----------------------------------------------------+
+|        ``exp2``             |                       ``exp2``                      |
++-----------------------------+-----------------------------------------------------+
+|        ``floor``            |                       ``Floor``                     |
++-----------------------------+-----------------------------------------------------+
+|      ``length``             |                     ``Length``                      |
++-----------------------------+-----------------------------------------------------+
+|        ``log``              |                       ``Log``                       |
++-----------------------------+-----------------------------------------------------+
+|        ``log2``             |                       ``Log2``                      |
++-----------------------------+-----------------------------------------------------+
+|     ``normalize``           |                   ``Normalize``                     |
++-----------------------------+-----------------------------------------------------+
+|        ``round``            |                      ``Round``                      |
++-----------------------------+-----------------------------------------------------+
+|       ``rsqrt``             |                  ``InverseSqrt``                    |
++-----------------------------+-----------------------------------------------------+
+|       ``sign``              |   ``SSign`` for ints, and ``FSign`` for floats      |
++-----------------------------+-----------------------------------------------------+
+|        ``sin``              |                       ``Sin``                       |
++-----------------------------+-----------------------------------------------------+
+|        ``sinh``             |                       ``Sinh``                      |
++-----------------------------+-----------------------------------------------------+
+|        ``tan``              |                       ``Tan``                       |
++-----------------------------+-----------------------------------------------------+
+|        ``tanh``             |                       ``Tanh``                      |
++-----------------------------+-----------------------------------------------------+
+|        ``sqrt``             |                       ``Sqrt``                      |
++-----------------------------+-----------------------------------------------------+
+|       ``trunc``             |                      ``Trunc``                      |
++-----------------------------+-----------------------------------------------------+
 
 
 Logistics
 Logistics
 =========
 =========

+ 12 - 0
tools/clang/include/clang/SPIRV/ModuleBuilder.h

@@ -172,6 +172,12 @@ public:
   /// \brief Creates a return value instruction.
   /// \brief Creates a return value instruction.
   void createReturnValue(uint32_t value);
   void createReturnValue(uint32_t value);
 
 
+  /// \brief Creates an OpExtInst instruction with the given instruction set id,
+  /// instruction number, and operands. Returns the <result-id> of the
+  /// instruction.
+  uint32_t createExtInst(uint32_t resultType, uint32_t setId, uint32_t instId,
+                         llvm::ArrayRef<uint32_t> operands);
+
   // === SPIR-V Module Structure ===
   // === SPIR-V Module Structure ===
 
 
   inline void requireCapability(spv::Capability);
   inline void requireCapability(spv::Capability);
@@ -189,6 +195,11 @@ public:
   void addExecutionMode(uint32_t entryPointId, spv::ExecutionMode em,
   void addExecutionMode(uint32_t entryPointId, spv::ExecutionMode em,
                         const std::vector<uint32_t> &params);
                         const std::vector<uint32_t> &params);
 
 
+  /// \brief If not added already, adds an OpExtInstImport (import of extended
+  /// instruction set) of the GLSL instruction set. Returns the <result-id> for
+  /// the imported GLSL instruction set.
+  uint32_t getGLSLExtInstSet();
+
   /// \brief Adds a stage input/ouput variable whose value is of the given type.
   /// \brief Adds a stage input/ouput variable whose value is of the given type.
   ///
   ///
   /// The corresponding pointer type of the given type will be constructed in
   /// The corresponding pointer type of the given type will be constructed in
@@ -251,6 +262,7 @@ private:
   /// The constructed instruction will appear in constructSite.
   /// The constructed instruction will appear in constructSite.
   InstBuilder instBuilder;
   InstBuilder instBuilder;
   std::vector<uint32_t> constructSite; ///< InstBuilder construction site.
   std::vector<uint32_t> constructSite; ///< InstBuilder construction site.
+  uint32_t glslExtSetId; ///< The <result-id> of GLSL extended instruction set.
 };
 };
 
 
 SPIRVContext *ModuleBuilder::getSPIRVContext() { return &theContext; }
 SPIRVContext *ModuleBuilder::getSPIRVContext() { return &theContext; }

+ 15 - 15
tools/clang/include/clang/SPIRV/Structure.h

@@ -212,14 +212,6 @@ struct Header {
   const uint32_t reserved;
   const uint32_t reserved;
 };
 };
 
 
-/// \brief The struct representing an extended instruction set.
-struct ExtInstSet {
-  inline ExtInstSet(uint32_t id, std::string name);
-
-  const uint32_t resultId;
-  const std::string setName;
-};
-
 /// \brief The struct representing an entry point.
 /// \brief The struct representing an entry point.
 struct EntryPoint {
 struct EntryPoint {
   inline EntryPoint(spv::ExecutionModel, uint32_t id, std::string name,
   inline EntryPoint(spv::ExecutionModel, uint32_t id, std::string name,
@@ -289,7 +281,7 @@ public:
 
 
   inline void addCapability(spv::Capability);
   inline void addCapability(spv::Capability);
   inline void addExtension(std::string extension);
   inline void addExtension(std::string extension);
-  inline void addExtInstSet(uint32_t setId, std::string extInstSet);
+  inline void addExtInstSet(uint32_t setId, llvm::StringRef extInstSet);
   inline void setAddressingModel(spv::AddressingModel);
   inline void setAddressingModel(spv::AddressingModel);
   inline void setMemoryModel(spv::MemoryModel);
   inline void setMemoryModel(spv::MemoryModel);
   inline void addEntryPoint(spv::ExecutionModel, uint32_t targetId,
   inline void addEntryPoint(spv::ExecutionModel, uint32_t targetId,
@@ -305,6 +297,10 @@ public:
   inline void addVariable(Instruction &&);
   inline void addVariable(Instruction &&);
   inline void addFunction(std::unique_ptr<Function>);
   inline void addFunction(std::unique_ptr<Function>);
 
 
+  /// \brief Returns the <result-id> of the given extended instruction set.
+  /// Returns 0 if the given set has not been imported.
+  inline uint32_t getExtInstSetId(llvm::StringRef setName);
+
 private:
 private:
   /// \brief Collects all the Integer type definitions in this module and
   /// \brief Collects all the Integer type definitions in this module and
   /// consumes them using the consumer within the given InstBuilder.
   /// consumes them using the consumer within the given InstBuilder.
@@ -322,7 +318,7 @@ private:
   Header header; ///< SPIR-V module header.
   Header header; ///< SPIR-V module header.
   std::vector<spv::Capability> capabilities;
   std::vector<spv::Capability> capabilities;
   std::vector<std::string> extensions;
   std::vector<std::string> extensions;
-  std::vector<ExtInstSet> extInstSets;
+  llvm::MapVector<const char *, uint32_t> extInstSets;
   // Addressing and memory model must exist for a valid SPIR-V module.
   // Addressing and memory model must exist for a valid SPIR-V module.
   // We make them optional here just to provide extra flexibility of
   // We make them optional here just to provide extra flexibility of
   // the representation.
   // the representation.
@@ -410,9 +406,6 @@ void Function::addBasicBlock(std::unique_ptr<BasicBlock> block) {
 
 
 // === Module components inline implementations ===
 // === Module components inline implementations ===
 
 
-ExtInstSet::ExtInstSet(uint32_t id, std::string name)
-    : resultId(id), setName(name) {}
-
 EntryPoint::EntryPoint(spv::ExecutionModel em, uint32_t id, std::string name,
 EntryPoint::EntryPoint(spv::ExecutionModel em, uint32_t id, std::string name,
                        const std::vector<uint32_t> &interface)
                        const std::vector<uint32_t> &interface)
     : executionModel(em), targetId(id), targetName(std::move(name)),
     : executionModel(em), targetId(id), targetName(std::move(name)),
@@ -442,8 +435,15 @@ void SPIRVModule::addExtension(std::string ext) {
   extensions.push_back(std::move(ext));
   extensions.push_back(std::move(ext));
 }
 }
 
 
-void SPIRVModule::addExtInstSet(uint32_t setId, std::string extInstSet) {
-  extInstSets.emplace_back(setId, extInstSet);
+uint32_t SPIRVModule::getExtInstSetId(llvm::StringRef setName) {
+  const auto &iter = extInstSets.find(setName.data());
+  if (iter != extInstSets.end())
+    return iter->second;
+  return 0;
+}
+
+void SPIRVModule::addExtInstSet(uint32_t setId, llvm::StringRef extInstSet) {
+  extInstSets.insert(std::make_pair(extInstSet.data(), setId));
 }
 }
 
 
 void SPIRVModule::setAddressingModel(spv::AddressingModel am) {
 void SPIRVModule::setAddressingModel(spv::AddressingModel am) {

+ 19 - 1
tools/clang/lib/SPIRV/ModuleBuilder.cpp

@@ -18,7 +18,7 @@ namespace spirv {
 
 
 ModuleBuilder::ModuleBuilder(SPIRVContext *C)
 ModuleBuilder::ModuleBuilder(SPIRVContext *C)
     : theContext(*C), theModule(), theFunction(nullptr), insertPoint(nullptr),
     : theContext(*C), theModule(), theFunction(nullptr), insertPoint(nullptr),
-      instBuilder(nullptr) {
+      instBuilder(nullptr), glslExtSetId(0) {
   instBuilder.setConsumer([this](std::vector<uint32_t> &&words) {
   instBuilder.setConsumer([this](std::vector<uint32_t> &&words) {
     this->constructSite = std::move(words);
     this->constructSite = std::move(words);
   });
   });
@@ -274,6 +274,16 @@ void ModuleBuilder::createReturnValue(uint32_t value) {
   insertPoint->appendInstruction(std::move(constructSite));
   insertPoint->appendInstruction(std::move(constructSite));
 }
 }
 
 
+uint32_t ModuleBuilder::createExtInst(uint32_t resultType, uint32_t setId,
+                                      uint32_t instId,
+                                      llvm::ArrayRef<uint32_t> operands) {
+  assert(insertPoint && "null insert point");
+  uint32_t resultId = theContext.takeNextId();
+  instBuilder.opExtInst(resultType, resultId, setId, instId, operands).x();
+  insertPoint->appendInstruction(std::move(constructSite));
+  return resultId;
+}
+
 void ModuleBuilder::addExecutionMode(uint32_t entryPointId,
 void ModuleBuilder::addExecutionMode(uint32_t entryPointId,
                                      spv::ExecutionMode em,
                                      spv::ExecutionMode em,
                                      const std::vector<uint32_t> &params) {
                                      const std::vector<uint32_t> &params) {
@@ -285,6 +295,14 @@ void ModuleBuilder::addExecutionMode(uint32_t entryPointId,
   theModule.addExecutionMode(std::move(constructSite));
   theModule.addExecutionMode(std::move(constructSite));
 }
 }
 
 
+uint32_t ModuleBuilder::getGLSLExtInstSet() {
+  if (glslExtSetId == 0) {
+    glslExtSetId = theContext.takeNextId();
+    theModule.addExtInstSet(glslExtSetId, "GLSL.std.450");
+  }
+  return glslExtSetId;
+}
+
 uint32_t ModuleBuilder::addStageIOVariable(uint32_t type,
 uint32_t ModuleBuilder::addStageIOVariable(uint32_t type,
                                            spv::StorageClass storageClass) {
                                            spv::StorageClass storageClass) {
   const uint32_t pointerType = getPointerType(type, storageClass);
   const uint32_t pointerType = getPointerType(type, storageClass);

+ 124 - 8
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -1037,7 +1037,8 @@ uint32_t SPIRVEmitter::doCastExpr(const CastExpr *expr) {
   }
   }
   case CastKind::CK_HLSLMatrixToVectorCast: {
   case CastKind::CK_HLSLMatrixToVectorCast: {
     // The underlying should already be a matrix of 1xN.
     // The underlying should already be a matrix of 1xN.
-    assert(TypeTranslator::is1xNMatrix(subExpr->getType()));
+    assert(TypeTranslator::is1xNMatrix(subExpr->getType()) ||
+           TypeTranslator::isMx1Matrix(subExpr->getType()));
     return doExpr(subExpr);
     return doExpr(subExpr);
   }
   }
   case CastKind::CK_FunctionToPointerDecay:
   case CastKind::CK_FunctionToPointerDecay:
@@ -2028,8 +2029,9 @@ uint32_t SPIRVEmitter::processMatrixBinaryOp(const Expr *lhs, const Expr *rhs,
   case BO_DivAssign:
   case BO_DivAssign:
   case BO_RemAssign: {
   case BO_RemAssign: {
     const uint32_t vecType = typeTranslator.getComponentVectorType(lhsType);
     const uint32_t vecType = typeTranslator.getComponentVectorType(lhsType);
-    const auto actOnEachVec = [this, spvOp, rhsVal](
-        uint32_t index, uint32_t vecType, uint32_t lhsVec) {
+    const auto actOnEachVec = [this, spvOp, rhsVal](uint32_t index,
+                                                    uint32_t vecType,
+                                                    uint32_t lhsVec) {
       // For each vector of lhs, we need to load the corresponding vector of
       // For each vector of lhs, we need to load the corresponding vector of
       // rhs and do the operation on them.
       // rhs and do the operation on them.
       const uint32_t rhsVec =
       const uint32_t rhsVec =
@@ -2138,11 +2140,29 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
   assert(hlsl::IsIntrinsicOp(callee) &&
   assert(hlsl::IsIntrinsicOp(callee) &&
          "doIntrinsicCallExpr was called for a non-intrinsic function.");
          "doIntrinsicCallExpr was called for a non-intrinsic function.");
 
 
+  const bool isFloatArg =
+      isFloatOrVecMatOfFloatType(callExpr->getArg(0)->getType());
+  GLSLstd450 glslOpcode = GLSLstd450Bad;
+  bool actOnEachVecInMat = false;
+
+#define INTRINSIC_OP_CASE(intrinsicOp, glslOp, doEachVec)                      \
+  case hlsl::IntrinsicOp::IOP_##intrinsicOp: {                                 \
+    glslOpcode = GLSLstd450::GLSLstd450##glslOp;                               \
+    actOnEachVecInMat = doEachVec;                                             \
+  } break
+
+#define INTRINSIC_OP_CASE_INT_FLOAT(intrinsicOp, glslIntOp, glslFloatOp,       \
+                                    doEachVec)                                 \
+  case hlsl::IntrinsicOp::IOP_##intrinsicOp: {                                 \
+    glslOpcode = isFloatArg ? GLSLstd450::GLSLstd450##glslFloatOp              \
+                            : GLSLstd450::GLSLstd450##glslIntOp;               \
+    actOnEachVecInMat = doEachVec;                                             \
+  } break
+
   // Figure out which intrinsic function to translate.
   // Figure out which intrinsic function to translate.
   llvm::StringRef group;
   llvm::StringRef group;
   uint32_t opcode = static_cast<uint32_t>(hlsl::IntrinsicOp::Num_Intrinsics);
   uint32_t opcode = static_cast<uint32_t>(hlsl::IntrinsicOp::Num_Intrinsics);
   hlsl::GetIntrinsicOp(callee, opcode, group);
   hlsl::GetIntrinsicOp(callee, opcode, group);
-
   switch (static_cast<hlsl::IntrinsicOp>(opcode)) {
   switch (static_cast<hlsl::IntrinsicOp>(opcode)) {
   case hlsl::IntrinsicOp::IOP_dot:
   case hlsl::IntrinsicOp::IOP_dot:
     return processIntrinsicDot(callExpr);
     return processIntrinsicDot(callExpr);
@@ -2154,13 +2174,49 @@ uint32_t SPIRVEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
   case hlsl::IntrinsicOp::IOP_asint:
   case hlsl::IntrinsicOp::IOP_asint:
   case hlsl::IntrinsicOp::IOP_asuint:
   case hlsl::IntrinsicOp::IOP_asuint:
     return processIntrinsicAsType(callExpr);
     return processIntrinsicAsType(callExpr);
+  case hlsl::IntrinsicOp::IOP_sign: {
+    if (isFloatArg)
+      return processIntrinsicFloatSign(callExpr);
+    else
+      return processIntrinsicUsingGLSLInst(callExpr,
+                                           GLSLstd450::GLSLstd450SSign,
+                                           /*actPerRowForMatrices*/ true);
+  }
+    INTRINSIC_OP_CASE(round, Round, true);
+    INTRINSIC_OP_CASE_INT_FLOAT(abs, SAbs, FAbs, true);
+    INTRINSIC_OP_CASE(acos, Acos, true);
+    INTRINSIC_OP_CASE(asin, Asin, true);
+    INTRINSIC_OP_CASE(atan, Atan, true);
+    INTRINSIC_OP_CASE(ceil, Ceil, true);
+    INTRINSIC_OP_CASE(cos, Cos, true);
+    INTRINSIC_OP_CASE(cosh, Cosh, true);
+    INTRINSIC_OP_CASE(degrees, Degrees, true);
+    INTRINSIC_OP_CASE(radians, Radians, true);
+    INTRINSIC_OP_CASE(determinant, Determinant, false);
+    INTRINSIC_OP_CASE(exp, Exp, true);
+    INTRINSIC_OP_CASE(exp2, Exp2, true);
+    INTRINSIC_OP_CASE(floor, Floor, true);
+    INTRINSIC_OP_CASE(length, Length, false);
+    INTRINSIC_OP_CASE(log, Log, true);
+    INTRINSIC_OP_CASE(log2, Log2, true);
+    INTRINSIC_OP_CASE(normalize, Normalize, false);
+    INTRINSIC_OP_CASE(rsqrt, InverseSqrt, true);
+    INTRINSIC_OP_CASE(sin, Sin, true);
+    INTRINSIC_OP_CASE(sinh, Sinh, true);
+    INTRINSIC_OP_CASE(tan, Tan, true);
+    INTRINSIC_OP_CASE(tanh, Tanh, true);
+    INTRINSIC_OP_CASE(sqrt, Sqrt, true);
+    INTRINSIC_OP_CASE(trunc, Trunc, true);
   default:
   default:
-    break;
+    emitError("Intrinsic function '%0' not yet implemented.")
+        << callee->getName();
+    return 0;
   }
   }
 
 
-  emitError("Intrinsic function '%0' not yet implemented.")
-      << callee->getName();
-  return 0;
+#undef INTRINSIC_OP_CASE
+#undef INTRINSIC_OP_CASE_INT_FLOAT
+
+  return processIntrinsicUsingGLSLInst(callExpr, glslOpcode, actOnEachVecInMat);
 }
 }
 
 
 uint32_t SPIRVEmitter::processIntrinsicDot(const CallExpr *callExpr) {
 uint32_t SPIRVEmitter::processIntrinsicDot(const CallExpr *callExpr) {
@@ -2336,6 +2392,66 @@ uint32_t SPIRVEmitter::processIntrinsicAsType(const CallExpr *callExpr) {
                                   doExpr(arg));
                                   doExpr(arg));
 }
 }
 
 
+uint32_t SPIRVEmitter::processIntrinsicFloatSign(const CallExpr *callExpr) {
+  // Import the GLSL.std.450 extended instruction set.
+  const uint32_t glslInstSetId = theBuilder.getGLSLExtInstSet();
+  const Expr *arg = callExpr->getArg(0);
+  const QualType returnType = callExpr->getType();
+  const QualType argType = arg->getType();
+  assert(isFloatOrVecMatOfFloatType(argType));
+  const uint32_t argTypeId = typeTranslator.translateType(argType);
+  const uint32_t argId = doExpr(arg);
+  uint32_t floatSignResultId = 0;
+
+  // For matrices, we can perform the instruction on each vector of the matrix.
+  if (TypeTranslator::isSpirvAcceptableMatrixType(argType)) {
+    const auto actOnEachVec = [this, glslInstSetId](uint32_t /*index*/,
+                                                    uint32_t vecType,
+                                                    uint32_t curRowId) {
+      return theBuilder.createExtInst(vecType, glslInstSetId,
+                                      GLSLstd450::GLSLstd450FSign, {curRowId});
+    };
+    floatSignResultId = processEachVectorInMatrix(arg, argId, actOnEachVec);
+  } else {
+    floatSignResultId = theBuilder.createExtInst(
+        argTypeId, glslInstSetId, GLSLstd450::GLSLstd450FSign, {argId});
+  }
+
+  return castToInt(floatSignResultId, arg->getType(), returnType);
+}
+
+uint32_t SPIRVEmitter::processIntrinsicUsingGLSLInst(
+    const CallExpr *callExpr, GLSLstd450 opcode, bool actPerRowForMatrices) {
+  // Import the GLSL.std.450 extended instruction set.
+  const uint32_t glslInstSetId = theBuilder.getGLSLExtInstSet();
+
+  if (callExpr->getNumArgs() == 1u) {
+    const uint32_t returnType =
+        typeTranslator.translateType(callExpr->getType());
+    const Expr *arg = callExpr->getArg(0);
+    const uint32_t argId = doExpr(arg);
+
+    // If the instruction does not operate on matrices, we can perform the
+    // instruction on each vector of the matrix.
+    if (actPerRowForMatrices &&
+        TypeTranslator::isSpirvAcceptableMatrixType(arg->getType())) {
+      const auto actOnEachVec = [this, glslInstSetId,
+                                 opcode](uint32_t /*index*/, uint32_t vecType,
+                                         uint32_t curRowId) {
+        return theBuilder.createExtInst(vecType, glslInstSetId, opcode,
+                                        {curRowId});
+      };
+      return processEachVectorInMatrix(arg, argId, actOnEachVec);
+    }
+
+    return theBuilder.createExtInst(returnType, glslInstSetId, opcode, {argId});
+  }
+
+  emitError("Unsupported intrinsic function %0.")
+      << cast<DeclRefExpr>(callExpr->getCallee())->getNameInfo().getAsString();
+  return 0;
+}
+
 uint32_t SPIRVEmitter::getValueZero(QualType type) {
 uint32_t SPIRVEmitter::getValueZero(QualType type) {
   if (type->isSignedIntegerType()) {
   if (type->isSignedIntegerType()) {
     return theBuilder.getConstantInt32(0);
     return theBuilder.getConstantInt32(0);

+ 21 - 4
tools/clang/lib/SPIRV/SPIRVEmitter.h

@@ -19,6 +19,7 @@
 #include <vector>
 #include <vector>
 
 
 #include "dxc/HLSL/DxilShaderModel.h"
 #include "dxc/HLSL/DxilShaderModel.h"
+#include "spirv/1.0/GLSL.std.450.h"
 #include "clang/AST/AST.h"
 #include "clang/AST/AST.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTContext.h"
@@ -209,14 +210,30 @@ private:
   uint32_t castToFloat(uint32_t value, QualType fromType, QualType toType);
   uint32_t castToFloat(uint32_t value, QualType fromType, QualType toType);
 
 
 private:
 private:
-  uint32_t processIntrinsicCallExpr(const CallExpr *callExpr);
+  /// Processes HLSL instrinsic functions.
+  uint32_t processIntrinsicCallExpr(const CallExpr *);
 
 
-  uint32_t processIntrinsicDot(const CallExpr *callExpr);
+  /// Processes the 'dot' intrinsic function.
+  uint32_t processIntrinsicDot(const CallExpr *);
 
 
-  uint32_t processIntrinsicAllOrAny(const CallExpr *callExpr, spv::Op spvOp);
+  /// Processes the 'all' and 'any' intrinsic functions.
+  uint32_t processIntrinsicAllOrAny(const CallExpr *, spv::Op);
 
 
   /// Processes the 'asfloat', 'asint', and 'asuint' intrinsic functions.
   /// Processes the 'asfloat', 'asint', and 'asuint' intrinsic functions.
-  uint32_t processIntrinsicAsType(const CallExpr *callExpr);
+  uint32_t processIntrinsicAsType(const CallExpr *);
+
+  /// Processes the 'sign' intrinsic function for float types.
+  /// The FSign instruction in the GLSL instruction set returns a floating point
+  /// result. The HLSL sign function, however, returns an integer. An extra
+  /// casting from float to integer is therefore performed by this method.
+  uint32_t processIntrinsicFloatSign(const CallExpr *);
+
+  /// Processes the given intrinsic function call using the given GLSL
+  /// extended instruction. If the given instruction cannot operate on matrices,
+  /// it performs the instruction on each row of the matrix and uses composite
+  /// construction to generate the resulting matrix.
+  uint32_t processIntrinsicUsingGLSLInst(const CallExpr *, GLSLstd450 instr,
+                                         bool canOperateOnMatrix);
 
 
 private:
 private:
   /// Returns the <result-id> for constant value 0 of the given type.
   /// Returns the <result-id> for constant value 0 of the given type.

+ 5 - 5
tools/clang/lib/SPIRV/Structure.cpp

@@ -141,9 +141,9 @@ void Function::take(InstBuilder *builder) {
   // validation rules.
   // validation rules.
   std::vector<BasicBlock *> orderedBlocks;
   std::vector<BasicBlock *> orderedBlocks;
   if (!blocks.empty()) {
   if (!blocks.empty()) {
-    BlockReadableOrderVisitor([&orderedBlocks](BasicBlock *block) {
-      orderedBlocks.push_back(block);
-    }).visit(blocks.front().get());
+    BlockReadableOrderVisitor(
+        [&orderedBlocks](BasicBlock *block) { orderedBlocks.push_back(block); })
+        .visit(blocks.front().get());
   }
   }
 
 
   // Write out all basic blocks.
   // Write out all basic blocks.
@@ -226,7 +226,7 @@ void SPIRVModule::take(InstBuilder *builder) {
   }
   }
 
 
   for (auto &inst : extInstSets) {
   for (auto &inst : extInstSets) {
-    builder->opExtInstImport(inst.resultId, inst.setName).x();
+    builder->opExtInstImport(inst.second, inst.first).x();
   }
   }
 
 
   if (addressingModel.hasValue() && memoryModel.hasValue()) {
   if (addressingModel.hasValue() && memoryModel.hasValue()) {
@@ -314,7 +314,7 @@ void SPIRVModule::takeConstantForArrayType(const Type &arrType,
   // If it finds the constant, feeds it into the consumer, and removes it
   // If it finds the constant, feeds it into the consumer, and removes it
   // from the constants collection.
   // from the constants collection.
   constants.remove_if([&consumer, arrayLengthResultId](
   constants.remove_if([&consumer, arrayLengthResultId](
-      std::pair<const Constant *, uint32_t> &item) {
+                          std::pair<const Constant *, uint32_t> &item) {
     const bool isArrayLengthConstant = (item.second == arrayLengthResultId);
     const bool isArrayLengthConstant = (item.second == arrayLengthResultId);
     if (isArrayLengthConstant)
     if (isArrayLengthConstant)
       consumer(item.first->withResultId(item.second));
       consumer(item.first->withResultId(item.second));

+ 10 - 0
tools/clang/lib/SPIRV/TypeTranslator.cpp

@@ -63,7 +63,17 @@ uint32_t TypeTranslator::translateType(QualType type) {
   }
   }
 
 
   if (hlsl::IsHLSLMatType(type)) {
   if (hlsl::IsHLSLMatType(type)) {
+    uint32_t elemCount = 0;
     const auto elemTy = hlsl::GetHLSLMatElementType(type);
     const auto elemTy = hlsl::GetHLSLMatElementType(type);
+
+    // 1x1 matrix is a scalar
+    if (is1x1Matrix(type))
+      return translateType(elemTy);
+
+    // Mx1 matrix or 1xN matrix is a vector.
+    if (isMx1Or1xNMatrix(type, nullptr, &elemCount))
+      return theBuilder.getVecType(translateType(elemTy), elemCount);
+
     // NOTE: According to Item "Data rules" of SPIR-V Spec 2.16.1 "Universal
     // NOTE: According to Item "Data rules" of SPIR-V Spec 2.16.1 "Universal
     // Validation Rules":
     // Validation Rules":
     //   Matrix types can only be parameterized with floating-point types.
     //   Matrix types can only be parameterized with floating-point types.

+ 79 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.abs.hlsl

@@ -0,0 +1,79 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+  int3 iresult3;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[FAbs_a:%\d+]] = OpExtInst %float [[glsl]] FAbs [[a]]
+// CHECK-NEXT: OpStore %result [[FAbs_a]]
+  float a;
+  result = abs(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[FAbs_b:%\d+]] = OpExtInst %float [[glsl]] FAbs [[b]]
+// CHECK-NEXT: OpStore %result [[FAbs_b]]
+  float1 b;
+  result = abs(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[FAbs_c:%\d+]] = OpExtInst %v3float [[glsl]] FAbs [[c]]
+// CHECK-NEXT: OpStore %result3 [[FAbs_c]]
+  float3 c;
+  result3 = abs(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[FAbs_d:%\d+]] = OpExtInst %float [[glsl]] FAbs [[d]]
+// CHECK-NEXT: OpStore %result [[FAbs_d]]
+  float1x1 d;
+  result = abs(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[FAbs_e:%\d+]] = OpExtInst %v2float [[glsl]] FAbs [[e]]
+// CHECK-NEXT: OpStore %result2 [[FAbs_e]]
+  float1x2 e;
+  result2 = abs(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[FAbs_f:%\d+]] = OpExtInst %v4float [[glsl]] FAbs [[f]]
+// CHECK-NEXT: OpStore %result4 [[FAbs_f]]
+  float4x1 f;
+  result4 = abs(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[FAbs_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] FAbs [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[FAbs_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] FAbs [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[FAbs_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] FAbs [[g_row2]]
+// CHECK-NEXT: [[FAbs_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[FAbs_g_row0]] [[FAbs_g_row1]] [[FAbs_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[FAbs_matrix]]
+  float3x2 g;
+  result3x2 = abs(g);
+
+// CHECK-NEXT: [[i:%\d+]] = OpLoad %v3int %i
+// CHECK-NEXT: [[SAbs_i:%\d+]] = OpExtInst %v3int [[glsl]] SAbs [[i]]
+// CHECK-NEXT: OpStore %iresult3 [[SAbs_i]]
+  int3 i;
+  iresult3 = abs(i);
+
+// TODO: Integer matrices are not supported yet. Therefore we cannot run the following test yet.
+// XXXXX-NEXT: [[h:%\d+]] = OpLoad %mat3v4float %h
+// XXXXX-NEXT: [[h_row0:%\d+]] = OpCompositeExtract %v4float [[h]] 0
+// XXXXX-NEXT: [[SAbs_h_row0:%\d+]] = OpExtInst %v4float [[glsl]] SAbs [[h_row0]]
+// XXXXX-NEXT: [[h_row1:%\d+]] = OpCompositeExtract %v4float [[h]] 1
+// XXXXX-NEXT: [[SAbs_h_row1:%\d+]] = OpExtInst %v4float [[glsl]] SAbs [[h_row1]]
+// XXXXX-NEXT: [[h_row2:%\d+]] = OpCompositeExtract %v4float [[h]] 2
+// XXXXX-NEXT: [[SAbs_h_row2:%\d+]] = OpExtInst %v4float [[glsl]] SAbs [[h_row2]]
+// XXXXX-NEXT: [[SAbs_matrix:%\d+]] = OpCompositeConstruct %mat3v4float [[SAbs_h_row0]] [[SAbs_h_row1]] [[SAbs_h_row2]]
+// XXXXX-NEXT: OpStore %result3x4 [[SAbs_matrix]]
+//  int3x4 h;
+//  int3x4 result3x4 = abs(h);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.acos.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'acos' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[acos_a:%\d+]] = OpExtInst %float [[glsl]] Acos [[a]]
+// CHECK-NEXT: OpStore %result [[acos_a]]
+  float a;
+  result = acos(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[acos_b:%\d+]] = OpExtInst %float [[glsl]] Acos [[b]]
+// CHECK-NEXT: OpStore %result [[acos_b]]
+  float1 b;
+  result = acos(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[acos_c:%\d+]] = OpExtInst %v3float [[glsl]] Acos [[c]]
+// CHECK-NEXT: OpStore %result3 [[acos_c]]
+  float3 c;
+  result3 = acos(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[acos_d:%\d+]] = OpExtInst %float [[glsl]] Acos [[d]]
+// CHECK-NEXT: OpStore %result [[acos_d]]
+  float1x1 d;
+  result = acos(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[acos_e:%\d+]] = OpExtInst %v2float [[glsl]] Acos [[e]]
+// CHECK-NEXT: OpStore %result2 [[acos_e]]
+  float1x2 e;
+  result2 = acos(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[acos_f:%\d+]] = OpExtInst %v4float [[glsl]] Acos [[f]]
+// CHECK-NEXT: OpStore %result4 [[acos_f]]
+  float4x1 f;
+  result4 = acos(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[acos_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Acos [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[acos_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Acos [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[acos_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Acos [[g_row2]]
+// CHECK-NEXT: [[acos_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[acos_g_row0]] [[acos_g_row1]] [[acos_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[acos_matrix]]
+  float3x2 g;
+  result3x2 = acos(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.asin.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'asin' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[asin_a:%\d+]] = OpExtInst %float [[glsl]] Asin [[a]]
+// CHECK-NEXT: OpStore %result [[asin_a]]
+  float a;
+  result = asin(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[asin_b:%\d+]] = OpExtInst %float [[glsl]] Asin [[b]]
+// CHECK-NEXT: OpStore %result [[asin_b]]
+  float1 b;
+  result = asin(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[asin_c:%\d+]] = OpExtInst %v3float [[glsl]] Asin [[c]]
+// CHECK-NEXT: OpStore %result3 [[asin_c]]
+  float3 c;
+  result3 = asin(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[asin_d:%\d+]] = OpExtInst %float [[glsl]] Asin [[d]]
+// CHECK-NEXT: OpStore %result [[asin_d]]
+  float1x1 d;
+  result = asin(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[asin_e:%\d+]] = OpExtInst %v2float [[glsl]] Asin [[e]]
+// CHECK-NEXT: OpStore %result2 [[asin_e]]
+  float1x2 e;
+  result2 = asin(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[asin_f:%\d+]] = OpExtInst %v4float [[glsl]] Asin [[f]]
+// CHECK-NEXT: OpStore %result4 [[asin_f]]
+  float4x1 f;
+  result4 = asin(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[asin_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Asin [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[asin_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Asin [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[asin_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Asin [[g_row2]]
+// CHECK-NEXT: [[asin_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[asin_g_row0]] [[asin_g_row1]] [[asin_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[asin_matrix]]
+  float3x2 g;
+  result3x2 = asin(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.atan.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'atan' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[atan_a:%\d+]] = OpExtInst %float [[glsl]] Atan [[a]]
+// CHECK-NEXT: OpStore %result [[atan_a]]
+  float a;
+  result = atan(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[atan_b:%\d+]] = OpExtInst %float [[glsl]] Atan [[b]]
+// CHECK-NEXT: OpStore %result [[atan_b]]
+  float1 b;
+  result = atan(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[atan_c:%\d+]] = OpExtInst %v3float [[glsl]] Atan [[c]]
+// CHECK-NEXT: OpStore %result3 [[atan_c]]
+  float3 c;
+  result3 = atan(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[atan_d:%\d+]] = OpExtInst %float [[glsl]] Atan [[d]]
+// CHECK-NEXT: OpStore %result [[atan_d]]
+  float1x1 d;
+  result = atan(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[atan_e:%\d+]] = OpExtInst %v2float [[glsl]] Atan [[e]]
+// CHECK-NEXT: OpStore %result2 [[atan_e]]
+  float1x2 e;
+  result2 = atan(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[atan_f:%\d+]] = OpExtInst %v4float [[glsl]] Atan [[f]]
+// CHECK-NEXT: OpStore %result4 [[atan_f]]
+  float4x1 f;
+  result4 = atan(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[atan_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Atan [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[atan_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Atan [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[atan_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Atan [[g_row2]]
+// CHECK-NEXT: [[atan_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[atan_g_row0]] [[atan_g_row1]] [[atan_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[atan_matrix]]
+  float3x2 g;
+  result3x2 = atan(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.ceil.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'ceil' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[ceil_a:%\d+]] = OpExtInst %float [[glsl]] Ceil [[a]]
+// CHECK-NEXT: OpStore %result [[ceil_a]]
+  float a;
+  result = ceil(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[ceil_b:%\d+]] = OpExtInst %float [[glsl]] Ceil [[b]]
+// CHECK-NEXT: OpStore %result [[ceil_b]]
+  float1 b;
+  result = ceil(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[ceil_c:%\d+]] = OpExtInst %v3float [[glsl]] Ceil [[c]]
+// CHECK-NEXT: OpStore %result3 [[ceil_c]]
+  float3 c;
+  result3 = ceil(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[ceil_d:%\d+]] = OpExtInst %float [[glsl]] Ceil [[d]]
+// CHECK-NEXT: OpStore %result [[ceil_d]]
+  float1x1 d;
+  result = ceil(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[ceil_e:%\d+]] = OpExtInst %v2float [[glsl]] Ceil [[e]]
+// CHECK-NEXT: OpStore %result2 [[ceil_e]]
+  float1x2 e;
+  result2 = ceil(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[ceil_f:%\d+]] = OpExtInst %v4float [[glsl]] Ceil [[f]]
+// CHECK-NEXT: OpStore %result4 [[ceil_f]]
+  float4x1 f;
+  result4 = ceil(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[ceil_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Ceil [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[ceil_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Ceil [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[ceil_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Ceil [[g_row2]]
+// CHECK-NEXT: [[ceil_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[ceil_g_row0]] [[ceil_g_row1]] [[ceil_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[ceil_matrix]]
+  float3x2 g;
+  result3x2 = ceil(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.cos.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'cos' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[cos_a:%\d+]] = OpExtInst %float [[glsl]] Cos [[a]]
+// CHECK-NEXT: OpStore %result [[cos_a]]
+  float a;
+  result = cos(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[cos_b:%\d+]] = OpExtInst %float [[glsl]] Cos [[b]]
+// CHECK-NEXT: OpStore %result [[cos_b]]
+  float1 b;
+  result = cos(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[cos_c:%\d+]] = OpExtInst %v3float [[glsl]] Cos [[c]]
+// CHECK-NEXT: OpStore %result3 [[cos_c]]
+  float3 c;
+  result3 = cos(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[cos_d:%\d+]] = OpExtInst %float [[glsl]] Cos [[d]]
+// CHECK-NEXT: OpStore %result [[cos_d]]
+  float1x1 d;
+  result = cos(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[cos_e:%\d+]] = OpExtInst %v2float [[glsl]] Cos [[e]]
+// CHECK-NEXT: OpStore %result2 [[cos_e]]
+  float1x2 e;
+  result2 = cos(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[cos_f:%\d+]] = OpExtInst %v4float [[glsl]] Cos [[f]]
+// CHECK-NEXT: OpStore %result4 [[cos_f]]
+  float4x1 f;
+  result4 = cos(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[cos_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Cos [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[cos_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Cos [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[cos_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Cos [[g_row2]]
+// CHECK-NEXT: [[cos_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[cos_g_row0]] [[cos_g_row1]] [[cos_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[cos_matrix]]
+  float3x2 g;
+  result3x2 = cos(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.cosh.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'cosh' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[cosh_a:%\d+]] = OpExtInst %float [[glsl]] Cosh [[a]]
+// CHECK-NEXT: OpStore %result [[cosh_a]]
+  float a;
+  result = cosh(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[cosh_b:%\d+]] = OpExtInst %float [[glsl]] Cosh [[b]]
+// CHECK-NEXT: OpStore %result [[cosh_b]]
+  float1 b;
+  result = cosh(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[cosh_c:%\d+]] = OpExtInst %v3float [[glsl]] Cosh [[c]]
+// CHECK-NEXT: OpStore %result3 [[cosh_c]]
+  float3 c;
+  result3 = cosh(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[cosh_d:%\d+]] = OpExtInst %float [[glsl]] Cosh [[d]]
+// CHECK-NEXT: OpStore %result [[cosh_d]]
+  float1x1 d;
+  result = cosh(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[cosh_e:%\d+]] = OpExtInst %v2float [[glsl]] Cosh [[e]]
+// CHECK-NEXT: OpStore %result2 [[cosh_e]]
+  float1x2 e;
+  result2 = cosh(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[cosh_f:%\d+]] = OpExtInst %v4float [[glsl]] Cosh [[f]]
+// CHECK-NEXT: OpStore %result4 [[cosh_f]]
+  float4x1 f;
+  result4 = cosh(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[cosh_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Cosh [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[cosh_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Cosh [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[cosh_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Cosh [[g_row2]]
+// CHECK-NEXT: [[cosh_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[cosh_g_row0]] [[cosh_g_row1]] [[cosh_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[cosh_matrix]]
+  float3x2 g;
+  result3x2 = cosh(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.degrees.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'degrees' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[degrees_a:%\d+]] = OpExtInst %float [[glsl]] Degrees [[a]]
+// CHECK-NEXT: OpStore %result [[degrees_a]]
+  float a;
+  result = degrees(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[degrees_b:%\d+]] = OpExtInst %float [[glsl]] Degrees [[b]]
+// CHECK-NEXT: OpStore %result [[degrees_b]]
+  float1 b;
+  result = degrees(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[degrees_c:%\d+]] = OpExtInst %v3float [[glsl]] Degrees [[c]]
+// CHECK-NEXT: OpStore %result3 [[degrees_c]]
+  float3 c;
+  result3 = degrees(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[degrees_d:%\d+]] = OpExtInst %float [[glsl]] Degrees [[d]]
+// CHECK-NEXT: OpStore %result [[degrees_d]]
+  float1x1 d;
+  result = degrees(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[degrees_e:%\d+]] = OpExtInst %v2float [[glsl]] Degrees [[e]]
+// CHECK-NEXT: OpStore %result2 [[degrees_e]]
+  float1x2 e;
+  result2 = degrees(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[degrees_f:%\d+]] = OpExtInst %v4float [[glsl]] Degrees [[f]]
+// CHECK-NEXT: OpStore %result4 [[degrees_f]]
+  float4x1 f;
+  result4 = degrees(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[degrees_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Degrees [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[degrees_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Degrees [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[degrees_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Degrees [[g_row2]]
+// CHECK-NEXT: [[degrees_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[degrees_g_row0]] [[degrees_g_row1]] [[degrees_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[degrees_matrix]]
+  float3x2 g;
+  result3x2 = degrees(g);
+}

+ 17 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.determinant.hlsl

@@ -0,0 +1,17 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'determinant' function can only operate matrix of floats. The matrix must also be a square matrix.
+// The return type is a float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+
+// CHECK:      [[a:%\d+]] = OpLoad %mat3v3float %a
+// CHECK-NEXT: [[determinant_a:%\d+]] = OpExtInst %float [[glsl]] Determinant [[a]]
+// CHECK-NEXT: OpStore %result [[determinant_a]]
+  float3x3 a;
+  result = determinant(a);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.exp.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'exp' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[exp_a:%\d+]] = OpExtInst %float [[glsl]] Exp [[a]]
+// CHECK-NEXT: OpStore %result [[exp_a]]
+  float a;
+  result = exp(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[exp_b:%\d+]] = OpExtInst %float [[glsl]] Exp [[b]]
+// CHECK-NEXT: OpStore %result [[exp_b]]
+  float1 b;
+  result = exp(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[exp_c:%\d+]] = OpExtInst %v3float [[glsl]] Exp [[c]]
+// CHECK-NEXT: OpStore %result3 [[exp_c]]
+  float3 c;
+  result3 = exp(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[exp_d:%\d+]] = OpExtInst %float [[glsl]] Exp [[d]]
+// CHECK-NEXT: OpStore %result [[exp_d]]
+  float1x1 d;
+  result = exp(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[exp_e:%\d+]] = OpExtInst %v2float [[glsl]] Exp [[e]]
+// CHECK-NEXT: OpStore %result2 [[exp_e]]
+  float1x2 e;
+  result2 = exp(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[exp_f:%\d+]] = OpExtInst %v4float [[glsl]] Exp [[f]]
+// CHECK-NEXT: OpStore %result4 [[exp_f]]
+  float4x1 f;
+  result4 = exp(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[exp_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Exp [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[exp_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Exp [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[exp_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Exp [[g_row2]]
+// CHECK-NEXT: [[exp_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[exp_g_row0]] [[exp_g_row1]] [[exp_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[exp_matrix]]
+  float3x2 g;
+  result3x2 = exp(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.exp2.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'exp2' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[exp2_a:%\d+]] = OpExtInst %float [[glsl]] Exp2 [[a]]
+// CHECK-NEXT: OpStore %result [[exp2_a]]
+  float a;
+  result = exp2(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[exp2_b:%\d+]] = OpExtInst %float [[glsl]] Exp2 [[b]]
+// CHECK-NEXT: OpStore %result [[exp2_b]]
+  float1 b;
+  result = exp2(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[exp2_c:%\d+]] = OpExtInst %v3float [[glsl]] Exp2 [[c]]
+// CHECK-NEXT: OpStore %result3 [[exp2_c]]
+  float3 c;
+  result3 = exp2(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[exp2_d:%\d+]] = OpExtInst %float [[glsl]] Exp2 [[d]]
+// CHECK-NEXT: OpStore %result [[exp2_d]]
+  float1x1 d;
+  result = exp2(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[exp2_e:%\d+]] = OpExtInst %v2float [[glsl]] Exp2 [[e]]
+// CHECK-NEXT: OpStore %result2 [[exp2_e]]
+  float1x2 e;
+  result2 = exp2(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[exp2_f:%\d+]] = OpExtInst %v4float [[glsl]] Exp2 [[f]]
+// CHECK-NEXT: OpStore %result4 [[exp2_f]]
+  float4x1 f;
+  result4 = exp2(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[exp2_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Exp2 [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[exp2_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Exp2 [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[exp2_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Exp2 [[g_row2]]
+// CHECK-NEXT: [[exp2_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[exp2_g_row0]] [[exp2_g_row1]] [[exp2_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[exp2_matrix]]
+  float3x2 g;
+  result3x2 = exp2(g);
+}

+ 51 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.floatsign.hlsl

@@ -0,0 +1,51 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'sign' function can operate on float, float vectors, and float matrices.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  int result;
+  int3 result3;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[sign_a:%\d+]] = OpExtInst %float [[glsl]] FSign [[a]]
+// CHECK-NEXT: [[sign_a_int:%\d+]] = OpConvertFToS %int [[sign_a]]
+// CHECK-NEXT: OpStore %result [[sign_a_int]]
+  float a;
+  result = sign(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[sign_b:%\d+]] = OpExtInst %float [[glsl]] FSign [[b]]
+// CHECK-NEXT: [[sign_b_int:%\d+]] = OpConvertFToS %int [[sign_b]]
+// CHECK-NEXT: OpStore %result [[sign_b_int]]
+  float1 b;
+  result = sign(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[sign_c:%\d+]] = OpExtInst %v3float [[glsl]] FSign [[c]]
+// CHECK-NEXT: [[sign_c_int:%\d+]] = OpConvertFToS %v3int [[sign_c]]
+// CHECK-NEXT: OpStore %result3 [[sign_c_int]]
+  float3 c;
+  result3 = sign(c);
+
+///////////////////////////////////////////////////////////////////////////
+// Note: The following do not work because FSign returns a float result, //
+// whereas the HLSL 'sign' function returns an integer result.           //
+// Therefore we need to cast the FSign result into a matrix of integers. //
+// Casting to Matrix of integers is currently not supported.             //
+///////////////////////////////////////////////////////////////////////////
+
+//  float1x1 d;
+//  result = sign(d);
+
+//  float1x2 e;
+//  int2 result2 = sign(e);
+
+//  float4x1 f;
+//  int4 result4 = sign(f);
+
+//  float3x2 g;
+//  int3x2 result3x2 = sign(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.floor.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'floor' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[floor_a:%\d+]] = OpExtInst %float [[glsl]] Floor [[a]]
+// CHECK-NEXT: OpStore %result [[floor_a]]
+  float a;
+  result = floor(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[floor_b:%\d+]] = OpExtInst %float [[glsl]] Floor [[b]]
+// CHECK-NEXT: OpStore %result [[floor_b]]
+  float1 b;
+  result = floor(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[floor_c:%\d+]] = OpExtInst %v3float [[glsl]] Floor [[c]]
+// CHECK-NEXT: OpStore %result3 [[floor_c]]
+  float3 c;
+  result3 = floor(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[floor_d:%\d+]] = OpExtInst %float [[glsl]] Floor [[d]]
+// CHECK-NEXT: OpStore %result [[floor_d]]
+  float1x1 d;
+  result = floor(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[floor_e:%\d+]] = OpExtInst %v2float [[glsl]] Floor [[e]]
+// CHECK-NEXT: OpStore %result2 [[floor_e]]
+  float1x2 e;
+  result2 = floor(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[floor_f:%\d+]] = OpExtInst %v4float [[glsl]] Floor [[f]]
+// CHECK-NEXT: OpStore %result4 [[floor_f]]
+  float4x1 f;
+  result4 = floor(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[floor_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Floor [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[floor_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Floor [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[floor_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Floor [[g_row2]]
+// CHECK-NEXT: [[floor_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[floor_g_row0]] [[floor_g_row1]] [[floor_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[floor_matrix]]
+  float3x2 g;
+  result3x2 = floor(g);
+}

+ 60 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.intsign.hlsl

@@ -0,0 +1,60 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'sign' function can operate on int, int vectors, and int matrices.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  int result;
+  int3 result3;
+
+// CHECK:      [[a:%\d+]] = OpLoad %int %a
+// CHECK-NEXT: [[sign_a:%\d+]] = OpExtInst %int [[glsl]] SSign [[a]]
+// CHECK-NEXT: OpStore %result [[sign_a]]
+  int a;
+  result = sign(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %int %b
+// CHECK-NEXT: [[sign_b:%\d+]] = OpExtInst %int [[glsl]] SSign [[b]]
+// CHECK-NEXT: OpStore %result [[sign_b]]
+  int1 b;
+  result = sign(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3int %c
+// CHECK-NEXT: [[sign_c:%\d+]] = OpExtInst %v3int [[glsl]] SSign [[c]]
+// CHECK-NEXT: OpStore %result3 [[sign_c]]
+  int3 c;
+  result3 = sign(c);
+
+// CHECK:      [[d:%\d+]] = OpLoad %int %d
+// CHECK-NEXT: [[sign_d:%\d+]] = OpExtInst %int [[glsl]] SSign [[d]]
+// CHECK-NEXT: OpStore %result [[sign_d]]
+  int1x1 d;
+  result = sign(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2int %e
+// CHECK-NEXT: [[sign_e:%\d+]] = OpExtInst %v2int [[glsl]] SSign [[e]]
+// CHECK-NEXT: OpStore %result2 [[sign_e]]
+  int1x2 e;
+  int2 result2 = sign(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4int %f
+// CHECK-NEXT: [[sign_f:%\d+]] = OpExtInst %v4int [[glsl]] SSign [[f]]
+// CHECK-NEXT: OpStore %result4 [[sign_f]]
+  int4x1 f;
+  int4 result4 = sign(f);
+
+// TODO: Integer matrices are not supported yet. Therefore we cannot run the following test yet.
+// XXXXX-NEXT: [[h:%\d+]] = OpLoad %mat3v4int %h
+// XXXXX-NEXT: [[h_row0:%\d+]] = OpCompositeExtract %v4int [[h]] 0
+// XXXXX-NEXT: [[SSign_h_row0:%\d+]] = OpExtInst %v4int [[glsl]] SSign [[h_row0]]
+// XXXXX-NEXT: [[h_row1:%\d+]] = OpCompositeExtract %v4int [[h]] 1
+// XXXXX-NEXT: [[SSign_h_row1:%\d+]] = OpExtInst %v4int [[glsl]] SSign [[h_row1]]
+// XXXXX-NEXT: [[h_row2:%\d+]] = OpCompositeExtract %v4int [[h]] 2
+// XXXXX-NEXT: [[SSign_h_row2:%\d+]] = OpExtInst %v4int [[glsl]] SSign [[h_row2]]
+// XXXXX-NEXT: [[SSign_matrix:%\d+]] = OpCompositeConstruct %mat3v4int [[SSign_h_row0]] [[SSign_h_row1]] [[SSign_h_row2]]
+// XXXXX-NEXT: OpStore %result3x4 [[SSign_matrix]]
+//  int3x4 h;
+//  int3x4 result3x4 = sign(h);
+}

+ 28 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.length.hlsl

@@ -0,0 +1,28 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'length' function can only operate on vector of floats.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[length_a:%\d+]] = OpExtInst %float [[glsl]] Length [[a]]
+// CHECK-NEXT: OpStore %result [[length_a]]
+  float a;
+  result = length(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[length_b:%\d+]] = OpExtInst %float [[glsl]] Length [[b]]
+// CHECK-NEXT: OpStore %result [[length_b]]
+  float1 b;
+  result = length(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[length_c:%\d+]] = OpExtInst %float [[glsl]] Length [[c]]
+// CHECK-NEXT: OpStore %result [[length_c]]
+  float3 c;
+  result = length(c);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.log.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'log' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[log_a:%\d+]] = OpExtInst %float [[glsl]] Log [[a]]
+// CHECK-NEXT: OpStore %result [[log_a]]
+  float a;
+  result = log(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[log_b:%\d+]] = OpExtInst %float [[glsl]] Log [[b]]
+// CHECK-NEXT: OpStore %result [[log_b]]
+  float1 b;
+  result = log(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[log_c:%\d+]] = OpExtInst %v3float [[glsl]] Log [[c]]
+// CHECK-NEXT: OpStore %result3 [[log_c]]
+  float3 c;
+  result3 = log(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[log_d:%\d+]] = OpExtInst %float [[glsl]] Log [[d]]
+// CHECK-NEXT: OpStore %result [[log_d]]
+  float1x1 d;
+  result = log(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[log_e:%\d+]] = OpExtInst %v2float [[glsl]] Log [[e]]
+// CHECK-NEXT: OpStore %result2 [[log_e]]
+  float1x2 e;
+  result2 = log(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[log_f:%\d+]] = OpExtInst %v4float [[glsl]] Log [[f]]
+// CHECK-NEXT: OpStore %result4 [[log_f]]
+  float4x1 f;
+  result4 = log(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[log_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Log [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[log_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Log [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[log_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Log [[g_row2]]
+// CHECK-NEXT: [[log_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[log_g_row0]] [[log_g_row1]] [[log_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[log_matrix]]
+  float3x2 g;
+  result3x2 = log(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.log2.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'log2' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[log2_a:%\d+]] = OpExtInst %float [[glsl]] Log2 [[a]]
+// CHECK-NEXT: OpStore %result [[log2_a]]
+  float a;
+  result = log2(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[log2_b:%\d+]] = OpExtInst %float [[glsl]] Log2 [[b]]
+// CHECK-NEXT: OpStore %result [[log2_b]]
+  float1 b;
+  result = log2(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[log2_c:%\d+]] = OpExtInst %v3float [[glsl]] Log2 [[c]]
+// CHECK-NEXT: OpStore %result3 [[log2_c]]
+  float3 c;
+  result3 = log2(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[log2_d:%\d+]] = OpExtInst %float [[glsl]] Log2 [[d]]
+// CHECK-NEXT: OpStore %result [[log2_d]]
+  float1x1 d;
+  result = log2(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[log2_e:%\d+]] = OpExtInst %v2float [[glsl]] Log2 [[e]]
+// CHECK-NEXT: OpStore %result2 [[log2_e]]
+  float1x2 e;
+  result2 = log2(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[log2_f:%\d+]] = OpExtInst %v4float [[glsl]] Log2 [[f]]
+// CHECK-NEXT: OpStore %result4 [[log2_f]]
+  float4x1 f;
+  result4 = log2(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[log2_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Log2 [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[log2_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Log2 [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[log2_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Log2 [[g_row2]]
+// CHECK-NEXT: [[log2_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[log2_g_row0]] [[log2_g_row1]] [[log2_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[log2_matrix]]
+  float3x2 g;
+  result3x2 = log2(g);
+}

+ 32 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.normalize.hlsl

@@ -0,0 +1,32 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'normalize' function can only operate on floats and vector of floats.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[normalize_a:%\d+]] = OpExtInst %float [[glsl]] Normalize [[a]]
+// CHECK-NEXT: OpStore %result [[normalize_a]]
+  float a;
+  result = normalize(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[normalize_b:%\d+]] = OpExtInst %float [[glsl]] Normalize [[b]]
+// CHECK-NEXT: OpStore %result [[normalize_b]]
+  float1 b;
+  result = normalize(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[normalize_c:%\d+]] = OpExtInst %v3float [[glsl]] Normalize [[c]]
+// CHECK-NEXT: OpStore %result3 [[normalize_c]]
+  float3 c;
+  result3 = normalize(c);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.radians.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'radians' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[radians_a:%\d+]] = OpExtInst %float [[glsl]] Radians [[a]]
+// CHECK-NEXT: OpStore %result [[radians_a]]
+  float a;
+  result = radians(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[radians_b:%\d+]] = OpExtInst %float [[glsl]] Radians [[b]]
+// CHECK-NEXT: OpStore %result [[radians_b]]
+  float1 b;
+  result = radians(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[radians_c:%\d+]] = OpExtInst %v3float [[glsl]] Radians [[c]]
+// CHECK-NEXT: OpStore %result3 [[radians_c]]
+  float3 c;
+  result3 = radians(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[radians_d:%\d+]] = OpExtInst %float [[glsl]] Radians [[d]]
+// CHECK-NEXT: OpStore %result [[radians_d]]
+  float1x1 d;
+  result = radians(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[radians_e:%\d+]] = OpExtInst %v2float [[glsl]] Radians [[e]]
+// CHECK-NEXT: OpStore %result2 [[radians_e]]
+  float1x2 e;
+  result2 = radians(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[radians_f:%\d+]] = OpExtInst %v4float [[glsl]] Radians [[f]]
+// CHECK-NEXT: OpStore %result4 [[radians_f]]
+  float4x1 f;
+  result4 = radians(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[radians_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Radians [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[radians_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Radians [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[radians_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Radians [[g_row2]]
+// CHECK-NEXT: [[radians_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[radians_g_row0]] [[radians_g_row1]] [[radians_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[radians_matrix]]
+  float3x2 g;
+  result3x2 = radians(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.round.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'round' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[round_a:%\d+]] = OpExtInst %float [[glsl]] Round [[a]]
+// CHECK-NEXT: OpStore %result [[round_a]]
+  float a;
+  result = round(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[round_b:%\d+]] = OpExtInst %float [[glsl]] Round [[b]]
+// CHECK-NEXT: OpStore %result [[round_b]]
+  float1 b;
+  result = round(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[round_c:%\d+]] = OpExtInst %v3float [[glsl]] Round [[c]]
+// CHECK-NEXT: OpStore %result3 [[round_c]]
+  float3 c;
+  result3 = round(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[round_d:%\d+]] = OpExtInst %float [[glsl]] Round [[d]]
+// CHECK-NEXT: OpStore %result [[round_d]]
+  float1x1 d;
+  result = round(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[round_e:%\d+]] = OpExtInst %v2float [[glsl]] Round [[e]]
+// CHECK-NEXT: OpStore %result2 [[round_e]]
+  float1x2 e;
+  result2 = round(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[round_f:%\d+]] = OpExtInst %v4float [[glsl]] Round [[f]]
+// CHECK-NEXT: OpStore %result4 [[round_f]]
+  float4x1 f;
+  result4 = round(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[round_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Round [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[round_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Round [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[round_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Round [[g_row2]]
+// CHECK-NEXT: [[round_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[round_g_row0]] [[round_g_row1]] [[round_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[round_matrix]]
+  float3x2 g;
+  result3x2 = round(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.rsqrt.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'rsqrt' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[rsqrt_a:%\d+]] = OpExtInst %float [[glsl]] InverseSqrt [[a]]
+// CHECK-NEXT: OpStore %result [[rsqrt_a]]
+  float a;
+  result = rsqrt(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[rsqrt_b:%\d+]] = OpExtInst %float [[glsl]] InverseSqrt [[b]]
+// CHECK-NEXT: OpStore %result [[rsqrt_b]]
+  float1 b;
+  result = rsqrt(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[rsqrt_c:%\d+]] = OpExtInst %v3float [[glsl]] InverseSqrt [[c]]
+// CHECK-NEXT: OpStore %result3 [[rsqrt_c]]
+  float3 c;
+  result3 = rsqrt(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[rsqrt_d:%\d+]] = OpExtInst %float [[glsl]] InverseSqrt [[d]]
+// CHECK-NEXT: OpStore %result [[rsqrt_d]]
+  float1x1 d;
+  result = rsqrt(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[rsqrt_e:%\d+]] = OpExtInst %v2float [[glsl]] InverseSqrt [[e]]
+// CHECK-NEXT: OpStore %result2 [[rsqrt_e]]
+  float1x2 e;
+  result2 = rsqrt(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[rsqrt_f:%\d+]] = OpExtInst %v4float [[glsl]] InverseSqrt [[f]]
+// CHECK-NEXT: OpStore %result4 [[rsqrt_f]]
+  float4x1 f;
+  result4 = rsqrt(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[rsqrt_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] InverseSqrt [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[rsqrt_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] InverseSqrt [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[rsqrt_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] InverseSqrt [[g_row2]]
+// CHECK-NEXT: [[rsqrt_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[rsqrt_g_row0]] [[rsqrt_g_row1]] [[rsqrt_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[rsqrt_matrix]]
+  float3x2 g;
+  result3x2 = rsqrt(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.sin.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'sin' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[sin_a:%\d+]] = OpExtInst %float [[glsl]] Sin [[a]]
+// CHECK-NEXT: OpStore %result [[sin_a]]
+  float a;
+  result = sin(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[sin_b:%\d+]] = OpExtInst %float [[glsl]] Sin [[b]]
+// CHECK-NEXT: OpStore %result [[sin_b]]
+  float1 b;
+  result = sin(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[sin_c:%\d+]] = OpExtInst %v3float [[glsl]] Sin [[c]]
+// CHECK-NEXT: OpStore %result3 [[sin_c]]
+  float3 c;
+  result3 = sin(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[sin_d:%\d+]] = OpExtInst %float [[glsl]] Sin [[d]]
+// CHECK-NEXT: OpStore %result [[sin_d]]
+  float1x1 d;
+  result = sin(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[sin_e:%\d+]] = OpExtInst %v2float [[glsl]] Sin [[e]]
+// CHECK-NEXT: OpStore %result2 [[sin_e]]
+  float1x2 e;
+  result2 = sin(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[sin_f:%\d+]] = OpExtInst %v4float [[glsl]] Sin [[f]]
+// CHECK-NEXT: OpStore %result4 [[sin_f]]
+  float4x1 f;
+  result4 = sin(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[sin_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Sin [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[sin_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Sin [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[sin_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Sin [[g_row2]]
+// CHECK-NEXT: [[sin_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[sin_g_row0]] [[sin_g_row1]] [[sin_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[sin_matrix]]
+  float3x2 g;
+  result3x2 = sin(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.sinh.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'sinh' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[sinh_a:%\d+]] = OpExtInst %float [[glsl]] Sinh [[a]]
+// CHECK-NEXT: OpStore %result [[sinh_a]]
+  float a;
+  result = sinh(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[sinh_b:%\d+]] = OpExtInst %float [[glsl]] Sinh [[b]]
+// CHECK-NEXT: OpStore %result [[sinh_b]]
+  float1 b;
+  result = sinh(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[sinh_c:%\d+]] = OpExtInst %v3float [[glsl]] Sinh [[c]]
+// CHECK-NEXT: OpStore %result3 [[sinh_c]]
+  float3 c;
+  result3 = sinh(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[sinh_d:%\d+]] = OpExtInst %float [[glsl]] Sinh [[d]]
+// CHECK-NEXT: OpStore %result [[sinh_d]]
+  float1x1 d;
+  result = sinh(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[sinh_e:%\d+]] = OpExtInst %v2float [[glsl]] Sinh [[e]]
+// CHECK-NEXT: OpStore %result2 [[sinh_e]]
+  float1x2 e;
+  result2 = sinh(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[sinh_f:%\d+]] = OpExtInst %v4float [[glsl]] Sinh [[f]]
+// CHECK-NEXT: OpStore %result4 [[sinh_f]]
+  float4x1 f;
+  result4 = sinh(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[sinh_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Sinh [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[sinh_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Sinh [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[sinh_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Sinh [[g_row2]]
+// CHECK-NEXT: [[sinh_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[sinh_g_row0]] [[sinh_g_row1]] [[sinh_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[sinh_matrix]]
+  float3x2 g;
+  result3x2 = sinh(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.sqrt.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'sqrt' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[sqrt_a:%\d+]] = OpExtInst %float [[glsl]] Sqrt [[a]]
+// CHECK-NEXT: OpStore %result [[sqrt_a]]
+  float a;
+  result = sqrt(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[sqrt_b:%\d+]] = OpExtInst %float [[glsl]] Sqrt [[b]]
+// CHECK-NEXT: OpStore %result [[sqrt_b]]
+  float1 b;
+  result = sqrt(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[sqrt_c:%\d+]] = OpExtInst %v3float [[glsl]] Sqrt [[c]]
+// CHECK-NEXT: OpStore %result3 [[sqrt_c]]
+  float3 c;
+  result3 = sqrt(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[sqrt_d:%\d+]] = OpExtInst %float [[glsl]] Sqrt [[d]]
+// CHECK-NEXT: OpStore %result [[sqrt_d]]
+  float1x1 d;
+  result = sqrt(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[sqrt_e:%\d+]] = OpExtInst %v2float [[glsl]] Sqrt [[e]]
+// CHECK-NEXT: OpStore %result2 [[sqrt_e]]
+  float1x2 e;
+  result2 = sqrt(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[sqrt_f:%\d+]] = OpExtInst %v4float [[glsl]] Sqrt [[f]]
+// CHECK-NEXT: OpStore %result4 [[sqrt_f]]
+  float4x1 f;
+  result4 = sqrt(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[sqrt_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Sqrt [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[sqrt_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Sqrt [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[sqrt_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Sqrt [[g_row2]]
+// CHECK-NEXT: [[sqrt_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[sqrt_g_row0]] [[sqrt_g_row1]] [[sqrt_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[sqrt_matrix]]
+  float3x2 g;
+  result3x2 = sqrt(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.tan.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'tan' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[tan_a:%\d+]] = OpExtInst %float [[glsl]] Tan [[a]]
+// CHECK-NEXT: OpStore %result [[tan_a]]
+  float a;
+  result = tan(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[tan_b:%\d+]] = OpExtInst %float [[glsl]] Tan [[b]]
+// CHECK-NEXT: OpStore %result [[tan_b]]
+  float1 b;
+  result = tan(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[tan_c:%\d+]] = OpExtInst %v3float [[glsl]] Tan [[c]]
+// CHECK-NEXT: OpStore %result3 [[tan_c]]
+  float3 c;
+  result3 = tan(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[tan_d:%\d+]] = OpExtInst %float [[glsl]] Tan [[d]]
+// CHECK-NEXT: OpStore %result [[tan_d]]
+  float1x1 d;
+  result = tan(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[tan_e:%\d+]] = OpExtInst %v2float [[glsl]] Tan [[e]]
+// CHECK-NEXT: OpStore %result2 [[tan_e]]
+  float1x2 e;
+  result2 = tan(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[tan_f:%\d+]] = OpExtInst %v4float [[glsl]] Tan [[f]]
+// CHECK-NEXT: OpStore %result4 [[tan_f]]
+  float4x1 f;
+  result4 = tan(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[tan_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Tan [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[tan_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Tan [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[tan_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Tan [[g_row2]]
+// CHECK-NEXT: [[tan_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[tan_g_row0]] [[tan_g_row1]] [[tan_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[tan_matrix]]
+  float3x2 g;
+  result3x2 = tan(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.tanh.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'tanh' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[tanh_a:%\d+]] = OpExtInst %float [[glsl]] Tanh [[a]]
+// CHECK-NEXT: OpStore %result [[tanh_a]]
+  float a;
+  result = tanh(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[tanh_b:%\d+]] = OpExtInst %float [[glsl]] Tanh [[b]]
+// CHECK-NEXT: OpStore %result [[tanh_b]]
+  float1 b;
+  result = tanh(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[tanh_c:%\d+]] = OpExtInst %v3float [[glsl]] Tanh [[c]]
+// CHECK-NEXT: OpStore %result3 [[tanh_c]]
+  float3 c;
+  result3 = tanh(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[tanh_d:%\d+]] = OpExtInst %float [[glsl]] Tanh [[d]]
+// CHECK-NEXT: OpStore %result [[tanh_d]]
+  float1x1 d;
+  result = tanh(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[tanh_e:%\d+]] = OpExtInst %v2float [[glsl]] Tanh [[e]]
+// CHECK-NEXT: OpStore %result2 [[tanh_e]]
+  float1x2 e;
+  result2 = tanh(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[tanh_f:%\d+]] = OpExtInst %v4float [[glsl]] Tanh [[f]]
+// CHECK-NEXT: OpStore %result4 [[tanh_f]]
+  float4x1 f;
+  result4 = tanh(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[tanh_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Tanh [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[tanh_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Tanh [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[tanh_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Tanh [[g_row2]]
+// CHECK-NEXT: [[tanh_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[tanh_g_row0]] [[tanh_g_row1]] [[tanh_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[tanh_matrix]]
+  float3x2 g;
+  result3x2 = tanh(g);
+}

+ 62 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.trunc.hlsl

@@ -0,0 +1,62 @@
+// Run: %dxc -T vs_6_0 -E main
+
+// According to HLSL reference:
+// The 'trunc' function can only operate on float, vector of float, and matrix of float.
+
+// CHECK:      [[glsl:%\d+]] = OpExtInstImport "GLSL.std.450"
+
+void main() {
+  float result;
+  float2 result2;
+  float3 result3;
+  float4 result4;
+  float3x2 result3x2;
+
+// CHECK:      [[a:%\d+]] = OpLoad %float %a
+// CHECK-NEXT: [[trunc_a:%\d+]] = OpExtInst %float [[glsl]] Trunc [[a]]
+// CHECK-NEXT: OpStore %result [[trunc_a]]
+  float a;
+  result = trunc(a);
+
+// CHECK-NEXT: [[b:%\d+]] = OpLoad %float %b
+// CHECK-NEXT: [[trunc_b:%\d+]] = OpExtInst %float [[glsl]] Trunc [[b]]
+// CHECK-NEXT: OpStore %result [[trunc_b]]
+  float1 b;
+  result = trunc(b);
+
+// CHECK-NEXT: [[c:%\d+]] = OpLoad %v3float %c
+// CHECK-NEXT: [[trunc_c:%\d+]] = OpExtInst %v3float [[glsl]] Trunc [[c]]
+// CHECK-NEXT: OpStore %result3 [[trunc_c]]
+  float3 c;
+  result3 = trunc(c);
+
+// CHECK-NEXT: [[d:%\d+]] = OpLoad %float %d
+// CHECK-NEXT: [[trunc_d:%\d+]] = OpExtInst %float [[glsl]] Trunc [[d]]
+// CHECK-NEXT: OpStore %result [[trunc_d]]
+  float1x1 d;
+  result = trunc(d);
+
+// CHECK-NEXT: [[e:%\d+]] = OpLoad %v2float %e
+// CHECK-NEXT: [[trunc_e:%\d+]] = OpExtInst %v2float [[glsl]] Trunc [[e]]
+// CHECK-NEXT: OpStore %result2 [[trunc_e]]
+  float1x2 e;
+  result2 = trunc(e);
+
+// CHECK-NEXT: [[f:%\d+]] = OpLoad %v4float %f
+// CHECK-NEXT: [[trunc_f:%\d+]] = OpExtInst %v4float [[glsl]] Trunc [[f]]
+// CHECK-NEXT: OpStore %result4 [[trunc_f]]
+  float4x1 f;
+  result4 = trunc(f);
+
+// CHECK-NEXT: [[g:%\d+]] = OpLoad %mat3v2float %g
+// CHECK-NEXT: [[g_row0:%\d+]] = OpCompositeExtract %v2float [[g]] 0
+// CHECK-NEXT: [[trunc_g_row0:%\d+]] = OpExtInst %v2float [[glsl]] Trunc [[g_row0]]
+// CHECK-NEXT: [[g_row1:%\d+]] = OpCompositeExtract %v2float [[g]] 1
+// CHECK-NEXT: [[trunc_g_row1:%\d+]] = OpExtInst %v2float [[glsl]] Trunc [[g_row1]]
+// CHECK-NEXT: [[g_row2:%\d+]] = OpCompositeExtract %v2float [[g]] 2
+// CHECK-NEXT: [[trunc_g_row2:%\d+]] = OpExtInst %v2float [[glsl]] Trunc [[g_row2]]
+// CHECK-NEXT: [[trunc_matrix:%\d+]] = OpCompositeConstruct %mat3v2float [[trunc_g_row0]] [[trunc_g_row1]] [[trunc_g_row2]]
+// CHECK-NEXT: OpStore %result3x2 [[trunc_matrix]]
+  float3x2 g;
+  result3x2 = trunc(g);
+}

+ 29 - 0
tools/clang/unittests/SPIRV/CodeGenSPIRVTest.cpp

@@ -245,5 +245,34 @@ TEST_F(FileTest, IntrinsicsAny) { runFileTest("intrinsics.any.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsfloat) { runFileTest("intrinsics.asfloat.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsfloat) { runFileTest("intrinsics.asfloat.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsint) { runFileTest("intrinsics.asint.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsint) { runFileTest("intrinsics.asint.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsuint) { runFileTest("intrinsics.asuint.hlsl"); }
 TEST_F(FileTest, IntrinsicsAsuint) { runFileTest("intrinsics.asuint.hlsl"); }
+TEST_F(FileTest, IntrinsicsRound) { runFileTest("intrinsics.round.hlsl"); }
+TEST_F(FileTest, IntrinsicsAbs) { runFileTest("intrinsics.abs.hlsl"); }
+TEST_F(FileTest, IntrinsicsCeil) { runFileTest("intrinsics.ceil.hlsl"); }
+TEST_F(FileTest, IntrinsicsDegrees) { runFileTest("intrinsics.degrees.hlsl"); }
+TEST_F(FileTest, IntrinsicsRadians) { runFileTest("intrinsics.radians.hlsl"); }
+TEST_F(FileTest, IntrinsicsDeterminant) { runFileTest("intrinsics.determinant.hlsl"); }
+TEST_F(FileTest, IntrinsicsExp) { runFileTest("intrinsics.exp.hlsl"); }
+TEST_F(FileTest, IntrinsicsExp2) { runFileTest("intrinsics.exp2.hlsl"); }
+TEST_F(FileTest, IntrinsicsFloor) { runFileTest("intrinsics.floor.hlsl"); }
+TEST_F(FileTest, IntrinsicsLength) { runFileTest("intrinsics.length.hlsl"); }
+TEST_F(FileTest, IntrinsicsLog) { runFileTest("intrinsics.log.hlsl"); }
+TEST_F(FileTest, IntrinsicsLog2) { runFileTest("intrinsics.log2.hlsl"); }
+TEST_F(FileTest, IntrinsicsNormalize) { runFileTest("intrinsics.normalize.hlsl"); }
+TEST_F(FileTest, IntrinsicsRsqrt) { runFileTest("intrinsics.rsqrt.hlsl"); }
+TEST_F(FileTest, IntrinsicsFloatSign) { runFileTest("intrinsics.floatsign.hlsl"); }
+TEST_F(FileTest, IntrinsicsIntSign) { runFileTest("intrinsics.intsign.hlsl"); }
+TEST_F(FileTest, IntrinsicsSqrt) { runFileTest("intrinsics.sqrt.hlsl"); }
+TEST_F(FileTest, IntrinsicsTrunc) { runFileTest("intrinsics.trunc.hlsl"); }
+
+// For intrinsic trigonometric functions
+TEST_F(FileTest, IntrinsicsSin) { runFileTest("intrinsics.sin.hlsl"); }
+TEST_F(FileTest, IntrinsicsCos) { runFileTest("intrinsics.cos.hlsl"); }
+TEST_F(FileTest, IntrinsicsTan) { runFileTest("intrinsics.tan.hlsl"); }
+TEST_F(FileTest, IntrinsicsSinh) { runFileTest("intrinsics.sinh.hlsl"); }
+TEST_F(FileTest, IntrinsicsCosh) { runFileTest("intrinsics.cosh.hlsl"); }
+TEST_F(FileTest, IntrinsicsTanh) { runFileTest("intrinsics.tanh.hlsl"); }
+TEST_F(FileTest, IntrinsicsAsin) { runFileTest("intrinsics.asin.hlsl"); }
+TEST_F(FileTest, IntrinsicsAcos) { runFileTest("intrinsics.acos.hlsl"); }
+TEST_F(FileTest, IntrinsicsAtan) { runFileTest("intrinsics.atan.hlsl"); }
 
 
 } // namespace
 } // namespace