https://github.com/farzonl created 
https://github.com/llvm/llvm-project/pull/170779

fixes #166206

- Add swizzle support if row index is constant
- Add test cases
- Add new AST type
- Add new LValue for Matrix Row Type
- TODO: Make the new LValue a dynamic index version of ExtVectorElt

>From 37cc571a727ea0fd6fd89088afb655cb11e173c2 Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <[email protected]>
Date: Mon, 24 Nov 2025 16:57:45 -0500
Subject: [PATCH] [HLSL][Matrix] Add support for single subscript accessor

fixes #166206

- Add swizzle support if row index is constant
- Add test cases
- Add new AST type
- Add new LValue for Matrix Row Type
- TODO: Make the new LValue a dynamic index version of ExtVectorElt
---
 clang/include/clang/AST/ComputeDependence.h   |   2 +
 clang/include/clang/AST/Expr.h                |  67 ++++++
 clang/include/clang/AST/RecursiveASTVisitor.h |   1 +
 clang/include/clang/AST/Stmt.h                |   1 +
 clang/include/clang/Basic/StmtNodes.td        |   1 +
 clang/include/clang/Sema/Sema.h               |   3 +
 clang/lib/AST/ComputeDependence.cpp           |   4 +
 clang/lib/AST/Expr.cpp                        |   1 +
 clang/lib/AST/ExprClassification.cpp          |   3 +
 clang/lib/AST/ExprConstant.cpp                |   1 +
 clang/lib/AST/ItaniumMangle.cpp               |   9 +
 clang/lib/AST/StmtPrinter.cpp                 |   8 +
 clang/lib/AST/StmtProfile.cpp                 |   5 +
 clang/lib/CodeGen/CGExpr.cpp                  |  93 ++++++++
 clang/lib/CodeGen/CGExprScalar.cpp            |  35 +++
 clang/lib/CodeGen/CGValue.h                   |  19 +-
 clang/lib/CodeGen/CodeGenFunction.h           |   1 +
 clang/lib/Sema/SemaExceptionSpec.cpp          |   1 +
 clang/lib/Sema/SemaExpr.cpp                   |  61 +++++-
 clang/lib/Sema/TreeTransform.h                |  29 +++
 clang/lib/Serialization/ASTReaderStmt.cpp     |   8 +
 clang/lib/Serialization/ASTWriterStmt.cpp     |   9 +
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp  |   5 +
 .../HLSL/matrix-single-subscript-getter.hlsl  |  77 +++++++
 .../HLSL/matrix-single-subscript-setter.hlsl  |  59 +++++
 .../HLSL/matrix-single-subscript-swizzle.hlsl |  56 +++++
 .../pch_with_matrix_single_subscript.hlsl     |  16 ++
 .../MatrixSingleSubscriptConstSwizzle.hlsl    |  60 +++++
 .../MatrixSingleSubscriptDynamicSwizzle.hlsl  |  10 +
 .../MatrixSingleSubscriptGetter.hlsl          | 205 ++++++++++++++++++
 .../MatrixSingleSubscriptSetter.hlsl          | 126 +++++++++++
 .../matrix_single_subscript_errors.hlsl       |  12 +
 clang/tools/libclang/CXCursor.cpp             |   5 +
 33 files changed, 991 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/AST/HLSL/matrix-single-subscript-getter.hlsl
 create mode 100644 clang/test/AST/HLSL/matrix-single-subscript-setter.hlsl
 create mode 100644 clang/test/AST/HLSL/matrix-single-subscript-swizzle.hlsl
 create mode 100644 clang/test/AST/HLSL/pch_with_matrix_single_subscript.hlsl
 create mode 100644 
clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptConstSwizzle.hlsl
 create mode 100644 
clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptDynamicSwizzle.hlsl
 create mode 100644 
clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptGetter.hlsl
 create mode 100644 
clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptSetter.hlsl
 create mode 100644 clang/test/SemaHLSL/matrix_single_subscript_errors.hlsl

diff --git a/clang/include/clang/AST/ComputeDependence.h 
b/clang/include/clang/AST/ComputeDependence.h
index c298f2620f211..895105640b931 100644
--- a/clang/include/clang/AST/ComputeDependence.h
+++ b/clang/include/clang/AST/ComputeDependence.h
@@ -28,6 +28,7 @@ class ParenExpr;
 class UnaryOperator;
 class UnaryExprOrTypeTraitExpr;
 class ArraySubscriptExpr;
+class MatrixSingleSubscriptExpr;
 class MatrixSubscriptExpr;
 class CompoundLiteralExpr;
 class ImplicitCastExpr;
@@ -117,6 +118,7 @@ ExprDependence computeDependence(ParenExpr *E);
 ExprDependence computeDependence(UnaryOperator *E, const ASTContext &Ctx);
 ExprDependence computeDependence(UnaryExprOrTypeTraitExpr *E);
 ExprDependence computeDependence(ArraySubscriptExpr *E);
+ExprDependence computeDependence(MatrixSingleSubscriptExpr *E);
 ExprDependence computeDependence(MatrixSubscriptExpr *E);
 ExprDependence computeDependence(CompoundLiteralExpr *E);
 ExprDependence computeDependence(ImplicitCastExpr *E);
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 573cc72db35c6..16d9bbe8ff7c1 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2790,6 +2790,73 @@ class ArraySubscriptExpr : public Expr {
   }
 };
 
+/// MatrixSingleSubscriptExpr - Matrix single subscript expression for the
+/// MatrixType extension when you want to get\set a vector from a Matrix.
+class MatrixSingleSubscriptExpr : public Expr {
+  enum { BASE, ROW_IDX, END_EXPR };
+  Stmt *SubExprs[END_EXPR];
+
+public:
+  /// matrix[row]
+  ///
+  /// \param Base        The matrix expression.
+  /// \param RowIdx      The row index expression.
+  /// \param T           The type of the row (usually a vector type).
+  /// \param RBracketLoc Location of the closing ']'.
+  MatrixSingleSubscriptExpr(Expr *Base, Expr *RowIdx, QualType T,
+                            SourceLocation RBracketLoc)
+      : Expr(MatrixSingleSubscriptExprClass, T,
+             Base->getValueKind(), // lvalue/rvalue follows the matrix base
+             OK_MatrixComponent) { // or OK_Ordinary/OK_VectorComponent if you
+                                   // prefer
+    SubExprs[BASE] = Base;
+    SubExprs[ROW_IDX] = RowIdx;
+    ArrayOrMatrixSubscriptExprBits.RBracketLoc = RBracketLoc;
+    setDependence(computeDependence(this));
+  }
+
+  /// Create an empty matrix single-subscript expression.
+  explicit MatrixSingleSubscriptExpr(EmptyShell Shell)
+      : Expr(MatrixSingleSubscriptExprClass, Shell) {}
+
+  Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
+  const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
+  void setBase(Expr *E) { SubExprs[BASE] = E; }
+
+  Expr *getRowIdx() { return cast<Expr>(SubExprs[ROW_IDX]); }
+  const Expr *getRowIdx() const { return cast<Expr>(SubExprs[ROW_IDX]); }
+  void setRowIdx(Expr *E) { SubExprs[ROW_IDX] = E; }
+
+  SourceLocation getBeginLoc() const LLVM_READONLY {
+    return getBase()->getBeginLoc();
+  }
+
+  SourceLocation getEndLoc() const { return getRBracketLoc(); }
+
+  SourceLocation getExprLoc() const LLVM_READONLY {
+    return getBase()->getExprLoc();
+  }
+
+  SourceLocation getRBracketLoc() const {
+    return ArrayOrMatrixSubscriptExprBits.RBracketLoc;
+  }
+  void setRBracketLoc(SourceLocation L) {
+    ArrayOrMatrixSubscriptExprBits.RBracketLoc = L;
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == MatrixSingleSubscriptExprClass;
+  }
+
+  // Iterators
+  child_range children() {
+    return child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
+  }
+  const_child_range children() const {
+    return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
+  }
+};
+
 /// MatrixSubscriptExpr - Matrix subscript expression for the MatrixType
 /// extension.
 /// MatrixSubscriptExpr can be either incomplete (only Base and RowIdx are set
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h 
b/clang/include/clang/AST/RecursiveASTVisitor.h
index 8f427427d71ed..92409b72e4f0c 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2893,6 +2893,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
 // over the children.
 DEF_TRAVERSE_STMT(AddrLabelExpr, {})
 DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
+DEF_TRAVERSE_STMT(MatrixSingleSubscriptExpr, {})
 DEF_TRAVERSE_STMT(MatrixSubscriptExpr, {})
 DEF_TRAVERSE_STMT(ArraySectionExpr, {})
 DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {})
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index e1cca34d2212c..21d0a7dfe577c 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -530,6 +530,7 @@ class alignas(void *) Stmt {
   class ArrayOrMatrixSubscriptExprBitfields {
     friend class ArraySubscriptExpr;
     friend class MatrixSubscriptExpr;
+    friend class MatrixSingleSubscriptExpr;
 
     LLVM_PREFERRED_TYPE(ExprBitfields)
     unsigned : NumExprBits;
diff --git a/clang/include/clang/Basic/StmtNodes.td 
b/clang/include/clang/Basic/StmtNodes.td
index bf3686bb372d5..ada74807e56e2 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -74,6 +74,7 @@ def UnaryOperator : StmtNode<Expr>;
 def OffsetOfExpr : StmtNode<Expr>;
 def UnaryExprOrTypeTraitExpr : StmtNode<Expr>;
 def ArraySubscriptExpr : StmtNode<Expr>;
+def MatrixSingleSubscriptExpr : StmtNode<Expr>;
 def MatrixSubscriptExpr : StmtNode<Expr>;
 def ArraySectionExpr : StmtNode<Expr>;
 def OMPIteratorExpr : StmtNode<Expr>;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4a601a0eaf1b9..d4d5c3d8bed17 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7406,6 +7406,9 @@ class Sema final : public SemaBase {
   ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
                                              Expr *Idx, SourceLocation RLoc);
 
+  ExprResult CreateBuiltinMatrixSingleSubscriptExpr(Expr *Base, Expr *RowIdx,
+                                                    SourceLocation RBLoc);
+
   ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
                                               Expr *ColumnIdx,
                                               SourceLocation RBLoc);
diff --git a/clang/lib/AST/ComputeDependence.cpp 
b/clang/lib/AST/ComputeDependence.cpp
index 638080ea781a9..8429f17d26be5 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -115,6 +115,10 @@ ExprDependence clang::computeDependence(ArraySubscriptExpr 
*E) {
   return E->getLHS()->getDependence() | E->getRHS()->getDependence();
 }
 
+ExprDependence clang::computeDependence(MatrixSingleSubscriptExpr *E) {
+  return E->getBase()->getDependence() | E->getRowIdx()->getDependence();
+}
+
 ExprDependence clang::computeDependence(MatrixSubscriptExpr *E) {
   return E->getBase()->getDependence() | E->getRowIdx()->getDependence() |
          (E->getColumnIdx() ? E->getColumnIdx()->getDependence()
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index ca7f3e16a9276..b400b2a083d9b 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3789,6 +3789,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
 
   case ParenExprClass:
   case ArraySubscriptExprClass:
+  case MatrixSingleSubscriptExprClass:
   case MatrixSubscriptExprClass:
   case ArraySectionExprClass:
   case OMPArrayShapingExprClass:
diff --git a/clang/lib/AST/ExprClassification.cpp 
b/clang/lib/AST/ExprClassification.cpp
index aeacd0dc765ef..9995d1b411c5b 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -259,6 +259,9 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const 
Expr *E) {
     }
     return Cl::CL_LValue;
 
+  case Expr::MatrixSingleSubscriptExprClass:
+    return ClassifyInternal(Ctx, 
cast<MatrixSingleSubscriptExpr>(E)->getBase());
+
   // Subscripting matrix types behaves like member accesses.
   case Expr::MatrixSubscriptExprClass:
     return ClassifyInternal(Ctx, cast<MatrixSubscriptExpr>(E)->getBase());
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 11c5e1c6e90f4..52481dc71b75d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -20667,6 +20667,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext 
&Ctx) {
   case Expr::ImaginaryLiteralClass:
   case Expr::StringLiteralClass:
   case Expr::ArraySubscriptExprClass:
+  case Expr::MatrixSingleSubscriptExprClass:
   case Expr::MatrixSubscriptExprClass:
   case Expr::ArraySectionExprClass:
   case Expr::OMPArrayShapingExprClass:
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 5572e0a7ae59c..cb71987fba766 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -5482,6 +5482,15 @@ void CXXNameMangler::mangleExpression(const Expr *E, 
unsigned Arity,
     break;
   }
 
+  case Expr::MatrixSingleSubscriptExprClass: {
+    NotPrimaryExpr();
+    const MatrixSingleSubscriptExpr *ME = cast<MatrixSingleSubscriptExpr>(E);
+    Out << "ix";
+    mangleExpression(ME->getBase());
+    mangleExpression(ME->getRowIdx());
+    break;
+  }
+
   case Expr::MatrixSubscriptExprClass: {
     NotPrimaryExpr();
     const MatrixSubscriptExpr *ME = cast<MatrixSubscriptExpr>(E);
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index ff8ca01ec5477..51b9c47f22ff0 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1685,6 +1685,14 @@ void 
StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) {
   OS << "]";
 }
 
+void StmtPrinter::VisitMatrixSingleSubscriptExpr(
+    MatrixSingleSubscriptExpr *Node) {
+  PrintExpr(Node->getBase());
+  OS << "[";
+  PrintExpr(Node->getRowIdx());
+  OS << "]";
+}
+
 void StmtPrinter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *Node) {
   PrintExpr(Node->getBase());
   OS << "[";
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 4a8c638c85331..c7b7c65715dfc 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1508,6 +1508,11 @@ void StmtProfiler::VisitArraySubscriptExpr(const 
ArraySubscriptExpr *S) {
   VisitExpr(S);
 }
 
+void StmtProfiler::VisitMatrixSingleSubscriptExpr(
+    const MatrixSingleSubscriptExpr *S) {
+  VisitExpr(S);
+}
+
 void StmtProfiler::VisitMatrixSubscriptExpr(const MatrixSubscriptExpr *S) {
   VisitExpr(S);
 }
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index e842158236cd4..ca06b5df94cb3 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1796,6 +1796,8 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E,
     return EmitUnaryOpLValue(cast<UnaryOperator>(E));
   case Expr::ArraySubscriptExprClass:
     return EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E));
+  case Expr::MatrixSingleSubscriptExprClass:
+    return EmitMatrixSingleSubscriptExpr(cast<MatrixSingleSubscriptExpr>(E));
   case Expr::MatrixSubscriptExprClass:
     return EmitMatrixSubscriptExpr(cast<MatrixSubscriptExpr>(E));
   case Expr::ArraySectionExprClass:
@@ -2440,6 +2442,35 @@ RValue CodeGenFunction::EmitLoadOfLValue(LValue LV, 
SourceLocation Loc) {
         Builder.CreateLoad(LV.getMatrixAddress(), LV.isVolatileQualified());
     return RValue::get(Builder.CreateExtractElement(Load, Idx, "matrixext"));
   }
+  if (LV.isMatrixRow()) {
+    QualType MatTy = LV.getType();
+    const ConstantMatrixType *MT = MatTy->castAs<ConstantMatrixType>();
+
+    unsigned NumRows = MT->getNumRows();
+    unsigned NumCols = MT->getNumColumns();
+
+    llvm::Value *MatrixVec = EmitLoadOfScalar(LV, Loc);
+
+    llvm::Value *Row = LV.getMatrixRowIdx();
+    llvm::Value *Result =
+        llvm::UndefValue::get(ConvertType(LV.getType())); // <NumCols x T>
+
+    llvm::MatrixBuilder MB(Builder);
+
+    for (unsigned Col = 0; Col < NumCols; ++Col) {
+      llvm::Value *ColIdx = llvm::ConstantInt::get(Row->getType(), Col);
+
+      llvm::Value *EltIndex = MB.CreateIndex(Row, ColIdx, NumRows);
+
+      llvm::Value *Elt = Builder.CreateExtractElement(MatrixVec, EltIndex);
+
+      llvm::Value *Lane = llvm::ConstantInt::get(Builder.getInt32Ty(), Col);
+
+      Result = Builder.CreateInsertElement(Result, Elt, Lane);
+    }
+
+    return RValue::get(Result);
+  }
 
   assert(LV.isBitField() && "Unknown LValue type!");
   return EmitLoadOfBitfieldLValue(LV, Loc);
@@ -2662,6 +2693,36 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, 
LValue Dst,
       addInstToCurrentSourceAtom(I, Vec);
       return;
     }
+    if (Dst.isMatrixRow()) {
+      QualType MatTy = Dst.getType();
+      const ConstantMatrixType *MT = MatTy->castAs<ConstantMatrixType>();
+
+      unsigned NumRows = MT->getNumRows();
+      unsigned NumCols = MT->getNumColumns();
+
+      llvm::Value *MatrixVec =
+          Builder.CreateLoad(Dst.getAddress(), "matrix.load");
+
+      llvm::Value *Row = Dst.getMatrixRowIdx();
+      llvm::Value *RowVal = Src.getScalarVal(); // <NumCols x T>
+
+      llvm::MatrixBuilder MB(Builder);
+
+      for (unsigned Col = 0; Col < NumCols; ++Col) {
+        llvm::Value *ColIdx = llvm::ConstantInt::get(Row->getType(), Col);
+
+        llvm::Value *EltIndex = MB.CreateIndex(Row, ColIdx, NumRows);
+
+        llvm::Value *Lane = llvm::ConstantInt::get(Builder.getInt32Ty(), Col);
+
+        llvm::Value *NewElt = Builder.CreateExtractElement(RowVal, Lane);
+
+        MatrixVec = Builder.CreateInsertElement(MatrixVec, NewElt, EltIndex);
+      }
+
+      Builder.CreateStore(MatrixVec, Dst.getAddress());
+      return;
+    }
 
     assert(Dst.isBitField() && "Unknown LValue type");
     return EmitStoreThroughBitfieldLValue(Src, Dst);
@@ -4874,6 +4935,35 @@ llvm::Value *CodeGenFunction::EmitMatrixIndexExpr(const 
Expr *E) {
   return Builder.CreateIntCast(Idx, IntPtrTy, IsSigned);
 }
 
+LValue CodeGenFunction::EmitMatrixSingleSubscriptExpr(
+    const MatrixSingleSubscriptExpr *E) {
+  LValue Base = EmitLValue(E->getBase());
+  llvm::Value *RowIdx = EmitMatrixIndexExpr(E->getRowIdx());
+
+  if (auto *RowConst = llvm::dyn_cast<llvm::ConstantInt>(RowIdx)) {
+
+    // Extract matrix shape from the AST type
+    const auto *MatTy = E->getBase()->getType()->castAs<ConstantMatrixType>();
+    unsigned NumCols = MatTy->getNumColumns();
+    llvm::SmallVector<llvm::Constant *, 8> Indices;
+    Indices.reserve(NumCols);
+
+    unsigned Row = RowConst->getZExtValue();
+    unsigned Start = Row * NumCols;
+    for (unsigned C = 0; C < NumCols; ++C) {
+      Indices.push_back(llvm::ConstantInt::get(Int32Ty, Start + C));
+    }
+    llvm::Constant *Elts = llvm::ConstantVector::get(Indices);
+    return LValue::MakeExtVectorElt(
+        MaybeConvertMatrixAddress(Base.getAddress(), *this), Elts,
+        E->getBase()->getType(), Base.getBaseInfo(), TBAAAccessInfo());
+  }
+
+  return LValue::MakeMatrixRow(
+      MaybeConvertMatrixAddress(Base.getAddress(), *this), RowIdx,
+      E->getBase()->getType(), Base.getBaseInfo(), TBAAAccessInfo());
+}
+
 LValue CodeGenFunction::EmitMatrixSubscriptExpr(const MatrixSubscriptExpr *E) {
   assert(
       !E->isIncomplete() &&
@@ -5146,6 +5236,9 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
     return LValue::MakeExtVectorElt(Base.getAddress(), CV, type,
                                     Base.getBaseInfo(), TBAAAccessInfo());
   }
+  if (Base.isMatrixRow())
+    return EmitUnsupportedLValue(E, "Matrix single index swizzle");
+
   assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!");
 
   llvm::Constant *BaseElts = Base.getExtVectorElts();
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 769bc37b0e131..70397e8cb99c2 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -599,6 +599,7 @@ class ScalarExprEmitter
   }
 
   Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E);
+  Value *VisitMatrixSingleSubscriptExpr(MatrixSingleSubscriptExpr *E);
   Value *VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E);
   Value *VisitShuffleVectorExpr(ShuffleVectorExpr *E);
   Value *VisitConvertVectorExpr(ConvertVectorExpr *E);
@@ -2109,6 +2110,40 @@ Value 
*ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
   return Builder.CreateExtractElement(Base, Idx, "vecext");
 }
 
+Value *ScalarExprEmitter::VisitMatrixSingleSubscriptExpr(
+    MatrixSingleSubscriptExpr *E) {
+  TestAndClearIgnoreResultAssign();
+
+  auto *MatrixTy = E->getBase()->getType()->castAs<ConstantMatrixType>();
+  unsigned NumRows = MatrixTy->getNumRows();
+  unsigned NumColumns = MatrixTy->getNumColumns();
+
+  // Row index
+  Value *RowIdx = CGF.EmitMatrixIndexExpr(E->getRowIdx());
+
+  llvm::MatrixBuilder MB(Builder);
+
+  // The row index must be in [0, NumRows)
+  if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0)
+    MB.CreateIndexAssumption(RowIdx, NumRows);
+
+  Value *FlatMatrix = Visit(E->getBase());
+  llvm::Type *ElemTy = CGF.ConvertType(MatrixTy->getElementType());
+  auto *ResultTy = llvm::FixedVectorType::get(ElemTy, NumColumns);
+  Value *RowVec = llvm::UndefValue::get(ResultTy);
+
+  for (unsigned Col = 0; Col != NumColumns; ++Col) {
+    Value *ColVal = llvm::ConstantInt::get(RowIdx->getType(), Col);
+    Value *EltIdx = MB.CreateIndex(RowIdx, ColVal, NumRows, "matrix_row_idx");
+    Value *Elt =
+        Builder.CreateExtractElement(FlatMatrix, EltIdx, "matrix_elem");
+    Value *Lane = llvm::ConstantInt::get(Builder.getInt32Ty(), Col);
+    RowVec = Builder.CreateInsertElement(RowVec, Elt, Lane, "matrix_row_ins");
+  }
+
+  return RowVec;
+}
+
 Value *ScalarExprEmitter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E) {
   TestAndClearIgnoreResultAssign();
 
diff --git a/clang/lib/CodeGen/CGValue.h b/clang/lib/CodeGen/CGValue.h
index 6b381b59e71cd..c08ca70de10e1 100644
--- a/clang/lib/CodeGen/CGValue.h
+++ b/clang/lib/CodeGen/CGValue.h
@@ -187,7 +187,8 @@ class LValue {
     BitField,     // This is a bitfield l-value, use getBitfield*.
     ExtVectorElt, // This is an extended vector subset, use getExtVectorComp
     GlobalReg,    // This is a register l-value, use getGlobalReg()
-    MatrixElt     // This is a matrix element, use getVector*
+    MatrixElt,    // This is a matrix element, use getVector*
+    MatrixRow     // This is a matrix vector subset, use getVector*
   } LVType;
 
   union {
@@ -282,6 +283,7 @@ class LValue {
   bool isExtVectorElt() const { return LVType == ExtVectorElt; }
   bool isGlobalReg() const { return LVType == GlobalReg; }
   bool isMatrixElt() const { return LVType == MatrixElt; }
+  bool isMatrixRow() const { return LVType == MatrixRow; }
 
   bool isVolatileQualified() const { return Quals.hasVolatile(); }
   bool isRestrictQualified() const { return Quals.hasRestrict(); }
@@ -398,6 +400,11 @@ class LValue {
     return VectorIdx;
   }
 
+  llvm::Value *getMatrixRowIdx() const {
+    assert(isMatrixRow());
+    return VectorIdx;
+  }
+
   // extended vector elements.
   Address getExtVectorAddress() const {
     assert(isExtVectorElt());
@@ -486,6 +493,16 @@ class LValue {
     return R;
   }
 
+  static LValue MakeMatrixRow(Address Addr, llvm::Value *RowIdx,
+                              QualType MatrixTy, LValueBaseInfo BaseInfo,
+                              TBAAAccessInfo TBAAInfo) {
+    LValue LV;
+    LV.LVType = MatrixRow;
+    LV.VectorIdx = RowIdx; // store the row index here
+    LV.Initialize(MatrixTy, MatrixTy.getQualifiers(), Addr, BaseInfo, 
TBAAInfo);
+    return LV;
+  }
+
   static LValue MakeMatrixElt(Address matAddress, llvm::Value *Idx,
                               QualType type, LValueBaseInfo BaseInfo,
                               TBAAAccessInfo TBAAInfo) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.h 
b/clang/lib/CodeGen/CodeGenFunction.h
index 8c4c1c8c2dc95..3abe516debcb0 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4412,6 +4412,7 @@ class CodeGenFunction : public CodeGenTypeCache {
   LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
                                 bool Accessed = false);
   llvm::Value *EmitMatrixIndexExpr(const Expr *E);
+  LValue EmitMatrixSingleSubscriptExpr(const MatrixSingleSubscriptExpr *E);
   LValue EmitMatrixSubscriptExpr(const MatrixSubscriptExpr *E);
   LValue EmitArraySectionExpr(const ArraySectionExpr *E,
                               bool IsLowerBound = true);
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp 
b/clang/lib/Sema/SemaExceptionSpec.cpp
index a0483c3027199..8b7f2e0a755d7 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1303,6 +1303,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
     // Some might be dependent for other reasons.
   case Expr::ArraySubscriptExprClass:
   case Expr::MatrixSubscriptExprClass:
+  case Expr::MatrixSingleSubscriptExprClass:
   case Expr::ArraySectionExprClass:
   case Expr::OMPArrayShapingExprClass:
   case Expr::OMPIteratorExprClass:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index cfabd1b76c103..fe82b8979baa7 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5090,6 +5090,62 @@ ExprResult Sema::tryConvertExprToType(Expr *E, QualType 
Ty) {
   return InitSeq.Perform(*this, Entity, Kind, E);
 }
 
+ExprResult Sema::CreateBuiltinMatrixSingleSubscriptExpr(Expr *Base,
+                                                        Expr *RowIdx,
+                                                        SourceLocation RBLoc) {
+  ExprResult BaseR = CheckPlaceholderExpr(Base);
+  if (BaseR.isInvalid())
+    return BaseR;
+  Base = BaseR.get();
+
+  ExprResult RowR = CheckPlaceholderExpr(RowIdx);
+  if (RowR.isInvalid())
+    return RowR;
+  RowIdx = RowR.get();
+
+  // Build an unanalyzed expression if any of the operands is type-dependent.
+  if (Base->isTypeDependent() || RowIdx->isTypeDependent())
+    return new (Context)
+        MatrixSingleSubscriptExpr(Base, RowIdx, Context.DependentTy, RBLoc);
+
+  // Check that IndexExpr is an integer expression. If it is a constant
+  // expression, check that it is less than Dim (= the number of elements in 
the
+  // corresponding dimension).
+  auto IsIndexValid = [&](Expr *IndexExpr, unsigned Dim,
+                          bool IsColumnIdx) -> Expr * {
+    if (!IndexExpr->getType()->isIntegerType() &&
+        !IndexExpr->isTypeDependent()) {
+      Diag(IndexExpr->getBeginLoc(), diag::err_matrix_index_not_integer)
+          << IsColumnIdx;
+      return nullptr;
+    }
+
+    if (std::optional<llvm::APSInt> Idx =
+            IndexExpr->getIntegerConstantExpr(Context)) {
+      if ((*Idx < 0 || *Idx >= Dim)) {
+        Diag(IndexExpr->getBeginLoc(), diag::err_matrix_index_outside_range)
+            << IsColumnIdx << Dim;
+        return nullptr;
+      }
+    }
+
+    ExprResult ConvExpr = IndexExpr;
+    assert(!ConvExpr.isInvalid() &&
+           "should be able to convert any integer type to size type");
+    return ConvExpr.get();
+  };
+
+  auto *MTy = Base->getType()->getAs<ConstantMatrixType>();
+  RowIdx = IsIndexValid(RowIdx, MTy->getNumRows(), false);
+  if (!RowIdx)
+    return ExprError();
+
+  QualType RowVecQT =
+      Context.getExtVectorType(MTy->getElementType(), MTy->getNumColumns());
+
+  return new (Context) MatrixSingleSubscriptExpr(Base, RowIdx, RowVecQT, 
RBLoc);
+}
+
 ExprResult Sema::CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
                                                   Expr *ColumnIdx,
                                                   SourceLocation RBLoc) {
@@ -5103,9 +5159,12 @@ ExprResult Sema::CreateBuiltinMatrixSubscriptExpr(Expr 
*Base, Expr *RowIdx,
     return RowR;
   RowIdx = RowR.get();
 
-  if (!ColumnIdx)
+  if (!ColumnIdx) {
+    if (getLangOpts().HLSL)
+      return CreateBuiltinMatrixSingleSubscriptExpr(Base, RowIdx, RBLoc);
     return new (Context) MatrixSubscriptExpr(
         Base, RowIdx, ColumnIdx, Context.IncompleteMatrixIdxTy, RBLoc);
+  }
 
   // Build an unanalyzed expression if any of the operands is type-dependent.
   if (Base->isTypeDependent() || RowIdx->isTypeDependent() ||
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 8e5dbeb792348..6b8b2317d8aa4 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2849,6 +2849,16 @@ class TreeTransform {
                                              RBracketLoc);
   }
 
+  /// Build a new matrix single subscript expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildMatrixSingleSubscriptExpr(Expr *Base, Expr *RowIdx,
+                                              SourceLocation RBracketLoc) {
+    return getSema().CreateBuiltinMatrixSingleSubscriptExpr(Base, RowIdx,
+                                                            RBracketLoc);
+  }
+
   /// Build a new matrix subscript expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
@@ -13378,6 +13388,25 @@ 
TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) {
       /*FIXME:*/ E->getLHS()->getBeginLoc(), RHS.get(), E->getRBracketLoc());
 }
 
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformMatrixSingleSubscriptExpr(
+    MatrixSingleSubscriptExpr *E) {
+  ExprResult Base = getDerived().TransformExpr(E->getBase());
+  if (Base.isInvalid())
+    return ExprError();
+
+  ExprResult RowIdx = getDerived().TransformExpr(E->getRowIdx());
+  if (RowIdx.isInvalid())
+    return ExprError();
+
+  if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() &&
+      RowIdx.get() == E->getRowIdx())
+    return E;
+
+  return getDerived().RebuildMatrixSingleSubscriptExpr(Base.get(), 
RowIdx.get(),
+                                                       E->getRBracketLoc());
+}
+
 template <typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformMatrixSubscriptExpr(MatrixSubscriptExpr *E) {
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index eef97a8588f0b..64fe19b2c660a 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -962,6 +962,14 @@ void 
ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
   E->setRBracketLoc(readSourceLocation());
 }
 
+void ASTStmtReader::VisitMatrixSingleSubscriptExpr(
+    MatrixSingleSubscriptExpr *E) {
+  VisitExpr(E);
+  E->setBase(Record.readSubExpr());
+  E->setRowIdx(Record.readSubExpr());
+  E->setRBracketLoc(readSourceLocation());
+}
+
 void ASTStmtReader::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E) {
   VisitExpr(E);
   E->setBase(Record.readSubExpr());
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp 
b/clang/lib/Serialization/ASTWriterStmt.cpp
index acf345392aa1a..0f6c81f6a4693 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -900,6 +900,15 @@ void 
ASTStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
   Code = serialization::EXPR_ARRAY_SUBSCRIPT;
 }
 
+void ASTStmtWriter::VisitMatrixSingleSubscriptExpr(
+    MatrixSingleSubscriptExpr *E) {
+  VisitExpr(E);
+  Record.AddStmt(E->getBase());
+  Record.AddStmt(E->getRowIdx());
+  Record.AddSourceLocation(E->getRBracketLoc());
+  Code = serialization::EXPR_ARRAY_SUBSCRIPT;
+}
+
 void ASTStmtWriter::VisitMatrixSubscriptExpr(MatrixSubscriptExpr *E) {
   VisitExpr(E);
   Record.AddStmt(E->getBase());
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index a759aee47b8ea..7e99418997afd 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -2082,6 +2082,11 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
       Bldr.addNodes(Dst);
       break;
 
+    case Stmt::MatrixSingleSubscriptExprClass:
+      llvm_unreachable(
+          "Support for MatrixSingleSubscriptExprClass is not implemented.");
+      break;
+
     case Stmt::MatrixSubscriptExprClass:
       llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
       break;
diff --git a/clang/test/AST/HLSL/matrix-single-subscript-getter.hlsl 
b/clang/test/AST/HLSL/matrix-single-subscript-getter.hlsl
new file mode 100644
index 0000000000000..01e4a26982c6b
--- /dev/null
+++ b/clang/test/AST/HLSL/matrix-single-subscript-getter.hlsl
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -o 
- %s | FileCheck %s 
+
+typedef float float4x4 __attribute__((matrix_type(4,4)));
+typedef int int4x4 __attribute__((matrix_type(4,4)));
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+
+export float4 getFloatMatrixDynamic(float4x4 M, int index) {
+// CHECK: FunctionDecl {{.*}} used getFloatMatrixDynamic 'float4 (float4x4, 
int)'
+// CHECK: ReturnStmt {{.*}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4':'matrix<float, 4, 4>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'index' 'int'
+    return M[index];
+}
+
+export int4 getIntMatrixDynamic(int4x4 M, int index) {
+// CHECK: FunctionDecl {{.*}} used getIntMatrixDynamic 'int4 (int4x4, int)'
+// CHECK: ReturnStmt {{.*}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'index' 'int'
+    return M[index];
+}
+
+export float4 AddFloatMatrixConstant(float4x4 M) {
+// CHECK: FunctionDecl {{.*}} used AddFloatMatrixConstant 'float4 (float4x4)'
+// CHECK: ReturnStmt {{.*}}
+// CHECK-NEXT: BinaryOperator {{.*}} 'vector<float, 4>' '+'
+// CHECK-NEXT: BinaryOperator {{.*}} 'vector<float, 4>' '+'
+// CHECK-NEXT: BinaryOperator {{.*}} 'vector<float, 4>' '+'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4':'matrix<float, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4':'matrix<float, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4':'matrix<float, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4':'matrix<float, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
+    return M[0] + M[1] + M[2] +M[3];
+}
+
+export int4 AddIntMatrixConstant(int4x4 M) {
+// CHECK: FunctionDecl {{.*}} used AddIntMatrixConstant 'int4 (int4x4)'
+// CHECK: ReturnStmt {{.*}}
+// CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 4>' '+'
+// CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 4>' '+'
+// CHECK-NEXT: BinaryOperator {{.*}} 'vector<int, 4>' '+'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
+   return M[0] + M[1] + M[2] +M[3];
+}
\ No newline at end of file
diff --git a/clang/test/AST/HLSL/matrix-single-subscript-setter.hlsl 
b/clang/test/AST/HLSL/matrix-single-subscript-setter.hlsl
new file mode 100644
index 0000000000000..c6f459eab0773
--- /dev/null
+++ b/clang/test/AST/HLSL/matrix-single-subscript-setter.hlsl
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -o 
- %s | FileCheck %s 
+
+typedef float float4x4 __attribute__((matrix_type(4,4)));
+typedef int int4x4 __attribute__((matrix_type(4,4)));
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+
+export void setMatrix(out float4x4 M, int index, float4 V) {
+// CHECK: BinaryOperator{{.*}} 'vector<float, 4>' lvalue matrixcomponent '='
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4 &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'index' 'int'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar 
{{.*}} 'V' 'float4':'vector<float, 4>'
+    M[index] = V;
+}
+
+export void setMatrixConstIndex(out int4x4 M, int4x4 N ) {
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' lvalue matrixcomponent '='
+// CHECK: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4 &__restrict'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'N' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
+    M[0] = N[3];
+
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' lvalue matrixcomponent '='
+// CHECK: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4 &__restrict'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'N' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
+    M[1] = N[2];
+
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' lvalue matrixcomponent '='
+// CHECK: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4 &__restrict'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'N' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
+    M[2] = N[1];
+
+// CHECK: BinaryOperator {{.*}} 'vector<int, 4>' lvalue matrixcomponent '='
+// CHECK: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4 &__restrict'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'N' 'int4x4':'matrix<int, 4, 4>'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0
+    M[3] = N[0];
+}
\ No newline at end of file
diff --git a/clang/test/AST/HLSL/matrix-single-subscript-swizzle.hlsl 
b/clang/test/AST/HLSL/matrix-single-subscript-swizzle.hlsl
new file mode 100644
index 0000000000000..5d7601e48682d
--- /dev/null
+++ b/clang/test/AST/HLSL/matrix-single-subscript-swizzle.hlsl
@@ -0,0 +1,56 @@
+
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -o 
- %s | FileCheck %s 
+
+typedef float float4x4 __attribute__((matrix_type(4,4)));
+typedef int int4x4 __attribute__((matrix_type(4,4)));
+
+typedef float float4 __attribute__((ext_vector_type(4)));
+typedef float float3 __attribute__((ext_vector_type(3)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+
+export void setMatrix(out float4x4 M, int index, float4 V) {
+// CHECK: FunctionDecl {{.*}} used setMatrix 'void (out float4x4, int, float4)'
+// CHECK: BinaryOperator {{.*}} 'float4':'vector<float, 4>' lvalue 
vectorcomponent '='
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'float4':'vector<float, 4>' lvalue 
vectorcomponent abgr
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4 &__restrict'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'index' 'int'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar 
{{.*}} 'V' 'float4':'vector<float, 4>'
+    M[index].abgr = V;
+}
+
+export void setMatrix1(out float4x4 M, float4 V) {
+// CHECK: FunctionDecl {{.*}} used setMatrix1 'void (out float4x4, float4)'
+// CHECK: BinaryOperator {{.*}} 'float4':'vector<float, 4>' lvalue 
vectorcomponent '='
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'float4':'vector<float, 4>' lvalue 
vectorcomponent abgr
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4 &__restrict'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector<float, 4>' 
<LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector<float, 4>' lvalue ParmVar 
{{.*}} 'V' 'float4':'vector<float, 4>'
+    M[3].abgr = V;
+}
+
+export void setMatrix2(out int4x4 M, int4 V) {
+// CHECK: FunctionDecl {{.*}} used setMatrix2 'void (out int4x4, int4)'
+// CHECK: BinaryOperator {{.*}} 'int4':'vector<int, 4>' lvalue vectorcomponent 
'='
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'int4':'vector<int, 4>' lvalue 
vectorcomponent rgba
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<int, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4x4':'matrix<int, 4, 4>' lvalue ParmVar 
{{.*}} 'M' 'int4x4 &__restrict'
+// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int4':'vector<int, 4>' <LValueToRValue>
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int4':'vector<int, 4>' lvalue ParmVar 
{{.*}} 'V' 'int4':'vector<int, 4>'
+    M[2].rgba = V;
+}
+
+export float3 getMatrix(float4x4 M, int index) {
+// CHECK: FunctionDecl {{.*}} used getMatrix 'float3 (float4x4, int)'
+// CHECK: ReturnStmt {{.*}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float3':'vector<float, 3>' 
<LValueToRValue>
+// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'float3':'vector<float, 3>' lvalue 
vectorcomponent rgb
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 4>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix<float, 4, 4>' lvalue 
ParmVar {{.*}} 'M' 'float4x4':'matrix<float, 4, 4>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'index' 'int'
+    return M[index].rgb;
+}
\ No newline at end of file
diff --git a/clang/test/AST/HLSL/pch_with_matrix_single_subscript.hlsl 
b/clang/test/AST/HLSL/pch_with_matrix_single_subscript.hlsl
new file mode 100644
index 0000000000000..089dd3f34d93b
--- /dev/null
+++ b/clang/test/AST/HLSL/pch_with_matrix_single_subscript.hlsl
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl 
-finclude-default-header -emit-pch -o %t %S/Inputs/pch.hlsl
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl 
-finclude-default-header -include-pch %t -ast-dump-all %s | FileCheck  %s
+
+float3x2 gM;
+
+// CHECK: FunctionDecl {{.*}} getRow 'float2 (uint)'
+// CHECK-NEXT: ParmVarDecl {{.*}} col:20 used row 'uint':'unsigned int'
+// CHECK-NEXT: CompoundStmt {{.*}}
+// CHECK-NEXT: ReturnStmt {{.*}}
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <LValueToRValue>
+// CHECK-NEXT: MatrixSingleSubscriptExpr {{.*}} 'vector<float, 2>' lvalue 
matrixcomponent
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl_constant float3x2':'matrix<float 
hlsl_constant, 3, 2>' lvalue Var {{.*}} 'gM' 'hlsl_constant 
float3x2':'matrix<float hlsl_constant, 3, 2>'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'uint':'unsigned int' lvalue ParmVar {{.*}} 
'row' 'uint':'unsigned int'
+float2 getRow(uint row) {  
+  return gM[row];
+}
diff --git 
a/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptConstSwizzle.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptConstSwizzle.hlsl
new file mode 100644
index 0000000000000..2e580e4495930
--- /dev/null
+++ 
b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptConstSwizzle.hlsl
@@ -0,0 +1,60 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.7-library -disable-llvm-passes 
-emit-llvm -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK-LABEL: define hidden void 
@_Z10setMatrix1Ru11matrix_typeILm4ELm4EfEDv4_f(
+// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) 
[[M:%.*]], <4 x float> noundef nofpclass(nan inf) [[V:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[V_ADDR:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT:    store ptr [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    store <4 x float> [[V]], ptr [[V_ADDR]], align 16
+// CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr [[V_ADDR]], align 16
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull 
[[META3:![0-9]+]], !align [[META4:![0-9]+]]
+// CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 
0, i32 15
+// CHECK-NEXT:    store float [[TMP2]], ptr [[TMP3]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+// CHECK-NEXT:    [[TMP5:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 
0, i32 14
+// CHECK-NEXT:    store float [[TMP4]], ptr [[TMP5]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 
0, i32 13
+// CHECK-NEXT:    store float [[TMP6]], ptr [[TMP7]], align 4
+// CHECK-NEXT:    [[TMP8:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+// CHECK-NEXT:    [[TMP9:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 
0, i32 12
+// CHECK-NEXT:    store float [[TMP8]], ptr [[TMP9]], align 4
+// CHECK-NEXT:    ret void
+//
+void setMatrix1(out float4x4 M, float4 V) {
+    M[3].abgr = V;
+}
+
+// CHECK-LABEL: define hidden void 
@_Z10setMatrix2Ru11matrix_typeILm4ELm4EiEDv4_i(
+// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) 
[[M:%.*]], <4 x i32> noundef [[V:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[V_ADDR:%.*]] = alloca <4 x i32>, align 16
+// CHECK-NEXT:    store ptr [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    store <4 x i32> [[V]], ptr [[V_ADDR]], align 16
+// CHECK-NEXT:    [[TMP0:%.*]] = load <4 x i32>, ptr [[V_ADDR]], align 16
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull 
[[META3]], !align [[META4]]
+// CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x i32> [[TMP0]], i32 0
+// CHECK-NEXT:    [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 
0, i32 8
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[TMP3]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x i32> [[TMP0]], i32 1
+// CHECK-NEXT:    [[TMP5:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 
0, i32 9
+// CHECK-NEXT:    store i32 [[TMP4]], ptr [[TMP5]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = extractelement <4 x i32> [[TMP0]], i32 2
+// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 
0, i32 10
+// CHECK-NEXT:    store i32 [[TMP6]], ptr [[TMP7]], align 4
+// CHECK-NEXT:    [[TMP8:%.*]] = extractelement <4 x i32> [[TMP0]], i32 3
+// CHECK-NEXT:    [[TMP9:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 
0, i32 11
+// CHECK-NEXT:    store i32 [[TMP8]], ptr [[TMP9]], align 4
+// CHECK-NEXT:    ret void
+//
+void setMatrix2(out int4x4 M, int4 V) {
+    M[2].rgba = V;
+}
+//.
+// CHECK: [[META3]] = !{}
+// CHECK: [[META4]] = !{i64 4}
+//.
diff --git 
a/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptDynamicSwizzle.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptDynamicSwizzle.hlsl
new file mode 100644
index 0000000000000..9ebc466de41e8
--- /dev/null
+++ 
b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptDynamicSwizzle.hlsl
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.7-library -disable-llvm-passes 
-emit-llvm -finclude-default-header -o - %s | FileCheck %s
+// XFAIL: *
+
+void setMatrix(out float4x4 M, int index, float4 V) {
+    M[index].abgr = V;
+}
+
+float3 getMatrix(float4x4 M, int index) {
+    return M[index].rgb;
+}
diff --git 
a/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptGetter.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptGetter.hlsl
new file mode 100644
index 0000000000000..e454bd8f7d3df
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptGetter.hlsl
@@ -0,0 +1,205 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.7-library -disable-llvm-passes 
-emit-llvm -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> 
@_Z24getFloatVecMatrixDynamicu11matrix_typeILm4ELm4EfEi(
+// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[M:%.*]], i32 noundef 
[[INDEX:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca [16 x float], align 4
+// CHECK-NEXT:    [[INDEX_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store <16 x float> [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load <16 x float>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = add i32 0, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM:%.*]] = extractelement <16 x float> [[TMP1]], 
i32 [[TMP2]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS:%.*]] = insertelement <4 x float> undef, 
float [[MATRIX_ELEM]], i32 0
+// CHECK-NEXT:    [[TMP3:%.*]] = add i32 4, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM1:%.*]] = extractelement <16 x float> [[TMP1]], 
i32 [[TMP3]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS2:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS]], float [[MATRIX_ELEM1]], i32 1
+// CHECK-NEXT:    [[TMP4:%.*]] = add i32 8, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM3:%.*]] = extractelement <16 x float> [[TMP1]], 
i32 [[TMP4]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS4:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS2]], float [[MATRIX_ELEM3]], i32 2
+// CHECK-NEXT:    [[TMP5:%.*]] = add i32 12, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM5:%.*]] = extractelement <16 x float> [[TMP1]], 
i32 [[TMP5]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS6:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS4]], float [[MATRIX_ELEM5]], i32 3
+// CHECK-NEXT:    ret <4 x float> [[MATRIX_ROW_INS6]]
+//
+float4 getFloatVecMatrixDynamic(float4x4 M, int index) {
+    return M[index];
+}
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float 
@_Z27getFloatScalarMatrixDynamicu11matrix_typeILm2ELm1EfEi(
+// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[M:%.*]], i32 noundef 
[[INDEX:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca [2 x float], align 4
+// CHECK-NEXT:    [[INDEX_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store <2 x float> [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load <2 x float>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = add i32 0, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM:%.*]] = extractelement <2 x float> [[TMP1]], 
i32 [[TMP2]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS:%.*]] = insertelement <1 x float> undef, 
float [[MATRIX_ELEM]], i32 0
+// CHECK-NEXT:    [[CAST_VTRUNC:%.*]] = extractelement <1 x float> 
[[MATRIX_ROW_INS]], i32 0
+// CHECK-NEXT:    ret float [[CAST_VTRUNC]]
+//
+float getFloatScalarMatrixDynamic(float2x1 M, int index) {
+    return M[index];
+}
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float 
@_Z28getFloatScalarMatrixConstantu11matrix_typeILm2ELm1EfE(
+// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[M:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca [2 x float], align 4
+// CHECK-NEXT:    store <2 x float> [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load <2 x float>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM:%.*]] = extractelement <2 x float> [[TMP0]], 
i32 0
+// CHECK-NEXT:    [[MATRIX_ROW_INS:%.*]] = insertelement <1 x float> undef, 
float [[MATRIX_ELEM]], i32 0
+// CHECK-NEXT:    [[CAST_VTRUNC:%.*]] = extractelement <1 x float> 
[[MATRIX_ROW_INS]], i32 0
+// CHECK-NEXT:    ret float [[CAST_VTRUNC]]
+//
+float getFloatScalarMatrixConstant(float2x1 M) {
+    return M[0];
+}
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float 
@_Z29getFloatScalarMatrixConstant2u11matrix_typeILm2ELm1EfE(
+// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[M:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca [2 x float], align 4
+// CHECK-NEXT:    store <2 x float> [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load <2 x float>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM:%.*]] = extractelement <2 x float> [[TMP0]], 
i32 1
+// CHECK-NEXT:    [[MATRIX_ROW_INS:%.*]] = insertelement <1 x float> undef, 
float [[MATRIX_ELEM]], i32 0
+// CHECK-NEXT:    [[CAST_VTRUNC:%.*]] = extractelement <1 x float> 
[[MATRIX_ROW_INS]], i32 0
+// CHECK-NEXT:    ret float [[CAST_VTRUNC]]
+//
+float getFloatScalarMatrixConstant2(float2x1 M) {
+    return M[1];
+}
+
+// CHECK-LABEL: define hidden noundef <4 x i32> 
@_Z19getIntMatrixDynamicu11matrix_typeILm4ELm4EiEi(
+// CHECK-SAME: <16 x i32> noundef [[M:%.*]], i32 noundef [[INDEX:%.*]]) 
#[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT:    [[INDEX_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store <16 x i32> [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load <16 x i32>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = add i32 0, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM:%.*]] = extractelement <16 x i32> [[TMP1]], 
i32 [[TMP2]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS:%.*]] = insertelement <4 x i32> undef, i32 
[[MATRIX_ELEM]], i32 0
+// CHECK-NEXT:    [[TMP3:%.*]] = add i32 4, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM1:%.*]] = extractelement <16 x i32> [[TMP1]], 
i32 [[TMP3]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS2:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS]], i32 [[MATRIX_ELEM1]], i32 1
+// CHECK-NEXT:    [[TMP4:%.*]] = add i32 8, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM3:%.*]] = extractelement <16 x i32> [[TMP1]], 
i32 [[TMP4]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS4:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS2]], i32 [[MATRIX_ELEM3]], i32 2
+// CHECK-NEXT:    [[TMP5:%.*]] = add i32 12, [[TMP0]]
+// CHECK-NEXT:    [[MATRIX_ELEM5:%.*]] = extractelement <16 x i32> [[TMP1]], 
i32 [[TMP5]]
+// CHECK-NEXT:    [[MATRIX_ROW_INS6:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS4]], i32 [[MATRIX_ELEM5]], i32 3
+// CHECK-NEXT:    ret <4 x i32> [[MATRIX_ROW_INS6]]
+//
+int4 getIntMatrixDynamic(int4x4 M, int index) {
+    return M[index];
+}
+
+// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x float> 
@_Z22AddFloatMatrixConstantu11matrix_typeILm4ELm4EfE(
+// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[M:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca [16 x float], align 4
+// CHECK-NEXT:    store <16 x float> [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load <16 x float>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM:%.*]] = extractelement <16 x float> [[TMP0]], 
i32 0
+// CHECK-NEXT:    [[MATRIX_ROW_INS:%.*]] = insertelement <4 x float> undef, 
float [[MATRIX_ELEM]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM1:%.*]] = extractelement <16 x float> [[TMP0]], 
i32 4
+// CHECK-NEXT:    [[MATRIX_ROW_INS2:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS]], float [[MATRIX_ELEM1]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM3:%.*]] = extractelement <16 x float> [[TMP0]], 
i32 8
+// CHECK-NEXT:    [[MATRIX_ROW_INS4:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS2]], float [[MATRIX_ELEM3]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM5:%.*]] = extractelement <16 x float> [[TMP0]], 
i32 12
+// CHECK-NEXT:    [[MATRIX_ROW_INS6:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS4]], float [[MATRIX_ELEM5]], i32 3
+// CHECK-NEXT:    [[TMP1:%.*]] = load <16 x float>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM7:%.*]] = extractelement <16 x float> [[TMP1]], 
i32 1
+// CHECK-NEXT:    [[MATRIX_ROW_INS8:%.*]] = insertelement <4 x float> undef, 
float [[MATRIX_ELEM7]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM9:%.*]] = extractelement <16 x float> [[TMP1]], 
i32 5
+// CHECK-NEXT:    [[MATRIX_ROW_INS10:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS8]], float [[MATRIX_ELEM9]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM11:%.*]] = extractelement <16 x float> 
[[TMP1]], i32 9
+// CHECK-NEXT:    [[MATRIX_ROW_INS12:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS10]], float [[MATRIX_ELEM11]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM13:%.*]] = extractelement <16 x float> 
[[TMP1]], i32 13
+// CHECK-NEXT:    [[MATRIX_ROW_INS14:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS12]], float [[MATRIX_ELEM13]], i32 3
+// CHECK-NEXT:    [[ADD:%.*]] = fadd reassoc nnan ninf nsz arcp afn <4 x 
float> [[MATRIX_ROW_INS6]], [[MATRIX_ROW_INS14]]
+// CHECK-NEXT:    [[TMP2:%.*]] = load <16 x float>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM15:%.*]] = extractelement <16 x float> 
[[TMP2]], i32 2
+// CHECK-NEXT:    [[MATRIX_ROW_INS16:%.*]] = insertelement <4 x float> undef, 
float [[MATRIX_ELEM15]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM17:%.*]] = extractelement <16 x float> 
[[TMP2]], i32 6
+// CHECK-NEXT:    [[MATRIX_ROW_INS18:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS16]], float [[MATRIX_ELEM17]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM19:%.*]] = extractelement <16 x float> 
[[TMP2]], i32 10
+// CHECK-NEXT:    [[MATRIX_ROW_INS20:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS18]], float [[MATRIX_ELEM19]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM21:%.*]] = extractelement <16 x float> 
[[TMP2]], i32 14
+// CHECK-NEXT:    [[MATRIX_ROW_INS22:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS20]], float [[MATRIX_ELEM21]], i32 3
+// CHECK-NEXT:    [[ADD23:%.*]] = fadd reassoc nnan ninf nsz arcp afn <4 x 
float> [[ADD]], [[MATRIX_ROW_INS22]]
+// CHECK-NEXT:    [[TMP3:%.*]] = load <16 x float>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM24:%.*]] = extractelement <16 x float> 
[[TMP3]], i32 3
+// CHECK-NEXT:    [[MATRIX_ROW_INS25:%.*]] = insertelement <4 x float> undef, 
float [[MATRIX_ELEM24]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM26:%.*]] = extractelement <16 x float> 
[[TMP3]], i32 7
+// CHECK-NEXT:    [[MATRIX_ROW_INS27:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS25]], float [[MATRIX_ELEM26]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM28:%.*]] = extractelement <16 x float> 
[[TMP3]], i32 11
+// CHECK-NEXT:    [[MATRIX_ROW_INS29:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS27]], float [[MATRIX_ELEM28]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM30:%.*]] = extractelement <16 x float> 
[[TMP3]], i32 15
+// CHECK-NEXT:    [[MATRIX_ROW_INS31:%.*]] = insertelement <4 x float> 
[[MATRIX_ROW_INS29]], float [[MATRIX_ELEM30]], i32 3
+// CHECK-NEXT:    [[ADD32:%.*]] = fadd reassoc nnan ninf nsz arcp afn <4 x 
float> [[ADD23]], [[MATRIX_ROW_INS31]]
+// CHECK-NEXT:    ret <4 x float> [[ADD32]]
+//
+float4 AddFloatMatrixConstant(float4x4 M) {
+    return M[0] + M[1] + M[2] +M[3];
+}
+
+// CHECK-LABEL: define hidden noundef <4 x i32> 
@_Z20AddIntMatrixConstantu11matrix_typeILm4ELm4EiE(
+// CHECK-SAME: <16 x i32> noundef [[M:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT:    store <16 x i32> [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i32>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM:%.*]] = extractelement <16 x i32> [[TMP0]], 
i32 0
+// CHECK-NEXT:    [[MATRIX_ROW_INS:%.*]] = insertelement <4 x i32> undef, i32 
[[MATRIX_ELEM]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM1:%.*]] = extractelement <16 x i32> [[TMP0]], 
i32 4
+// CHECK-NEXT:    [[MATRIX_ROW_INS2:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS]], i32 [[MATRIX_ELEM1]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM3:%.*]] = extractelement <16 x i32> [[TMP0]], 
i32 8
+// CHECK-NEXT:    [[MATRIX_ROW_INS4:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS2]], i32 [[MATRIX_ELEM3]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM5:%.*]] = extractelement <16 x i32> [[TMP0]], 
i32 12
+// CHECK-NEXT:    [[MATRIX_ROW_INS6:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS4]], i32 [[MATRIX_ELEM5]], i32 3
+// CHECK-NEXT:    [[TMP1:%.*]] = load <16 x i32>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM7:%.*]] = extractelement <16 x i32> [[TMP1]], 
i32 1
+// CHECK-NEXT:    [[MATRIX_ROW_INS8:%.*]] = insertelement <4 x i32> undef, i32 
[[MATRIX_ELEM7]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM9:%.*]] = extractelement <16 x i32> [[TMP1]], 
i32 5
+// CHECK-NEXT:    [[MATRIX_ROW_INS10:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS8]], i32 [[MATRIX_ELEM9]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM11:%.*]] = extractelement <16 x i32> [[TMP1]], 
i32 9
+// CHECK-NEXT:    [[MATRIX_ROW_INS12:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS10]], i32 [[MATRIX_ELEM11]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM13:%.*]] = extractelement <16 x i32> [[TMP1]], 
i32 13
+// CHECK-NEXT:    [[MATRIX_ROW_INS14:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS12]], i32 [[MATRIX_ELEM13]], i32 3
+// CHECK-NEXT:    [[ADD:%.*]] = add <4 x i32> [[MATRIX_ROW_INS6]], 
[[MATRIX_ROW_INS14]]
+// CHECK-NEXT:    [[TMP2:%.*]] = load <16 x i32>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM15:%.*]] = extractelement <16 x i32> [[TMP2]], 
i32 2
+// CHECK-NEXT:    [[MATRIX_ROW_INS16:%.*]] = insertelement <4 x i32> undef, 
i32 [[MATRIX_ELEM15]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM17:%.*]] = extractelement <16 x i32> [[TMP2]], 
i32 6
+// CHECK-NEXT:    [[MATRIX_ROW_INS18:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS16]], i32 [[MATRIX_ELEM17]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM19:%.*]] = extractelement <16 x i32> [[TMP2]], 
i32 10
+// CHECK-NEXT:    [[MATRIX_ROW_INS20:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS18]], i32 [[MATRIX_ELEM19]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM21:%.*]] = extractelement <16 x i32> [[TMP2]], 
i32 14
+// CHECK-NEXT:    [[MATRIX_ROW_INS22:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS20]], i32 [[MATRIX_ELEM21]], i32 3
+// CHECK-NEXT:    [[ADD23:%.*]] = add <4 x i32> [[ADD]], [[MATRIX_ROW_INS22]]
+// CHECK-NEXT:    [[TMP3:%.*]] = load <16 x i32>, ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM24:%.*]] = extractelement <16 x i32> [[TMP3]], 
i32 3
+// CHECK-NEXT:    [[MATRIX_ROW_INS25:%.*]] = insertelement <4 x i32> undef, 
i32 [[MATRIX_ELEM24]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM26:%.*]] = extractelement <16 x i32> [[TMP3]], 
i32 7
+// CHECK-NEXT:    [[MATRIX_ROW_INS27:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS25]], i32 [[MATRIX_ELEM26]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM28:%.*]] = extractelement <16 x i32> [[TMP3]], 
i32 11
+// CHECK-NEXT:    [[MATRIX_ROW_INS29:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS27]], i32 [[MATRIX_ELEM28]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM30:%.*]] = extractelement <16 x i32> [[TMP3]], 
i32 15
+// CHECK-NEXT:    [[MATRIX_ROW_INS31:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS29]], i32 [[MATRIX_ELEM30]], i32 3
+// CHECK-NEXT:    [[ADD32:%.*]] = add <4 x i32> [[ADD23]], [[MATRIX_ROW_INS31]]
+// CHECK-NEXT:    ret <4 x i32> [[ADD32]]
+//
+int4 AddIntMatrixConstant(int4x4 M) {
+   return M[0] + M[1] + M[2] +M[3];
+}
diff --git 
a/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptSetter.hlsl 
b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptSetter.hlsl
new file mode 100644
index 0000000000000..68ce98fde2feb
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSingleSubscriptSetter.hlsl
@@ -0,0 +1,126 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.7-library -disable-llvm-passes 
-emit-llvm -finclude-default-header -o - %s | FileCheck %s
+
+// CHECK-LABEL: define hidden void 
@_Z9setMatrixRu11matrix_typeILm4ELm4EfEiDv4_f(
+// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) 
[[M:%.*]], i32 noundef [[INDEX:%.*]], <4 x float> noundef nofpclass(nan inf) 
[[V:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[INDEX_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[V_ADDR:%.*]] = alloca <4 x float>, align 16
+// CHECK-NEXT:    store ptr [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    store <4 x float> [[V]], ptr [[V_ADDR]], align 16
+// CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr [[V_ADDR]], align 16
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull 
[[META3:![0-9]+]], !align [[META4:![0-9]+]]
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_LOAD:%.*]] = load <16 x float>, ptr [[TMP1]], align 
4
+// CHECK-NEXT:    [[TMP3:%.*]] = add i32 0, [[TMP2]]
+// CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+// CHECK-NEXT:    [[TMP5:%.*]] = insertelement <16 x float> [[MATRIX_LOAD]], 
float [[TMP4]], i32 [[TMP3]]
+// CHECK-NEXT:    [[TMP6:%.*]] = add i32 4, [[TMP2]]
+// CHECK-NEXT:    [[TMP7:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+// CHECK-NEXT:    [[TMP8:%.*]] = insertelement <16 x float> [[TMP5]], float 
[[TMP7]], i32 [[TMP6]]
+// CHECK-NEXT:    [[TMP9:%.*]] = add i32 8, [[TMP2]]
+// CHECK-NEXT:    [[TMP10:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+// CHECK-NEXT:    [[TMP11:%.*]] = insertelement <16 x float> [[TMP8]], float 
[[TMP10]], i32 [[TMP9]]
+// CHECK-NEXT:    [[TMP12:%.*]] = add i32 12, [[TMP2]]
+// CHECK-NEXT:    [[TMP13:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+// CHECK-NEXT:    [[TMP14:%.*]] = insertelement <16 x float> [[TMP11]], float 
[[TMP13]], i32 [[TMP12]]
+// CHECK-NEXT:    store <16 x float> [[TMP14]], ptr [[TMP1]], align 4
+// CHECK-NEXT:    ret void
+//
+void setMatrix(out float4x4 M, int index, float4 V) {
+    M[index] = V;
+}
+
+// CHECK-LABEL: define hidden void 
@_Z15setMatrixScalarRu11matrix_typeILm2ELm1EfEif(
+// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(8) 
[[M:%.*]], i32 noundef [[INDEX:%.*]], float noundef nofpclass(nan inf) 
[[S:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[INDEX_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[S_ADDR:%.*]] = alloca float, align 4
+// CHECK-NEXT:    store ptr [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[INDEX]], ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    store float [[S]], ptr [[S_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[S_ADDR]], align 4
+// CHECK-NEXT:    [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x float> 
poison, float [[TMP0]], i64 0
+// CHECK-NEXT:    [[SPLAT_SPLAT:%.*]] = shufflevector <1 x float> 
[[SPLAT_SPLATINSERT]], <1 x float> poison, <1 x i32> zeroinitializer
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull 
[[META3]], !align [[META4]]
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[INDEX_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_LOAD:%.*]] = load <2 x float>, ptr [[TMP1]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = add i32 0, [[TMP2]]
+// CHECK-NEXT:    [[TMP4:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], 
i32 0
+// CHECK-NEXT:    [[TMP5:%.*]] = insertelement <2 x float> [[MATRIX_LOAD]], 
float [[TMP4]], i32 [[TMP3]]
+// CHECK-NEXT:    store <2 x float> [[TMP5]], ptr [[TMP1]], align 4
+// CHECK-NEXT:    ret void
+//
+void setMatrixScalar(out float2x1 M, int index, float S) {
+    M[index] = S;
+}
+
+// CHECK-LABEL: define hidden void 
@_Z19setMatrixConstIndexRu11matrix_typeILm4ELm4EiES_(
+// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) 
[[M:%.*]], <16 x i32> noundef [[N:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[M_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[N_ADDR:%.*]] = alloca [16 x i32], align 4
+// CHECK-NEXT:    store ptr [[M]], ptr [[M_ADDR]], align 4
+// CHECK-NEXT:    store <16 x i32> [[N]], ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i32>, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM:%.*]] = extractelement <16 x i32> [[TMP0]], 
i32 3
+// CHECK-NEXT:    [[MATRIX_ROW_INS:%.*]] = insertelement <4 x i32> undef, i32 
[[MATRIX_ELEM]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM1:%.*]] = extractelement <16 x i32> [[TMP0]], 
i32 7
+// CHECK-NEXT:    [[MATRIX_ROW_INS2:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS]], i32 [[MATRIX_ELEM1]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM3:%.*]] = extractelement <16 x i32> [[TMP0]], 
i32 11
+// CHECK-NEXT:    [[MATRIX_ROW_INS4:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS2]], i32 [[MATRIX_ELEM3]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM5:%.*]] = extractelement <16 x i32> [[TMP0]], 
i32 15
+// CHECK-NEXT:    [[MATRIX_ROW_INS6:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS4]], i32 [[MATRIX_ELEM5]], i32 3
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull 
[[META3]], !align [[META4]]
+// CHECK-NEXT:    store <4 x i32> [[MATRIX_ROW_INS6]], ptr [[TMP1]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load <16 x i32>, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM7:%.*]] = extractelement <16 x i32> [[TMP2]], 
i32 2
+// CHECK-NEXT:    [[MATRIX_ROW_INS8:%.*]] = insertelement <4 x i32> undef, i32 
[[MATRIX_ELEM7]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM9:%.*]] = extractelement <16 x i32> [[TMP2]], 
i32 6
+// CHECK-NEXT:    [[MATRIX_ROW_INS10:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS8]], i32 [[MATRIX_ELEM9]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM11:%.*]] = extractelement <16 x i32> [[TMP2]], 
i32 10
+// CHECK-NEXT:    [[MATRIX_ROW_INS12:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS10]], i32 [[MATRIX_ELEM11]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM13:%.*]] = extractelement <16 x i32> [[TMP2]], 
i32 14
+// CHECK-NEXT:    [[MATRIX_ROW_INS14:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS12]], i32 [[MATRIX_ELEM13]], i32 3
+// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull 
[[META3]], !align [[META4]]
+// CHECK-NEXT:    [[TMP4:%.*]] = getelementptr <16 x i32>, ptr [[TMP3]], i32 
0, i32 4
+// CHECK-NEXT:    store <4 x i32> [[MATRIX_ROW_INS14]], ptr [[TMP4]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load <16 x i32>, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM15:%.*]] = extractelement <16 x i32> [[TMP5]], 
i32 1
+// CHECK-NEXT:    [[MATRIX_ROW_INS16:%.*]] = insertelement <4 x i32> undef, 
i32 [[MATRIX_ELEM15]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM17:%.*]] = extractelement <16 x i32> [[TMP5]], 
i32 5
+// CHECK-NEXT:    [[MATRIX_ROW_INS18:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS16]], i32 [[MATRIX_ELEM17]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM19:%.*]] = extractelement <16 x i32> [[TMP5]], 
i32 9
+// CHECK-NEXT:    [[MATRIX_ROW_INS20:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS18]], i32 [[MATRIX_ELEM19]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM21:%.*]] = extractelement <16 x i32> [[TMP5]], 
i32 13
+// CHECK-NEXT:    [[MATRIX_ROW_INS22:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS20]], i32 [[MATRIX_ELEM21]], i32 3
+// CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull 
[[META3]], !align [[META4]]
+// CHECK-NEXT:    [[TMP7:%.*]] = getelementptr <16 x i32>, ptr [[TMP6]], i32 
0, i32 8
+// CHECK-NEXT:    store <4 x i32> [[MATRIX_ROW_INS22]], ptr [[TMP7]], align 4
+// CHECK-NEXT:    [[TMP8:%.*]] = load <16 x i32>, ptr [[N_ADDR]], align 4
+// CHECK-NEXT:    [[MATRIX_ELEM23:%.*]] = extractelement <16 x i32> [[TMP8]], 
i32 0
+// CHECK-NEXT:    [[MATRIX_ROW_INS24:%.*]] = insertelement <4 x i32> undef, 
i32 [[MATRIX_ELEM23]], i32 0
+// CHECK-NEXT:    [[MATRIX_ELEM25:%.*]] = extractelement <16 x i32> [[TMP8]], 
i32 4
+// CHECK-NEXT:    [[MATRIX_ROW_INS26:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS24]], i32 [[MATRIX_ELEM25]], i32 1
+// CHECK-NEXT:    [[MATRIX_ELEM27:%.*]] = extractelement <16 x i32> [[TMP8]], 
i32 8
+// CHECK-NEXT:    [[MATRIX_ROW_INS28:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS26]], i32 [[MATRIX_ELEM27]], i32 2
+// CHECK-NEXT:    [[MATRIX_ELEM29:%.*]] = extractelement <16 x i32> [[TMP8]], 
i32 12
+// CHECK-NEXT:    [[MATRIX_ROW_INS30:%.*]] = insertelement <4 x i32> 
[[MATRIX_ROW_INS28]], i32 [[MATRIX_ELEM29]], i32 3
+// CHECK-NEXT:    [[TMP9:%.*]] = load ptr, ptr [[M_ADDR]], align 4, !nonnull 
[[META3]], !align [[META4]]
+// CHECK-NEXT:    [[TMP10:%.*]] = getelementptr <16 x i32>, ptr [[TMP9]], i32 
0, i32 12
+// CHECK-NEXT:    store <4 x i32> [[MATRIX_ROW_INS30]], ptr [[TMP10]], align 4
+// CHECK-NEXT:    ret void
+//
+void setMatrixConstIndex(out int4x4 M, int4x4 N ) {
+    M[0] = N[3];
+    M[1] = N[2];
+    M[2] = N[1];
+    M[3] = N[0];
+}
+//.
+// CHECK: [[META3]] = !{}
+// CHECK: [[META4]] = !{i64 4}
+//.
diff --git a/clang/test/SemaHLSL/matrix_single_subscript_errors.hlsl 
b/clang/test/SemaHLSL/matrix_single_subscript_errors.hlsl
new file mode 100644
index 0000000000000..cb611b6555644
--- /dev/null
+++ b/clang/test/SemaHLSL/matrix_single_subscript_errors.hlsl
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.4-library 
-finclude-default-header -verify %s
+
+float2x3 gM;
+
+void bad_index_type(float f) {
+  gM[f]; // expected-error {{matrix row index is not an integer}}
+}
+
+// 2 rows: valid row indices: 0, 1
+void bad_constant_row_index() {
+  gM[2]; // expected-error {{matrix row index is outside the allowed range}}
+}
diff --git a/clang/tools/libclang/CXCursor.cpp 
b/clang/tools/libclang/CXCursor.cpp
index 0a43d73063c1f..1de1c18a2249f 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -425,6 +425,11 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl 
*Parent,
     K = CXCursor_ArraySubscriptExpr;
     break;
 
+  case Stmt::MatrixSingleSubscriptExprClass:
+    // TODO: add support for MatrixSingleSubscriptExpr.
+    K = CXCursor_UnexposedExpr;
+    break;
+
   case Stmt::MatrixSubscriptExprClass:
     // TODO: add support for MatrixSubscriptExpr.
     K = CXCursor_UnexposedExpr;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to