brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.3 KiB · 3094165 Raw
187 lines · cpp
1// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 62// REQUIRES: webassembly-registered-target3 4// Simple calls to known variadic functions that are completely elided when5// optimisations are on This is a functional check that the expand-variadic pass6// is consistent with clang's va_arg handling7 8// When expand-variadics is added to the default pipeline, clang -O1 will9// suffice here -Wno-varargs avoids warning second argument to 'va_start' is not10// the last named parameter11 12// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -Wno-varargs -O1 -emit-llvm -o - | opt - -S --passes='module(expand-variadics,default<O1>)' --expand-variadics-override=optimize -o - | FileCheck %s13 14#include <stdarg.h>15#include <stdint.h>16 17template <typename X, typename Y> static X first(...) {18  va_list va;19  __builtin_va_start(va, 0);20  X r = va_arg(va, X);21  va_end(va);22  return r;23}24 25template <typename X, typename Y> static Y second(...) {26  va_list va;27  __builtin_va_start(va, 0);28  va_arg(va, X);29  Y r = va_arg(va, Y);30  va_end(va);31  return r;32}33 34extern "C" {35 36// CHECK-LABEL: define noundef i32 @first_pair_i32(37// CHECK-SAME: i32 noundef returned [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {38// CHECK-NEXT:  [[ENTRY:.*:]]39// CHECK-NEXT:    ret i32 [[X]]40//41int first_pair_i32(int x, int y) { return first<int, int>(x, y); }42 43// CHECK-LABEL: define noundef i32 @second_pair_i32(44// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {45// CHECK-NEXT:  [[ENTRY:.*:]]46// CHECK-NEXT:    ret i32 [[Y]]47//48int second_pair_i32(int x, int y) { return second<int, int>(x, y); }49 50// CHECK-LABEL: define noundef double @first_pair_f64(51// CHECK-SAME: double noundef returned [[X:%.*]], double noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {52// CHECK-NEXT:  [[ENTRY:.*:]]53// CHECK-NEXT:    ret double [[X]]54//55double first_pair_f64(double x, double y) {56  return first<double, double>(x, y);57}58 59// CHECK-LABEL: define noundef double @second_pair_f64(60// CHECK-SAME: double noundef [[X:%.*]], double noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {61// CHECK-NEXT:  [[ENTRY:.*:]]62// CHECK-NEXT:    ret double [[Y]]63//64double second_pair_f64(double x, double y) {65  return second<double, double>(x, y);66}67}68 69extern "C" {70 71// CHECK-LABEL: define noundef i32 @first_i32_f64(72// CHECK-SAME: i32 noundef returned [[X:%.*]], double noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {73// CHECK-NEXT:  [[ENTRY:.*:]]74// CHECK-NEXT:    ret i32 [[X]]75//76int first_i32_f64(int x, double y) { return first<int, double>(x, y); }77 78// CHECK-LABEL: define noundef double @second_i32_f64(79// CHECK-SAME: i32 noundef [[X:%.*]], double noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {80// CHECK-NEXT:  [[ENTRY:.*:]]81// CHECK-NEXT:    ret double [[Y]]82//83double second_i32_f64(int x, double y) { return second<int, double>(x, y); }84 85// CHECK-LABEL: define noundef double @first_f64_i32(86// CHECK-SAME: double noundef returned [[X:%.*]], i32 noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {87// CHECK-NEXT:  [[ENTRY:.*:]]88// CHECK-NEXT:    ret double [[X]]89//90double first_f64_i32(double x, int y) { return first<double, int>(x, y); }91 92// CHECK-LABEL: define noundef i32 @second_f64_i32(93// CHECK-SAME: double noundef [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {94// CHECK-NEXT:  [[ENTRY:.*:]]95// CHECK-NEXT:    ret i32 [[Y]]96//97int second_f64_i32(double x, int y) { return second<double, int>(x, y); }98}99 100extern "C" {101typedef uint64_t ulong2 __attribute__((__vector_size__(16), __aligned__(16)));102 103// CHECK-LABEL: define noundef i32 @first_i32_ulong2(104// CHECK-SAME: i32 noundef returned [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {105// CHECK-NEXT:  [[ENTRY:.*:]]106// CHECK-NEXT:    ret i32 [[X]]107//108int first_i32_ulong2(int x, ulong2 *y) { return first<int, ulong2>(x, *y); }109 110// CHECK-LABEL: define void @second_i32_ulong2(111// CHECK-SAME: i32 noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {112// CHECK-NEXT:  [[ENTRY:.*:]]113// CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[Y]], align 16, !tbaa [[DOUBLE_TBAA6:![0-9]+]]114// CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[DOUBLE_TBAA6]]115// CHECK-NEXT:    ret void116//117void second_i32_ulong2(int x, ulong2 *y, ulong2 *r) {118  *r = second<int, ulong2>(x, *y);119}120 121// CHECK-LABEL: define void @first_ulong2_i32(122// CHECK-SAME: ptr noundef readonly captures(none) [[X:%.*]], i32 noundef [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 16)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {123// CHECK-NEXT:  [[ENTRY:.*:]]124// CHECK-NEXT:    [[TMP0:%.*]] = load <2 x i64>, ptr [[X]], align 16, !tbaa [[DOUBLE_TBAA6]]125// CHECK-NEXT:    store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[DOUBLE_TBAA6]]126// CHECK-NEXT:    ret void127//128void first_ulong2_i32(ulong2 *x, int y, ulong2 *r) {129  *r = first<ulong2, int>(*x, y);130}131 132// CHECK-LABEL: define noundef i32 @second_ulong2_i32(133// CHECK-SAME: ptr noundef readonly captures(none) [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {134// CHECK-NEXT:  [[ENTRY:.*:]]135// CHECK-NEXT:    ret i32 [[Y]]136//137int second_ulong2_i32(ulong2 *x, int y) { return second<ulong2, int>(*x, y); }138}139 140// ascending alignment141typedef struct {142  char c;143  short s;144  int i;145  long l;146  float f;147  double d;148} asc;149 150extern "C" {151 152// CHECK-LABEL: define noundef i32 @first_i32_asc(153// CHECK-SAME: i32 noundef returned [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {154// CHECK-NEXT:  [[ENTRY:.*:]]155// CHECK-NEXT:    ret i32 [[X]]156//157int first_i32_asc(int x, asc *y) { return first<int, asc>(x, *y); }158 159// CHECK-LABEL: define void @second_i32_asc(160// CHECK-SAME: i32 noundef [[X:%.*]], ptr noundef readonly captures(none) [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {161// CHECK-NEXT:  [[ENTRY:.*:]]162// CHECK-NEXT:    tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[Y]], i32 24, i1 false)163// CHECK-NEXT:    ret void164//165void second_i32_asc(int x, asc *y, asc *r) { *r = second<int, asc>(x, *y); }166 167// CHECK-LABEL: define void @first_asc_i32(168// CHECK-SAME: ptr noundef readonly captures(none) [[X:%.*]], i32 noundef [[Y:%.*]], ptr noundef writeonly captures(none) initializes((0, 24)) [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {169// CHECK-NEXT:  [[ENTRY:.*:]]170// CHECK-NEXT:    tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[X]], i32 24, i1 false)171// CHECK-NEXT:    ret void172//173void first_asc_i32(asc *x, int y, asc *r) { *r = first<asc, int>(*x, y); }174 175// CHECK-LABEL: define noundef i32 @second_asc_i32(176// CHECK-SAME: ptr noundef readonly captures(none) [[X:%.*]], i32 noundef returned [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] {177// CHECK-NEXT:  [[ENTRY:.*:]]178// CHECK-NEXT:    ret i32 [[Y]]179//180int second_asc_i32(asc *x, int y) { return second<asc, int>(*x, y); }181}182//.183// CHECK: [[META4:![0-9]+]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}184// CHECK: [[META5]] = !{!"Simple C++ TBAA"}185// CHECK: [[DOUBLE_TBAA6]] = !{[[META4]], [[META4]], i64 0}186//.187