xref: /llvm-project/clang/test/CodeGenHLSL/implicit-norecurse-attrib.hlsl (revision 1ac3665e66c7ddb20ef26bc275ad005186ab09fb)
1// RUN: %clang_cc1 -x hlsl -triple dxil-pc-shadermodel6.3-library  -finclude-default-header %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
2// RUN: %clang_cc1 -x hlsl -triple dxil-pc-shadermodel6.0-compute  -finclude-default-header %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s
3
4// Verify that a few different function types all get the NoRecurse attribute
5
6#define MAX 100
7
8struct Node {
9  uint value;
10  uint key;
11  uint left, right;
12};
13
14// CHECK: Function Attrs:{{.*}}norecurse
15// CHECK: define noundef i32 @_Z4FindA100_4Nodej(ptr noundef byval([100 x %struct.Node]) align 4 %SortedTree, i32 noundef %key) [[IntAttr:\#[0-9]+]]
16// CHECK: ret i32
17// Find and return value corresponding to key in the SortedTree
18uint Find(Node SortedTree[MAX], uint key) {
19  uint nix = 0; // head
20  while(true) {
21    if (nix < 0)
22      return 0.0; // Not found
23    Node n = SortedTree[nix];
24    if (n.key == key)
25      return n.value;
26    if (key < n.key)
27      nix = n.left;
28    else
29      nix = n.right;
30  }
31}
32
33// CHECK: Function Attrs:{{.*}}norecurse
34// CHECK: define noundef i1 @_Z8InitTreeA100_4NodeN4hlsl8RWBufferIDv4_jEEj(ptr noundef byval([100 x %struct.Node]) align 4 %tree, ptr noundef byval(%"class.hlsl::RWBuffer") align 4 %encodedTree, i32 noundef %maxDepth) [[ExtAttr:\#[0-9]+]]
35// CHECK: ret i1
36// Initialize tree with given buffer
37// Imagine the inout works
38export
39bool InitTree(/*inout*/ Node tree[MAX], RWBuffer<uint4> encodedTree, uint maxDepth) {
40  uint size = pow(2.f, (float)maxDepth) - 1;
41  if (size > MAX) return false;
42  for (uint i = 1; i < size; i++) {
43    tree[i].value = encodedTree[i].x;
44    tree[i].key   = encodedTree[i].y;
45    tree[i].left  = encodedTree[i].z;
46    tree[i].right = encodedTree[i].w;
47  }
48  return true;
49}
50
51RWBuffer<uint4> gTree;
52
53// Mangled entry points are internal
54// CHECK: Function Attrs:{{.*}}norecurse
55// CHECK: define internal void @_Z4mainj(i32 noundef %GI) [[IntAttr]]
56// CHECK: ret void
57
58// Canonical entry points are external and shader attributed
59// CHECK: Function Attrs:{{.*}}norecurse
60// CHECK: define void @main() [[EntryAttr:\#[0-9]+]]
61// CHECK: ret void
62
63[numthreads(1,1,1)]
64[shader("compute")]
65void main(uint GI : SV_GroupIndex) {
66  Node haystack[MAX];
67  uint needle = 0;
68  if (InitTree(haystack, gTree, GI))
69    needle = Find(haystack, needle);
70}
71
72// Mangled entry points are internal
73// CHECK: Function Attrs:{{.*}}norecurse
74// CHECK: define internal void @_Z11defaultMainv() [[IntAttr]]
75// CHECK: ret void
76
77// Canonical entry points are external and shader attributed
78// CHECK: Function Attrs:{{.*}}norecurse
79// CHECK: define void @defaultMain() [[EntryAttr]]
80// CHECK: ret void
81
82[numthreads(1,1,1)]
83[shader("compute")]
84void defaultMain() {
85  Node haystack[MAX];
86  uint needle = 0;
87  if (InitTree(haystack, gTree, 4))
88    needle = Find(haystack, needle);
89}
90
91// CHECK: attributes [[IntAttr]] = {{.*}} norecurse
92// CHECK: attributes [[ExtAttr]] = {{.*}} norecurse
93// CHECK: attributes [[EntryAttr]] = {{.*}} norecurse
94