1// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -disable-llvm-passes -emit-llvm -finclude-default-header -o - %s | FileCheck %s 2 3// CHECK-LABEL: increment 4void increment(inout int Arr[2]) { 5 for (int I = 0; I < 2; I++) 6 Arr[0] += 2; 7} 8 9// CHECK-LABEL: arrayCall 10// CHECK: [[A:%.*]] = alloca [2 x i32], align 4 11// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 12// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) 13// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) 14// CHECK-NEXT: call void @{{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3 15// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) 16// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 17// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 18// CHECK-NEXT: ret i32 [[B]] 19export int arrayCall() { 20 int A[2] = { 0, 1 }; 21 increment(A); 22 return A[0]; 23} 24 25// CHECK-LABEL: fn2 26void fn2(out int Arr[2]) { 27 Arr[0] += 5; 28 Arr[1] += 6; 29} 30 31// CHECK-LABEL: arrayCall2 32// CHECK: [[A:%.*]] = alloca [2 x i32], align 4 33// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 34// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) 35// CHECK-NEXT: call void @{{.*}}fn2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3 36// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) 37// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 38// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 39// CHECK-NEXT: ret i32 [[B]] 40export int arrayCall2() { 41 int A[2] = { 0, 1 }; 42 fn2(A); 43 return A[0]; 44} 45 46// CHECK-LABEL: nestedCall 47void nestedCall(inout int Arr[2], uint index) { 48 if (index < 2) { 49 Arr[index] += 2; 50 nestedCall(Arr, index+1); 51 } 52} 53 54// CHECK-LABEL: arrayCall3 55// CHECK: [[A:%.*]] = alloca [2 x i32], align 4 56// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 57// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) 58// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) 59// CHECK-NEXT: call void @{{.*}}nestedCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]], i32 noundef 0) #3 60// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) 61// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 1 62// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 63// CHECK-NEXt: ret i32 [[B]] 64export int arrayCall3() { 65 int A[2] = { 0, 1 }; 66 nestedCall(A, 0); 67 return A[1]; 68} 69 70// CHECK-LABEL: outerCall 71// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4 72// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 %{{.*}}, i32 8, i1 false) 73// CHECK-NEXT: call void {{.*}}increment{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3 74// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 {{.*}}, ptr align 4 [[Tmp]], i32 8, i1 false) 75// CHECK-NEXT: ret void 76void outerCall(inout int Arr[2]) { 77 increment(Arr); 78} 79 80// CHECK-LABEL: arrayCall4 81// CHECK: [[A:%.*]] = alloca [2 x i32], align 4 82// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 83// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) 84// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) 85// CHECK-NEXT: call void @{{.*}}outerCall{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3 86// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) 87// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 88// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 89// CHECK-NEXT: ret i32 [[B]] 90export int arrayCall4() { 91 int A[2] = { 0, 1 }; 92 outerCall(A); 93 return A[0]; 94} 95 96// CHECK-LABEL: fn3 97void fn3(int Arr[2]) {} 98 99// CHECK-LABEL: outerCall2 100// CHECK: [[Tmp:%.*]] = alloca [2 x i32], align 4 101// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 {{.*}}, i32 8, i1 false) 102// CHECK-NEXT: call void {{.*}}fn3{{.*}}(ptr noundef byval([2 x i32]) align 4 [[Tmp]]) #3 103// CHECK-NEXT: ret void 104void outerCall2(inout int Arr[2]) { 105 fn3(Arr); 106} 107 108// CHECK-LABEL: arrayCall5 109// CHECK: [[A:%.*]] = alloca [2 x i32], align 4 110// CHECK-NEXT: [[Tmp:%.*]] = alloca [2 x i32], align 4 111// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 @{{.*}}, i32 8, i1 false) 112// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[Tmp]], ptr align 4 [[A]], i32 8, i1 false) 113// CHECK-NEXT: call void @{{.*}}outerCall2{{.*}}(ptr noalias noundef byval([2 x i32]) align 4 [[Tmp]]) #3 114// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 4 [[A]], ptr align 4 [[Tmp]], i32 8, i1 false) 115// CHECK-NEXT: [[Idx:%.*]] = getelementptr inbounds [2 x i32], ptr [[A]], i32 0, i32 0 116// CHECK-NEXT: [[B:%.*]] = load i32, ptr [[Idx]], align 4 117// CHECK-NEXT: ret i32 [[B]] 118export int arrayCall5() { 119 int A[2] = { 0, 1 }; 120 outerCall2(A); 121 return A[0]; 122} 123