1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=optimize < %s | FileCheck %s -check-prefixes=CHECK,OPT 3; RUN: opt -mtriple=wasm32-unknown-unknown -S --passes=expand-variadics --expand-variadics-override=lowering < %s | FileCheck %s -check-prefixes=CHECK,ABI 4; REQUIRES: webassembly-registered-target 5 6declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) 7 8declare void @llvm.va_copy.p0(ptr, ptr) 9 10declare void @valist(ptr noundef) 11 12declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) 13 14declare void @llvm.va_start.p0(ptr) 15 16declare void @llvm.va_end.p0(ptr) 17 18 19define void @start_once(...) { 20; OPT-LABEL: @start_once( 21; OPT-NEXT: entry: 22; OPT-NEXT: [[VA_START:%.*]] = alloca ptr, align 4 23; OPT-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[VA_START]]) 24; OPT-NEXT: call void @llvm.va_start.p0(ptr [[VA_START]]) 25; OPT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VA_START]], align 4 26; OPT-NEXT: call void @start_once.valist(ptr [[TMP0]]) 27; OPT-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[VA_START]]) 28; OPT-NEXT: ret void 29; 30; ABI-LABEL: @start_once( 31; ABI-NEXT: entry: 32; ABI-NEXT: [[S:%.*]] = alloca ptr, align 4 33; ABI-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[S]]) 34; ABI-NEXT: store ptr [[VARARGS:%.*]], ptr [[S]], align 4 35; ABI-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S]], align 4 36; ABI-NEXT: call void @valist(ptr noundef [[TMP0]]) 37; ABI-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[S]]) 38; ABI-NEXT: ret void 39; 40entry: 41 %s = alloca ptr, align 4 42 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s) 43 call void @llvm.va_start.p0(ptr nonnull %s) 44 %0 = load ptr, ptr %s, align 4 45 call void @valist(ptr noundef %0) 46 call void @llvm.va_end.p0(ptr %s) 47 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s) 48 ret void 49} 50 51 52define void @start_twice(...) { 53; OPT-LABEL: @start_twice( 54; OPT-NEXT: entry: 55; OPT-NEXT: [[VA_START:%.*]] = alloca ptr, align 4 56; OPT-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[VA_START]]) 57; OPT-NEXT: call void @llvm.va_start.p0(ptr [[VA_START]]) 58; OPT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[VA_START]], align 4 59; OPT-NEXT: call void @start_twice.valist(ptr [[TMP0]]) 60; OPT-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr [[VA_START]]) 61; OPT-NEXT: ret void 62; 63; ABI-LABEL: @start_twice( 64; ABI-NEXT: entry: 65; ABI-NEXT: [[S0:%.*]] = alloca ptr, align 4 66; ABI-NEXT: [[S1:%.*]] = alloca ptr, align 4 67; ABI-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[S0]]) 68; ABI-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[S1]]) 69; ABI-NEXT: store ptr [[VARARGS:%.*]], ptr [[S0]], align 4 70; ABI-NEXT: [[TMP0:%.*]] = load ptr, ptr [[S0]], align 4 71; ABI-NEXT: call void @valist(ptr noundef [[TMP0]]) 72; ABI-NEXT: store ptr [[VARARGS]], ptr [[S1]], align 4 73; ABI-NEXT: [[TMP1:%.*]] = load ptr, ptr [[S1]], align 4 74; ABI-NEXT: call void @valist(ptr noundef [[TMP1]]) 75; ABI-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[S1]]) 76; ABI-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[S0]]) 77; ABI-NEXT: ret void 78; 79entry: 80 %s0 = alloca ptr, align 4 81 %s1 = alloca ptr, align 4 82 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s0) 83 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %s1) 84 call void @llvm.va_start.p0(ptr nonnull %s0) 85 %0 = load ptr, ptr %s0, align 4 86 call void @valist(ptr noundef %0) 87 call void @llvm.va_end.p0(ptr %s0) 88 call void @llvm.va_start.p0(ptr nonnull %s1) 89 %1 = load ptr, ptr %s1, align 4 90 call void @valist(ptr noundef %1) 91 call void @llvm.va_end.p0(ptr %s1) 92 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s1) 93 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %s0) 94 ret void 95} 96 97define void @copy(ptr noundef %va) { 98; CHECK-LABEL: @copy( 99; CHECK-NEXT: entry: 100; CHECK-NEXT: [[VA_ADDR:%.*]] = alloca ptr, align 4 101; CHECK-NEXT: [[CP:%.*]] = alloca ptr, align 4 102; CHECK-NEXT: store ptr [[VA:%.*]], ptr [[VA_ADDR]], align 4 103; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[CP]]) 104; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[CP]], ptr [[VA_ADDR]], i32 4, i1 false) 105; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[CP]], align 4 106; CHECK-NEXT: call void @valist(ptr noundef [[TMP0]]) 107; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[CP]]) 108; CHECK-NEXT: ret void 109; 110entry: 111 %va.addr = alloca ptr, align 4 112 %cp = alloca ptr, align 4 113 store ptr %va, ptr %va.addr, align 4 114 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %cp) 115 call void @llvm.va_copy.p0(ptr nonnull %cp, ptr nonnull %va.addr) 116 %0 = load ptr, ptr %cp, align 4 117 call void @valist(ptr noundef %0) 118 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %cp) 119 ret void 120} 121