[clang] [HLSL] Use icmp ne instead of trunc on boolean load (PR #221105)
Dan Brown via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 13 22:12:33 PDT 2026
https://github.com/danbrown-amd updated https://github.com/llvm/llvm-project/pull/221105
>From fd03dab0bfc9b9c3acbe02f83850bfa70284c08a Mon Sep 17 00:00:00 2001
From: danbrown-amd <danbrown at amd.com>
Date: Thu, 3 Sep 2026 18:46:23 -0600
Subject: [PATCH 1/3] Use icmp-ne instead of truncation on boolean load
Fixes #140824
Assisted-by: Claude Sonnet 4
---
clang/lib/CodeGen/CGExpr.cpp | 5 +++--
clang/lib/Frontend/CompilerInvocation.cpp | 6 ++++++
clang/test/CodeGenHLSL/strict-bool.hlsl | 2 +-
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 019159dd620fd..f5d053e6b6713 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5681,9 +5681,10 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
Address VecMem = CreateMemTemp(E->getBase()->getType());
// need to zero extend an hlsl boolean vector to store it back to memory
QualType Ty = E->getBase()->getType();
- llvm::Type *LTy = convertTypeForLoadStore(Ty, Vec->getType());
- if (LTy->getScalarSizeInBits() > Vec->getType()->getScalarSizeInBits())
+ if (getLangOpts().HLSL && Ty->isExtVectorBoolType()) {
+ llvm::Type *LTy = convertTypeForLoadStore(Ty, Vec->getType());
Vec = Builder.CreateZExt(Vec, LTy);
+ }
Builder.CreateStore(Vec, VecMem);
Base = MakeAddrLValue(VecMem, Ty, AlignmentSource::Decl);
}
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index c9281c2a6d6b4..0a3a235fbac33 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -657,6 +657,12 @@ static bool FixupInvocation(CompilerInvocation &Invocation,
Warnings.insert(Warnings.begin(), "vector-conversion");
if (!llvm::is_contained(Warnings, "matrix-conversion"))
Warnings.insert(Warnings.begin(), "matrix-conversion");
+
+ // HLSL booleans in memory are i32; any non-zero value is true.
+ // Use icmp-ne rather than truncation to avoid InstCombine rewriting
+ // trunc i32 to i1 into an illegal wide <N x i1> bitcast (issue #140824).
+ if (!Args.hasArg(OPT_load_bool_from_mem))
+ CodeGenOpts.setLoadBoolFromMem(CodeGenOptions::BoolFromMem::NonZero);
}
// When these options are used, the compiler is allowed to apply
diff --git a/clang/test/CodeGenHLSL/strict-bool.hlsl b/clang/test/CodeGenHLSL/strict-bool.hlsl
index 31867065e77a3..30bdc02231fa5 100644
--- a/clang/test/CodeGenHLSL/strict-bool.hlsl
+++ b/clang/test/CodeGenHLSL/strict-bool.hlsl
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O1 -load-bool-from-mem=truncate -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK-TRUNCATE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O1 -load-bool-from-mem=nonzero -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK-NONZERO
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O0 -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK-NONZERO
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O1 -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK-NONZERO
typedef bool bool8_t __attribute__((ext_vector_type(8)));
extern bool8_t vec;
>From a54e001a8ec8dc38aaaed2eed75b54af43a15fa8 Mon Sep 17 00:00:00 2001
From: danbrown-amd <danbrown at amd.com>
Date: Thu, 8 Oct 2026 16:30:54 -0600
Subject: [PATCH 2/3] Revert test and one source file as per review comments
---
clang/lib/CodeGen/CGExpr.cpp | 5 ++---
clang/test/CodeGenHLSL/strict-bool.hlsl | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index f5d053e6b6713..019159dd620fd 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5681,10 +5681,9 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
Address VecMem = CreateMemTemp(E->getBase()->getType());
// need to zero extend an hlsl boolean vector to store it back to memory
QualType Ty = E->getBase()->getType();
- if (getLangOpts().HLSL && Ty->isExtVectorBoolType()) {
- llvm::Type *LTy = convertTypeForLoadStore(Ty, Vec->getType());
+ llvm::Type *LTy = convertTypeForLoadStore(Ty, Vec->getType());
+ if (LTy->getScalarSizeInBits() > Vec->getType()->getScalarSizeInBits())
Vec = Builder.CreateZExt(Vec, LTy);
- }
Builder.CreateStore(Vec, VecMem);
Base = MakeAddrLValue(VecMem, Ty, AlignmentSource::Decl);
}
diff --git a/clang/test/CodeGenHLSL/strict-bool.hlsl b/clang/test/CodeGenHLSL/strict-bool.hlsl
index 30bdc02231fa5..31867065e77a3 100644
--- a/clang/test/CodeGenHLSL/strict-bool.hlsl
+++ b/clang/test/CodeGenHLSL/strict-bool.hlsl
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O1 -load-bool-from-mem=truncate -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK-TRUNCATE
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O1 -load-bool-from-mem=nonzero -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK-NONZERO
-// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O1 -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK-NONZERO
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -O0 -emit-llvm -o - %s | FileCheck %s -check-prefixes=CHECK-NONZERO
typedef bool bool8_t __attribute__((ext_vector_type(8)));
extern bool8_t vec;
>From 3591f213ca47a3e79e4f86de7a5d8e561250d358 Mon Sep 17 00:00:00 2001
From: danbrown-amd <danbrown at amd.com>
Date: Tue, 13 Oct 2026 23:10:48 -0600
Subject: [PATCH 3/3] Address additional review comments
---
clang/include/clang/Basic/DiagnosticFrontendKinds.td | 3 +++
clang/lib/Driver/ToolChains/HLSL.cpp | 1 +
clang/lib/Frontend/CompilerInvocation.cpp | 4 ++++
clang/test/Driver/HLSL/load-bool-from-mem.hlsl | 3 +++
4 files changed, 11 insertions(+)
create mode 100644 clang/test/Driver/HLSL/load-bool-from-mem.hlsl
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 66eeb08034bf4..2281836406e63 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -514,6 +514,9 @@ def warn_hlsl_signature_packing_ignored : Warning<
def warn_hlsl_failed_to_embed_source
: Warning<"failed to embed source for '%0' into dx.source.contents">,
InGroup<HLSLDXCCompat>;
+def warn_hlsl_bool_from_mem
+ : Warning<"-load-bool-from-mem=%0 ignored for HLSL (always nonzero)">,
+ InGroup<OptionIgnored>, DefaultWarn;
def err_data_layout_mismatch : Error<"backend data layout '%0' does not match "
"expected target description '%1'">;
diff --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp
index b5356f1ec45d3..7b0be0ab1f402 100644
--- a/clang/lib/Driver/ToolChains/HLSL.cpp
+++ b/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -689,4 +689,5 @@ void HLSLToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
CC1Args.push_back("-Wconversion");
CC1Args.push_back("-Wvector-conversion");
CC1Args.push_back("-Wmatrix-conversion");
+ CC1Args.push_back("-load-bool-from-mem=nonzero");
}
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 0a3a235fbac33..49246f7b6d4d0 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -663,6 +663,10 @@ static bool FixupInvocation(CompilerInvocation &Invocation,
// trunc i32 to i1 into an illegal wide <N x i1> bitcast (issue #140824).
if (!Args.hasArg(OPT_load_bool_from_mem))
CodeGenOpts.setLoadBoolFromMem(CodeGenOptions::BoolFromMem::NonZero);
+ else if (CodeGenOpts.getLoadBoolFromMem() !=
+ CodeGenOptions::BoolFromMem::NonZero)
+ Diags.Report(diag::warn_hlsl_bool_from_mem)
+ << Args.getLastArg(OPT_load_bool_from_mem)->getValue();
}
// When these options are used, the compiler is allowed to apply
diff --git a/clang/test/Driver/HLSL/load-bool-from-mem.hlsl b/clang/test/Driver/HLSL/load-bool-from-mem.hlsl
new file mode 100644
index 0000000000000..23ee8cca8b6de
--- /dev/null
+++ b/clang/test/Driver/HLSL/load-bool-from-mem.hlsl
@@ -0,0 +1,3 @@
+// RUN: %clang_dxc -T cs_6_3 -### %s 2>&1 | FileCheck %s
+
+// CHECK: "-load-bool-from-mem=nonzero"
More information about the cfe-commits
mailing list