1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -S -mtriple=nvptx64-- --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s 3 4%struct.S1 = type { i32, i8, i64 } 5%struct.S2 = type { i64, i64 } 6 7@__const.bar.s1 = private unnamed_addr constant %struct.S1 { i32 1, i8 1, i64 1 }, align 8 8@__const.qux.s = private unnamed_addr constant %struct.S2 { i64 1, i64 1 }, align 8 9 10define dso_local i32 @variadics1(i32 noundef %first, ...) { 11; CHECK-LABEL: define dso_local i32 @variadics1( 12; CHECK-SAME: i32 noundef [[FIRST:%.*]], ptr [[VARARGS:%.*]]) { 13; CHECK-NEXT: [[ENTRY:.*:]] 14; CHECK-NEXT: [[VLIST:%.*]] = alloca ptr, align 8 15; CHECK-NEXT: store ptr [[VARARGS]], ptr [[VLIST]], align 8 16; CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VLIST]], align 8 17; CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i64 4 18; CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VLIST]], align 8 19; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARGP_CUR]], align 4 20; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[FIRST]], [[TMP0]] 21; CHECK-NEXT: [[ARGP_CUR1:%.*]] = load ptr, ptr [[VLIST]], align 8 22; CHECK-NEXT: [[ARGP_NEXT2:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR1]], i64 4 23; CHECK-NEXT: store ptr [[ARGP_NEXT2]], ptr [[VLIST]], align 8 24; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARGP_CUR1]], align 4 25; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[ADD]], [[TMP1]] 26; CHECK-NEXT: [[ARGP_CUR4:%.*]] = load ptr, ptr [[VLIST]], align 8 27; CHECK-NEXT: [[ARGP_NEXT5:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR4]], i64 4 28; CHECK-NEXT: store ptr [[ARGP_NEXT5]], ptr [[VLIST]], align 8 29; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARGP_CUR4]], align 4 30; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[ADD3]], [[TMP2]] 31; CHECK-NEXT: [[ARGP_CUR7:%.*]] = load ptr, ptr [[VLIST]], align 8 32; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR7]], i32 7 33; CHECK-NEXT: [[ARGP_CUR7_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP3]], i64 -8) 34; CHECK-NEXT: [[ARGP_NEXT8:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR7_ALIGNED]], i64 8 35; CHECK-NEXT: store ptr [[ARGP_NEXT8]], ptr [[VLIST]], align 8 36; CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[ARGP_CUR7_ALIGNED]], align 8 37; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ADD6]] to i64 38; CHECK-NEXT: [[ADD9:%.*]] = add nsw i64 [[CONV]], [[TMP4]] 39; CHECK-NEXT: [[CONV10:%.*]] = trunc i64 [[ADD9]] to i32 40; CHECK-NEXT: [[ARGP_CUR11:%.*]] = load ptr, ptr [[VLIST]], align 8 41; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR11]], i32 7 42; CHECK-NEXT: [[ARGP_CUR11_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP5]], i64 -8) 43; CHECK-NEXT: [[ARGP_NEXT12:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR11_ALIGNED]], i64 8 44; CHECK-NEXT: store ptr [[ARGP_NEXT12]], ptr [[VLIST]], align 8 45; CHECK-NEXT: [[TMP6:%.*]] = load double, ptr [[ARGP_CUR11_ALIGNED]], align 8 46; CHECK-NEXT: [[CONV13:%.*]] = sitofp i32 [[CONV10]] to double 47; CHECK-NEXT: [[ADD14:%.*]] = fadd double [[CONV13]], [[TMP6]] 48; CHECK-NEXT: [[CONV15:%.*]] = fptosi double [[ADD14]] to i32 49; CHECK-NEXT: [[ARGP_CUR16:%.*]] = load ptr, ptr [[VLIST]], align 8 50; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR16]], i32 7 51; CHECK-NEXT: [[ARGP_CUR16_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP7]], i64 -8) 52; CHECK-NEXT: [[ARGP_NEXT17:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR16_ALIGNED]], i64 8 53; CHECK-NEXT: store ptr [[ARGP_NEXT17]], ptr [[VLIST]], align 8 54; CHECK-NEXT: [[TMP8:%.*]] = load double, ptr [[ARGP_CUR16_ALIGNED]], align 8 55; CHECK-NEXT: [[CONV18:%.*]] = sitofp i32 [[CONV15]] to double 56; CHECK-NEXT: [[ADD19:%.*]] = fadd double [[CONV18]], [[TMP8]] 57; CHECK-NEXT: [[CONV20:%.*]] = fptosi double [[ADD19]] to i32 58; CHECK-NEXT: ret i32 [[CONV20]] 59; 60entry: 61 %vlist = alloca ptr, align 8 62 call void @llvm.va_start.p0(ptr %vlist) 63 %argp.cur = load ptr, ptr %vlist, align 8 64 %argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 4 65 store ptr %argp.next, ptr %vlist, align 8 66 %0 = load i32, ptr %argp.cur, align 4 67 %add = add nsw i32 %first, %0 68 %argp.cur1 = load ptr, ptr %vlist, align 8 69 %argp.next2 = getelementptr inbounds i8, ptr %argp.cur1, i64 4 70 store ptr %argp.next2, ptr %vlist, align 8 71 %1 = load i32, ptr %argp.cur1, align 4 72 %add3 = add nsw i32 %add, %1 73 %argp.cur4 = load ptr, ptr %vlist, align 8 74 %argp.next5 = getelementptr inbounds i8, ptr %argp.cur4, i64 4 75 store ptr %argp.next5, ptr %vlist, align 8 76 %2 = load i32, ptr %argp.cur4, align 4 77 %add6 = add nsw i32 %add3, %2 78 %argp.cur7 = load ptr, ptr %vlist, align 8 79 %3 = getelementptr inbounds i8, ptr %argp.cur7, i32 7 80 %argp.cur7.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %3, i64 -8) 81 %argp.next8 = getelementptr inbounds i8, ptr %argp.cur7.aligned, i64 8 82 store ptr %argp.next8, ptr %vlist, align 8 83 %4 = load i64, ptr %argp.cur7.aligned, align 8 84 %conv = sext i32 %add6 to i64 85 %add9 = add nsw i64 %conv, %4 86 %conv10 = trunc i64 %add9 to i32 87 %argp.cur11 = load ptr, ptr %vlist, align 8 88 %5 = getelementptr inbounds i8, ptr %argp.cur11, i32 7 89 %argp.cur11.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %5, i64 -8) 90 %argp.next12 = getelementptr inbounds i8, ptr %argp.cur11.aligned, i64 8 91 store ptr %argp.next12, ptr %vlist, align 8 92 %6 = load double, ptr %argp.cur11.aligned, align 8 93 %conv13 = sitofp i32 %conv10 to double 94 %add14 = fadd double %conv13, %6 95 %conv15 = fptosi double %add14 to i32 96 %argp.cur16 = load ptr, ptr %vlist, align 8 97 %7 = getelementptr inbounds i8, ptr %argp.cur16, i32 7 98 %argp.cur16.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %7, i64 -8) 99 %argp.next17 = getelementptr inbounds i8, ptr %argp.cur16.aligned, i64 8 100 store ptr %argp.next17, ptr %vlist, align 8 101 %8 = load double, ptr %argp.cur16.aligned, align 8 102 %conv18 = sitofp i32 %conv15 to double 103 %add19 = fadd double %conv18, %8 104 %conv20 = fptosi double %add19 to i32 105 call void @llvm.va_end.p0(ptr %vlist) 106 ret i32 %conv20 107} 108 109declare void @llvm.va_start.p0(ptr) 110 111declare ptr @llvm.ptrmask.p0.i64(ptr, i64) 112 113declare void @llvm.va_end.p0(ptr) 114 115define dso_local i32 @foo() { 116; CHECK-LABEL: define dso_local i32 @foo() { 117; CHECK-NEXT: [[ENTRY:.*:]] 118; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[FOO_VARARG:%.*]], align 8 119; CHECK-NEXT: [[CONV:%.*]] = sext i8 1 to i32 120; CHECK-NEXT: [[CONV1:%.*]] = sext i16 1 to i32 121; CHECK-NEXT: [[CONV2:%.*]] = fpext float 1.000000e+00 to double 122; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 40, ptr [[VARARG_BUFFER]]) 123; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[FOO_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0 124; CHECK-NEXT: store i32 [[CONV]], ptr [[TMP0]], align 4 125; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[FOO_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 1 126; CHECK-NEXT: store i32 [[CONV1]], ptr [[TMP1]], align 4 127; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[FOO_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 2 128; CHECK-NEXT: store i32 1, ptr [[TMP2]], align 4 129; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw [[FOO_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 4 130; CHECK-NEXT: store i64 1, ptr [[TMP3]], align 8 131; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw [[FOO_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 5 132; CHECK-NEXT: store double [[CONV2]], ptr [[TMP4]], align 8 133; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw [[FOO_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 6 134; CHECK-NEXT: store double 1.000000e+00, ptr [[TMP5]], align 8 135; CHECK-NEXT: [[CALL:%.*]] = call i32 @variadics1(i32 noundef 1, ptr [[VARARG_BUFFER]]) 136; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 40, ptr [[VARARG_BUFFER]]) 137; CHECK-NEXT: ret i32 [[CALL]] 138; 139entry: 140 %conv = sext i8 1 to i32 141 %conv1 = sext i16 1 to i32 142 %conv2 = fpext float 1.000000e+00 to double 143 %call = call i32 (i32, ...) @variadics1(i32 noundef 1, i32 noundef %conv, i32 noundef %conv1, i32 noundef 1, i64 noundef 1, double noundef %conv2, double noundef 1.000000e+00) 144 ret i32 %call 145} 146 147define dso_local i32 @variadics2(i32 noundef %first, ...) { 148; CHECK-LABEL: define dso_local i32 @variadics2( 149; CHECK-SAME: i32 noundef [[FIRST:%.*]], ptr [[VARARGS:%.*]]) { 150; CHECK-NEXT: [[ENTRY:.*:]] 151; CHECK-NEXT: [[VLIST:%.*]] = alloca ptr, align 8 152; CHECK-NEXT: [[S1_SROA_3:%.*]] = alloca [3 x i8], align 1 153; CHECK-NEXT: store ptr [[VARARGS]], ptr [[VLIST]], align 8 154; CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VLIST]], align 8 155; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 156; CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -8) 157; CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16 158; CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VLIST]], align 8 159; CHECK-NEXT: [[S1_SROA_0_0_COPYLOAD:%.*]] = load i32, ptr [[ARGP_CUR_ALIGNED]], align 8 160; CHECK-NEXT: [[S1_SROA_2_0_ARGP_CUR_ALIGNED_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 4 161; CHECK-NEXT: [[S1_SROA_2_0_COPYLOAD:%.*]] = load i8, ptr [[S1_SROA_2_0_ARGP_CUR_ALIGNED_SROA_IDX]], align 4 162; CHECK-NEXT: [[S1_SROA_3_0_ARGP_CUR_ALIGNED_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 5 163; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[S1_SROA_3]], ptr align 1 [[S1_SROA_3_0_ARGP_CUR_ALIGNED_SROA_IDX]], i64 3, i1 false) 164; CHECK-NEXT: [[S1_SROA_31_0_ARGP_CUR_ALIGNED_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 8 165; CHECK-NEXT: [[S1_SROA_31_0_COPYLOAD:%.*]] = load i64, ptr [[S1_SROA_31_0_ARGP_CUR_ALIGNED_SROA_IDX]], align 8 166; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[FIRST]], [[S1_SROA_0_0_COPYLOAD]] 167; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[S1_SROA_2_0_COPYLOAD]] to i32 168; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD]], [[CONV]] 169; CHECK-NEXT: [[CONV2:%.*]] = sext i32 [[ADD1]] to i64 170; CHECK-NEXT: [[ADD3:%.*]] = add nsw i64 [[CONV2]], [[S1_SROA_31_0_COPYLOAD]] 171; CHECK-NEXT: [[CONV4:%.*]] = trunc i64 [[ADD3]] to i32 172; CHECK-NEXT: ret i32 [[CONV4]] 173; 174entry: 175 %vlist = alloca ptr, align 8 176 %s1.sroa.3 = alloca [3 x i8], align 1 177 call void @llvm.va_start.p0(ptr %vlist) 178 %argp.cur = load ptr, ptr %vlist, align 8 179 %0 = getelementptr inbounds i8, ptr %argp.cur, i32 7 180 %argp.cur.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %0, i64 -8) 181 %argp.next = getelementptr inbounds i8, ptr %argp.cur.aligned, i64 16 182 store ptr %argp.next, ptr %vlist, align 8 183 %s1.sroa.0.0.copyload = load i32, ptr %argp.cur.aligned, align 8 184 %s1.sroa.2.0.argp.cur.aligned.sroa_idx = getelementptr inbounds i8, ptr %argp.cur.aligned, i64 4 185 %s1.sroa.2.0.copyload = load i8, ptr %s1.sroa.2.0.argp.cur.aligned.sroa_idx, align 4 186 %s1.sroa.3.0.argp.cur.aligned.sroa_idx = getelementptr inbounds i8, ptr %argp.cur.aligned, i64 5 187 call void @llvm.memcpy.p0.p0.i64(ptr align 1 %s1.sroa.3, ptr align 1 %s1.sroa.3.0.argp.cur.aligned.sroa_idx, i64 3, i1 false) 188 %s1.sroa.31.0.argp.cur.aligned.sroa_idx = getelementptr inbounds i8, ptr %argp.cur.aligned, i64 8 189 %s1.sroa.31.0.copyload = load i64, ptr %s1.sroa.31.0.argp.cur.aligned.sroa_idx, align 8 190 %add = add nsw i32 %first, %s1.sroa.0.0.copyload 191 %conv = sext i8 %s1.sroa.2.0.copyload to i32 192 %add1 = add nsw i32 %add, %conv 193 %conv2 = sext i32 %add1 to i64 194 %add3 = add nsw i64 %conv2, %s1.sroa.31.0.copyload 195 %conv4 = trunc i64 %add3 to i32 196 call void @llvm.va_end.p0(ptr %vlist) 197 ret i32 %conv4 198} 199 200declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) 201 202define dso_local i32 @bar() { 203; CHECK-LABEL: define dso_local i32 @bar() { 204; CHECK-NEXT: [[ENTRY:.*:]] 205; CHECK-NEXT: [[S1_SROA_3:%.*]] = alloca [3 x i8], align 1 206; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[BAR_VARARG:%.*]], align 8 207; CHECK-NEXT: [[S1_SROA_0_0_COPYLOAD:%.*]] = load i32, ptr @__const.bar.s1, align 8 208; CHECK-NEXT: [[S1_SROA_2_0_COPYLOAD:%.*]] = load i8, ptr getelementptr inbounds (i8, ptr @__const.bar.s1, i64 4), align 4 209; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[S1_SROA_3]], ptr align 1 getelementptr inbounds (i8, ptr @__const.bar.s1, i64 5), i64 3, i1 false) 210; CHECK-NEXT: [[S1_SROA_31_0_COPYLOAD:%.*]] = load i64, ptr getelementptr inbounds (i8, ptr @__const.bar.s1, i64 8), align 8 211; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 16, ptr [[VARARG_BUFFER]]) 212; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[BAR_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0 213; CHECK-NEXT: store i32 [[S1_SROA_0_0_COPYLOAD]], ptr [[TMP0]], align 4 214; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[BAR_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 1 215; CHECK-NEXT: store i8 [[S1_SROA_2_0_COPYLOAD]], ptr [[TMP1]], align 1 216; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw [[BAR_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 3 217; CHECK-NEXT: store i64 [[S1_SROA_31_0_COPYLOAD]], ptr [[TMP2]], align 8 218; CHECK-NEXT: [[CALL:%.*]] = call i32 @variadics2(i32 noundef 1, ptr [[VARARG_BUFFER]]) 219; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 16, ptr [[VARARG_BUFFER]]) 220; CHECK-NEXT: ret i32 [[CALL]] 221; 222entry: 223 %s1.sroa.3 = alloca [3 x i8], align 1 224 %s1.sroa.0.0.copyload = load i32, ptr @__const.bar.s1, align 8 225 %s1.sroa.2.0.copyload = load i8, ptr getelementptr inbounds (i8, ptr @__const.bar.s1, i64 4), align 4 226 call void @llvm.memcpy.p0.p0.i64(ptr align 1 %s1.sroa.3, ptr align 1 getelementptr inbounds (i8, ptr @__const.bar.s1, i64 5), i64 3, i1 false) 227 %s1.sroa.31.0.copyload = load i64, ptr getelementptr inbounds (i8, ptr @__const.bar.s1, i64 8), align 8 228 %call = call i32 (i32, ...) @variadics2(i32 noundef 1, i32 %s1.sroa.0.0.copyload, i8 %s1.sroa.2.0.copyload, i64 %s1.sroa.31.0.copyload) 229 ret i32 %call 230} 231 232define dso_local i32 @variadics3(i32 noundef %first, ...) { 233; CHECK-LABEL: define dso_local i32 @variadics3( 234; CHECK-SAME: i32 noundef [[FIRST:%.*]], ptr [[VARARGS:%.*]]) { 235; CHECK-NEXT: [[ENTRY:.*:]] 236; CHECK-NEXT: [[VLIST:%.*]] = alloca ptr, align 8 237; CHECK-NEXT: store ptr [[VARARGS]], ptr [[VLIST]], align 8 238; CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VLIST]], align 8 239; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 15 240; CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -16) 241; CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 16 242; CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VLIST]], align 8 243; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[ARGP_CUR_ALIGNED]], align 16 244; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x i32> [[TMP1]], i64 0 245; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x i32> [[TMP1]], i64 1 246; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP2]], [[TMP3]] 247; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x i32> [[TMP1]], i64 2 248; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD]], [[TMP4]] 249; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x i32> [[TMP1]], i64 3 250; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[ADD1]], [[TMP5]] 251; CHECK-NEXT: ret i32 [[ADD2]] 252; 253entry: 254 %vlist = alloca ptr, align 8 255 call void @llvm.va_start.p0(ptr %vlist) 256 %argp.cur = load ptr, ptr %vlist, align 8 257 %0 = getelementptr inbounds i8, ptr %argp.cur, i32 15 258 %argp.cur.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %0, i64 -16) 259 %argp.next = getelementptr inbounds i8, ptr %argp.cur.aligned, i64 16 260 store ptr %argp.next, ptr %vlist, align 8 261 %1 = load <4 x i32>, ptr %argp.cur.aligned, align 16 262 call void @llvm.va_end.p0(ptr %vlist) 263 %2 = extractelement <4 x i32> %1, i64 0 264 %3 = extractelement <4 x i32> %1, i64 1 265 %add = add nsw i32 %2, %3 266 %4 = extractelement <4 x i32> %1, i64 2 267 %add1 = add nsw i32 %add, %4 268 %5 = extractelement <4 x i32> %1, i64 3 269 %add2 = add nsw i32 %add1, %5 270 ret i32 %add2 271} 272 273define dso_local i32 @baz() { 274; CHECK-LABEL: define dso_local i32 @baz() { 275; CHECK-NEXT: [[ENTRY:.*:]] 276; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[BAZ_VARARG:%.*]], align 16 277; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 16, ptr [[VARARG_BUFFER]]) 278; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[BAZ_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0 279; CHECK-NEXT: store <4 x i32> splat (i32 1), ptr [[TMP0]], align 16 280; CHECK-NEXT: [[CALL:%.*]] = call i32 @variadics3(i32 noundef 1, ptr [[VARARG_BUFFER]]) 281; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 16, ptr [[VARARG_BUFFER]]) 282; CHECK-NEXT: ret i32 [[CALL]] 283; 284entry: 285 %call = call i32 (i32, ...) @variadics3(i32 noundef 1, <4 x i32> noundef <i32 1, i32 1, i32 1, i32 1>) 286 ret i32 %call 287} 288 289define dso_local i32 @variadics4(ptr noundef byval(%struct.S2) align 8 %first, ...) { 290; CHECK-LABEL: define dso_local i32 @variadics4( 291; CHECK-SAME: ptr noundef byval([[STRUCT_S2:%.*]]) align 8 [[FIRST:%.*]], ptr [[VARARGS:%.*]]) { 292; CHECK-NEXT: [[ENTRY:.*:]] 293; CHECK-NEXT: [[VLIST:%.*]] = alloca ptr, align 8 294; CHECK-NEXT: store ptr [[VARARGS]], ptr [[VLIST]], align 8 295; CHECK-NEXT: [[ARGP_CUR:%.*]] = load ptr, ptr [[VLIST]], align 8 296; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR]], i32 7 297; CHECK-NEXT: [[ARGP_CUR_ALIGNED:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[TMP0]], i64 -8) 298; CHECK-NEXT: [[ARGP_NEXT:%.*]] = getelementptr inbounds i8, ptr [[ARGP_CUR_ALIGNED]], i64 8 299; CHECK-NEXT: store ptr [[ARGP_NEXT]], ptr [[VLIST]], align 8 300; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[ARGP_CUR_ALIGNED]], align 8 301; CHECK-NEXT: [[X1:%.*]] = getelementptr inbounds [[STRUCT_S2]], ptr [[FIRST]], i32 0, i32 0 302; CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[X1]], align 8 303; CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds [[STRUCT_S2]], ptr [[FIRST]], i32 0, i32 1 304; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[Y]], align 8 305; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[TMP2]], [[TMP3]] 306; CHECK-NEXT: [[ADD2:%.*]] = add nsw i64 [[ADD]], [[TMP1]] 307; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[ADD2]] to i32 308; CHECK-NEXT: ret i32 [[CONV]] 309; 310entry: 311 %vlist = alloca ptr, align 8 312 call void @llvm.va_start.p0(ptr %vlist) 313 %argp.cur = load ptr, ptr %vlist, align 8 314 %0 = getelementptr inbounds i8, ptr %argp.cur, i32 7 315 %argp.cur.aligned = call ptr @llvm.ptrmask.p0.i64(ptr %0, i64 -8) 316 %argp.next = getelementptr inbounds i8, ptr %argp.cur.aligned, i64 8 317 store ptr %argp.next, ptr %vlist, align 8 318 %1 = load i64, ptr %argp.cur.aligned, align 8 319 %x1 = getelementptr inbounds %struct.S2, ptr %first, i32 0, i32 0 320 %2 = load i64, ptr %x1, align 8 321 %y = getelementptr inbounds %struct.S2, ptr %first, i32 0, i32 1 322 %3 = load i64, ptr %y, align 8 323 %add = add nsw i64 %2, %3 324 %add2 = add nsw i64 %add, %1 325 %conv = trunc i64 %add2 to i32 326 call void @llvm.va_end.p0(ptr %vlist) 327 ret i32 %conv 328} 329 330define dso_local void @qux() { 331; CHECK-LABEL: define dso_local void @qux() { 332; CHECK-NEXT: [[ENTRY:.*:]] 333; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S2:%.*]], align 8 334; CHECK-NEXT: [[VARARG_BUFFER:%.*]] = alloca [[QUX_VARARG:%.*]], align 8 335; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[S]], ptr align 8 @__const.qux.s, i64 16, i1 false) 336; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 8, ptr [[VARARG_BUFFER]]) 337; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[QUX_VARARG]], ptr [[VARARG_BUFFER]], i32 0, i32 0 338; CHECK-NEXT: store i64 1, ptr [[TMP0]], align 8 339; CHECK-NEXT: [[CALL:%.*]] = call i32 @variadics4(ptr noundef byval([[STRUCT_S2]]) align 8 [[S]], ptr [[VARARG_BUFFER]]) 340; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 8, ptr [[VARARG_BUFFER]]) 341; CHECK-NEXT: ret void 342; 343entry: 344 %s = alloca %struct.S2, align 8 345 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %s, ptr align 8 @__const.qux.s, i64 16, i1 false) 346 %call = call i32 (ptr, ...) @variadics4(ptr noundef byval(%struct.S2) align 8 %s, i64 noundef 1) 347 ret void 348} 349