1// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE 2// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE 3// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library %s -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK,INLINE 4// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s --check-prefixes=CHECK,NOINLINE 5// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute %s -emit-llvm -O0 -o - | FileCheck %s --check-prefixes=CHECK,INLINE 6// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute %s -emit-llvm -O1 -o - | FileCheck %s --check-prefixes=CHECK,INLINE 7 8// Tests that user functions will always be inlined. 9// This includes exported functions and mangled entry point implementation functions. 10// The unmangled entry functions must not be alwaysinlined. 11 12#define MAX 100 13 14float nums[MAX]; 15 16// Verify that all functions have the alwaysinline attribute 17// NOINLINE: Function Attrs: alwaysinline 18// NOINLINE: define void @_Z4swapA100_jjj(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %ix1, i32 noundef %ix2) [[IntAttr:\#[0-9]+]] 19// NOINLINE: ret void 20// Swap the values of Buf at indices ix1 and ix2 21void swap(unsigned Buf[MAX], unsigned ix1, unsigned ix2) { 22 float tmp = Buf[ix1]; 23 Buf[ix1] = Buf[ix2]; 24 Buf[ix2] = tmp; 25} 26 27// NOINLINE: Function Attrs: alwaysinline 28// NOINLINE: define void @_Z10BubbleSortA100_jj(ptr noundef byval([100 x i32]) align 4 %Buf, i32 noundef %size) [[IntAttr]] 29// NOINLINE: ret void 30// Inefficiently sort Buf in place 31void BubbleSort(unsigned Buf[MAX], unsigned size) { 32 bool swapped = true; 33 while (swapped) { 34 swapped = false; 35 for (unsigned i = 1; i < size; i++) { 36 if (Buf[i] < Buf[i-1]) { 37 swap(Buf, i, i-1); 38 swapped = true; 39 } 40 } 41 } 42} 43 44// Note ExtAttr is the inlined export set of attribs 45// CHECK: Function Attrs: alwaysinline 46// CHECK: define noundef i32 @_Z11RemoveDupesA100_jj(ptr {{[a-z_ ]*}}noundef byval([100 x i32]) align 4 {{.*}}%Buf, i32 noundef %size) {{[a-z_ ]*}}[[ExtAttr:\#[0-9]+]] 47// CHECK: ret i32 48// Sort Buf and remove any duplicate values 49// returns the number of values left 50export 51unsigned RemoveDupes(unsigned Buf[MAX], unsigned size) { 52 BubbleSort(Buf, size); 53 unsigned insertPt = 0; 54 for (unsigned i = 1; i < size; i++) { 55 if (Buf[i] == Buf[i-1]) 56 insertPt++; 57 else 58 Buf[insertPt] = Buf[i]; 59 } 60 return insertPt; 61} 62 63 64RWBuffer<unsigned> Indices; 65 66// The mangled version of main only remains without inlining 67// because it has internal linkage from the start 68// Note main functions get the norecurse attrib, which IntAttr reflects 69// NOINLINE: Function Attrs: alwaysinline 70// NOINLINE: define internal void @_Z4mainj(i32 noundef %GI) [[IntAttr]] 71// NOINLINE: ret void 72 73// The unmangled version is not inlined, EntryAttr reflects that 74// CHECK: Function Attrs: {{.*}}noinline 75// CHECK: define void @main() {{[a-z_ ]*}}[[EntryAttr:\#[0-9]+]] 76// Make sure function calls are inlined when AlwaysInline is run 77// This only leaves calls to llvm. intrinsics 78// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}} 79// CHECK: ret void 80 81[numthreads(1,1,1)] 82[shader("compute")] 83void main(unsigned int GI : SV_GroupIndex) { 84 unsigned tmpIndices[MAX]; 85 if (GI > MAX) return; 86 for (unsigned i = 1; i < GI; i++) 87 tmpIndices[i] = Indices[i]; 88 RemoveDupes(tmpIndices, GI); 89 for (unsigned i = 1; i < GI; i++) 90 tmpIndices[i] = Indices[i]; 91} 92 93// The mangled version of main only remains without inlining 94// because it has internal linkage from the start 95// Note main functions get the norecurse attrib, which IntAttr reflects 96// NOINLINE: Function Attrs: alwaysinline 97// NOINLINE: define internal void @_Z6main10v() [[IntAttr]] 98// NOINLINE: ret void 99 100// The unmangled version is not inlined, EntryAttr reflects that 101// CHECK: Function Attrs: {{.*}}noinline 102// CHECK: define void @main10() {{[a-z_ ]*}}[[EntryAttr]] 103// Make sure function calls are inlined when AlwaysInline is run 104// This only leaves calls to llvm. intrinsics 105// INLINE-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}} 106// CHECK: ret void 107 108[numthreads(1,1,1)] 109[shader("compute")] 110void main10() { 111 main(10); 112} 113 114// NOINLINE: attributes [[IntAttr]] = {{.*}} alwaysinline 115// CHECK: attributes [[ExtAttr]] = {{.*}} alwaysinline 116// CHECK: attributes [[EntryAttr]] = {{.*}} noinline 117