| // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6 | |
| // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s | |
| struct P { | |
| float a; | |
| }; | |
| struct S : P { | |
| double b; | |
| int c[2]; | |
| }; | |
| // CHECK-LABEL: define hidden void @_Z5case11S( | |
| // CHECK-SAME: ptr nofreeobj noundef align 1 dead_on_return dereferenceable(20) [[S:%.*]]) #[[ATTR0:[0-9]+]] { | |
| // CHECK-NEXT: [[ENTRY:.*:]] | |
| // CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.experimental.convergence.entry() | |
| // CHECK-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 4 | |
| // CHECK-NEXT: [[SLOCAL:%.*]] = alloca [[STRUCT_S:%.*]], align 1 | |
| // CHECK-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 4 | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[SLOCAL]], ptr align 1 [[S]], i32 20, i1 false) | |
| // CHECK-NEXT: ret void | |
| // | |
| void case1(S s) { | |
| // struct initialization | |
| S sLocal = s; | |
| } | |
| // CHECK-LABEL: define hidden void @_Z5case21S( | |
| // CHECK-SAME: ptr nofreeobj noundef align 1 dead_on_return dereferenceable(20) [[S:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: [[ENTRY:.*:]] | |
| // CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.experimental.convergence.entry() | |
| // CHECK-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 4 | |
| // CHECK-NEXT: [[SLOCAL:%.*]] = alloca [[STRUCT_S:%.*]], align 1 | |
| // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S]], align 1 | |
| // CHECK-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 4 | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[SLOCAL]], ptr align 1 [[S]], i32 20, i1 false) | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[SLOCAL]], i32 20, i1 false) | |
| // CHECK-NEXT: ret void | |
| // | |
| void case2(S s) { | |
| S sLocal; | |
| // struct assignment | |
| sLocal = s; | |
| } | |
| // CHECK-LABEL: define hidden void @_Z4useS1S( | |
| // CHECK-SAME: ptr nofreeobj noundef align 1 dead_on_return dereferenceable(20) [[S:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: [[ENTRY:.*:]] | |
| // CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.experimental.convergence.entry() | |
| // CHECK-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 4 | |
| // CHECK-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 4 | |
| // CHECK-NEXT: ret void | |
| // | |
| void useS(S s) {} | |
| // CHECK-LABEL: define hidden void @_Z5case31S( | |
| // CHECK-SAME: ptr nofreeobj noundef align 1 dead_on_return dereferenceable(20) [[S:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: [[ENTRY:.*:]] | |
| // CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.experimental.convergence.entry() | |
| // CHECK-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 4 | |
| // CHECK-NEXT: [[BYVAL_TEMP:%.*]] = alloca [[STRUCT_S:%.*]], align 1 | |
| // CHECK-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 4 | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[BYVAL_TEMP]], ptr align 1 [[S]], i32 20, i1 false) | |
| // CHECK-NEXT: call void @_Z4useS1S(ptr nofreeobj noundef align 1 dead_on_return dereferenceable(20) [[BYVAL_TEMP]]) #[[ATTR3:[0-9]+]] [ "convergencectrl"(token [[TMP0]]) ] | |
| // CHECK-NEXT: ret void | |
| // | |
| void case3(S s) { | |
| // struct argument passing | |
| useS(s); | |
| } | |
| // CHECK-LABEL: define hidden void @_Z5case41S( | |
| // CHECK-SAME: ptr nofreeobj noundef align 1 dead_on_return dereferenceable(20) [[S:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: [[ENTRY:.*:]] | |
| // CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.experimental.convergence.entry() | |
| // CHECK-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 4 | |
| // CHECK-NEXT: [[PLOCAL:%.*]] = alloca [[STRUCT_P:%.*]], align 1 | |
| // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S:%.*]], align 1 | |
| // CHECK-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 4 | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[S]], i32 20, i1 false) | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[PLOCAL]], ptr align 1 [[TMP]], i32 4, i1 false) | |
| // CHECK-NEXT: ret void | |
| // | |
| void case4(S s) { | |
| // derived to base conversion in initialization | |
| P pLocal = s; | |
| } | |
| // CHECK-LABEL: define hidden void @_Z5case51S( | |
| // CHECK-SAME: ptr nofreeobj noundef align 1 dead_on_return dereferenceable(20) [[S:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: [[ENTRY:.*:]] | |
| // CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.experimental.convergence.entry() | |
| // CHECK-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 4 | |
| // CHECK-NEXT: [[P:%.*]] = alloca [[STRUCT_P:%.*]], align 1 | |
| // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_P]], align 1 | |
| // CHECK-NEXT: [[TMP1:%.*]] = alloca [[STRUCT_S:%.*]], align 1 | |
| // CHECK-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 4 | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TMP1]], ptr align 1 [[S]], i32 20, i1 false) | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[P]], ptr align 1 [[TMP1]], i32 4, i1 false) | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[P]], i32 4, i1 false) | |
| // CHECK-NEXT: ret void | |
| // | |
| void case5(S s) { | |
| P p; | |
| // derived to base conversion in assignment | |
| p = s; | |
| } | |
| // CHECK-LABEL: define hidden void @_Z4useP1P( | |
| // CHECK-SAME: ptr nofreeobj noundef align 1 dead_on_return dereferenceable(4) [[P:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: [[ENTRY:.*:]] | |
| // CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.experimental.convergence.entry() | |
| // CHECK-NEXT: [[P_INDIRECT_ADDR:%.*]] = alloca ptr, align 4 | |
| // CHECK-NEXT: store ptr [[P]], ptr [[P_INDIRECT_ADDR]], align 4 | |
| // CHECK-NEXT: ret void | |
| // | |
| void useP(P p) {} | |
| // CHECK-LABEL: define hidden void @_Z5case61S( | |
| // CHECK-SAME: ptr nofreeobj noundef align 1 dead_on_return dereferenceable(20) [[S:%.*]]) #[[ATTR0]] { | |
| // CHECK-NEXT: [[ENTRY:.*:]] | |
| // CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.experimental.convergence.entry() | |
| // CHECK-NEXT: [[S_INDIRECT_ADDR:%.*]] = alloca ptr, align 4 | |
| // CHECK-NEXT: [[AGG_TMP:%.*]] = alloca [[STRUCT_P:%.*]], align 1 | |
| // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S:%.*]], align 1 | |
| // CHECK-NEXT: store ptr [[S]], ptr [[S_INDIRECT_ADDR]], align 4 | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[TMP]], ptr align 1 [[S]], i32 20, i1 false) | |
| // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr align 1 [[AGG_TMP]], ptr align 1 [[TMP]], i32 4, i1 false) | |
| // CHECK-NEXT: call void @_Z4useP1P(ptr nofreeobj noundef align 1 dead_on_return dereferenceable(4) [[AGG_TMP]]) #[[ATTR3]] [ "convergencectrl"(token [[TMP0]]) ] | |
| // CHECK-NEXT: ret void | |
| // | |
| void case6(S s) { | |
| // derived to base conversion in argument passing | |
| useP(s); | |
| } |