From 929f118cb4e48578bca6443418a3f1d1c1839eb8 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi Date: Sun, 7 Dec 2025 19:07:17 -0500 Subject: [PATCH 1/2] [HLSL][Matrix] Add Matrix Swizzle AST Node fixes #159438 --- clang/include/clang/AST/ComputeDependence.h | 2 + clang/include/clang/AST/Expr.h | 100 +++-- clang/include/clang/AST/RecursiveASTVisitor.h | 1 + clang/include/clang/AST/TextNodeDumper.h | 1 + .../clang/Basic/DiagnosticSemaKinds.td | 12 + clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Sema/SemaHLSL.h | 4 + .../include/clang/Serialization/ASTBitCodes.h | 3 + clang/lib/AST/ByteCode/Compiler.cpp | 6 + clang/lib/AST/ByteCode/Compiler.h | 1 + clang/lib/AST/ComputeDependence.cpp | 4 + clang/lib/AST/Expr.cpp | 126 ++++++- clang/lib/AST/ExprClassification.cpp | 15 + clang/lib/AST/ExprConstant.cpp | 8 + clang/lib/AST/ItaniumMangle.cpp | 1 + clang/lib/AST/StmtPrinter.cpp | 6 + clang/lib/AST/StmtProfile.cpp | 5 + clang/lib/AST/TextNodeDumper.cpp | 4 + clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 2 + clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 2 + clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 + clang/lib/CodeGen/CGExpr.cpp | 47 +++ clang/lib/CodeGen/CGExprScalar.cpp | 1 + clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Sema/SemaExceptionSpec.cpp | 1 + clang/lib/Sema/SemaExpr.cpp | 3 + clang/lib/Sema/SemaExprMember.cpp | 17 + clang/lib/Sema/SemaHLSL.cpp | 199 ++++++++++ clang/lib/Sema/TreeTransform.h | 31 +- clang/lib/Serialization/ASTReaderStmt.cpp | 11 + clang/lib/Serialization/ASTWriterStmt.cpp | 8 + clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + .../AST/HLSL/matrix-member-access-scalar.hlsl | 38 ++ ...x-member-access-swizzle-ast-dump-json.hlsl | 25 ++ ...atrix-member-access-swizzle-ast-print.hlsl | 21 ++ .../HLSL/matrix-member-access-swizzle.hlsl | 49 +++ .../pch_with_matrix_element_accessor.hlsl | 26 ++ ...member-one-based-accessor-scalar-load.hlsl | 230 ++++++++++++ ...ember-one-based-accessor-scalar-store.hlsl | 345 ++++++++++++++++++ .../matrix-member-one-based-swizzle-load.hlsl | 108 ++++++ ...matrix-member-one-based-swizzle-store.hlsl | 230 ++++++++++++ ...ember-zero-based-accessor-scalar-load.hlsl | 230 ++++++++++++ ...mber-zero-based-accessor-scalar-store.hlsl | 345 ++++++++++++++++++ ...matrix-member-zero-based-swizzle-load.hlsl | 108 ++++++ ...atrix-member-zero-based-swizzle-store.hlsl | 230 ++++++++++++ .../SemaHLSL/matrix-member-access-errors.hlsl | 28 ++ clang/tools/libclang/CXCursor.cpp | 1 + 47 files changed, 2600 insertions(+), 40 deletions(-) create mode 100644 clang/test/AST/HLSL/matrix-member-access-scalar.hlsl create mode 100644 clang/test/AST/HLSL/matrix-member-access-swizzle-ast-dump-json.hlsl create mode 100644 clang/test/AST/HLSL/matrix-member-access-swizzle-ast-print.hlsl create mode 100644 clang/test/AST/HLSL/matrix-member-access-swizzle.hlsl create mode 100644 clang/test/AST/HLSL/pch_with_matrix_element_accessor.hlsl create mode 100644 clang/test/CodeGenHLSL/matrix-member-one-based-accessor-scalar-load.hlsl create mode 100644 clang/test/CodeGenHLSL/matrix-member-one-based-accessor-scalar-store.hlsl create mode 100644 clang/test/CodeGenHLSL/matrix-member-one-based-swizzle-load.hlsl create mode 100644 clang/test/CodeGenHLSL/matrix-member-one-based-swizzle-store.hlsl create mode 100644 clang/test/CodeGenHLSL/matrix-member-zero-based-accessor-scalar-load.hlsl create mode 100644 clang/test/CodeGenHLSL/matrix-member-zero-based-accessor-scalar-store.hlsl create mode 100644 clang/test/CodeGenHLSL/matrix-member-zero-based-swizzle-load.hlsl create mode 100644 clang/test/CodeGenHLSL/matrix-member-zero-based-swizzle-store.hlsl create mode 100644 clang/test/SemaHLSL/matrix-member-access-errors.hlsl diff --git a/clang/include/clang/AST/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h index c298f2620f211..16fdbfcac0864 100644 --- a/clang/include/clang/AST/ComputeDependence.h +++ b/clang/include/clang/AST/ComputeDependence.h @@ -44,6 +44,7 @@ class ArrayInitLoopExpr; class ImplicitValueInitExpr; class InitListExpr; class ExtVectorElementExpr; +class MatrixElementExpr; class BlockExpr; class AsTypeExpr; class DeclRefExpr; @@ -133,6 +134,7 @@ ExprDependence computeDependence(ArrayInitLoopExpr *E); ExprDependence computeDependence(ImplicitValueInitExpr *E); ExprDependence computeDependence(InitListExpr *E); ExprDependence computeDependence(ExtVectorElementExpr *E); +ExprDependence computeDependence(MatrixElementExpr *E); ExprDependence computeDependence(BlockExpr *E, bool ContainsUnexpandedParameterPack); ExprDependence computeDependence(AsTypeExpr *E); diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 573cc72db35c6..59f2c7a46dac2 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -291,6 +291,7 @@ class Expr : public ValueStmt { LV_NotObjectType, LV_IncompleteVoidType, LV_DuplicateVectorComponents, + LV_DuplicateMatrixComponents, LV_InvalidExpression, LV_InvalidMessageExpression, LV_MemberFunction, @@ -306,6 +307,7 @@ class Expr : public ValueStmt { MLV_NotObjectType, MLV_IncompleteVoidType, MLV_DuplicateVectorComponents, + MLV_DuplicateMatrixComponents, MLV_InvalidExpression, MLV_LValueCast, // Specialized form of MLV_InvalidExpression. MLV_IncompleteType, @@ -344,6 +346,7 @@ class Expr : public ValueStmt { CL_Void, // Void cannot be an lvalue in C. CL_AddressableVoid, // Void expression whose address can be taken in C. CL_DuplicateVectorComponents, // A vector shuffle with dupes. + CL_DuplicateMatrixComponents, // A matrix shuffle with dupes. CL_MemberFunction, // An expression referring to a member function CL_SubObjCPropertySetting, CL_ClassTemporary, // A temporary of class type, or subobject thereof. @@ -6488,30 +6491,24 @@ class GenericSelectionExpr final // Clang Extensions //===----------------------------------------------------------------------===// -/// ExtVectorElementExpr - This represents access to specific elements of a -/// vector, and may occur on the left hand side or right hand side. For example -/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector. -/// -/// Note that the base may have either vector or pointer to vector type, just -/// like a struct field reference. -/// -class ExtVectorElementExpr : public Expr { +template class ElementAccessExprBase : public Expr { +protected: Stmt *Base; IdentifierInfo *Accessor; SourceLocation AccessorLoc; -public: - ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base, - IdentifierInfo &accessor, SourceLocation loc) - : Expr(ExtVectorElementExprClass, ty, VK, - (VK == VK_PRValue ? OK_Ordinary : OK_VectorComponent)), - Base(base), Accessor(&accessor), AccessorLoc(loc) { - setDependence(computeDependence(this)); + + ElementAccessExprBase(StmtClass SC, QualType Ty, ExprValueKind VK, Expr *Base, + IdentifierInfo &Accessor, SourceLocation Loc, + ExprObjectKind OK) + : Expr(SC, Ty, VK, OK), Base(Base), Accessor(&Accessor), + AccessorLoc(Loc) { + setDependence(computeDependence(static_cast(this))); } - /// Build an empty vector element expression. - explicit ExtVectorElementExpr(EmptyShell Empty) - : Expr(ExtVectorElementExprClass, Empty) { } + explicit ElementAccessExprBase(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty) {} +public: const Expr *getBase() const { return cast(Base); } Expr *getBase() { return cast(Base); } void setBase(Expr *E) { Base = E; } @@ -6522,22 +6519,45 @@ class ExtVectorElementExpr : public Expr { SourceLocation getAccessorLoc() const { return AccessorLoc; } void setAccessorLoc(SourceLocation L) { AccessorLoc = L; } - /// getNumElements - Get the number of components being selected. - unsigned getNumElements() const; - - /// containsDuplicateElements - Return true if any element access is - /// repeated. - bool containsDuplicateElements() const; - - /// getEncodedElementAccess - Encode the elements accessed into an llvm - /// aggregate Constant of ConstantInt(s). - void getEncodedElementAccess(SmallVectorImpl &Elts) const; - SourceLocation getBeginLoc() const LLVM_READONLY { return getBase()->getBeginLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { return AccessorLoc; } + /*static bool classof(const Stmt *T) { + return T->getStmtClass() == ExtVectorElementExprClass || + T->getStmtClass() == MatrixElementExprClass; + }*/ + + child_range children() { return child_range(&Base, &Base + 1); } + const_child_range children() const { + return const_child_range(&Base, &Base + 1); + } +}; + +/// ExtVectorElementExpr - This represents access to specific elements of a +/// vector, and may occur on the left hand side or right hand side. For example +/// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector. +/// +/// Note that the base may have either vector or pointer to vector type, just +/// like a struct field reference. +/// +class ExtVectorElementExpr + : public ElementAccessExprBase { +public: + ExtVectorElementExpr(QualType Ty, ExprValueKind VK, Expr *Base, + IdentifierInfo &Accessor, SourceLocation Loc) + : ElementAccessExprBase( + ExtVectorElementExprClass, Ty, VK, Base, Accessor, Loc, + (VK == VK_PRValue ? OK_Ordinary : OK_VectorComponent)) {} + + explicit ExtVectorElementExpr(EmptyShell Empty) + : ElementAccessExprBase(ExtVectorElementExprClass, Empty) {} + + unsigned getNumElements() const; + bool containsDuplicateElements() const; + void getEncodedElementAccess(SmallVectorImpl &Elts) const; + /// isArrow - Return true if the base expression is a pointer to vector, /// return false if the base expression is a vector. bool isArrow() const; @@ -6545,11 +6565,25 @@ class ExtVectorElementExpr : public Expr { static bool classof(const Stmt *T) { return T->getStmtClass() == ExtVectorElementExprClass; } +}; - // Iterators - child_range children() { return child_range(&Base, &Base+1); } - const_child_range children() const { - return const_child_range(&Base, &Base + 1); +class MatrixElementExpr : public ElementAccessExprBase { +public: + MatrixElementExpr(QualType Ty, ExprValueKind VK, Expr *Base, + IdentifierInfo &Accessor, SourceLocation Loc) + : ElementAccessExprBase( + MatrixElementExprClass, Ty, VK, Base, Accessor, Loc, + OK_Ordinary /*TODO: Should we add a new OK_MatrixComponent?*/) {} + + explicit MatrixElementExpr(EmptyShell Empty) + : ElementAccessExprBase(MatrixElementExprClass, Empty) {} + + unsigned getNumElements() const; + bool containsDuplicateElements() const; + void getEncodedElementAccess(SmallVectorImpl &Elts) const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() == MatrixElementExprClass; } }; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 8f427427d71ed..0cc10403657ca 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2940,6 +2940,7 @@ DEF_TRAVERSE_STMT(UserDefinedLiteral, {}) DEF_TRAVERSE_STMT(DesignatedInitExpr, {}) DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {}) DEF_TRAVERSE_STMT(ExtVectorElementExpr, {}) +DEF_TRAVERSE_STMT(MatrixElementExpr, {}) DEF_TRAVERSE_STMT(GNUNullExpr, {}) DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {}) DEF_TRAVERSE_STMT(NoInitExpr, {}) diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 88ecd526e3d7e..ab828be124b0b 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -286,6 +286,7 @@ class TextNodeDumper void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); void VisitMemberExpr(const MemberExpr *Node); void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node); + void VisitMatrixElementExpr(const MatrixElementExpr *Node); void VisitBinaryOperator(const BinaryOperator *Node); void VisitCompoundAssignOperator(const CompoundAssignOperator *Node); void VisitAddrLabelExpr(const AddrLabelExpr *Node); diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index fec278c21a89e..bba27597be6bd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9336,6 +9336,8 @@ def err_typecheck_lvalue_casts_not_supported : Error< def err_typecheck_duplicate_vector_components_not_mlvalue : Error< "vector is not assignable (contains duplicate components)">; +def err_typecheck_duplicate_matrix_components_not_mlvalue : Error< + "matrix is not assignable (contains duplicate components)">; def err_block_decl_ref_not_modifiable_lvalue : Error< "variable is not assignable (missing __block type specifier)">; def err_lambda_decl_ref_not_modifiable_lvalue : Error< @@ -13061,6 +13063,7 @@ def err_builtin_matrix_stride_too_small: Error< "stride must be greater or equal to the number of rows">; def err_builtin_matrix_invalid_dimension: Error< "%0 dimension is outside the allowed range [1, %1]">; +def err_builtin_matrix_invalid_member: Error<"invalid matrix member '%0' expected %1">; def warn_mismatched_import : Warning< "import %select{module|name}0 (%1) does not match the import %select{module|name}0 (%2) of the " @@ -13318,6 +13321,15 @@ def err_hlsl_builtin_scalar_vector_mismatch "%select{all|second and third}0 arguments to %1 must be of scalar or " "vector type with matching scalar element type%diff{: $ vs $|}2,3">; +def err_hlsl_matrix_element_not_in_bounds : Error< + "matrix %select{row|column}0 element accessor is out of bounds of %select{zero|one}1 based indexing">; + +def err_hlsl_matrix_index_out_of_bounds : Error< + "matrix %select{row|column}0 index %1 is out of bounds of %select{rows|columns}0 size %2">; + +def err_hlsl_matrix_swizzle_invalid_length : Error< + "matrix swizzle length must be between 1 and 4 but is %0">; + def warn_hlsl_impcast_vector_truncation : Warning< "implicit conversion truncates vector: %0 to %1">, InGroup; diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index bf3686bb372d5..950ebba66b720 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -91,6 +91,7 @@ def CStyleCastExpr : StmtNode; def OMPArrayShapingExpr : StmtNode; def CompoundLiteralExpr : StmtNode; def ExtVectorElementExpr : StmtNode; +def MatrixElementExpr : StmtNode; def InitListExpr : StmtNode; def DesignatedInitExpr : StmtNode; def DesignatedInitUpdateExpr : StmtNode; diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index a2faa91d1e54d..953b3529c40b6 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -214,6 +214,10 @@ class SemaHLSL : public SemaBase { bool transformInitList(const InitializedEntity &Entity, InitListExpr *Init); bool handleInitialization(VarDecl *VDecl, Expr *&Init); void deduceAddressSpace(VarDecl *Decl); + QualType CheckMatrixComponent(Sema &S, QualType baseType, ExprValueKind &VK, + SourceLocation OpLoc, + const IdentifierInfo *CompName, + SourceLocation CompLoc); private: // HLSL resource type attributes need to be processed all at once. diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index d7d429eacd67a..2fc71b7f916ac 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1693,6 +1693,9 @@ enum StmtCode { /// An ExtVectorElementExpr record. EXPR_EXT_VECTOR_ELEMENT, + /// A MatrixElementExpr record. + EXPR_MATRIX_ELEMENT, + /// An InitListExpr record. EXPR_INIT_LIST, diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index ed5493c315dd7..5f988a47040d5 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -4092,6 +4092,12 @@ bool Compiler::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) { return true; } +template +bool Compiler::VisitMatrixElementExpr(const MatrixElementExpr *Node) { + // TODO + return false; +} + template bool Compiler::VisitExtVectorElementExpr( const ExtVectorElementExpr *E) { diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 1bd15c3d79563..8f9a2b16f8596 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -223,6 +223,7 @@ class Compiler : public ConstStmtVisitor, bool>, bool VisitConvertVectorExpr(const ConvertVectorExpr *E); bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E); bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E); + bool VisitMatrixElementExpr(const MatrixElementExpr *E); bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E); bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); bool VisitStmtExpr(const StmtExpr *E); diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 638080ea781a9..610aa16e9ae13 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -252,6 +252,10 @@ ExprDependence clang::computeDependence(ExtVectorElementExpr *E) { return E->getBase()->getDependence(); } +ExprDependence clang::computeDependence(MatrixElementExpr *E) { + return E->getBase()->getDependence(); +} + ExprDependence clang::computeDependence(BlockExpr *E, bool ContainsUnexpandedParameterPack) { auto D = toExprDependenceForImpliedType(E->getType()->getDependence()); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index ca7f3e16a9276..2fd071fa3fb45 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -25,6 +25,7 @@ #include "clang/AST/IgnoreExpr.h" #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" +#include "clang/AST/TypeBase.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" @@ -3798,6 +3799,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case BinaryConditionalOperatorClass: case CompoundLiteralExprClass: case ExtVectorElementExprClass: + case MatrixElementExprClass: case DesignatedInitExprClass: case DesignatedInitUpdateExprClass: case ArrayInitLoopExprClass: @@ -4418,7 +4420,14 @@ unsigned ExtVectorElementExpr::getNumElements() const { return 1; } -/// containsDuplicateElements - Return true if any element access is repeated. +unsigned MatrixElementExpr::getNumElements() const { + if (const ConstantMatrixType *MT = getType()->getAs()) + return MT->getNumElementsFlattened(); + return 1; +} + +/// containsDuplicateElements - Return true if any Vector element access is +/// repeated. bool ExtVectorElementExpr::containsDuplicateElements() const { // FIXME: Refactor this code to an accessor on the AST node which returns the // "type" of component access, and share with code below and in Sema. @@ -4439,6 +4448,68 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { return false; } +/// containsDuplicateElements - Return true if any Matrix element access is +/// repeated. +bool MatrixElementExpr::containsDuplicateElements() const { + StringRef Comp = Accessor->getName(); + assert(!Comp.empty() && Comp[0] == '_' && "invalid matrix accessor"); + + // Get the matrix type so we know bounds. + const ConstantMatrixType *MT = + getBase()->getType()->getAs(); + assert(MT && "MatrixElementExpr base must be a matrix type"); + + unsigned Rows = MT->getNumRows(); + unsigned Cols = MT->getNumColumns(); + unsigned Max = Rows * Cols; + + // Zero-indexed: _mRC (4 chars per component) + // One-indexed: _RC (3 chars per component) + bool IsZeroIndexed = false; + unsigned ChunkLen = 0; + + if (Comp.size() >= 2 && Comp[0] == '_' && Comp[1] == 'm') { + IsZeroIndexed = true; + ChunkLen = 4; + } else { + IsZeroIndexed = false; + ChunkLen = 3; + } + + assert(ChunkLen && "unrecognized matrix swizzle format"); + assert(Comp.size() % ChunkLen == 0 && + "matrix swizzle accessor has invalid length"); + + // Track visited elements using real matrix size. + SmallVector Seen(Max, false); + + for (unsigned I = 0, e = Comp.size(); I < e; I += ChunkLen) { + unsigned Row = 0, Col = 0; + + if (IsZeroIndexed) { + // Pattern: _mRC + assert(Comp[I] == '_' && Comp[I + 1] == 'm'); + Row = Comp[I + 2] - '0'; // 0..(Rows-1) + Col = Comp[I + 3] - '0'; + } else { + // Pattern: _RC + assert(Comp[I] == '_'); + Row = (Comp[I + 1] - '1'); // 1..Rows (ie same as 0..Rows-1) + Col = (Comp[I + 2] - '1'); + } + + // Bounds check (Sema should enforce correctness, but we assert anyway) + assert(Row < Rows && Col < Cols && "matrix swizzle index out of bounds"); + + unsigned Index = Row * Cols + Col; + if (Seen[Index]) + return true; + + Seen[Index] = true; + } + return false; +} + /// getEncodedElementAccess - We encode the fields as a llvm ConstantArray. void ExtVectorElementExpr::getEncodedElementAccess( SmallVectorImpl &Elts) const { @@ -4472,6 +4543,59 @@ void ExtVectorElementExpr::getEncodedElementAccess( } } +void MatrixElementExpr::getEncodedElementAccess( + SmallVectorImpl &Elts) const { + StringRef Comp = Accessor->getName(); + assert(!Comp.empty() && Comp[0] == '_' && "invalid matrix accessor"); + + const ConstantMatrixType *MT = + getBase()->getType()->getAs(); + assert(MT && "MatrixElementExpr base must be a matrix type"); + + unsigned Rows = MT->getNumRows(); + unsigned Cols = MT->getNumColumns(); + + // Zero-indexed: _mRC (4 chars per component: '_', 'm', row, col) + // One-indexed: _RC (3 chars per component: '_', row, col) + bool IsZeroIndexed = false; + unsigned ChunkLen = 0; + + if (Comp.size() >= 2 && Comp[0] == '_' && Comp[1] == 'm') { + IsZeroIndexed = true; + ChunkLen = 4; + } else { + IsZeroIndexed = false; + ChunkLen = 3; + } + + assert(ChunkLen != 0 && "unrecognized matrix swizzle format"); + assert(Comp.size() % ChunkLen == 0 && + "matrix swizzle accessor has invalid length"); + + for (unsigned i = 0, e = Comp.size(); i < e; i += ChunkLen) { + unsigned Row = 0, Col = 0; + + if (IsZeroIndexed) { + // Pattern: _mRC + assert(Comp[i] == '_' && Comp[i + 1] == 'm' && + "invalid zero-indexed matrix swizzle component"); + Row = static_cast(Comp[i + 2] - '0'); // 0..Rows-1 + Col = static_cast(Comp[i + 3] - '0'); // 0..Cols-1 + } else { + // Pattern: _RC + assert(Comp[i] == '_' && "invalid one-indexed matrix swizzle component"); + Row = static_cast(Comp[i + 1] - '1'); // 1..Rows -> 0..Rows-1 + Col = static_cast(Comp[i + 2] - '1'); // 1..Cols -> 0..Cols-1 + } + + // Sema should have validated these, but assert here for sanity. + assert(Row < Rows && Col < Cols && "matrix swizzle index out of range"); + + unsigned Index = Row * Cols + Col; + Elts.push_back(Index); + } +} + ShuffleVectorExpr::ShuffleVectorExpr(const ASTContext &C, ArrayRef args, QualType Type, SourceLocation BLoc, SourceLocation RP) diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index aeacd0dc765ef..7bb5a2202c3bf 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -63,6 +63,7 @@ Cl Expr::ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const { case Cl::CL_Void: case Cl::CL_AddressableVoid: case Cl::CL_DuplicateVectorComponents: + case Cl::CL_DuplicateMatrixComponents: case Cl::CL_MemberFunction: case Cl::CL_SubObjCPropertySetting: case Cl::CL_ClassTemporary: @@ -369,6 +370,16 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return Cl::CL_LValue; return ClassifyInternal(Ctx, cast(E)->getBase()); + // Matrix element access is an lvalue unless there are duplicates + // in the shuffle expression. + case Expr::MatrixElementExprClass: + if (cast(E)->containsDuplicateElements()) + return Cl::CL_DuplicateMatrixComponents; + // NOTE: MatrixElementExpr is currently only used by HLSL which does not + // have pointers so there is no isArrow() necessary or way to test + // Cl::CL_LValue + return ClassifyInternal(Ctx, cast(E)->getBase()); + // Simply look at the actual default argument. case Expr::CXXDefaultArgExprClass: return ClassifyInternal(Ctx, cast(E)->getExpr()); @@ -735,6 +746,8 @@ Expr::LValueClassification Expr::ClassifyLValue(ASTContext &Ctx) const { case Cl::CL_Void: return LV_InvalidExpression; case Cl::CL_AddressableVoid: return LV_IncompleteVoidType; case Cl::CL_DuplicateVectorComponents: return LV_DuplicateVectorComponents; + case Cl::CL_DuplicateMatrixComponents: + return LV_DuplicateMatrixComponents; case Cl::CL_MemberFunction: return LV_MemberFunction; case Cl::CL_SubObjCPropertySetting: return LV_SubObjCPropertySetting; case Cl::CL_ClassTemporary: return LV_ClassTemporary; @@ -756,6 +769,8 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const { case Cl::CL_Void: return MLV_InvalidExpression; case Cl::CL_AddressableVoid: return MLV_IncompleteVoidType; case Cl::CL_DuplicateVectorComponents: return MLV_DuplicateVectorComponents; + case Cl::CL_DuplicateMatrixComponents: + return MLV_DuplicateMatrixComponents; case Cl::CL_MemberFunction: return MLV_MemberFunction; case Cl::CL_SubObjCPropertySetting: return MLV_SubObjCPropertySetting; case Cl::CL_ClassTemporary: return MLV_ClassTemporary; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index d81496ffd74e0..fafb1d83563d6 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8993,6 +8993,8 @@ class ExprEvaluatorBase DerivedSuccess(Result, E); } + bool VisitMatrixElementExpr(const MatrixElementExpr *E) { return false; } + bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E) { APValue Val; if (!Evaluate(Val, Info, E->getBase())) @@ -9335,6 +9337,7 @@ class LValueExprEvaluator bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E); + bool VisitMatrixElementExpr(const MatrixElementExpr *E); bool VisitUnaryDeref(const UnaryOperator *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); @@ -9696,6 +9699,10 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); } +bool LValueExprEvaluator::VisitMatrixElementExpr(const MatrixElementExpr *E) { + return false; +} + bool LValueExprEvaluator::VisitExtVectorElementExpr( const ExtVectorElementExpr *E) { bool Success = true; @@ -20840,6 +20847,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: + case Expr::MatrixElementExprClass: case Expr::DesignatedInitExprClass: case Expr::ArrayInitLoopExprClass: case Expr::ArrayInitIndexExprClass: diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 5572e0a7ae59c..50864145e50cb 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -4951,6 +4951,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, case Expr::ChooseExprClass: case Expr::CompoundLiteralExprClass: case Expr::ExtVectorElementExprClass: + case Expr::MatrixElementExprClass: case Expr::GenericSelectionExprClass: case Expr::ObjCEncodeExprClass: case Expr::ObjCIsaExprClass: diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index ff8ca01ec5477..8cee55f63fab8 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1813,6 +1813,12 @@ void StmtPrinter::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { OS << Node->getAccessor().getName(); } +void StmtPrinter::VisitMatrixElementExpr(MatrixElementExpr *Node) { + PrintExpr(Node->getBase()); + OS << "."; + OS << Node->getAccessor().getName(); +} + void StmtPrinter::VisitCStyleCastExpr(CStyleCastExpr *Node) { OS << '('; Node->getTypeAsWritten().print(OS, Policy); diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 4a8c638c85331..e26fd44388a4e 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1667,6 +1667,11 @@ void StmtProfiler::VisitExtVectorElementExpr(const ExtVectorElementExpr *S) { VisitName(&S->getAccessor()); } +void StmtProfiler::VisitMatrixElementExpr(const MatrixElementExpr *S) { + VisitExpr(S); + VisitName(&S->getAccessor()); +} + void StmtProfiler::VisitBlockExpr(const BlockExpr *S) { VisitExpr(S); VisitDecl(S->getBlockDecl()); diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 7bc0404db1bee..aebfb9fa53fa1 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1675,6 +1675,10 @@ void TextNodeDumper::VisitExtVectorElementExpr( OS << " " << Node->getAccessor().getNameStart(); } +void TextNodeDumper::VisitMatrixElementExpr(const MatrixElementExpr *Node) { + OS << " " << Node->getAccessor().getNameStart(); +} + void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) { OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; if (Node->hasStoredFPFeatures()) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 25ce1ba26da09..f62580a91daeb 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -379,6 +379,8 @@ class ScalarExprEmitter : public StmtVisitor { mlir::Value VisitExtVectorElementExpr(Expr *e) { return emitLoadOfLValue(e); } + mlir::Value VisitMatrixElementExpr(Expr *e) { return emitLoadOfLValue(e); } + mlir::Value VisitMemberExpr(MemberExpr *e); mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) { diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 492cbb69fabb3..957c63050cc35 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -946,6 +946,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) { return emitArraySubscriptExpr(cast(e)); case Expr::ExtVectorElementExprClass: return emitExtVectorElementExpr(cast(e)); + case Expr::MatrixElementExprClass: + return emitMatrixElementExpr(cast(e)); case Expr::UnaryOperatorClass: return emitUnaryOpLValue(cast(e)); case Expr::StringLiteralClass: diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 0df812bcfb94e..0ca06aa027a3c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1333,6 +1333,8 @@ class CIRGenFunction : public CIRGenTypeCache { LValue emitExtVectorElementExpr(const ExtVectorElementExpr *e); + LValue emitMatrixElementExpr(cost MatrixElementExpr *e); + Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo = nullptr); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 3bde8e1fa2ac3..c155edb8c922c 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -29,6 +29,7 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" #include "clang/AST/InferAlloc.h" #include "clang/AST/NSAPI.h" #include "clang/AST/ParentMapContext.h" @@ -1802,6 +1803,8 @@ LValue CodeGenFunction::EmitLValueHelper(const Expr *E, return EmitArraySectionExpr(cast(E)); case Expr::ExtVectorElementExprClass: return EmitExtVectorElementExpr(cast(E)); + case Expr::MatrixElementExprClass: + return EmitMatrixElementExpr(cast(E)); case Expr::CXXThisExprClass: return MakeAddrLValue(LoadCXXThisAddress(), E->getType()); case Expr::MemberExprClass: @@ -2266,6 +2269,50 @@ static RawAddress MaybeConvertMatrixAddress(RawAddress Addr, return Addr; } +LValue CodeGenFunction::EmitMatrixElementExpr(const MatrixElementExpr *E) { + // return EmitUnsupportedLValue(E, "Matrix swizzle"); + LValue Base; + if (E->getBase()->isGLValue()) + Base = EmitLValue(E->getBase()); + else { + assert(E->getBase()->getType()->isConstantMatrixType() && + "Result must be a Constant Matrix"); + llvm::Value *Mat = EmitScalarExpr(E->getBase()); + Address MatMem = CreateMemTemp(E->getBase()->getType()); + QualType Ty = E->getBase()->getType(); + llvm::Type *LTy = convertTypeForLoadStore(Ty, Mat->getType()); + if (LTy->getScalarSizeInBits() > Mat->getType()->getScalarSizeInBits()) + Mat = Builder.CreateZExt(Mat, LTy); + Builder.CreateStore(Mat, MatMem); + Base = MakeAddrLValue(MatMem, Ty, AlignmentSource::Decl); + } + QualType type = + E->getType().withCVRQualifiers(Base.getQuals().getCVRQualifiers()); + + // Encode the element access list into a vector of unsigned indices. + SmallVector Indices; + E->getEncodedElementAccess(Indices); + + if (Base.isSimple()) { + llvm::Constant *CV = + llvm::ConstantDataVector::get(getLLVMContext(), Indices); + return LValue::MakeExtVectorElt( + MaybeConvertMatrixAddress(Base.getAddress(), *this), CV, type, + Base.getBaseInfo(), TBAAAccessInfo()); + } + assert(Base.isExtVectorElt() && "Can only subscript lvalue vec elts here!"); + + llvm::Constant *BaseElts = Base.getExtVectorElts(); + SmallVector CElts; + + for (unsigned Index : Indices) + CElts.push_back(BaseElts->getAggregateElement(Index)); + llvm::Constant *CV = llvm::ConstantVector::get(CElts); + return LValue::MakeExtVectorElt( + MaybeConvertMatrixAddress(Base.getExtVectorAddress(), *this), CV, type, + Base.getBaseInfo(), TBAAAccessInfo()); +} + // Emit a store of a matrix LValue. This may require casting the original // pointer to memory address (ArrayType) to a pointer to the value type // (VectorType). diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 769bc37b0e131..0a8e039c48823 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -604,6 +604,7 @@ class ScalarExprEmitter Value *VisitConvertVectorExpr(ConvertVectorExpr *E); Value *VisitMemberExpr(MemberExpr *E); Value *VisitExtVectorElementExpr(Expr *E) { return EmitLoadOfLValue(E); } + Value *VisitMatrixElementExpr(Expr *E) { return EmitLoadOfLValue(E); } Value *VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { // Strictly speaking, we shouldn't be calling EmitLoadOfLValue, which // transitively calls EmitCompoundLiteralLValue, here in C++ since compound diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 8c4c1c8c2dc95..1a870644c637d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4416,6 +4416,7 @@ class CodeGenFunction : public CodeGenTypeCache { LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound = true); LValue EmitExtVectorElementExpr(const ExtVectorElementExpr *E); + LValue EmitMatrixElementExpr(const MatrixElementExpr *E); LValue EmitMemberExpr(const MemberExpr *E); LValue EmitObjCIsaExpr(const ObjCIsaExpr *E); LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E); diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index a0483c3027199..1e49963155032 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1276,6 +1276,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Expr::DesignatedInitUpdateExprClass: case Expr::ExprWithCleanupsClass: case Expr::ExtVectorElementExprClass: + case Expr::MatrixElementExprClass: case Expr::InitListExprClass: case Expr::ArrayInitLoopExprClass: case Expr::MemberExprClass: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index a8c2e39b49923..44de9e26e9293 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -14010,6 +14010,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_DuplicateVectorComponents: DiagID = diag::err_typecheck_duplicate_vector_components_not_mlvalue; break; + case Expr::MLV_DuplicateMatrixComponents: + DiagID = diag::err_typecheck_duplicate_matrix_components_not_mlvalue; + break; case Expr::MLV_NoSetterProperty: llvm_unreachable("readonly properties should be processed differently"); case Expr::MLV_InvalidMessageExpression: diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index aedfc5e88b1c6..80d0f4945db67 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -14,11 +14,13 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeBase.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenMP.h" @@ -1617,6 +1619,21 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, ExtVectorElementExpr(ret, VK, BaseExpr.get(), *Member, MemberLoc); } + if (S.getLangOpts().HLSL && BaseType->isConstantMatrixType()) { + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + ExprValueKind VK = BaseExpr.get()->getValueKind(); + QualType Ret = S.HLSL().CheckMatrixComponent(S, BaseType, VK, OpLoc, Member, + MemberLoc); + if (Ret.isNull()) + return ExprError(); + Qualifiers BaseQ = + S.Context.getCanonicalType(BaseExpr.get()->getType()).getQualifiers(); + Ret = S.Context.getQualifiedType(Ret, BaseQ); + + return new (S.Context) + MatrixElementExpr(Ret, VK, BaseExpr.get(), *Member, MemberLoc); + } + // Adjust builtin-sel to the appropriate redefinition type if that's // not just a pointer to builtin-sel again. if (IsArrow && BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) && diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index dadea331f930b..8d37d9a69727f 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -4620,6 +4620,205 @@ bool SemaHLSL::transformInitList(const InitializedEntity &Entity, return true; } +QualType SemaHLSL::CheckMatrixComponent(Sema &S, QualType baseType, + ExprValueKind &VK, SourceLocation OpLoc, + const IdentifierInfo *CompName, + SourceLocation CompLoc) { + const auto *MT = baseType->getAs(); + StringRef AccessorName = CompName->getName(); + assert(MT && + "CheckMatrixComponent is intended to be used on ConstantMatrixType"); + assert(!AccessorName.empty() && "Matrix Accessor must have a name"); + + unsigned Rows = MT->getNumRows(); + unsigned Cols = MT->getNumColumns(); + bool IsZeroBasedAccessor = false; + unsigned ChunkLen = 0; + if (AccessorName.size() < 2) { + const char Expected[] = "length 4 for zero based: \'_mRC\' or length 3 for " + "one-based: \'_RC\' accessor"; + S.Diag(OpLoc, diag::err_builtin_matrix_invalid_member) + << CompName->getName() << StringRef(Expected, sizeof(Expected) - 1) + << SourceRange(CompLoc); + return QualType(); + } + if (AccessorName[0] == '_' && AccessorName[1] == 'm') { + IsZeroBasedAccessor = true; // zero-based: 00..33 + ChunkLen = 4; // zero-based: "_mRC" + } else if (AccessorName[0] == '_') + // one-based: 11..44 + ChunkLen = 3; // one-based: "_RC" + else { + const char Expected[] = + "zero based: \'_mRC\' or one-based: \'_RC\' accessor"; + S.Diag(OpLoc, diag::err_builtin_matrix_invalid_member) + << CompName->getName() << StringRef(Expected, sizeof(Expected) - 1) + << SourceRange(CompLoc); + return QualType(); + } + + if (IsZeroBasedAccessor && AccessorName.size() < 4) { + const char Expected[] = "zero based: \'_mRC\' accessor"; + S.Diag(OpLoc, diag::err_builtin_matrix_invalid_member) + << CompName->getName() << StringRef(Expected, sizeof(Expected) - 1) + << SourceRange(CompLoc); + return QualType(); + } + + if (AccessorName.size() < 3) { + const char Expected[] = "one-based: \'_RC\' accessor"; + S.Diag(OpLoc, diag::err_builtin_matrix_invalid_member) + << CompName->getName() << StringRef(Expected, sizeof(Expected) - 1) + << SourceRange(CompLoc); + return QualType(); + } + + auto isDigit = [](char c) { return c >= '0' && c <= '9'; }; + auto isZeroBasedIndex = [](int i) { return i >= 0 && i <= 3; }; + auto isOneBasedIndex = [](int i) { return i >= 1 && i <= 4; }; + + bool HasRepeated = false; + SmallVector Seen(Rows * Cols, false); + unsigned NumComponents = 0; + const char *Begin = AccessorName.data(); + + for (unsigned I = 0, E = AccessorName.size(); I < E; I += ChunkLen) { + const char *Chunk = Begin + I; + char RowChar = 0, ColChar = 0; + if (IsZeroBasedAccessor) { + // Zero-based: "_mRC" + if (Chunk[0] != '_' || Chunk[1] != 'm') { + char Bad = (Chunk[0] != '_') ? Chunk[0] : Chunk[1]; + const char Expected[] = "\'_m\' prefix"; + S.Diag(OpLoc.getLocWithOffset(I + (Bad == Chunk[0] ? 1 : 2)), + diag::err_builtin_matrix_invalid_member) + << StringRef(&Bad, 1) << StringRef(Expected, sizeof(Expected) - 1) + << SourceRange(CompLoc); + return QualType(); + } + RowChar = Chunk[2]; + ColChar = Chunk[3]; + } else { + // One-based: "_RC" + if (Chunk[0] != '_') { + const char Expected[] = "\'_\' prefix"; + S.Diag(OpLoc.getLocWithOffset(I + 1), + diag::err_builtin_matrix_invalid_member) + << StringRef(&Chunk[0], 1) + << StringRef(Expected, sizeof(Expected) - 1) + << SourceRange(CompLoc); + return QualType(); + } + RowChar = Chunk[1]; + ColChar = Chunk[2]; + } + + // Must be digits. + bool isDigitsError = false; + if (!isDigit(RowChar)) { + const char Expected[] = "row as integer"; + unsigned BadPos = IsZeroBasedAccessor ? 2 : 1; + S.Diag(OpLoc.getLocWithOffset(I + BadPos + 1), + diag::err_builtin_matrix_invalid_member) + << StringRef(&RowChar, 1) << StringRef(Expected, sizeof(Expected) - 1) + << SourceRange(CompLoc); + isDigitsError = true; + } + + if (!isDigit(ColChar)) { + const char Expected[] = "column as integer"; + unsigned BadPos = IsZeroBasedAccessor ? 3 : 2; + S.Diag(OpLoc.getLocWithOffset(I + BadPos + 1), + diag::err_builtin_matrix_invalid_member) + << StringRef(&ColChar, 1) << StringRef(Expected, sizeof(Expected) - 1) + << SourceRange(CompLoc); + isDigitsError = true; + } + if (isDigitsError) + return QualType(); + + unsigned Row = RowChar - '0'; + unsigned Col = ColChar - '0'; + + bool HasIndexingError = false; + if (IsZeroBasedAccessor) { + // 0-based [0..3] + if (!isZeroBasedIndex(Row)) { + S.Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds) + << /*row*/ 0 << /*zero-based*/ 0 << SourceRange(CompLoc); + HasIndexingError = true; + } + if (!isZeroBasedIndex(Col)) { + S.Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds) + << /*col*/ 1 << /*zero-based*/ 0 << SourceRange(CompLoc); + HasIndexingError = true; + } + } else { + // 1-based [1..4] + if (!isOneBasedIndex(Row)) { + S.Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds) + << /*row*/ 0 << /*one-based*/ 1 << SourceRange(CompLoc); + HasIndexingError = true; + } + if (!isOneBasedIndex(Col)) { + S.Diag(OpLoc, diag::err_hlsl_matrix_element_not_in_bounds) + << /*col*/ 1 << /*one-based*/ 1 << SourceRange(CompLoc); + HasIndexingError = true; + } + // Convert to 0-based after range checking. + Row--; + Col--; + } + + if (HasIndexingError) + return QualType(); + + // Note: matrix swizzle index is hard coded. That means Row and Col can + // potentially be larger than Rows and Cols if matrix size is less than + // the max index size. + bool HasBoundsError = false; + if (Row >= Rows) { + Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds) + << /*Row*/ 0 << Row << Rows << SourceRange(CompLoc); + HasBoundsError = true; + } + if (Col >= Cols) { + Diag(OpLoc, diag::err_hlsl_matrix_index_out_of_bounds) + << /*Col*/ 1 << Col << Cols << SourceRange(CompLoc); + HasBoundsError = true; + } + if (HasBoundsError) + return QualType(); + + unsigned FlatIndex = Row * Cols + Col; + if (Seen[FlatIndex]) + HasRepeated = true; + Seen[FlatIndex] = true; + ++NumComponents; + } + if (NumComponents == 0 || NumComponents > 4) { + S.Diag(OpLoc, diag::err_hlsl_matrix_swizzle_invalid_length) + << NumComponents << SourceRange(CompLoc); + return QualType(); + } + + QualType ElemTy = MT->getElementType(); + QualType VT = S.Context.getExtVectorType(ElemTy, NumComponents); + if (HasRepeated) + VK = VK_PRValue; + + for (Sema::ExtVectorDeclsType::iterator + I = S.ExtVectorDecls.begin(S.getExternalSource()), + E = S.ExtVectorDecls.end(); + I != E; ++I) { + if ((*I)->getUnderlyingType() == VT) + return S.Context.getTypedefType(ElaboratedTypeKeyword::None, + /*Qualifier=*/std::nullopt, *I); + } + + return VT; +} + bool SemaHLSL::handleInitialization(VarDecl *VDecl, Expr *&Init) { const HLSLVkConstantIdAttr *ConstIdAttr = VDecl->getAttr(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8e5dbeb792348..343de007b0a97 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3072,14 +3072,15 @@ class TreeTransform { Init); } - /// Build a new extended vector element access expression. + /// Build a new extended vector or matrix element access expression. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildExtVectorElementExpr(Expr *Base, SourceLocation OpLoc, - bool IsArrow, - SourceLocation AccessorLoc, - IdentifierInfo &Accessor) { + ExprResult RebuildExtVectorOrMatrixElementExpr(Expr *Base, + SourceLocation OpLoc, + bool IsArrow, + SourceLocation AccessorLoc, + IdentifierInfo &Accessor) { CXXScopeSpec SS; DeclarationNameInfo NameInfo(&Accessor, AccessorLoc); @@ -13876,11 +13877,29 @@ TreeTransform::TransformExtVectorElementExpr(ExtVectorElementExpr *E) { // FIXME: Bad source location SourceLocation FakeOperatorLoc = SemaRef.getLocForEndOfToken(E->getBase()->getEndLoc()); - return getDerived().RebuildExtVectorElementExpr( + return getDerived().RebuildExtVectorOrMatrixElementExpr( Base.get(), FakeOperatorLoc, E->isArrow(), E->getAccessorLoc(), E->getAccessor()); } +template +ExprResult +TreeTransform::TransformMatrixElementExpr(MatrixElementExpr *E) { + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase()) + return E; + + // FIXME: Bad source location + SourceLocation FakeOperatorLoc = + SemaRef.getLocForEndOfToken(E->getBase()->getEndLoc()); + return getDerived().RebuildExtVectorOrMatrixElementExpr( + Base.get(), FakeOperatorLoc, /*isArrow*/ false, E->getAccessorLoc(), + E->getAccessor()); +} + template ExprResult TreeTransform::TransformInitListExpr(InitListExpr *E) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index eef97a8588f0b..6bea9f2efca5c 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1217,6 +1217,13 @@ void ASTStmtReader::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { E->setAccessorLoc(readSourceLocation()); } +void ASTStmtReader::VisitMatrixElementExpr(MatrixElementExpr *E) { + VisitExpr(E); + E->setBase(Record.readSubExpr()); + E->setAccessor(Record.readIdentifier()); + E->setAccessorLoc(readSourceLocation()); +} + void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { VisitExpr(E); if (auto *SyntForm = cast_or_null(Record.readSubStmt())) @@ -3359,6 +3366,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) ExtVectorElementExpr(Empty); break; + case EXPR_MATRIX_ELEMENT: + S = new (Context) MatrixElementExpr(Empty); + break; + case EXPR_INIT_LIST: S = new (Context) InitListExpr(Empty); break; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index acf345392aa1a..3b7847f23f825 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1184,6 +1184,14 @@ void ASTStmtWriter::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { Code = serialization::EXPR_EXT_VECTOR_ELEMENT; } +void ASTStmtWriter::VisitMatrixElementExpr(MatrixElementExpr *E) { + VisitExpr(E); + Record.AddStmt(E->getBase()); + Record.AddIdentifierRef(&E->getAccessor()); + Record.AddSourceLocation(E->getAccessorLoc()); + Code = serialization::EXPR_MATRIX_ELEMENT; +} + void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) { VisitExpr(E); // NOTE: only add the (possibly null) syntactic form. diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index a759aee47b8ea..925afd6f3a660 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1928,6 +1928,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::DesignatedInitUpdateExprClass: case Stmt::ArrayInitIndexExprClass: case Stmt::ExtVectorElementExprClass: + case Stmt::MatrixElementExprClass: case Stmt::ImaginaryLiteralClass: case Stmt::ObjCAtCatchStmtClass: case Stmt::ObjCAtFinallyStmtClass: diff --git a/clang/test/AST/HLSL/matrix-member-access-scalar.hlsl b/clang/test/AST/HLSL/matrix-member-access-scalar.hlsl new file mode 100644 index 0000000000000..b403d27b29760 --- /dev/null +++ b/clang/test/AST/HLSL/matrix-member-access-scalar.hlsl @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s + +typedef float float3x3 __attribute__((matrix_type(3,3))); + +[numthreads(1,1,1)] +void ok() { + float3x3 A; + + // CHECK: BinaryOperator {{.*}} 'vector' lvalue '=' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'vector' lvalue _m12 + // CHECK-NEXT: DeclRefExpr {{.*}} 'float3x3':'matrix' lvalue Var {{.*}} 'A' 'float3x3':'matrix' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' + // CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.140000e+00 + A._m12 = 3.14; + + // CHECK: VarDecl {{.*}} r 'float' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'vector' lvalue _m00 + // CHECK-NEXT: DeclRefExpr {{.*}} 'float3x3':'matrix' lvalue Var {{.*}} 'A' 'float3x3':'matrix' + float r = A._m00; + + // CHECK: VarDecl {{.*}} good1 'float' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'vector' lvalue _11 + // CHECK-NEXT: DeclRefExpr {{.*}} 'float3x3':'matrix' lvalue Var {{.*}} 'A' 'float3x3':'matrix' + float good1 = A._11; + + // CHECK: BinaryOperator {{.*}} 'vector' lvalue '=' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'vector' lvalue _33 + // CHECK-NEXT: DeclRefExpr {{.*}} 'float3x3':'matrix' lvalue Var {{.*}} 'A' 'float3x3':'matrix' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' + // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue Var {{.*}} 'R' 'float' + float R; + A._33 = R; +} diff --git a/clang/test/AST/HLSL/matrix-member-access-swizzle-ast-dump-json.hlsl b/clang/test/AST/HLSL/matrix-member-access-swizzle-ast-dump-json.hlsl new file mode 100644 index 0000000000000..afb144624696a --- /dev/null +++ b/clang/test/AST/HLSL/matrix-member-access-swizzle-ast-dump-json.hlsl @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl \ +// RUN: -ast-dump=json -disable-llvm-passes -o - -hlsl-entry main %s \ +// RUN: | FileCheck %s + +typedef float float4x4 __attribute__((matrix_type(4,4))); +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); + +float4x4 gMat; + +[numthreads(1, 1, 1)] +void main() { + float4x4 A = gMat; + + // one-based swizzle + float3 v1 = A._11_22_33; + + // zero-based swizzle + float2 v2 = A._m00_m11; +} + +// CHECK: "kind": "MatrixElementExpr" +// CHECK-NEXT: "range": { +// CHECK: "kind": "MatrixElementExpr" +// CHECK-NEXT: "range": { diff --git a/clang/test/AST/HLSL/matrix-member-access-swizzle-ast-print.hlsl b/clang/test/AST/HLSL/matrix-member-access-swizzle-ast-print.hlsl new file mode 100644 index 0000000000000..fa265987bd000 --- /dev/null +++ b/clang/test/AST/HLSL/matrix-member-access-swizzle-ast-print.hlsl @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl \ +// RUN: -ast-print -disable-llvm-passes -o - -hlsl-entry main %s \ +// RUN: | FileCheck %s + +typedef float float4x4 __attribute__((matrix_type(4,4))); +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); + +float4x4 gMat; + +[numthreads(1, 1, 1)] +void main() { + float4x4 A = gMat; + float3 v1 = A._11_22_33; + float2 v2 = A._m00_m11; +} + +// CHECK: float4x4 gMat; +// CHECK: float4x4 A = gMat; +// CHECK: float3 v1 = A._11_22_33; +// CHECK: float2 v2 = A._m00_m11; diff --git a/clang/test/AST/HLSL/matrix-member-access-swizzle.hlsl b/clang/test/AST/HLSL/matrix-member-access-swizzle.hlsl new file mode 100644 index 0000000000000..2d0169e799802 --- /dev/null +++ b/clang/test/AST/HLSL/matrix-member-access-swizzle.hlsl @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s + +typedef float float3x3 __attribute__((matrix_type(3,3))); +typedef float float4x4 __attribute__((matrix_type(4,4))); +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); +typedef float float4 __attribute__((ext_vector_type(4))); + +[numthreads(1,1,1)] +void ok() { + float3x3 A; + + // CHECK: BinaryOperator {{.*}} 'float2':'vector' lvalue '=' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'float2':'vector' lvalue _m12_m21 + // CHECK-NEXT: DeclRefExpr {{.*}} 'float3x3':'matrix' lvalue Var {{.*}} 'A' 'float3x3':'matrix' + // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'float2':'vector' xx + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' + // CHECK-NEXT: FloatingLiteral {{.*}} 'float' 3.140000e+00 + A._m12_m21 = 3.14.xx; + + // CHECK: VarDecl {{.*}}r 'float2':'vector' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'float2':'vector' lvalue _m00_m11 + // CHECK-NEXT: DeclRefExpr {{.*}} 'float3x3':'matrix' lvalue Var {{.*}} 'A' 'float3x3':'matrix' + float2 r = A._m00_m11; + + // CHECK: VarDecl {{.*}} good1 'float3':'vector' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float3':'vector' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'float3':'vector' lvalue _11_22_33 + // CHECK-NEXT: DeclRefExpr {{.*}} 'float3x3':'matrix' lvalue Var {{.*}} 'A' 'float3x3':'matrix' + float3 good1 = A._11_22_33; + + // CHECK: BinaryOperator {{.*}} 'float4':'vector' lvalue '=' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'float4':'vector' lvalue _11_22_33_44 + // CHECK-NEXT: DeclRefExpr {{.*}} 'float4x4':'matrix' lvalue Var {{.*}} 'B' 'float4x4':'matrix' + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector' + // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector' lvalue Var {{.*}} 'R' 'float4':'vector' + float4 R; + float4x4 B; + B._11_22_33_44 = R; + + // CHECK: BinaryOperator {{.*}} 'float3':'vector' lvalue '=' + // CHECK-NEXT: MatrixElementExpr {{.*}} 'float3':'vector' lvalue _11_22_33 + // CHECK-NEXT: DeclRefExpr{{.*}} 'float3x3':'matrix' lvalue Var {{.*}} 'A' 'float3x3':'matrix' + // CHECK-NEXT: ImplicitCastExpr {{.*}}'float3':'vector' + // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'float3':'vector' lvalue vectorcomponent rgb + // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector' lvalue Var {{.*}} 'R' 'float4':'vector' + A._11_22_33 = R.rgb; +} diff --git a/clang/test/AST/HLSL/pch_with_matrix_element_accessor.hlsl b/clang/test/AST/HLSL/pch_with_matrix_element_accessor.hlsl new file mode 100644 index 0000000000000..605a119e3beac --- /dev/null +++ b/clang/test/AST/HLSL/pch_with_matrix_element_accessor.hlsl @@ -0,0 +1,26 @@ +// 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 + +float4x4 gM; + +// CHECK: FunctionDecl {{.*}} getDiag 'float4 ()' +// CHECK-NEXT: CompoundStmt {{.*}} +// CHECK-NEXT: ReturnStmt {{.*}} +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector' +// CHECK-NEXT: MatrixElementExpr {{.*}} 'vector' lvalue _11_22_33_44 +// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl_constant float4x4':'matrix' lvalue Var {{.*}} 'gM' 'hlsl_constant float4x4':'matrix' +float4 getDiag() { + return gM._11_22_33_44; +} + +// CHECK: FunctionDecl {{.*}} setRowZero 'void (float4)' +// CHECK-NEXT: ParmVarDecl {{.*}} used V 'float4':'vector' +// CHECK-NEXT: CompoundStmt {{.*}} +// CHECK-NEXT: BinaryOperator {{.*}} 'vector' lvalue '=' +// CHECK-NEXT: MatrixElementExpr {{.*}} 'vector' lvalue _m00_m01_m02_m03 +// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl_constant float4x4':'matrix' lvalue Var {{.*}} 'gM' 'hlsl_constant float4x4':'matrix' +// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float4':'vector' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector' lvalue ParmVar {{.*}} 'V' 'float4':'vector' +void setRowZero(float4 V) { + gM._m00_m01_m02_m03 = V; +} \ No newline at end of file diff --git a/clang/test/CodeGenHLSL/matrix-member-one-based-accessor-scalar-load.hlsl b/clang/test/CodeGenHLSL/matrix-member-one-based-accessor-scalar-load.hlsl new file mode 100644 index 0000000000000..1d3d4d17e0c8a --- /dev/null +++ b/clang/test/CodeGenHLSL/matrix-member-one-based-accessor-scalar-load.hlsl @@ -0,0 +1,230 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 + +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return11u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return11(int4x4 A) { + return A._11; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return12u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return12(int4x4 A) { + return A._12; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return13u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return13(int4x4 A) { + return A._13; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return14u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return14(int4x4 A) { + return A._14; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return21u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return21(int4x4 A) { + return A._21; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return22u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return22(int4x4 A) { + return A._22; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return23u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return23(int4x4 A) { + return A._23; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return24u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return24(int4x4 A) { + return A._24; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return31u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return31(int4x4 A) { + return A._31; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return32u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return32(int4x4 A) { + return A._32; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return33u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return33(int4x4 A) { + return A._33; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return34u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return34(int4x4 A) { + return A._34; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return41u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return41(int4x4 A) { + return A._41; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return42u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return42(int4x4 A) { + return A._42; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return43u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return43(int4x4 A) { + return A._43; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z8Return44u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int Return44(int4x4 A) { + return A._44; +} + diff --git a/clang/test/CodeGenHLSL/matrix-member-one-based-accessor-scalar-store.hlsl b/clang/test/CodeGenHLSL/matrix-member-one-based-accessor-scalar-store.hlsl new file mode 100644 index 0000000000000..5f80f924b024f --- /dev/null +++ b/clang/test/CodeGenHLSL/matrix-member-one-based-accessor-scalar-store.hlsl @@ -0,0 +1,345 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 + +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat11Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4:![0-9]+]], !align [[META5:![0-9]+]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat11(out int4x4 A, int I) { + return A._11 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat12Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 1 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat12(out int4x4 A, int I) { + return A._12 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat13Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 2 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat13(out int4x4 A, int I) { + return A._13 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat14Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 3 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat14(out int4x4 A, int I) { + return A._14 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat21Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 4 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat21(out int4x4 A, int I) { + return A._21 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat22Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 5 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat22(out int4x4 A, int I) { + return A._22 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat23Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 6 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat23(out int4x4 A, int I) { + return A._23 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat24Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 7 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat24(out int4x4 A, int I) { + return A._24 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat31Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], 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: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat31(out int4x4 A, int I) { + return A._31 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat32Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 9 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat32(out int4x4 A, int I) { + return A._32 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat33Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 10 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat33(out int4x4 A, int I) { + return A._33 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat34Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 11 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat34(out int4x4 A, int I) { + return A._34 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat41Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 12 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat41(out int4x4 A, int I) { + return A._41 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat42Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 13 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat42(out int4x4 A, int I) { + return A._42 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat43Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 14 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat43(out int4x4 A, int I) { + return A._43 = I; +} + +// CHECK-LABEL: define hidden noundef i32 @_Z18StoreScalarAtMat44Ru11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <1 x i32> [[SPLAT_SPLATINSERT]], <1 x i32> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 15 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x i32> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret i32 [[CAST_VTRUNC]] +// +int StoreScalarAtMat44(out int4x4 A, int I) { + return A._44 = I; +} + +//. +// CHECK: [[META4]] = !{} +// CHECK: [[META5]] = !{i64 4} +//. diff --git a/clang/test/CodeGenHLSL/matrix-member-one-based-swizzle-load.hlsl b/clang/test/CodeGenHLSL/matrix-member-one-based-swizzle-load.hlsl new file mode 100644 index 0000000000000..31a56811473af --- /dev/null +++ b/clang/test/CodeGenHLSL/matrix-member-one-based-swizzle-load.hlsl @@ -0,0 +1,108 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: define hidden noundef <4 x i32> @_Z17ReturnOnesSwizzleu11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int4 ReturnOnesSwizzle(int4x4 A) { + return A._11_12_13_14; +} + +// CHECK-LABEL: define hidden noundef <4 x i32> @_Z18ReturnOnesSwizzle2u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int4 ReturnOnesSwizzle2(int4x4 A) { + return A._11_21_31_41; +} + +// CHECK-LABEL: define hidden noundef <4 x i32> @_Z17ReturnTwosSwizzleu11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int4 ReturnTwosSwizzle(int4x4 A) { + return A._21_22_23_24; +} + +// CHECK-LABEL: define hidden noundef <4 x i32> @_Z18ReturnTwosSwizzle2u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int4 ReturnTwosSwizzle2(int4x4 A) { + return A._12_22_32_42; +} + +// CHECK-LABEL: define hidden noundef <4 x i32> @_Z19ReturnThreesSwizzleu11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int4 ReturnThreesSwizzle(int4x4 A) { + return A._31_32_33_34; +} + +// CHECK-LABEL: define hidden noundef <4 x i32> @_Z20ReturnThreesSwizzle2u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int4 ReturnThreesSwizzle2(int4x4 A) { + return A._13_23_33_43; +} + +// CHECK-LABEL: define hidden noundef <4 x i32> @_Z18ReturnFoursSwizzleu11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int4 ReturnFoursSwizzle(int4x4 A) { + return A._41_42_43_44; +} + +// CHECK-LABEL: define hidden noundef <4 x i32> @_Z19ReturnFoursSwizzle2u11matrix_typeILm4ELm4EiE( +// CHECK-SAME: <16 x i32> noundef [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: store <16 x i32> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x i32>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x i32> [[TMP0]], <16 x i32> poison, <4 x i32> +// CHECK-NEXT: ret <4 x i32> [[TMP1]] +// +int4 ReturnFoursSwizzle2(int4x4 A) { + return A._14_24_34_44; +} diff --git a/clang/test/CodeGenHLSL/matrix-member-one-based-swizzle-store.hlsl b/clang/test/CodeGenHLSL/matrix-member-one-based-swizzle-store.hlsl new file mode 100644 index 0000000000000..ff7fab662a012 --- /dev/null +++ b/clang/test/CodeGenHLSL/matrix-member-one-based-swizzle-store.hlsl @@ -0,0 +1,230 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: define hidden void @_Z19OnesSwizzleToScalarRu11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x i32> [[CAST_SPLAT]], <1 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4:![0-9]+]], !align [[META5:![0-9]+]] +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP2]], align 4 +// CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 1 +// CHECK-NEXT: store i32 [[TMP4]], ptr [[TMP5]], align 4 +// CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i32> [[TMP1]], i32 2 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 2 +// CHECK-NEXT: store i32 [[TMP6]], ptr [[TMP7]], align 4 +// CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 3 +// CHECK-NEXT: store i32 [[TMP8]], ptr [[TMP9]], align 4 +// CHECK-NEXT: ret void +// +void OnesSwizzleToScalar(out int4x4 A, int I) { + A._11_12_13_14 = I.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z19OnesSwizzleToVectorRu11matrix_typeILm4ELm4EiEDv4_i( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], <4 x i32> noundef [[V:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: store ptr [[A]], ptr [[A_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i32> [[TMP0]], i32 0 +// CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x i32> [[TMP0]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 4 +// CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP4]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i32> [[TMP0]], i32 2 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 8 +// CHECK-NEXT: store i32 [[TMP5]], ptr [[TMP6]], align 4 +// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x i32> [[TMP0]], i32 3 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 12 +// CHECK-NEXT: store i32 [[TMP7]], ptr [[TMP8]], align 4 +// CHECK-NEXT: ret void +// +void OnesSwizzleToVector(out int4x4 A, int4 V) { + A._11_21_31_41 = V; +} + +// CHECK-LABEL: define hidden void @_Z19TwosSwizzleToScalarRu11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x i32> [[CAST_SPLAT]], <1 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 4 +// CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP4]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 5 +// CHECK-NEXT: store i32 [[TMP5]], ptr [[TMP6]], align 4 +// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x i32> [[TMP1]], i32 2 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 6 +// CHECK-NEXT: store i32 [[TMP7]], ptr [[TMP8]], align 4 +// CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 7 +// CHECK-NEXT: store i32 [[TMP9]], ptr [[TMP10]], align 4 +// CHECK-NEXT: ret void +// +void TwosSwizzleToScalar(out int4x4 A, int I) { + A._21_22_23_24 = I.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z19TwosSwizzleToVectorRu11matrix_typeILm4ELm4EiEDv4_i( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], <4 x i32> noundef [[V:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: store ptr [[A]], ptr [[A_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i32> [[TMP0]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 1 +// 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 5 +// 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 9 +// 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 13 +// CHECK-NEXT: store i32 [[TMP8]], ptr [[TMP9]], align 4 +// CHECK-NEXT: ret void +// +void TwosSwizzleToVector(out int4x4 A, int4 V) { + A._12_22_32_42 = V; +} + +// CHECK-LABEL: define hidden void @_Z21ThreesSwizzleToScalarRu11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x i32> [[CAST_SPLAT]], <1 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 8 +// CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP4]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 9 +// CHECK-NEXT: store i32 [[TMP5]], ptr [[TMP6]], align 4 +// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x i32> [[TMP1]], i32 2 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 10 +// CHECK-NEXT: store i32 [[TMP7]], ptr [[TMP8]], align 4 +// CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 11 +// CHECK-NEXT: store i32 [[TMP9]], ptr [[TMP10]], align 4 +// CHECK-NEXT: ret void +// +void ThreesSwizzleToScalar(out int4x4 A, int I) { + A._31_32_33_34 = I.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z21ThreesSwizzleToVectorRu11matrix_typeILm4ELm4EiEDv4_i( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], <4 x i32> noundef [[V:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: store ptr [[A]], ptr [[A_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i32> [[TMP0]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 2 +// 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 6 +// 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 14 +// CHECK-NEXT: store i32 [[TMP8]], ptr [[TMP9]], align 4 +// CHECK-NEXT: ret void +// +void ThreesSwizzleToVector(out int4x4 A, int4 V) { + A._13_23_33_43 = V; +} + +// CHECK-LABEL: define hidden void @_Z20FoursSwizzleToScalarRu11matrix_typeILm4ELm4EiEi( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[I]], ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 +// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x i32> poison, i32 [[TMP0]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x i32> [[CAST_SPLAT]], <1 x i32> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x i32> [[TMP1]], i32 0 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 12 +// CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP4]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i32> [[TMP1]], i32 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 13 +// CHECK-NEXT: store i32 [[TMP5]], ptr [[TMP6]], align 4 +// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x i32> [[TMP1]], i32 2 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 14 +// CHECK-NEXT: store i32 [[TMP7]], ptr [[TMP8]], align 4 +// CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x i32> [[TMP1]], i32 3 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr <16 x i32>, ptr [[TMP2]], i32 0, i32 15 +// CHECK-NEXT: store i32 [[TMP9]], ptr [[TMP10]], align 4 +// CHECK-NEXT: ret void +// +void FoursSwizzleToScalar(out int4x4 A, int I) { + A._41_42_43_44 = I.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z20FoursSwizzleToVectorRu11matrix_typeILm4ELm4EiEDv4_i( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], <4 x i32> noundef [[V:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x i32>, align 16 +// CHECK-NEXT: store ptr [[A]], ptr [[A_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i32> [[TMP0]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x i32>, ptr [[TMP1]], i32 0, i32 12 +// 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 13 +// 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 14 +// 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 15 +// CHECK-NEXT: store i32 [[TMP8]], ptr [[TMP9]], align 4 +// CHECK-NEXT: ret void +// +void FoursSwizzleToVector(out int4x4 A, int4 V) { + A._41_42_43_44 = V; +} +//. +// CHECK: [[META4]] = !{} +// CHECK: [[META5]] = !{i64 4} +//. diff --git a/clang/test/CodeGenHLSL/matrix-member-zero-based-accessor-scalar-load.hlsl b/clang/test/CodeGenHLSL/matrix-member-zero-based-accessor-scalar-load.hlsl new file mode 100644 index 0000000000000..f99bbb2bf2b02 --- /dev/null +++ b/clang/test/CodeGenHLSL/matrix-member-zero-based-accessor-scalar-load.hlsl @@ -0,0 +1,230 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 + +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return00u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> zeroinitializer +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return00(float4x4 A) { + return A._m00; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return01u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return01(float4x4 A) { + return A._m01; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return02u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return02(float4x4 A) { + return A._m02; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return03u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return03(float4x4 A) { + return A._m03; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return10u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return10(float4x4 A) { + return A._m10; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return11u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return11(float4x4 A) { + return A._m11; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return12u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return12(float4x4 A) { + return A._m12; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return13u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return13(float4x4 A) { + return A._m13; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return20u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return20(float4x4 A) { + return A._m20; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return21u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return21(float4x4 A) { + return A._m21; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return22u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return22(float4x4 A) { + return A._m22; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return23u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return23(float4x4 A) { + return A._m23; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return30u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return30(float4x4 A) { + return A._m30; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return31u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return31(float4x4 A) { + return A._m31; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return32u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return32(float4x4 A) { + return A._m32; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z8Return33u11matrix_typeILm4ELm4EfE( +// CHECK-SAME: <16 x float> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x float], align 4 +// CHECK-NEXT: store <16 x float> [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x float>, ptr [[A_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x float> [[TMP0]], <16 x float> poison, <1 x i32> +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[TMP1]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float Return33(float4x4 A) { + return A._m33; +} + diff --git a/clang/test/CodeGenHLSL/matrix-member-zero-based-accessor-scalar-store.hlsl b/clang/test/CodeGenHLSL/matrix-member-zero-based-accessor-scalar-store.hlsl new file mode 100644 index 0000000000000..3c11f5fc29515 --- /dev/null +++ b/clang/test/CodeGenHLSL/matrix-member-zero-based-accessor-scalar-store.hlsl @@ -0,0 +1,345 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 + +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat00Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4:![0-9]+]], !align [[META5:![0-9]+]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP1]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat00(out float4x4 A, float F) { + return A._m00 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat01Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 1 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat01(out float4x4 A, float F) { + return A._m01 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat02Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 2 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat02(out float4x4 A, float F) { + return A._m02 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat03Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 3 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat03(out float4x4 A, float F) { + return A._m03 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat10Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 4 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat10(out float4x4 A, float F) { + return A._m10 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat11Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 5 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat11(out float4x4 A, float F) { + return A._m11 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat12Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 6 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat12(out float4x4 A, float F) { + return A._m12 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat13Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 7 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat13(out float4x4 A, float F) { + return A._m13 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat20Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 8 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat20(out float4x4 A, float F) { + return A._m20 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat21Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 9 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat21(out float4x4 A, float F) { + return A._m21 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat22Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 10 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat22(out float4x4 A, float F) { + return A._m22 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat23Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 11 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat23(out float4x4 A, float F) { + return A._m23 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat30Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 12 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat30(out float4x4 A, float F) { + return A._m30 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat31Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 13 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat31(out float4x4 A, float F) { + return A._m31 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat32Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x float>, ptr [[TMP1]], i32 0, i32 14 +// CHECK-NEXT: store float [[TMP2]], ptr [[TMP3]], align 4 +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat32(out float4x4 A, float F) { + return A._m32 = F; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) float @_Z18StoreScalarAtMat33Ru11matrix_typeILm4ELm4EfEf( +// CHECK-SAME: ptr noalias noundef nonnull align 4 dereferenceable(64) [[A:%.*]], float noundef nofpclass(nan inf) [[F:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[F_ADDR:%.*]] = alloca float, align 4 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store float [[F]], ptr [[F_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[F_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 [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], 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: [[CAST_VTRUNC:%.*]] = extractelement <1 x float> [[SPLAT_SPLAT]], i32 0 +// CHECK-NEXT: ret float [[CAST_VTRUNC]] +// +float StoreScalarAtMat33(out float4x4 A, float F) { + return A._m33 = F; +} + +//. +// CHECK: [[META4]] = !{} +// CHECK: [[META5]] = !{i64 4} +//. diff --git a/clang/test/CodeGenHLSL/matrix-member-zero-based-swizzle-load.hlsl b/clang/test/CodeGenHLSL/matrix-member-zero-based-swizzle-load.hlsl new file mode 100644 index 0000000000000..6a58094f59bc2 --- /dev/null +++ b/clang/test/CodeGenHLSL/matrix-member-zero-based-swizzle-load.hlsl @@ -0,0 +1,108 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z18ReturnZerosSwizzleu11matrix_typeILm4ELm4EDhE( +// CHECK-SAME: <16 x half> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x half], align 2 +// CHECK-NEXT: store <16 x half> [[A]], ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x half>, ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x half> [[TMP0]], <16 x half> poison, <4 x i32> +// CHECK-NEXT: ret <4 x half> [[TMP1]] +// +half4 ReturnZerosSwizzle(half4x4 A) { + return A._m00_m01_m02_m03; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z19ReturnZerosSwizzle2u11matrix_typeILm4ELm4EDhE( +// CHECK-SAME: <16 x half> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x half], align 2 +// CHECK-NEXT: store <16 x half> [[A]], ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x half>, ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x half> [[TMP0]], <16 x half> poison, <4 x i32> +// CHECK-NEXT: ret <4 x half> [[TMP1]] +// +half4 ReturnZerosSwizzle2(half4x4 A) { + return A._m00_m10_m20_m30; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z17ReturnOnesSwizzleu11matrix_typeILm4ELm4EDhE( +// CHECK-SAME: <16 x half> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x half], align 2 +// CHECK-NEXT: store <16 x half> [[A]], ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x half>, ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x half> [[TMP0]], <16 x half> poison, <4 x i32> +// CHECK-NEXT: ret <4 x half> [[TMP1]] +// +half4 ReturnOnesSwizzle(half4x4 A) { + return A._m10_m11_m12_m13; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z18ReturnOnesSwizzle2u11matrix_typeILm4ELm4EDhE( +// CHECK-SAME: <16 x half> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x half], align 2 +// CHECK-NEXT: store <16 x half> [[A]], ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x half>, ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x half> [[TMP0]], <16 x half> poison, <4 x i32> +// CHECK-NEXT: ret <4 x half> [[TMP1]] +// +half4 ReturnOnesSwizzle2(half4x4 A) { + return A._m01_m11_m21_m31; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z17ReturnTwosSwizzleu11matrix_typeILm4ELm4EDhE( +// CHECK-SAME: <16 x half> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x half], align 2 +// CHECK-NEXT: store <16 x half> [[A]], ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x half>, ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x half> [[TMP0]], <16 x half> poison, <4 x i32> +// CHECK-NEXT: ret <4 x half> [[TMP1]] +// +half4 ReturnTwosSwizzle(half4x4 A) { + return A._m20_m21_m22_m23; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z18ReturnTwosSwizzle2u11matrix_typeILm4ELm4EDhE( +// CHECK-SAME: <16 x half> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x half], align 2 +// CHECK-NEXT: store <16 x half> [[A]], ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x half>, ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x half> [[TMP0]], <16 x half> poison, <4 x i32> +// CHECK-NEXT: ret <4 x half> [[TMP1]] +// +half4 ReturnTwosSwizzle2(half4x4 A) { + return A._m02_m12_m22_m32; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z19ReturnThreesSwizzleu11matrix_typeILm4ELm4EDhE( +// CHECK-SAME: <16 x half> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x half], align 2 +// CHECK-NEXT: store <16 x half> [[A]], ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x half>, ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x half> [[TMP0]], <16 x half> poison, <4 x i32> +// CHECK-NEXT: ret <4 x half> [[TMP1]] +// +half4 ReturnThreesSwizzle(half4x4 A) { + return A._m30_m31_m32_m33; +} + +// CHECK-LABEL: define hidden noundef nofpclass(nan inf) <4 x half> @_Z20ReturnThreesSwizzle2u11matrix_typeILm4ELm4EDhE( +// CHECK-SAME: <16 x half> noundef nofpclass(nan inf) [[A:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca [16 x half], align 2 +// CHECK-NEXT: store <16 x half> [[A]], ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP0:%.*]] = load <16 x half>, ptr [[A_ADDR]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <16 x half> [[TMP0]], <16 x half> poison, <4 x i32> +// CHECK-NEXT: ret <4 x half> [[TMP1]] +// +half4 ReturnThreesSwizzle2(half4x4 A) { + return A._m03_m13_m23_m33; +} diff --git a/clang/test/CodeGenHLSL/matrix-member-zero-based-swizzle-store.hlsl b/clang/test/CodeGenHLSL/matrix-member-zero-based-swizzle-store.hlsl new file mode 100644 index 0000000000000..72fbc015d5934 --- /dev/null +++ b/clang/test/CodeGenHLSL/matrix-member-zero-based-swizzle-store.hlsl @@ -0,0 +1,230 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -x hlsl -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +// CHECK-LABEL: define hidden void @_Z20ZerosSwizzleToScalarRu11matrix_typeILm4ELm4EdEd( +// CHECK-SAME: ptr noalias noundef nonnull align 8 dereferenceable(128) [[A:%.*]], double noundef nofpclass(nan inf) [[D:%.*]]) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store double [[D]], ptr [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[D_ADDR]], align 8 +// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x double> poison, double [[TMP0]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x double> [[CAST_SPLAT]], <1 x double> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4:![0-9]+]], !align [[META5:![0-9]+]] +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 0 +// CHECK-NEXT: store double [[TMP3]], ptr [[TMP2]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP1]], i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 1 +// CHECK-NEXT: store double [[TMP4]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x double> [[TMP1]], i32 2 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 2 +// CHECK-NEXT: store double [[TMP6]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x double> [[TMP1]], i32 3 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 3 +// CHECK-NEXT: store double [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: ret void +// +void ZerosSwizzleToScalar(out double4x4 A, double D) { + A._m00_m01_m02_m03 = D.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z20ZerosSwizzleToVectorRu11matrix_typeILm4ELm4EdEDv4_d( +// CHECK-SAME: ptr noalias noundef nonnull align 8 dereferenceable(128) [[A:%.*]], <4 x double> noundef nofpclass(nan inf) [[V:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store <4 x double> [[V]], ptr [[V_ADDR]], align 32 +// CHECK-NEXT: [[TMP0:%.*]] = load <4 x double>, ptr [[V_ADDR]], align 32 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP0]], i32 0 +// CHECK-NEXT: store double [[TMP2]], ptr [[TMP1]], align 8 +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP0]], i32 1 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 4 +// CHECK-NEXT: store double [[TMP3]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP0]], i32 2 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 8 +// CHECK-NEXT: store double [[TMP5]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x double> [[TMP0]], i32 3 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 12 +// CHECK-NEXT: store double [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-NEXT: ret void +// +void ZerosSwizzleToVector(out double4x4 A, double4 V) { + A._m00_m10_m20_m30 = V; +} + +// CHECK-LABEL: define hidden void @_Z19OnesSwizzleToScalarRu11matrix_typeILm4ELm4EdEd( +// CHECK-SAME: ptr noalias noundef nonnull align 8 dereferenceable(128) [[A:%.*]], double noundef nofpclass(nan inf) [[D:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store double [[D]], ptr [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[D_ADDR]], align 8 +// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x double> poison, double [[TMP0]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x double> [[CAST_SPLAT]], <1 x double> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 0 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 4 +// CHECK-NEXT: store double [[TMP3]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 5 +// CHECK-NEXT: store double [[TMP5]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x double> [[TMP1]], i32 2 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 6 +// CHECK-NEXT: store double [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x double> [[TMP1]], i32 3 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 7 +// CHECK-NEXT: store double [[TMP9]], ptr [[TMP10]], align 8 +// CHECK-NEXT: ret void +// +void OnesSwizzleToScalar(out double4x4 A, double D) { + A._m10_m11_m12_m13 = D.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z19OnesSwizzleToVectorRu11matrix_typeILm4ELm4EdEDv4_d( +// CHECK-SAME: ptr noalias noundef nonnull align 8 dereferenceable(128) [[A:%.*]], <4 x double> noundef nofpclass(nan inf) [[V:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store <4 x double> [[V]], ptr [[V_ADDR]], align 32 +// CHECK-NEXT: [[TMP0:%.*]] = load <4 x double>, ptr [[V_ADDR]], align 32 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP0]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 1 +// CHECK-NEXT: store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP0]], i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 5 +// CHECK-NEXT: store double [[TMP4]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x double> [[TMP0]], i32 2 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 9 +// CHECK-NEXT: store double [[TMP6]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x double> [[TMP0]], i32 3 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 13 +// CHECK-NEXT: store double [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: ret void +// +void OnesSwizzleToVector(out double4x4 A, double4 V) { + A._m01_m11_m21_m31 = V; +} + +// CHECK-LABEL: define hidden void @_Z19TwosSwizzleToScalarRu11matrix_typeILm4ELm4EdEd( +// CHECK-SAME: ptr noalias noundef nonnull align 8 dereferenceable(128) [[A:%.*]], double noundef nofpclass(nan inf) [[D:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store double [[D]], ptr [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[D_ADDR]], align 8 +// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x double> poison, double [[TMP0]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x double> [[CAST_SPLAT]], <1 x double> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 0 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 8 +// CHECK-NEXT: store double [[TMP3]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 9 +// CHECK-NEXT: store double [[TMP5]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x double> [[TMP1]], i32 2 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 10 +// CHECK-NEXT: store double [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x double> [[TMP1]], i32 3 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 11 +// CHECK-NEXT: store double [[TMP9]], ptr [[TMP10]], align 8 +// CHECK-NEXT: ret void +// +void TwosSwizzleToScalar(out double4x4 A, double D) { + A._m20_m21_m22_m23 = D.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z19TwosSwizzleToVectorRu11matrix_typeILm4ELm4EdEDv4_d( +// CHECK-SAME: ptr noalias noundef nonnull align 8 dereferenceable(128) [[A:%.*]], <4 x double> noundef nofpclass(nan inf) [[V:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store <4 x double> [[V]], ptr [[V_ADDR]], align 32 +// CHECK-NEXT: [[TMP0:%.*]] = load <4 x double>, ptr [[V_ADDR]], align 32 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP0]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 2 +// CHECK-NEXT: store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP0]], i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 6 +// CHECK-NEXT: store double [[TMP4]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x double> [[TMP0]], i32 2 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 10 +// CHECK-NEXT: store double [[TMP6]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x double> [[TMP0]], i32 3 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 14 +// CHECK-NEXT: store double [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: ret void +// +void TwosSwizzleToVector(out double4x4 A, double4 V) { + A._m02_m12_m22_m32 = V; +} + +// CHECK-LABEL: define hidden void @_Z21ThreesSwizzleToScalarRu11matrix_typeILm4ELm4EdEd( +// CHECK-SAME: ptr noalias noundef nonnull align 8 dereferenceable(128) [[A:%.*]], double noundef nofpclass(nan inf) [[D:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[D_ADDR:%.*]] = alloca double, align 8 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store double [[D]], ptr [[D_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load double, ptr [[D_ADDR]], align 8 +// CHECK-NEXT: [[CAST_SPLAT:%.*]] = insertelement <1 x double> poison, double [[TMP0]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <1 x double> [[CAST_SPLAT]], <1 x double> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 0 +// CHECK-NEXT: [[TMP4:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 12 +// CHECK-NEXT: store double [[TMP3]], ptr [[TMP4]], align 8 +// CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 1 +// CHECK-NEXT: [[TMP6:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 13 +// CHECK-NEXT: store double [[TMP5]], ptr [[TMP6]], align 8 +// CHECK-NEXT: [[TMP7:%.*]] = extractelement <4 x double> [[TMP1]], i32 2 +// CHECK-NEXT: [[TMP8:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 14 +// CHECK-NEXT: store double [[TMP7]], ptr [[TMP8]], align 8 +// CHECK-NEXT: [[TMP9:%.*]] = extractelement <4 x double> [[TMP1]], i32 3 +// CHECK-NEXT: [[TMP10:%.*]] = getelementptr <16 x double>, ptr [[TMP2]], i32 0, i32 15 +// CHECK-NEXT: store double [[TMP9]], ptr [[TMP10]], align 8 +// CHECK-NEXT: ret void +// +void ThreesSwizzleToScalar(out double4x4 A, double D) { + A._m30_m31_m32_m33 = D.xxxx; +} + +// CHECK-LABEL: define hidden void @_Z21ThreesSwizzleToVectorRu11matrix_typeILm4ELm4EdEDv4_d( +// CHECK-SAME: ptr noalias noundef nonnull align 8 dereferenceable(128) [[A:%.*]], <4 x double> noundef nofpclass(nan inf) [[V:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[V_ADDR:%.*]] = alloca <4 x double>, align 32 +// CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 4 +// CHECK-NEXT: store <4 x double> [[V]], ptr [[V_ADDR]], align 32 +// CHECK-NEXT: [[TMP0:%.*]] = load <4 x double>, ptr [[V_ADDR]], align 32 +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 4, !nonnull [[META4]], !align [[META5]] +// CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP0]], i32 0 +// CHECK-NEXT: [[TMP3:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 3 +// CHECK-NEXT: store double [[TMP2]], ptr [[TMP3]], align 8 +// CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP0]], i32 1 +// CHECK-NEXT: [[TMP5:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 7 +// CHECK-NEXT: store double [[TMP4]], ptr [[TMP5]], align 8 +// CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x double> [[TMP0]], i32 2 +// CHECK-NEXT: [[TMP7:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 11 +// CHECK-NEXT: store double [[TMP6]], ptr [[TMP7]], align 8 +// CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x double> [[TMP0]], i32 3 +// CHECK-NEXT: [[TMP9:%.*]] = getelementptr <16 x double>, ptr [[TMP1]], i32 0, i32 15 +// CHECK-NEXT: store double [[TMP8]], ptr [[TMP9]], align 8 +// CHECK-NEXT: ret void +// +void ThreesSwizzleToVector(out double4x4 A, double4 V) { + A._m03_m13_m23_m33 = V; +} +//. +// CHECK: [[META4]] = !{} +// CHECK: [[META5]] = !{i64 8} +//. diff --git a/clang/test/SemaHLSL/matrix-member-access-errors.hlsl b/clang/test/SemaHLSL/matrix-member-access-errors.hlsl new file mode 100644 index 0000000000000..33c540420f593 --- /dev/null +++ b/clang/test/SemaHLSL/matrix-member-access-errors.hlsl @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -finclude-default-header -verify %s + +void foo() { + float3x3 A; + float r = A._m00; // read is ok + float good1 = A._11; + float good2 = A._33; + + float bad0 = A._m44; // expected-error {{matrix row element accessor is out of bounds of zero based indexing}} expected-error {{matrix column element accessor is out of bounds of zero based indexing}} + float bad1 = A._m33; // expected-error {{matrix row index 3 is out of bounds of rows size 3}} expected-error {{matrix column index 3 is out of bounds of columns size 3}} + float bad2 = A._mA2; // expected-error {{invalid matrix member 'A' expected row as integer}} + float bad3 = A._m2F; // expected-error {{invalid matrix member 'F' expected column as integer}} + + float bad4 = A._00; // expected-error {{matrix row element accessor is out of bounds of one based indexing}} expected-error {{matrix column element accessor is out of bounds of one based indexing}} + float bad5 = A._44; // expected-error {{matrix row index 3 is out of bounds of rows size 3}} expected-error {{matrix column index 3 is out of bounds of columns size 3}} + float bad6 = A._55; // expected-error {{matrix row element accessor is out of bounds of one based indexing}} expected-error {{matrix column element accessor is out of bounds of one based indexing}} + float bad7 = A.foo; // expected-error {{invalid matrix member 'foo' expected zero based: '_mRC' or one-based: '_RC' accessor}} + float2 bad8 = A._m00_33; // expected-error {{invalid matrix member '3' expected '_m' prefix}} + float2 bad9 = A._11_m33; // expected-error {{invalid matrix member 'm' expected row as integer}} + float bad10 = A._m0000; // expected-error {{invalid matrix member '0' expected '_m' prefix}} + float bad11 = A._m1; // expected-error {{invalid matrix member '_m1' expected zero based: '_mRC' accessor}} + float bad12 = A._m; // expected-error {{invalid matrix member '_m' expected zero based: '_mRC' accessor}} + float bad13 = A._1; // expected-error {{invalid matrix member '_1' expected one-based: '_RC' accessor}} + float bad14 = A.m; // expected-error {{invalid matrix member 'm' expected length 4 for zero based: '_mRC' or length 3 for one-based: '_RC' accessor}} + + A._m12 = 3.14; // write is OK + A._m00_m00 = 1.xx; // expected-error {{matrix is not assignable (contains duplicate components)}} +} diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 0a43d73063c1f..ef2dee0c5612c 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -317,6 +317,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::ExprWithCleanupsClass: case Stmt::ExpressionTraitExprClass: case Stmt::ExtVectorElementExprClass: + case Stmt::MatrixElementExprClass: case Stmt::ImplicitCastExprClass: case Stmt::ImplicitValueInitExprClass: case Stmt::NoInitExprClass: From 06ce71fd5b6567b9ae10c328ac5859c4130da181 Mon Sep 17 00:00:00 2001 From: Farzon Lotfi Date: Mon, 8 Dec 2025 17:37:38 -0500 Subject: [PATCH 2/2] - Remove all the Expr Constant AST visitors. - Remove CIR emitter stubs - Run clan format --- clang/include/clang/AST/Expr.h | 17 ++++++----------- clang/lib/AST/ByteCode/Compiler.cpp | 6 ------ clang/lib/AST/ByteCode/Compiler.h | 1 - clang/lib/AST/ExprConstant.cpp | 7 ------- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 2 -- clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 -- .../HLSL/pch_with_matrix_element_accessor.hlsl | 2 +- 7 files changed, 7 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 59f2c7a46dac2..f0d9004a70cb7 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -309,7 +309,7 @@ class Expr : public ValueStmt { MLV_DuplicateVectorComponents, MLV_DuplicateMatrixComponents, MLV_InvalidExpression, - MLV_LValueCast, // Specialized form of MLV_InvalidExpression. + MLV_LValueCast, // Specialized form of MLV_InvalidExpression. MLV_IncompleteType, MLV_ConstQualified, MLV_ConstQualifiedField, @@ -342,17 +342,17 @@ class Expr : public ValueStmt { enum Kinds { CL_LValue, CL_XValue, - CL_Function, // Functions cannot be lvalues in C. - CL_Void, // Void cannot be an lvalue in C. + CL_Function, // Functions cannot be lvalues in C. + CL_Void, // Void cannot be an lvalue in C. CL_AddressableVoid, // Void expression whose address can be taken in C. CL_DuplicateVectorComponents, // A vector shuffle with dupes. CL_DuplicateMatrixComponents, // A matrix shuffle with dupes. CL_MemberFunction, // An expression referring to a member function CL_SubObjCPropertySetting, - CL_ClassTemporary, // A temporary of class type, or subobject thereof. - CL_ArrayTemporary, // A temporary of array type. + CL_ClassTemporary, // A temporary of class type, or subobject thereof. + CL_ArrayTemporary, // A temporary of array type. CL_ObjCMessageRValue, // ObjC message is an rvalue - CL_PRValue // A prvalue for any other reason, of any other type + CL_PRValue // A prvalue for any other reason, of any other type }; /// The results of modification testing. enum ModifiableType { @@ -6524,11 +6524,6 @@ template class ElementAccessExprBase : public Expr { } SourceLocation getEndLoc() const LLVM_READONLY { return AccessorLoc; } - /*static bool classof(const Stmt *T) { - return T->getStmtClass() == ExtVectorElementExprClass || - T->getStmtClass() == MatrixElementExprClass; - }*/ - child_range children() { return child_range(&Base, &Base + 1); } const_child_range children() const { return const_child_range(&Base, &Base + 1); diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 5f988a47040d5..ed5493c315dd7 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -4092,12 +4092,6 @@ bool Compiler::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) { return true; } -template -bool Compiler::VisitMatrixElementExpr(const MatrixElementExpr *Node) { - // TODO - return false; -} - template bool Compiler::VisitExtVectorElementExpr( const ExtVectorElementExpr *E) { diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 8f9a2b16f8596..1bd15c3d79563 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -223,7 +223,6 @@ class Compiler : public ConstStmtVisitor, bool>, bool VisitConvertVectorExpr(const ConvertVectorExpr *E); bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E); bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E); - bool VisitMatrixElementExpr(const MatrixElementExpr *E); bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E); bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E); bool VisitStmtExpr(const StmtExpr *E); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index fafb1d83563d6..5492f80af74c9 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8993,8 +8993,6 @@ class ExprEvaluatorBase DerivedSuccess(Result, E); } - bool VisitMatrixElementExpr(const MatrixElementExpr *E) { return false; } - bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E) { APValue Val; if (!Evaluate(Val, Info, E->getBase())) @@ -9337,7 +9335,6 @@ class LValueExprEvaluator bool VisitCXXUuidofExpr(const CXXUuidofExpr *E); bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E); bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E); - bool VisitMatrixElementExpr(const MatrixElementExpr *E); bool VisitUnaryDeref(const UnaryOperator *E); bool VisitUnaryReal(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E); @@ -9699,10 +9696,6 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { return LValueExprEvaluatorBaseTy::VisitMemberExpr(E); } -bool LValueExprEvaluator::VisitMatrixElementExpr(const MatrixElementExpr *E) { - return false; -} - bool LValueExprEvaluator::VisitExtVectorElementExpr( const ExtVectorElementExpr *E) { bool Success = true; diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index 957c63050cc35..492cbb69fabb3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -946,8 +946,6 @@ LValue CIRGenFunction::emitLValue(const Expr *e) { return emitArraySubscriptExpr(cast(e)); case Expr::ExtVectorElementExprClass: return emitExtVectorElementExpr(cast(e)); - case Expr::MatrixElementExprClass: - return emitMatrixElementExpr(cast(e)); case Expr::UnaryOperatorClass: return emitUnaryOpLValue(cast(e)); case Expr::StringLiteralClass: diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 0ca06aa027a3c..0df812bcfb94e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1333,8 +1333,6 @@ class CIRGenFunction : public CIRGenTypeCache { LValue emitExtVectorElementExpr(const ExtVectorElementExpr *e); - LValue emitMatrixElementExpr(cost MatrixElementExpr *e); - Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo = nullptr); diff --git a/clang/test/AST/HLSL/pch_with_matrix_element_accessor.hlsl b/clang/test/AST/HLSL/pch_with_matrix_element_accessor.hlsl index 605a119e3beac..46f340a4196d8 100644 --- a/clang/test/AST/HLSL/pch_with_matrix_element_accessor.hlsl +++ b/clang/test/AST/HLSL/pch_with_matrix_element_accessor.hlsl @@ -23,4 +23,4 @@ float4 getDiag() { // CHECK-NEXT: DeclRefExpr {{.*}} 'float4':'vector' lvalue ParmVar {{.*}} 'V' 'float4':'vector' void setRowZero(float4 V) { gM._m00_m01_m02_m03 = V; -} \ No newline at end of file +}