[clang] 1c762c2 - [HLSL] Implement the 'and' HLSL function (#127098)

via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 19 11:22:49 PST 2025


Author: Deric Cheung
Date: 2025-02-19T11:22:46-08:00
New Revision: 1c762c288ff4ff613cf26833ef55100fd0da0a34

URL: https://github.com/llvm/llvm-project/commit/1c762c288ff4ff613cf26833ef55100fd0da0a34
DIFF: https://github.com/llvm/llvm-project/commit/1c762c288ff4ff613cf26833ef55100fd0da0a34.diff

LOG: [HLSL] Implement the 'and' HLSL function (#127098)

Addresses #125604 

- Implements `and` as an HLSL builtin function
- The `and` HLSL builtin function gets lowered to the the LLVM `and`
instruction

Added: 
    clang/test/CodeGenHLSL/builtins/and.hlsl
    clang/test/SemaHLSL/BuiltIns/and-errors.hlsl

Modified: 
    clang/include/clang/Basic/Builtins.td
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/lib/Headers/hlsl/hlsl_intrinsics.h
    clang/lib/Sema/SemaHLSL.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 0e5df338dd2e5..0e8b0189540bd 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4771,6 +4771,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 4688381040be2..a73ba1ff138fb 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19506,6 +19506,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..f03b620eee142 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -249,6 +249,28 @@ 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.
+
+// TODO: Clean up clang-format marker once we've resolved
+//       https://github.com/llvm/llvm-project/issues/127851
+//
+// clang-format off
+_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);
+// clang-format on
+
 //===----------------------------------------------------------------------===//
 // any builtins
 //===----------------------------------------------------------------------===//

diff  --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 957c3a0888438..20275ded8a561 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2245,6 +2245,20 @@ 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;
+    if (CheckScalarOrVector(&SemaRef, TheCall, getASTContext().BoolTy, 0))
+      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..b77889cd9ae70
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/and.hlsl
@@ -0,0 +1,68 @@
+// 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);
+}
+
+// CHECK-LABEL: define noundef <4 x i1> @_Z13test_and_int4Dv4_iS_(
+// CHECK-SAME: <4 x i32> noundef [[X:%.*]], <4 x i32> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne <4 x i32> [[X]], zeroinitializer
+// CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp ne <4 x i32> [[Y]], zeroinitializer
+// CHECK-NEXT:    [[HLSL_AND:%.*]] = and <4 x i1> [[TOBOOL]], [[TOBOOL1]]
+// CHECK-NEXT:    ret <4 x i1> [[HLSL_AND]]
+//
+bool4 test_and_int4(int4 x, int4 y) {
+  return and(x, y);
+}
+
+// CHECK-LABEL: define noundef <4 x i1> @_Z15test_and_float4Dv4_fS_(
+// CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[X:%.*]], <4 x float> noundef nofpclass(nan inf) [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[TOBOOL:%.*]] = fcmp reassoc nnan ninf nsz arcp afn une <4 x float> [[X]], zeroinitializer
+// CHECK-NEXT:    [[TOBOOL1:%.*]] = fcmp reassoc nnan ninf nsz arcp afn une <4 x float> [[Y]], zeroinitializer
+// CHECK-NEXT:    [[HLSL_AND:%.*]] = and <4 x i1> [[TOBOOL]], [[TOBOOL1]]
+// CHECK-NEXT:    ret <4 x i1> [[HLSL_AND]]
+//
+bool4 test_and_float4(float4 x, float4 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..0a99feb023d73
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/and-errors.hlsl
@@ -0,0 +1,23 @@
+// 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}}
+}
+
+bool test_incorrect_type(int a) {
+  return __builtin_hlsl_and(a, a);
+  // expected-error at -1{{invalid operand of type 'int' where 'bool' or a vector of such type is required}}
+}


        


More information about the cfe-commits mailing list