Skip to content

Commit 23efe73

Browse files
authoredFeb 28, 2025··
[HLSL] Add "or" intrinsic (#128979)
Include HLSL or_intrinsic, add codegen in CGBuiltin, and the corresponding tests in or.hlsl. Additionally, incorporate logical-operator-errors to handle both 'and' and 'or' semantic diagnostics.
1 parent 88ae5bd commit 23efe73

File tree

7 files changed

+142
-23
lines changed

7 files changed

+142
-23
lines changed
 

‎clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4783,6 +4783,12 @@ def HLSLAnd : LangBuiltin<"HLSL_LANG"> {
47834783
let Prototype = "void(...)";
47844784
}
47854785

4786+
def HLSLOr : LangBuiltin<"HLSL_LANG"> {
4787+
let Spellings = ["__builtin_hlsl_or"];
4788+
let Attributes = [NoThrow, Const];
4789+
let Prototype = "void(...)";
4790+
}
4791+
47864792
def HLSLAny : LangBuiltin<"HLSL_LANG"> {
47874793
let Spellings = ["__builtin_hlsl_any"];
47884794
let Attributes = [NoThrow, Const];

‎clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19493,6 +19493,11 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
1949319493
Value *Op1 = EmitScalarExpr(E->getArg(1));
1949419494
return Builder.CreateAnd(Op0, Op1, "hlsl.and");
1949519495
}
19496+
case Builtin::BI__builtin_hlsl_or: {
19497+
Value *Op0 = EmitScalarExpr(E->getArg(0));
19498+
Value *Op1 = EmitScalarExpr(E->getArg(1));
19499+
return Builder.CreateOr(Op0, Op1, "hlsl.or");
19500+
}
1949619501
case Builtin::BI__builtin_hlsl_any: {
1949719502
Value *Op0 = EmitScalarExpr(E->getArg(0));
1949819503
return Builder.CreateIntrinsic(

‎clang/lib/Headers/hlsl/hlsl_intrinsics.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,28 @@ _HLSL_BUILTIN_ALIAS(__builtin_hlsl_and)
290290
bool4 and(bool4 x, bool4 y);
291291
// clang-format on
292292

293+
//===----------------------------------------------------------------------===//
294+
// or builtins
295+
//===----------------------------------------------------------------------===//
296+
297+
/// \fn bool or(bool x, bool y)
298+
/// \brief Logically ors two boolean vectors elementwise and produces a bool
299+
/// vector output.
300+
301+
// TODO: Clean up clang-format marker once we've resolved
302+
// https://github.com/llvm/llvm-project/issues/127851
303+
//
304+
// clang-format off
305+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_or)
306+
bool or(bool, bool);
307+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_or)
308+
bool2 or(bool2, bool2);
309+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_or)
310+
bool3 or(bool3, bool3);
311+
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_or)
312+
bool4 or(bool4, bool4);
313+
// clang-format on
314+
293315
//===----------------------------------------------------------------------===//
294316
// any builtins
295317
//===----------------------------------------------------------------------===//

‎clang/lib/Sema/SemaHLSL.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2293,7 +2293,8 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
22932293

22942294
break;
22952295
}
2296-
case Builtin::BI__builtin_hlsl_and: {
2296+
case Builtin::BI__builtin_hlsl_and:
2297+
case Builtin::BI__builtin_hlsl_or: {
22972298
if (SemaRef.checkArgCount(TheCall, 2))
22982299
return true;
22992300
if (CheckVectorElementCallArgs(&SemaRef, TheCall))
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple \
2+
// RUN: dxil-pc-shadermodel6.3-library %s \
3+
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s
4+
5+
//CHECK-LABEL: define noundef i1 @_Z14test_or_scalarbb(
6+
//CHECK-SAME: i1 noundef [[X:%.*]], i1 noundef [[Y:%.*]]) #[[ATTR0:[0-9]+]] {
7+
//CHECK-NEXT: entry:
8+
//CHECK: [[HLSL_OR:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
9+
//CHECK: ret i1 [[HLSL_OR]]
10+
bool test_or_scalar(bool x, bool y)
11+
{
12+
return or(x, y);
13+
}
14+
15+
//CHECK-LABEL: define noundef <2 x i1> @_Z13test_or_bool2Dv2_bS_(
16+
//CHECK-SAME: <2 x i1> noundef [[X:%.*]], <2 x i1> noundef [[Y:%.*]]) #[[ATTR0]] {
17+
//CHECK-NEXT: entry:
18+
//CHECK: [[HLSL_OR:%.*]] = or <2 x i1> [[A:%.*]], [[B:%.*]]
19+
//CHECK: ret <2 x i1> [[HLSL_OR]]
20+
bool2 test_or_bool2(bool2 x, bool2 y)
21+
{
22+
return or(x, y);
23+
}
24+
25+
//CHECK-LABEL: define noundef <3 x i1> @_Z13test_or_bool3Dv3_bS_(
26+
//CHECK-SAME: <3 x i1> noundef [[X:%.*]], <3 x i1> noundef [[Y:%.*]]) #[[ATTR0]] {
27+
//CHECK-NEXT: entry:
28+
//CHECK: [[HLSL_OR:%.*]] = or <3 x i1> [[A:%.*]], [[B:%.*]]
29+
//CHECK: ret <3 x i1> [[HLSL_OR]]
30+
bool3 test_or_bool3(bool3 x, bool3 y)
31+
{
32+
return or(x, y);
33+
}
34+
35+
//CHECK-LABEL: define noundef <4 x i1> @_Z13test_or_bool4Dv4_bS_(
36+
//CHECK-SAME: <4 x i1> noundef [[X:%.*]], <4 x i1> noundef [[Y:%.*]]) #[[ATTR0]] {
37+
//CHECK-NEXT: entry:
38+
//CHECK: [[HLSL_OR:%.*]] = or <4 x i1> [[A:%.*]], [[B:%.*]]
39+
//CHECK: ret <4 x i1> [[HLSL_OR]]
40+
bool4 test_or_bool4(bool4 x, bool4 y)
41+
{
42+
return or(x, y);
43+
}
44+
45+
//CHECK-LABEL: define noundef i1 @_Z11test_or_intii(
46+
//CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
47+
//CHECK-NEXT: entry:
48+
//CHECK: [[TOBBOL:%.*]] = icmp ne i32 [[A:%.*]], 0
49+
//CHECK: [[TOBBOL1:%.*]] = icmp ne i32 [[B:%.*]], 0
50+
//CHECK: [[HLSL_OR:%.*]] = or i1 [[TOBBOL]], [[TOBBOL1]]
51+
//CHECK: ret i1 [[HLSL_OR]]
52+
bool test_or_int(int x, int y)
53+
{
54+
return or(x, y);
55+
}
56+
57+
//CHECK-LABEL: define noundef <4 x i1> @_Z12test_or_int4Dv4_iS_(
58+
//CHECK-SAME: <4 x i32> noundef [[X:%.*]], <4 x i32> noundef [[Y:%.*]]) #[[ATTR0]] {
59+
//CHECK-NEXT: entry:
60+
//CHECK: [[TOBOOL:%.*]] = icmp ne <4 x i32> [[A:%.*]], zeroinitializer
61+
//CHECK: [[TOBOOL1:%.*]] = icmp ne <4 x i32> [[B:%.*]], zeroinitializer
62+
//CHECK: [[HLSL_OR:%.*]] = or <4 x i1> [[TOBOOL]], [[TOBOOL1]]
63+
//CHECK: ret <4 x i1> [[HLSL_OR]]
64+
bool4 test_or_int4(int4 x, int4 y)
65+
{
66+
return or(x, y);
67+
}
68+
69+
//CHECK-LABEL: define noundef <4 x i1> @_Z14test_or_float4Dv4_fS_(
70+
//CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[X:%.*]], <4 x float> noundef nofpclass(nan inf) [[Y:%.*]]) #[[ATTR0]] {
71+
//CHECK-NEXT: entry:
72+
//CHECK: [[TOBOOL:%.*]] = fcmp reassoc nnan ninf nsz arcp afn une <4 x float> [[A:%.*]], zeroinitializer
73+
//CHECK: [[TOBOOL1:%.*]] = fcmp reassoc nnan ninf nsz arcp afn une <4 x float> [[B:%.*]], zeroinitializer
74+
//CHECK: [[HLSL_OR:%.*]] = or <4 x i1> [[TOBOOL]], [[TOBOOL1]]
75+
//CHECK: ret <4 x i1> [[HLSL_OR]]
76+
bool4 test_or_float4(float4 x, float4 y)
77+
{
78+
return or(x, y);
79+
}
80+

‎clang/test/SemaHLSL/BuiltIns/and-errors.hlsl

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify -DTEST_FUNC=__builtin_hlsl_or
2+
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -verify -DTEST_FUNC=__builtin_hlsl_and
3+
4+
5+
bool test_too_few_arg(bool a)
6+
{
7+
return TEST_FUNC(a);
8+
// expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
9+
}
10+
11+
bool test_too_many_arg(bool a)
12+
{
13+
return TEST_FUNC(a, a, a);
14+
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
15+
}
16+
17+
bool2 test_mismatched_args(bool2 a, bool3 b)
18+
{
19+
return TEST_FUNC(a, b);
20+
// expected-error@-1 {{all arguments to}}{{_builtin_hlsl_or|_builtin_hlsl_and }}{{must have the same type}}
21+
}
22+
23+
bool test_incorrect_type(int a)
24+
{
25+
return TEST_FUNC(a, a);
26+
// expected-error@-1{{invalid operand of type 'int' where 'bool' or a vector of such type is required}}
27+
}

0 commit comments

Comments
 (0)
Please sign in to comment.