[clang] [HLSL] Make memory representation of boolean vectors in HLSL, vectors of i32. Add support for boolean swizzling. (PR #123977)
Sarah Spall via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 22 10:15:40 PST 2025
https://github.com/spall created https://github.com/llvm/llvm-project/pull/123977
Make the memory representation of boolean vectors in HLSL, vectors of i32.
Allow boolean swizzling for boolean vectors in HLSL.
Add tests for boolean vectors and boolean vector swizzling.
Closes #91639
>From 50f8b16bf83d70cc37f2ac7e70c9195a4c4cda02 Mon Sep 17 00:00:00 2001
From: Sarah Spall <spall at planetbauer.com>
Date: Thu, 16 Jan 2025 01:32:25 +0000
Subject: [PATCH 1/7] wip
---
clang/lib/CodeGen/CGExpr.cpp | 19 +++++++++++++++++++
clang/lib/CodeGen/CodeGenTypes.cpp | 6 ++++++
2 files changed, 25 insertions(+)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 054f8d1eadb8c5..be8effb4dd40e7 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1986,6 +1986,10 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
if (const auto *ClangVecTy = Ty->getAs<VectorType>()) {
// Boolean vectors use `iN` as storage type.
if (ClangVecTy->isExtVectorBoolType()) {
+ if (getLangOpts().HLSL) {
+ llvm::Value *Value = Builder.CreateLoad(Addr, Volatile, "load_boolvec");
+ return EmitFromMemory(Value, Ty);
+ }
llvm::Type *ValTy = ConvertType(Ty);
unsigned ValNumElems =
cast<llvm::FixedVectorType>(ValTy)->getNumElements();
@@ -2064,6 +2068,9 @@ llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
if (Ty->isExtVectorBoolType()) {
llvm::Type *StoreTy = convertTypeForLoadStore(Ty, Value->getType());
+ if (getLangOpts().HLSL)
+ return Builder.CreateZExt(Value, StoreTy);
+
// Expand to the memory bit width.
unsigned MemNumElems = StoreTy->getPrimitiveSizeInBits();
// <N x i1> --> <P x i1>.
@@ -2081,6 +2088,9 @@ llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
if (Ty->isExtVectorBoolType()) {
const auto *RawIntTy = Value->getType();
+ if (getLangOpts().HLSL)
+ return Builder.CreateTrunc(Value, ConvertType(Ty), "loadedv");
+
// Bitcast iP --> <P x i1>.
auto *PaddedVecTy = llvm::FixedVectorType::get(
Builder.getInt1Ty(), RawIntTy->getPrimitiveSizeInBits());
@@ -2407,6 +2417,11 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
// Read/modify/write the vector, inserting the new element.
llvm::Value *Vec = Builder.CreateLoad(Dst.getVectorAddress(),
Dst.isVolatileQualified());
+ llvm::Type *OldVecTy = Vec->getType();
+ if (getLangOpts().HLSL && Dst.getType()->isExtVectorBoolType())
+
+ Vec = Builder.CreateTrunc(Vec, ConvertType(Dst.getType()), "truncboolv");
+
auto *IRStoreTy = dyn_cast<llvm::IntegerType>(Vec->getType());
if (IRStoreTy) {
auto *IRVecTy = llvm::FixedVectorType::get(
@@ -2420,6 +2435,10 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
// <N x i1> --> <iN>.
Vec = Builder.CreateBitCast(Vec, IRStoreTy);
}
+
+ if (getLangOpts().HLSL && Dst.getType()->isExtVectorBoolType())
+ Vec = Builder.CreateZExt(Vec, OldVecTy);
+
Builder.CreateStore(Vec, Dst.getVectorAddress(),
Dst.isVolatileQualified());
return;
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index 09191a4901f493..e7f280e3823a3f 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -112,6 +112,12 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) {
// Check for the boolean vector case.
if (T->isExtVectorBoolType()) {
auto *FixedVT = cast<llvm::FixedVectorType>(R);
+
+ if (Context.getLangOpts().HLSL) {
+ llvm::Type *IRElemTy = ConvertTypeForMem(Context.BoolTy);
+ return llvm::FixedVectorType::get(IRElemTy, FixedVT->getNumElements());
+ }
+
// Pad to at least one byte.
uint64_t BytePadded = std::max<uint64_t>(FixedVT->getNumElements(), 8);
return llvm::IntegerType::get(FixedVT->getContext(), BytePadded);
>From b231f4e47ed263bf798455d8d303383caf1be635 Mon Sep 17 00:00:00 2001
From: Sarah Spall <spall at planetbauer.com>
Date: Thu, 16 Jan 2025 19:30:58 +0000
Subject: [PATCH 2/7] bool vector swizzle is allowed in hlsl
---
clang/lib/Sema/SemaExprMember.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp
index d130e8b86bc56d..dcf7feab752b5e 100644
--- a/clang/lib/Sema/SemaExprMember.cpp
+++ b/clang/lib/Sema/SemaExprMember.cpp
@@ -1697,7 +1697,7 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
QualType(), false);
}
- if (BaseType->isExtVectorBoolType()) {
+ if (BaseType->isExtVectorBoolType() && !S.Context.getLangOpts().HLSL) {
// We disallow element access for ext_vector_type bool. There is no way to
// materialize a reference to a vector element as a pointer (each element is
// one bit in the vector).
>From dd7e4595f47fb02fab4450e69a5ab07fd21f67d3 Mon Sep 17 00:00:00 2001
From: Sarah Spall <spall at planetbauer.com>
Date: Tue, 21 Jan 2025 16:50:33 +0000
Subject: [PATCH 3/7] swizzle tests for boolean vectors
---
.../CodeGenHLSL/builtins/ScalarSwizzles.hlsl | 79 ++++++++++++++++++-
1 file changed, 77 insertions(+), 2 deletions(-)
diff --git a/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl b/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl
index 97711c9ee25a10..8e246959df94fe 100644
--- a/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl
@@ -11,13 +11,23 @@ int2 ToTwoInts(int V){
}
// CHECK-LABEL: ToFourFloats
-// [[splat:%.*]] = insertelement <1 x float> poison, float {{.*}}, i64 0
-// [[vec4:%.*]] = shufflevector <1 x float> [[splat]], <1 x float> poison, <4 x i32> zeroinitializer
+// CHECK: [[splat:%.*]] = insertelement <1 x float> poison, float {{.*}}, i64 0
+// CHECK: [[vec4:%.*]] = shufflevector <1 x float> [[splat]], <1 x float> poison, <4 x i32> zeroinitializer
// ret <4 x float> [[vec4]]
float4 ToFourFloats(float V){
return V.rrrr;
}
+// CHECK-LABEL: ToFourBools
+// CHECK: {{%.*}} = zext i1 {{.*}} to i32
+// CHECK: [[splat:%.*]] = insertelement <1 x i32> poison, i32 {{.*}}, i64 0
+// CHECK-NEXT: [[vec4:%.*]] = shufflevector <1 x i32> [[splat]], <1 x i32> poison, <4 x i32> zeroinitializer
+// CHECK-NEXT: [[vec2Ret:%.*]] = trunc <4 x i32> [[vec4]] to <4 x i1>
+// CHECK-NEXT: ret <4 x i1> [[vec2Ret]]
+bool4 ToFourBools(bool V) {
+ return V.rrrr;
+}
+
// CHECK-LABEL: FillOne
// CHECK: [[vec1Ptr:%.*]] = alloca <1 x i32>, align 4
// CHECK: store <1 x i32> splat (i32 1), ptr [[vec1Ptr]], align 4
@@ -93,6 +103,17 @@ vector<float, 1> FillOneHalfFloat(){
return .5f.r;
}
+// CHECK-LABEL: FillTrue
+// CHECK: [[Tmp:%.*]] = alloca <1 x i32>, align 1
+// CHECK-NEXT: store <1 x i1> splat (i1 true), ptr [[Tmp]], align 1
+// CHECK-NEXT: [[Vec1:%.*]] = load <1 x i32>, ptr [[Tmp]], align 1
+// CHECK-NEXT: [[Vec2:%.*]] = shufflevector <1 x i32> [[Vec1]], <1 x i32> poison, <2 x i32> zeroinitializer
+// CHECK-NEXT: [[Vec2Ret:%.*]] = trunc <2 x i32> [[Vec2]] to <2 x i1>
+// CHECK-NEXT: ret <2 x i1> [[Vec2Ret]]
+bool2 FillTrue() {
+ return true.xx;
+}
+
// The initial codegen for this case is correct but a bit odd. The IR optimizer
// cleans this up very nicely.
@@ -110,6 +131,24 @@ float2 HowManyFloats(float V) {
return V.rr.rr;
}
+// CHECK-LABEL: HowManyBools
+// CHECK: [[VAddr:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[Vec2Ptr:%.*]] = alloca <2 x i32>, align 1
+// CHECK-NEXT: [[Tmp:%.*]] = zext i1 {{.*}} to i32
+// CHECK-NEXT: store i32 [[Tmp]], ptr [[VAddr]], align 4
+// CHECK-NEXT: [[VVal:%.*]] = load i32, ptr [[VAddr]], align 4
+// CHECK-NEXT: [[Splat:%.*]] = insertelement <1 x i32> poison, i32 [[VVal]], i64 0
+// CHECK-NEXT: [[Vec2:%.*]] = shufflevector <1 x i32> [[Splat]], <1 x i32> poison, <2 x i32> zeroinitializer
+// CHECK-NEXT: [[Trunc:%.*]] = trunc <2 x i32> [[Vec2]] to <2 x i1>
+// CHECK-NEXT: store <2 x i1> [[Trunc]], ptr [[Vec2Ptr]], align 1
+// CHECK-NEXT: [[V2:%.*]] = load <2 x i32>, ptr [[Vec2Ptr]], align 1
+// CHECK-NEXT: [[V3:%.*]] = shufflevector <2 x i32> [[V2]], <2 x i32> poison, <2 x i32> zeroinitializer
+// CHECK-NEXT: [[LV1:%.*]] = trunc <2 x i32> [[V3]] to <2 x i1>
+// CHECK-NEXT: ret <2 x i1> [[LV1]]
+bool2 HowManyBools(bool V) {
+ return V.rr.rr;
+}
+
// This codegen is gnarly because `1.l` is a double, so this creates double
// vectors that need to be truncated down to floats. The optimizer cleans this
// up nicely too.
@@ -166,3 +205,39 @@ int AssignInt(int V){
X.x = V.x + V.x;
return X;
}
+
+// CHECK-LABEL: AssignBool
+// CHECK: [[VAddr:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[XAddr:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[Zext:%.*]] = zext i1 %V to i32
+// CHECK-NEXT: store i32 [[Zext]], ptr [[VAddr]], align 4
+// CHECK-NEXT: [[X:%.*]] = load i32, ptr [[VAddr]], align 4
+// CHECK-NEXT: [[Splat:%.*]] = insertelement <1 x i32> poison, i32 [[X]], i64 0
+// CHECK-NEXT: [[Y:%.*]] = extractelement <1 x i32> [[Splat]], i32 0
+// CHECK-NEXT: [[Z:%.*]] = trunc i32 [[Y]] to i1
+// CHECK-NEXT: [[A:%.*]] = zext i1 [[Z]] to i32
+// CHECK-NEXT: store i32 [[A]], ptr [[XAddr]], align 4
+// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[VAddr]], align 4
+// CHECK-NEXT: [[Splat2:%.*]] = insertelement <1 x i32> poison, i32 [[B]], i64 0
+// CHECK-NEXT: [[C:%.*]] = extractelement <1 x i32> [[Splat2]], i32 0
+// CHECK-NEXT: [[D:%.*]] = trunc i32 [[C]] to i1
+// CHECK-NEXT: br i1 [[D]], label %lor.end, label %lor.rhs
+
+// CHECK: lor.rhs:
+// CHECK-NEXT: [[E:%.*]] = load i32, ptr [[VAddr]], align 4
+// CHECK-NEXT: [[Splat3:%.*]] = insertelement <1 x i32> poison, i32 [[E]], i64 0
+// CHECK-NEXT: [[F:%.*]] = extractelement <1 x i32> [[Splat3]], i32 0
+// CHECK-NEXT: [[G:%.*]] = trunc i32 [[F]] to i1
+// CHECK-NEXT: br label %lor.end
+
+// CHECK: lor.end:
+// CHECK-NEXT: [[H:%.*]] = phi i1 [ true, %entry ], [ [[G]], %lor.rhs ]
+// CHECK-NEXT: store i1 [[H]], ptr [[XAddr]], align 4
+// CHECK-NEXT: [[I:%.*]] = load i32, ptr [[XAddr]], align 4
+// CHECK-NEXT: [[LoadV:%.*]] = trunc i32 [[I]] to i1
+// CHECK-NEXT: ret i1 [[LoadV]]
+bool AssignBool(bool V) {
+ bool X = V.x;
+ X.x = V.x || V.x;
+ return X;
+}
>From 6734eedc466fc6202f7eb84484864d63dd0bb39d Mon Sep 17 00:00:00 2001
From: Sarah Spall <spall at planetbauer.com>
Date: Tue, 21 Jan 2025 16:53:10 +0000
Subject: [PATCH 4/7] vector swizzle boolean vectors
---
clang/lib/CodeGen/CGExpr.cpp | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index be8effb4dd40e7..331da27764df12 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2353,7 +2353,13 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) {
if (!ExprVT) {
unsigned InIdx = getAccessedFieldNo(0, Elts);
llvm::Value *Elt = llvm::ConstantInt::get(SizeTy, InIdx);
- return RValue::get(Builder.CreateExtractElement(Vec, Elt));
+
+ llvm::Value *Element = Builder.CreateExtractElement(Vec, Elt);
+
+ if (getLangOpts().HLSL && LV.getType()->isBooleanType())
+ Element = Builder.CreateTrunc(Element, ConvertType(LV.getType()));
+
+ return RValue::get(Element);
}
// Always use shuffle vector to try to retain the original program structure
@@ -2364,6 +2370,10 @@ RValue CodeGenFunction::EmitLoadOfExtVectorElementLValue(LValue LV) {
Mask.push_back(getAccessedFieldNo(i, Elts));
Vec = Builder.CreateShuffleVector(Vec, Mask);
+
+ if (getLangOpts().HLSL && LV.getType()->isExtVectorBoolType())
+ Vec = EmitFromMemory(Vec, LV.getType());
+
return RValue::get(Vec);
}
>From d9a4777cc755bdd9950e50f3f2bcf0a6f844a4a1 Mon Sep 17 00:00:00 2001
From: Sarah Spall <spall at planetbauer.com>
Date: Tue, 21 Jan 2025 18:17:07 +0000
Subject: [PATCH 5/7] fix test broken by changes
---
.../standard_conversion_sequences.hlsl | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hlsl
index 1665a0260ab054..6770efefe94feb 100644
--- a/clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hlsl
+++ b/clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hlsl
@@ -91,13 +91,12 @@ void l4_to_i2() {
// CHECK-LABEL: i2_to_b2
// CHECK: [[l2:%.*]] = alloca <2 x i32>
-// CHECK: [[b2:%.*]] = alloca i8
+// CHECK: [[b2:%.*]] = alloca <2 x i32>
// CHECK: store <2 x i32> splat (i32 8), ptr [[i2]]
// CHECK: [[veci2:%.*]] = load <2 x i32>, ptr [[i2]]
// CHECK: [[vecb2:%.*]] = icmp ne <2 x i32> [[veci2]], zeroinitializer
-// CHECK: [[vecb8:%.*]] = shufflevector <2 x i1> [[vecb2]], <2 x i1> poison, <8 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-// CHECK: [[i8:%.*]] = bitcast <8 x i1> [[vecb8]] to i8
-// CHECK: store i8 [[i8]], ptr [[b2]]
+// CHECK: [[vecb8:%.*]] = zext <2 x i1> [[vecb2]] to <2 x i32>
+// CHECK: store <2 x i32> [[vecb8]], ptr [[b2]]
void i2_to_b2() {
vector<int, 2> i2 = 8;
vector<bool, 2> b2 = i2;
@@ -105,14 +104,13 @@ void i2_to_b2() {
// CHECK-LABEL: d4_to_b2
// CHECK: [[d4:%.*]] = alloca <4 x double>
-// CHECK: [[b2:%.*]] = alloca i8
+// CHECK: [[b2:%.*]] = alloca <2 x i32>
// CHECK: store <4 x double> splat (double 9.000000e+00), ptr [[d4]]
// CHECK: [[vecd4:%.*]] = load <4 x double>, ptr [[d4]]
// CHECK: [[vecb4:%.*]] = fcmp reassoc nnan ninf nsz arcp afn une <4 x double> [[vecd4]], zeroinitializer
// CHECK: [[vecd2:%.*]] = shufflevector <4 x i1> [[vecb4]], <4 x i1> poison, <2 x i32> <i32 0, i32 1>
-// CHECK: [[vecb8:%.*]] = shufflevector <2 x i1> [[vecd2]], <2 x i1> poison, <8 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
-// CHECK: [[i8:%.*]] = bitcast <8 x i1> [[vecb8]] to i8
-// CHECK: store i8 [[i8]], ptr [[b2]]
+// CHECK: [[vecb8:%.*]] = zext <2 x i1> [[vecd2]] to <2 x i32>
+// CHECK: store <2 x i32> [[vecb8]], ptr [[b2]]
void d4_to_b2() {
vector<double,4> d4 = 9.0;
vector<bool, 2> b2 = d4;
>From e0638d10baadcf7793ed307a73e36f9159877c21 Mon Sep 17 00:00:00 2001
From: Sarah Spall <spall at planetbauer.com>
Date: Tue, 21 Jan 2025 18:18:59 +0000
Subject: [PATCH 6/7] actually make clang format happy
---
clang/lib/CodeGen/CGExpr.cpp | 17 +++++++++--------
clang/lib/CodeGen/CodeGenTypes.cpp | 4 ++--
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 331da27764df12..906876f1d878bd 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -1987,8 +1987,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
// Boolean vectors use `iN` as storage type.
if (ClangVecTy->isExtVectorBoolType()) {
if (getLangOpts().HLSL) {
- llvm::Value *Value = Builder.CreateLoad(Addr, Volatile, "load_boolvec");
- return EmitFromMemory(Value, Ty);
+ llvm::Value *Value = Builder.CreateLoad(Addr, Volatile, "load_boolvec");
+ return EmitFromMemory(Value, Ty);
}
llvm::Type *ValTy = ConvertType(Ty);
unsigned ValNumElems =
@@ -2090,7 +2090,7 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
const auto *RawIntTy = Value->getType();
if (getLangOpts().HLSL)
return Builder.CreateTrunc(Value, ConvertType(Ty), "loadedv");
-
+
// Bitcast iP --> <P x i1>.
auto *PaddedVecTy = llvm::FixedVectorType::get(
Builder.getInt1Ty(), RawIntTy->getPrimitiveSizeInBits());
@@ -2429,9 +2429,10 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
Dst.isVolatileQualified());
llvm::Type *OldVecTy = Vec->getType();
if (getLangOpts().HLSL && Dst.getType()->isExtVectorBoolType())
-
- Vec = Builder.CreateTrunc(Vec, ConvertType(Dst.getType()), "truncboolv");
-
+
+ Vec =
+ Builder.CreateTrunc(Vec, ConvertType(Dst.getType()), "truncboolv");
+
auto *IRStoreTy = dyn_cast<llvm::IntegerType>(Vec->getType());
if (IRStoreTy) {
auto *IRVecTy = llvm::FixedVectorType::get(
@@ -2447,8 +2448,8 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
}
if (getLangOpts().HLSL && Dst.getType()->isExtVectorBoolType())
- Vec = Builder.CreateZExt(Vec, OldVecTy);
-
+ Vec = Builder.CreateZExt(Vec, OldVecTy);
+
Builder.CreateStore(Vec, Dst.getVectorAddress(),
Dst.isVolatileQualified());
return;
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index e7f280e3823a3f..778161c6a5818e 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -112,12 +112,12 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) {
// Check for the boolean vector case.
if (T->isExtVectorBoolType()) {
auto *FixedVT = cast<llvm::FixedVectorType>(R);
-
+
if (Context.getLangOpts().HLSL) {
llvm::Type *IRElemTy = ConvertTypeForMem(Context.BoolTy);
return llvm::FixedVectorType::get(IRElemTy, FixedVT->getNumElements());
}
-
+
// Pad to at least one byte.
uint64_t BytePadded = std::max<uint64_t>(FixedVT->getNumElements(), 8);
return llvm::IntegerType::get(FixedVT->getContext(), BytePadded);
>From 2e534a50c7059080b295a31d6cd8b4ac8072a688 Mon Sep 17 00:00:00 2001
From: Sarah Spall <spall at planetbauer.com>
Date: Wed, 22 Jan 2025 18:05:17 +0000
Subject: [PATCH 7/7] new test
---
clang/test/CodeGenHLSL/BoolVector.hlsl | 32 ++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 clang/test/CodeGenHLSL/BoolVector.hlsl
diff --git a/clang/test/CodeGenHLSL/BoolVector.hlsl b/clang/test/CodeGenHLSL/BoolVector.hlsl
new file mode 100644
index 00000000000000..16aa6c0e56cee4
--- /dev/null
+++ b/clang/test/CodeGenHLSL/BoolVector.hlsl
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+
+// CHECK-LABEL: fn
+// CHECK: [[B:%.*]] = alloca <2 x i32>, align 1
+// CHECK-NEXT: store <2 x i32> splat (i32 1), ptr [[B]], align 1
+// CHECK-NEXT: [[BoolVec:%.*]] = load <2 x i32>, ptr [[B]], align 1
+// CHECK-NEXT: [[L:%.*]] = trunc <2 x i32> [[BoolVec:%.*]] to <2 x i1>
+// CHECK-NEXT: [[VecExt:%.*]] = extractelement <2 x i1> [[L]], i32 0
+// CHECK-NEXT: ret i1 [[VecExt]]
+bool fn() {
+ bool2 B = {true,true};
+ return B[0];
+}
+
+// CHECK-LABEL: fn2
+// CHECK: [[VAddr:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[A:%.*]] = alloca <2 x i32>, align 1
+// CHECK-NEXT: [[StoreV:%.*]] = zext i1 {{.*}} to i32
+// CHECK-NEXT: store i32 [[StoreV]], ptr [[VAddr]], align 4
+// CHECK-NEXT: [[L:%.*]] = load i32, ptr [[VAddr]], align 4
+// CHECK-NEXT: [[LoadV:%.*]] = trunc i32 [[L]] to i1
+// CHECK-NEXT: [[Vec:%.*]] = insertelement <2 x i1> poison, i1 [[LoadV]], i32 0
+// CHECK-NEXT: [[Vec1:%.*]] = insertelement <2 x i1> [[Vec]], i1 true, i32 1
+// CHECK-NEXT: [[Z:%.*]] = zext <2 x i1> [[Vec1]] to <2 x i32>
+// CHECK-NEXT: store <2 x i32> [[Z]], ptr [[A]], align 1
+// CHECK-NEXT: [[LoadBV:%.*]] = load <2 x i32>, ptr [[A]], align 1
+// CHECK-NEXT: [[LoadV2:%.*]] = trunc <2 x i32> [[LoadBV]] to <2 x i1>
+// CHECK-NEXT: ret <2 x i1> [[LoadV2]]
+bool2 fn2(bool V) {
+ bool2 A = {V,true};
+ return A;
+}
More information about the cfe-commits
mailing list