Skip to content

[HLSL] Add "or" intrinsic #128979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -4783,6 +4783,12 @@ def HLSLAnd : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

def HLSLOr : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_or"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}

def HLSLAny : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_any"];
let Attributes = [NoThrow, Const];
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19492,6 +19492,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
Value *Op1 = EmitScalarExpr(E->getArg(1));
return Builder.CreateAnd(Op0, Op1, "hlsl.and");
}
case Builtin::BI__builtin_hlsl_or: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
return Builder.CreateOr(Op0, Op1, "hlsl.or");
}
case Builtin::BI__builtin_hlsl_any: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,28 @@ _HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
bool4 and(bool4 x, bool4 y);
// clang-format on

//===----------------------------------------------------------------------===//
// or builtins
//===----------------------------------------------------------------------===//

/// \fn bool or(bool x, bool y)
/// \brief Logically ors 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_or)
bool or(bool, bool);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_or)
bool2 or(bool2, bool2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_or)
bool3 or(bool3, bool3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_or)
bool4 or(bool4, bool4);
// clang-format on

//===----------------------------------------------------------------------===//
// any builtins
//===----------------------------------------------------------------------===//
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2291,7 +2291,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {

break;
}
case Builtin::BI__builtin_hlsl_and: {
case Builtin::BI__builtin_hlsl_and:
case Builtin::BI__builtin_hlsl_or: {
if (SemaRef.checkArgCount(TheCall, 2))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are doing the same sema checks for the and intrinsic. Delete this whole block and merge the and an or builtins as fall through cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code updated with suggested changes.

return true;
if (CheckVectorElementCallArgs(&SemaRef, TheCall))
Expand Down
80 changes: 80 additions & 0 deletions clang/test/CodeGenHLSL/builtins/or.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// RUN: %clang_cc1 -finclude-default-header -triple \
// RUN: dxil-pc-shadermodel6.3-library %s \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s

//CHECK-LABEL: define noundef i1 @_Z14test_or_scalarbb(
//CHECK-SAME: i1 noundef [[X:%.*]], i1 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
//CHECK-NEXT: entry:
//CHECK: [[HLSL_OR:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
//CHECK: ret i1 [[HLSL_OR]]
bool test_or_scalar(bool x, bool y)
{
return or(x, y);
}

//CHECK-LABEL: define noundef <2 x i1> @_Z13test_or_bool2Dv2_bS_(
//CHECK-SAME: <2 x i1> noundef [[X:%.*]], <2 x i1> noundef [[Y:%.*]]) #[[ATTR0]] {
//CHECK-NEXT: entry:
//CHECK: [[HLSL_OR:%.*]] = or <2 x i1> [[A:%.*]], [[B:%.*]]
//CHECK: ret <2 x i1> [[HLSL_OR]]
bool2 test_or_bool2(bool2 x, bool2 y)
{
return or(x, y);
}

//CHECK-LABEL: define noundef <3 x i1> @_Z13test_or_bool3Dv3_bS_(
//CHECK-SAME: <3 x i1> noundef [[X:%.*]], <3 x i1> noundef [[Y:%.*]]) #[[ATTR0]] {
//CHECK-NEXT: entry:
//CHECK: [[HLSL_OR:%.*]] = or <3 x i1> [[A:%.*]], [[B:%.*]]
//CHECK: ret <3 x i1> [[HLSL_OR]]
bool3 test_or_bool3(bool3 x, bool3 y)
{
return or(x, y);
}

//CHECK-LABEL: define noundef <4 x i1> @_Z13test_or_bool4Dv4_bS_(
//CHECK-SAME: <4 x i1> noundef [[X:%.*]], <4 x i1> noundef [[Y:%.*]]) #[[ATTR0]] {
//CHECK-NEXT: entry:
//CHECK: [[HLSL_OR:%.*]] = or <4 x i1> [[A:%.*]], [[B:%.*]]
//CHECK: ret <4 x i1> [[HLSL_OR]]
bool4 test_or_bool4(bool4 x, bool4 y)
{
return or(x, y);
}

//CHECK-LABEL: define noundef i1 @_Z11test_or_intii(
//CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
//CHECK-NEXT: entry:
//CHECK: [[TOBBOL:%.*]] = icmp ne i32 [[A:%.*]], 0
//CHECK: [[TOBBOL1:%.*]] = icmp ne i32 [[B:%.*]], 0
//CHECK: [[HLSL_OR:%.*]] = or i1 [[TOBBOL]], [[TOBBOL1]]
//CHECK: ret i1 [[HLSL_OR]]
bool test_or_int(int x, int y)
{
return or(x, y);
}

//CHECK-LABEL: define noundef <4 x i1> @_Z12test_or_int4Dv4_iS_(
//CHECK-SAME: <4 x i32> noundef [[X:%.*]], <4 x i32> noundef [[Y:%.*]]) #[[ATTR0]] {
//CHECK-NEXT: entry:
//CHECK: [[TOBOOL:%.*]] = icmp ne <4 x i32> [[A:%.*]], zeroinitializer
//CHECK: [[TOBOOL1:%.*]] = icmp ne <4 x i32> [[B:%.*]], zeroinitializer
//CHECK: [[HLSL_OR:%.*]] = or <4 x i1> [[TOBOOL]], [[TOBOOL1]]
//CHECK: ret <4 x i1> [[HLSL_OR]]
bool4 test_or_int4(int4 x, int4 y)
{
return or(x, y);
}

//CHECK-LABEL: define noundef <4 x i1> @_Z14test_or_float4Dv4_fS_(
//CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[X:%.*]], <4 x float> noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR0]] {
//CHECK-NEXT: entry:
//CHECK: [[TOBOOL:%.*]] = fcmp reassoc nnan ninf nsz arcp afn une <4 x float> [[A:%.*]], zeroinitializer
//CHECK: [[TOBOOL1:%.*]] = fcmp reassoc nnan ninf nsz arcp afn une <4 x float> [[B:%.*]], zeroinitializer
//CHECK: [[HLSL_OR:%.*]] = or <4 x i1> [[TOBOOL]], [[TOBOOL1]]
//CHECK: ret <4 x i1> [[HLSL_OR]]
bool4 test_or_float4(float4 x, float4 y)
{
return or(x, y);
}

22 changes: 0 additions & 22 deletions clang/test/SemaHLSL/BuiltIns/and-errors.hlsl

This file was deleted.

27 changes: 27 additions & 0 deletions clang/test/SemaHLSL/BuiltIns/logical-operator-errors.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify -DTEST_FUNC=__builtin_hlsl_or
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify -DTEST_FUNC=__builtin_hlsl_and


bool test_too_few_arg(bool a)
{
return TEST_FUNC(a);
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
}

bool test_too_many_arg(bool a)
{
return TEST_FUNC(a, a, a);
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
}

bool2 test_mismatched_args(bool2 a, bool3 b)
{
return TEST_FUNC(a, b);
// expected-error@-1 {{all arguments to}}{{_builtin_hlsl_or|_builtin_hlsl_and }}{{must have the same type}}
}

bool test_incorrect_type(int a)
{
return TEST_FUNC(a, a);
// expected-error@-1{{invalid operand of type 'int' where 'bool' or a vector of such type is required}}
}