https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/175809
>From ed8c130a8f975f293eb1299e73cb9a2edce2204e Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Tue, 13 Jan 2026 09:55:35 -0800 Subject: [PATCH 1/6] If already the correct type, do not mutate the Value of bool vec/matrix --- clang/lib/CodeGen/CGExpr.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index a8e53e77b2e8c..30308b5b109a6 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2218,6 +2218,10 @@ llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) { if (Ty->isExtVectorBoolType() || Ty->isConstantMatrixBoolType()) { llvm::Type *StoreTy = convertTypeForLoadStore(Ty, Value->getType()); + + if (Value->getType() == StoreTy) + return Value; + if (StoreTy->isVectorTy() && StoreTy->getScalarSizeInBits() > Value->getType()->getScalarSizeInBits()) return Builder.CreateZExt(Value, StoreTy); >From a7f7f9d323111239d0c7cf867b980df638540160 Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Tue, 13 Jan 2026 10:20:38 -0800 Subject: [PATCH 2/6] Add boolean matrix splat tests --- .../BasicFeatures/MatrixSplat.hlsl | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/clang/test/CodeGenHLSL/BasicFeatures/MatrixSplat.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSplat.hlsl index 802c418f1dad5..618bdbdfe4102 100644 --- a/clang/test/CodeGenHLSL/BasicFeatures/MatrixSplat.hlsl +++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSplat.hlsl @@ -23,6 +23,17 @@ void ConstantFloatSplat() { float2x2 M = 3.25; } +// CHECK-LABEL: define hidden void @_Z17ConstantBoolSplatv( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[M:%.*]] = alloca [9 x i32], align 4 +// CHECK-NEXT: store <9 x i32> splat (i32 1), ptr [[M]], align 4 +// CHECK-NEXT: ret void +// +void ConstantBoolSplat() { + bool3x3 M = true; +} + // CHECK-LABEL: define hidden void @_Z12DynamicSplatf( // CHECK-SAME: float noundef nofpclass(nan inf) [[VALUE:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] @@ -39,6 +50,25 @@ void DynamicSplat(float Value) { float3x3 M = Value; } +// CHECK-LABEL: define hidden void @_Z16DynamicBoolSplatb( +// CHECK-SAME: i1 noundef [[VALUE:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[VALUE_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[M:%.*]] = alloca [16 x i32], align 4 +// CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[VALUE]] to i32 +// CHECK-NEXT: store i32 [[STOREDV]], ptr [[VALUE_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[VALUE_ADDR]], align 4 +// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i32 [[TMP0]] to i1 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <16 x i1> poison, i1 [[LOADEDV]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <16 x i1> [[SPLAT_SPLATINSERT]], <16 x i1> poison, <16 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = zext <16 x i1> [[SPLAT_SPLAT]] to <16 x i32> +// CHECK-NEXT: store <16 x i32> [[TMP1]], ptr [[M]], align 4 +// CHECK-NEXT: ret void +// +void DynamicBoolSplat(bool Value) { + bool4x4 M = Value; +} + // CHECK-LABEL: define hidden void @_Z13CastThenSplatDv4_f( // CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[VALUE:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] @@ -55,3 +85,22 @@ void DynamicSplat(float Value) { void CastThenSplat(float4 Value) { float3x3 M = (float) Value; } + +// CHECK-LABEL: define hidden void @_Z17BoolCastThenSplatDv3_i( +// CHECK-SAME: <3 x i32> noundef [[VALUE:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[VALUE_ADDR:%.*]] = alloca <3 x i32>, align 16 +// CHECK-NEXT: [[M:%.*]] = alloca [4 x i32], align 4 +// CHECK-NEXT: store <3 x i32> [[VALUE]], ptr [[VALUE_ADDR]], align 16 +// CHECK-NEXT: [[TMP0:%.*]] = load <3 x i32>, ptr [[VALUE_ADDR]], align 16 +// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne <3 x i32> [[TMP0]], zeroinitializer +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <3 x i1> [[TOBOOL]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <4 x i1> poison, i1 [[CAST_VTRUNC]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <4 x i1> [[SPLAT_SPLATINSERT]], <4 x i1> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = zext <4 x i1> [[SPLAT_SPLAT]] to <4 x i32> +// CHECK-NEXT: store <4 x i32> [[TMP1]], ptr [[M]], align 4 +// CHECK-NEXT: ret void +// +void BoolCastThenSplat(int3 Value) { + bool2x2 M = (bool) Value; +} >From d0c32af087073671d0a5f774448d0e40399ae339 Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Tue, 13 Jan 2026 10:23:27 -0800 Subject: [PATCH 3/6] Add boolean splat case to prepareMatrixSplat This commit re-adds Farzon's changes to support boolean splats in prepareMatrixSplat. https://github.com/llvm/llvm-project/pull/170885/changes/e80fe5c7cb993aa6e380abec94302477d56ac03a Co-authored-by: Farzon Lotfi <[email protected]> --- clang/lib/Sema/SemaExpr.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4d787a60eba3b..5e849ee69379d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7899,14 +7899,26 @@ ExprResult Sema::prepareMatrixSplat(QualType MatrixTy, Expr *SplattedExpr) { assert(DestElemTy->isFloatingType() || DestElemTy->isIntegralOrEnumerationType()); - // TODO: Add support for boolean matrix once exposed - // https://github.com/llvm/llvm-project/issues/170920 - ExprResult CastExprRes = SplattedExpr; - CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy); - if (CastExprRes.isInvalid()) - return ExprError(); - SplattedExpr = CastExprRes.get(); - + CastKind CK; + if (SplattedExpr->getType()->isBooleanType()) { + // As with vectors, we want `true` to become -1 when splatting, and we + // need a two-step cast if the destination element type is floating. + if (DestElemTy->isFloatingType()) { + // Cast boolean to signed integral, then to floating. + ExprResult CastExprRes = ImpCastExprToType(SplattedExpr, Context.IntTy, + CK_BooleanToSignedIntegral); + SplattedExpr = CastExprRes.get(); + CK = CK_IntegralToFloating; + } else { + CK = CK_BooleanToSignedIntegral; + } + } else { + ExprResult CastExprRes = SplattedExpr; + CK = PrepareScalarCast(CastExprRes, DestElemTy); + if (CastExprRes.isInvalid()) + return ExprError(); + SplattedExpr = CastExprRes.get(); + } return ImpCastExprToType(SplattedExpr, DestElemTy, CK); } >From 2bfb6623eed97827d2ad637d92ba3c92c9fe5497 Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Tue, 13 Jan 2026 11:09:10 -0800 Subject: [PATCH 4/6] Revert "Add boolean splat case to prepareMatrixSplat" This reverts commit d0c32af087073671d0a5f774448d0e40399ae339. --- clang/lib/Sema/SemaExpr.cpp | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5e849ee69379d..4d787a60eba3b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7899,26 +7899,14 @@ ExprResult Sema::prepareMatrixSplat(QualType MatrixTy, Expr *SplattedExpr) { assert(DestElemTy->isFloatingType() || DestElemTy->isIntegralOrEnumerationType()); - CastKind CK; - if (SplattedExpr->getType()->isBooleanType()) { - // As with vectors, we want `true` to become -1 when splatting, and we - // need a two-step cast if the destination element type is floating. - if (DestElemTy->isFloatingType()) { - // Cast boolean to signed integral, then to floating. - ExprResult CastExprRes = ImpCastExprToType(SplattedExpr, Context.IntTy, - CK_BooleanToSignedIntegral); - SplattedExpr = CastExprRes.get(); - CK = CK_IntegralToFloating; - } else { - CK = CK_BooleanToSignedIntegral; - } - } else { - ExprResult CastExprRes = SplattedExpr; - CK = PrepareScalarCast(CastExprRes, DestElemTy); - if (CastExprRes.isInvalid()) - return ExprError(); - SplattedExpr = CastExprRes.get(); - } + // TODO: Add support for boolean matrix once exposed + // https://github.com/llvm/llvm-project/issues/170920 + ExprResult CastExprRes = SplattedExpr; + CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy); + if (CastExprRes.isInvalid()) + return ExprError(); + SplattedExpr = CastExprRes.get(); + return ImpCastExprToType(SplattedExpr, DestElemTy, CK); } >From ac51a0c11f52e73d9e185d0bf45356c38518d90a Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Tue, 13 Jan 2026 11:10:10 -0800 Subject: [PATCH 5/6] Remove TODO comment that is not needed for boolean matrix splats --- clang/lib/Sema/SemaExpr.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4d787a60eba3b..51739c3b49ac9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7899,8 +7899,6 @@ ExprResult Sema::prepareMatrixSplat(QualType MatrixTy, Expr *SplattedExpr) { assert(DestElemTy->isFloatingType() || DestElemTy->isIntegralOrEnumerationType()); - // TODO: Add support for boolean matrix once exposed - // https://github.com/llvm/llvm-project/issues/170920 ExprResult CastExprRes = SplattedExpr; CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy); if (CastExprRes.isInvalid()) >From b12f6d3bd445628963c57d3930f013e3ebde6c11 Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Tue, 13 Jan 2026 11:58:25 -0800 Subject: [PATCH 6/6] Add more tests for boolean-related matrix splats --- .../BasicFeatures/MatrixSplat.hlsl | 57 +++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/clang/test/CodeGenHLSL/BasicFeatures/MatrixSplat.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSplat.hlsl index 618bdbdfe4102..9b9538e0afdd1 100644 --- a/clang/test/CodeGenHLSL/BasicFeatures/MatrixSplat.hlsl +++ b/clang/test/CodeGenHLSL/BasicFeatures/MatrixSplat.hlsl @@ -23,17 +23,28 @@ void ConstantFloatSplat() { float2x2 M = 3.25; } -// CHECK-LABEL: define hidden void @_Z17ConstantBoolSplatv( +// CHECK-LABEL: define hidden void @_Z21ConstantTrueBoolSplatv( // CHECK-SAME: ) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[M:%.*]] = alloca [9 x i32], align 4 // CHECK-NEXT: store <9 x i32> splat (i32 1), ptr [[M]], align 4 // CHECK-NEXT: ret void // -void ConstantBoolSplat() { +void ConstantTrueBoolSplat() { bool3x3 M = true; } +// CHECK-LABEL: define hidden void @_Z22ConstantFalseBoolSplatv( +// CHECK-SAME: ) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[M:%.*]] = alloca [9 x i32], align 4 +// CHECK-NEXT: store <9 x i32> zeroinitializer, ptr [[M]], align 4 +// CHECK-NEXT: ret void +// +void ConstantFalseBoolSplat() { + bool3x3 M = false; +} + // CHECK-LABEL: define hidden void @_Z12DynamicSplatf( // CHECK-SAME: float noundef nofpclass(nan inf) [[VALUE:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] @@ -86,7 +97,7 @@ void CastThenSplat(float4 Value) { float3x3 M = (float) Value; } -// CHECK-LABEL: define hidden void @_Z17BoolCastThenSplatDv3_i( +// CHECK-LABEL: define hidden void @_Z30ExplicitIntToBoolCastThenSplatDv3_i( // CHECK-SAME: <3 x i32> noundef [[VALUE:%.*]]) #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[VALUE_ADDR:%.*]] = alloca <3 x i32>, align 16 @@ -101,6 +112,44 @@ void CastThenSplat(float4 Value) { // CHECK-NEXT: store <4 x i32> [[TMP1]], ptr [[M]], align 4 // CHECK-NEXT: ret void // -void BoolCastThenSplat(int3 Value) { +void ExplicitIntToBoolCastThenSplat(int3 Value) { bool2x2 M = (bool) Value; } + +// CHECK-LABEL: define hidden void @_Z32ExplicitFloatToBoolCastThenSplatDv2_f( +// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[VALUE:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[VALUE_ADDR:%.*]] = alloca <2 x float>, align 8 +// CHECK-NEXT: [[M:%.*]] = alloca [6 x i32], align 4 +// CHECK-NEXT: store <2 x float> [[VALUE]], ptr [[VALUE_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load <2 x float>, ptr [[VALUE_ADDR]], align 8 +// CHECK-NEXT: [[TOBOOL:%.*]] = fcmp reassoc nnan ninf nsz arcp afn une <2 x float> [[TMP0]], zeroinitializer +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <2 x i1> [[TOBOOL]], i32 0 +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <6 x i1> poison, i1 [[CAST_VTRUNC]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <6 x i1> [[SPLAT_SPLATINSERT]], <6 x i1> poison, <6 x i32> zeroinitializer +// CHECK-NEXT: [[TMP1:%.*]] = zext <6 x i1> [[SPLAT_SPLAT]] to <6 x i32> +// CHECK-NEXT: store <6 x i32> [[TMP1]], ptr [[M]], align 4 +// CHECK-NEXT: ret void +// +void ExplicitFloatToBoolCastThenSplat(float2 Value) { + bool2x3 M = (bool) Value; +} + +// CHECK-LABEL: define hidden void @_Z32ExplicitBoolToFloatCastThenSplatb( +// CHECK-SAME: i1 noundef [[VALUE:%.*]]) #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[VALUE_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[M:%.*]] = alloca [6 x float], align 4 +// CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[VALUE]] to i32 +// CHECK-NEXT: store i32 [[STOREDV]], ptr [[VALUE_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[VALUE_ADDR]], align 4 +// CHECK-NEXT: [[LOADEDV:%.*]] = trunc i32 [[TMP0]] to i1 +// CHECK-NEXT: [[CONV:%.*]] = uitofp i1 [[LOADEDV]] to float +// CHECK-NEXT: [[SPLAT_SPLATINSERT:%.*]] = insertelement <6 x float> poison, float [[CONV]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT:%.*]] = shufflevector <6 x float> [[SPLAT_SPLATINSERT]], <6 x float> poison, <6 x i32> zeroinitializer +// CHECK-NEXT: store <6 x float> [[SPLAT_SPLAT]], ptr [[M]], align 4 +// CHECK-NEXT: ret void +// +void ExplicitBoolToFloatCastThenSplat(bool Value) { + float3x2 M = (float) Value; +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
