[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)

Deric Cheung via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 13 10:19:07 PST 2025


https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/127098

>From 5b093ca42fdc24f89bfccac25e6f2e17155432f6 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Wed, 12 Feb 2025 21:24:00 +0000
Subject: [PATCH 1/3] Implement the 'and' HLSL function

---
 clang/include/clang/Basic/Builtins.td        |  6 +++
 clang/lib/CodeGen/CGBuiltin.cpp              |  5 +++
 clang/lib/Headers/hlsl/hlsl_intrinsics.h     | 16 +++++++
 clang/lib/Sema/SemaHLSL.cpp                  | 11 +++++
 clang/test/CodeGenHLSL/builtins/and.hlsl     | 45 ++++++++++++++++++++
 clang/test/SemaHLSL/BuiltIns/and-errors.hlsl | 27 ++++++++++++
 6 files changed, 110 insertions(+)
 create mode 100644 clang/test/CodeGenHLSL/builtins/and.hlsl
 create mode 100644 clang/test/SemaHLSL/BuiltIns/and-errors.hlsl

diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 29939242596ba..de758d88f8f92 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4765,6 +4765,12 @@ def HLSLAll : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "bool(...)";
 }
 
+def HLSLAnd : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_and"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
 def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_any"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 361e4c4bf2e2e..82527cb5e1f7a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19463,6 +19463,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
         CGM.getHLSLRuntime().getAllIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
         "hlsl.all");
   }
+  case Builtin::BI__builtin_hlsl_and: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    Value *Op1 = EmitScalarExpr(E->getArg(1));
+    return Builder.CreateAnd(Op0, Op1, "hlsl.and");
+  }
   case Builtin::BI__builtin_hlsl_any: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     return Builder.CreateIntrinsic(
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index d1f5fdff8b600..7016b45d1c641 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -249,6 +249,22 @@ bool all(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_all)
 bool all(double4);
 
+//===----------------------------------------------------------------------===//
+// and builtins
+//===----------------------------------------------------------------------===//
+
+// \fn bool and(bool x, bool y)
+// \brief Logically ands two boolean vectors elementwise and produces a bool vector output.
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
+bool and(bool x, bool y);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
+bool2 and(bool2 x, bool2 y);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
+bool3 and(bool3 x, bool3 y);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
+bool4 and(bool4 x, bool4 y);
+
 //===----------------------------------------------------------------------===//
 // any builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 4abd870ad6aaa..7297fb3a9e4d0 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2245,6 +2245,17 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
 
     break;
   }
+  case Builtin::BI__builtin_hlsl_and: {
+    if (SemaRef.checkArgCount(TheCall, 2))
+      return true;
+    if (CheckVectorElementCallArgs(&SemaRef, TheCall))
+      return true;
+    ExprResult A = TheCall->getArg(0);
+    QualType ArgTyA = A.get()->getType();
+    // return type is the same as the input type
+    TheCall->setType(ArgTyA);
+    break;
+  }
   case Builtin::BI__builtin_hlsl_all:
   case Builtin::BI__builtin_hlsl_any: {
     if (SemaRef.checkArgCount(TheCall, 1))
diff --git a/clang/test/CodeGenHLSL/builtins/and.hlsl b/clang/test/CodeGenHLSL/builtins/and.hlsl
new file mode 100644
index 0000000000000..60295f192f5cc
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/and.hlsl
@@ -0,0 +1,45 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -finclude-default-header -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s \
+// RUN:   -emit-llvm -O1 -o - | FileCheck %s
+
+// CHECK-LABEL: define noundef i1 @_Z15test_and_scalarbb(
+// CHECK-SAME: i1 noundef [[X:%.*]], i1 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[HLSL_AND:%.*]] = and i1 [[X]], [[Y]]
+// CHECK-NEXT:    ret i1 [[HLSL_AND]]
+//
+bool test_and_scalar(bool x, bool y) {
+  return and(x, y);
+}
+
+// CHECK-LABEL: define noundef <2 x i1> @_Z14test_and_bool2Dv2_bS_(
+// CHECK-SAME: <2 x i1> noundef [[X:%.*]], <2 x i1> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[HLSL_AND:%.*]] = and <2 x i1> [[X]], [[Y]]
+// CHECK-NEXT:    ret <2 x i1> [[HLSL_AND]]
+//
+bool2 test_and_bool2(bool2 x, bool2 y) {
+  return and(x, y);
+}
+
+// CHECK-LABEL: define noundef <3 x i1> @_Z14test_and_bool3Dv3_bS_(
+// CHECK-SAME: <3 x i1> noundef [[X:%.*]], <3 x i1> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[HLSL_AND:%.*]] = and <3 x i1> [[X]], [[Y]]
+// CHECK-NEXT:    ret <3 x i1> [[HLSL_AND]]
+//
+bool3 test_and_bool3(bool3 x, bool3 y) {
+  return and(x, y);
+}
+
+// CHECK-LABEL: define noundef <4 x i1> @_Z14test_and_bool4Dv4_bS_(
+// CHECK-SAME: <4 x i1> noundef [[X:%.*]], <4 x i1> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[HLSL_AND:%.*]] = and <4 x i1> [[X]], [[Y]]
+// CHECK-NEXT:    ret <4 x i1> [[HLSL_AND]]
+//
+bool4 test_and_bool4(bool4 x, bool4 y) {
+  return and(x, y);
+}
+
diff --git a/clang/test/SemaHLSL/BuiltIns/and-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/and-errors.hlsl
new file mode 100644
index 0000000000000..0fbf172d46ccd
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/and-errors.hlsl
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -finclude-default-header -triple \
+// RUN:   dxil-pc-shadermodel6.3-library %s \
+// RUN:   -emit-llvm -O1 -verify
+
+bool test_too_few_arg(bool a) {
+  return __builtin_hlsl_and(a);
+  // expected-error at -1 {{too few arguments to function call, expected 2, have 1}}
+}
+
+bool test_too_many_arg(bool a) {
+  return __builtin_hlsl_and(a, a, a);
+  // expected-error at -1 {{too many arguments to function call, expected 2, have 3}}
+}
+
+bool2 test_mismatched_args(bool2 a, bool3 b) {
+  return __builtin_hlsl_and(a, b);
+  // expected-error at -1 {{all arguments to '__builtin_hlsl_and' must have the same type}}
+}
+
+struct S {
+  bool a;
+};
+
+bool test_invalid_type_conversion(S s) {
+  return __builtin_hlsl_and(s, s);
+  // expected-error at -1{{no viable conversion from returned value of type 'S' to function return type 'bool'}}
+}

>From ce311652dfb30b1e7c484c2d998b43dd9283d463 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Thu, 13 Feb 2025 17:43:48 +0000
Subject: [PATCH 2/3] Apply clang-format

---
 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 7016b45d1c641..c3f5bb28d5838 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -254,16 +254,17 @@ bool all(double4);
 //===----------------------------------------------------------------------===//
 
 // \fn bool and(bool x, bool y)
-// \brief Logically ands two boolean vectors elementwise and produces a bool vector output.
+// \brief Logically ands two boolean vectors elementwise and produces a bool
+// vector output.
 
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
-bool and(bool x, bool y);
+bool and (bool x, bool y);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
-bool2 and(bool2 x, bool2 y);
+bool2 and (bool2 x, bool2 y);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
-bool3 and(bool3 x, bool3 y);
+bool3 and (bool3 x, bool3 y);
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
-bool4 and(bool4 x, bool4 y);
+bool4 and (bool4 x, bool4 y);
 
 //===----------------------------------------------------------------------===//
 // any builtins

>From 1f2e8d745d246ae3497e3b7edd20d78898a53ac3 Mon Sep 17 00:00:00 2001
From: Icohedron <cheung.deric at gmail.com>
Date: Thu, 13 Feb 2025 18:18:50 +0000
Subject: [PATCH 3/3] Add additional forward slash to and builtin docs

---
 clang/lib/Headers/hlsl/hlsl_intrinsics.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index c3f5bb28d5838..abac41f34e8ac 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -253,9 +253,9 @@ bool all(double4);
 // and builtins
 //===----------------------------------------------------------------------===//
 
-// \fn bool and(bool x, bool y)
-// \brief Logically ands two boolean vectors elementwise and produces a bool
-// vector output.
+/// \fn bool and(bool x, bool y)
+/// \brief Logically ands two boolean vectors elementwise and produces a bool
+/// vector output.
 
 _HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
 bool and (bool x, bool y);



More information about the cfe-commits mailing list