|
| 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 | + |
| 8 | +struct Node { |
| 9 | + uint value; |
| 10 | + uint key; |
| 11 | + uint left, right; |
| 12 | +}; |
| 13 | + |
| 14 | +// CHECK: Function Attrs:{{.*}}norecurse |
| 15 | +// CHECK: define noundef i32 @"?Find@@YAIY0GE@UNode@@I@Z"(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 |
| 18 | +uint 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 @"?InitTree@@YA_NY0GE@UNode@@V?$RWBuffer@T?$__vector@I$03@__clang@@@hlsl@@I@Z"(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 |
| 38 | +export |
| 39 | +bool InitTree(/*inout*/ Node tree[MAX], RWBuffer<uint4> encodedTree, uint maxDepth) { |
| 40 | + uint size = pow(2.f, 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 | + |
| 51 | +RWBuffer<uint4> gTree; |
| 52 | + |
| 53 | +// Mangled entry points are internal |
| 54 | +// CHECK: Function Attrs:{{.*}}norecurse |
| 55 | +// CHECK: define internal void @"?main@@YAXI@Z"(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")] |
| 65 | +void 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 @"?defaultMain@@YAXXZ"() [[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")] |
| 84 | +void 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 |
0 commit comments