244 lines · c
1// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 62// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - \3// RUN: | FileCheck %s4//5// Test __sync_ builtins for __int128 aligned to 16 bytes.6 7#include <stdint.h>8 9__int128 Ptr __attribute__((aligned(16)));10__int128 Val __attribute__((aligned(16)));11__int128 OldVal __attribute__((aligned(16)));12 13// CHECK-LABEL: define dso_local void @f1(14// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {15// CHECK-NEXT: [[ENTRY:.*:]]16// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6:![0-9]+]]17// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr @Ptr, i128 [[TMP0]] seq_cst, align 1618// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]19// CHECK-NEXT: ret void20//21__int128 f1() {22 return __sync_fetch_and_add(&Ptr, Val);23}24 25// CHECK-LABEL: define dso_local void @f2(26// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {27// CHECK-NEXT: [[ENTRY:.*:]]28// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]29// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw sub ptr @Ptr, i128 [[TMP0]] seq_cst, align 1630// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]31// CHECK-NEXT: ret void32//33__int128 f2() {34 return __sync_fetch_and_sub(&Ptr, Val);35}36 37// CHECK-LABEL: define dso_local void @f3(38// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {39// CHECK-NEXT: [[ENTRY:.*:]]40// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]41// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr @Ptr, i128 [[TMP0]] seq_cst, align 1642// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]43// CHECK-NEXT: ret void44//45__int128 f3() {46 return __sync_fetch_and_or(&Ptr, Val);47}48 49// CHECK-LABEL: define dso_local void @f4(50// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {51// CHECK-NEXT: [[ENTRY:.*:]]52// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]53// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw and ptr @Ptr, i128 [[TMP0]] seq_cst, align 1654// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]55// CHECK-NEXT: ret void56//57__int128 f4() {58 return __sync_fetch_and_and(&Ptr, Val);59}60 61// CHECK-LABEL: define dso_local void @f5(62// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {63// CHECK-NEXT: [[ENTRY:.*:]]64// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]65// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xor ptr @Ptr, i128 [[TMP0]] seq_cst, align 1666// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]67// CHECK-NEXT: ret void68//69__int128 f5() {70 return __sync_fetch_and_xor(&Ptr, Val);71}72 73// CHECK-LABEL: define dso_local void @f6(74// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {75// CHECK-NEXT: [[ENTRY:.*:]]76// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]77// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw nand ptr @Ptr, i128 [[TMP0]] seq_cst, align 1678// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]79// CHECK-NEXT: ret void80//81__int128 f6() {82 return __sync_fetch_and_nand(&Ptr, Val);83}84 85// CHECK-LABEL: define dso_local void @f7(86// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {87// CHECK-NEXT: [[ENTRY:.*:]]88// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]89// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr @Ptr, i128 [[TMP0]] seq_cst, align 1690// CHECK-NEXT: [[TMP2:%.*]] = add i128 [[TMP1]], [[TMP0]]91// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]92// CHECK-NEXT: ret void93//94__int128 f7() {95 return __sync_add_and_fetch(&Ptr, Val);96}97 98// CHECK-LABEL: define dso_local void @f8(99// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {100// CHECK-NEXT: [[ENTRY:.*:]]101// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]102// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw sub ptr @Ptr, i128 [[TMP0]] seq_cst, align 16103// CHECK-NEXT: [[TMP2:%.*]] = sub i128 [[TMP1]], [[TMP0]]104// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]105// CHECK-NEXT: ret void106//107__int128 f8() {108 return __sync_sub_and_fetch(&Ptr, Val);109}110 111// CHECK-LABEL: define dso_local void @f9(112// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {113// CHECK-NEXT: [[ENTRY:.*:]]114// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]115// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr @Ptr, i128 [[TMP0]] seq_cst, align 16116// CHECK-NEXT: [[TMP2:%.*]] = or i128 [[TMP1]], [[TMP0]]117// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]118// CHECK-NEXT: ret void119//120__int128 f9() {121 return __sync_or_and_fetch(&Ptr, Val);122}123 124// CHECK-LABEL: define dso_local void @f10(125// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {126// CHECK-NEXT: [[ENTRY:.*:]]127// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]128// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw and ptr @Ptr, i128 [[TMP0]] seq_cst, align 16129// CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]]130// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]131// CHECK-NEXT: ret void132//133__int128 f10() {134 return __sync_and_and_fetch(&Ptr, Val);135}136 137// CHECK-LABEL: define dso_local void @f11(138// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {139// CHECK-NEXT: [[ENTRY:.*:]]140// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]141// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xor ptr @Ptr, i128 [[TMP0]] seq_cst, align 16142// CHECK-NEXT: [[TMP2:%.*]] = xor i128 [[TMP1]], [[TMP0]]143// CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]144// CHECK-NEXT: ret void145//146__int128 f11() {147 return __sync_xor_and_fetch(&Ptr, Val);148}149 150// CHECK-LABEL: define dso_local void @f12(151// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {152// CHECK-NEXT: [[ENTRY:.*:]]153// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]154// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw nand ptr @Ptr, i128 [[TMP0]] seq_cst, align 16155// CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]]156// CHECK-NEXT: [[TMP3:%.*]] = xor i128 [[TMP2]], -1157// CHECK-NEXT: store i128 [[TMP3]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]158// CHECK-NEXT: ret void159//160__int128 f12() {161 return __sync_nand_and_fetch(&Ptr, Val);162}163 164// CHECK-LABEL: define dso_local zeroext i1 @f13(165// CHECK-SAME: ) local_unnamed_addr #[[ATTR1:[0-9]+]] {166// CHECK-NEXT: [[ENTRY:.*:]]167// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @OldVal, align 16, !tbaa [[__INT128_TBAA6]]168// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]169// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr @Ptr, i128 [[TMP0]], i128 [[TMP1]] seq_cst seq_cst, align 16170// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i128, i1 } [[TMP2]], 1171// CHECK-NEXT: ret i1 [[TMP3]]172//173_Bool f13() {174 return __sync_bool_compare_and_swap(&Ptr, OldVal, Val);175}176 177// CHECK-LABEL: define dso_local void @f14(178// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {179// CHECK-NEXT: [[ENTRY:.*:]]180// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @OldVal, align 16, !tbaa [[__INT128_TBAA6]]181// CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]182// CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr @Ptr, i128 [[TMP0]], i128 [[TMP1]] seq_cst seq_cst, align 16183// CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i128, i1 } [[TMP2]], 0184// CHECK-NEXT: store i128 [[TMP3]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]185// CHECK-NEXT: ret void186//187__int128 f14() {188 return __sync_val_compare_and_swap(&Ptr, OldVal, Val);189}190 191// CHECK-LABEL: define dso_local void @f15(192// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {193// CHECK-NEXT: [[ENTRY:.*:]]194// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]195// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr @Ptr, i128 [[TMP0]] seq_cst, align 16196// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]197// CHECK-NEXT: ret void198//199__int128 f15() {200 return __sync_lock_test_and_set(&Ptr, Val);201}202 203// CHECK-LABEL: define dso_local void @f16(204// CHECK-SAME: ) local_unnamed_addr #[[ATTR1]] {205// CHECK-NEXT: [[ENTRY:.*:]]206// CHECK-NEXT: store atomic i128 0, ptr @Ptr release, align 16207// CHECK-NEXT: ret void208//209void f16() {210 return __sync_lock_release(&Ptr);211}212 213// CHECK-LABEL: define dso_local void @f17(214// CHECK-SAME: ptr dead_on_unwind noalias writable writeonly sret(i128) align 8 captures(none) initializes((0, 16)) [[AGG_RESULT:%.*]]) local_unnamed_addr #[[ATTR0]] {215// CHECK-NEXT: [[ENTRY:.*:]]216// CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[__INT128_TBAA6]]217// CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr @Ptr, i128 [[TMP0]] seq_cst, align 16218// CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT]], align 8, !tbaa [[__INT128_TBAA6]]219// CHECK-NEXT: ret void220//221__int128 f17() {222 return __sync_swap(&Ptr, Val);223}224 225// Test that a statement expression compiles.226// CHECK-LABEL: define dso_local void @f18(227// CHECK-SAME: ptr dead_on_return noundef readonly captures(none) [[TMP0:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] {228// CHECK-NEXT: [[ENTRY:.*:]]229// CHECK-NEXT: [[T_ADDR:%.*]] = alloca i128, align 8230// CHECK-NEXT: [[T:%.*]] = load i128, ptr [[TMP0]], align 8, !tbaa [[__INT128_TBAA6]]231// CHECK-NEXT: store i128 [[T]], ptr [[T_ADDR]], align 8, !tbaa [[__INT128_TBAA6]]232// CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[T_ADDR]], i128 [[T]], i128 [[T]] seq_cst seq_cst, align 16233// CHECK-NEXT: ret void234//235void f18(__int128 t) {236 __sync_bool_compare_and_swap(({int x = 1; &t;}), t, t);237}238//.239// CHECK: [[META4:![0-9]+]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}240// CHECK: [[META5]] = !{!"Simple C/C++ TBAA"}241// CHECK: [[__INT128_TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}242// CHECK: [[META7]] = !{!"__int128", [[META4]], i64 0}243//.244