https://github.com/farzonl updated https://github.com/llvm/llvm-project/pull/170779
>From 4c112b909939aa3b78c51253af98bee38d701ad5 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 | 94 ++++++++ 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, 992 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..9bca92e239669 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -40,6 +40,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" @@ -1796,6 +1797,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 +2443,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::PoisonValue::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 +2694,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 +4936,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 +5237,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..a978f34baef16 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::PoisonValue::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
