| // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py |
| // RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - \ |
| // RUN: | FileCheck %s |
| // |
| // Test __sync_ builtins for __int128 aligned to 16 bytes. |
| |
| #include <stdint.h> |
| |
| __int128 Ptr __attribute__((aligned(16))); |
| __int128 Val __attribute__((aligned(16))); |
| __int128 OldVal __attribute__((aligned(16))); |
| |
| // CHECK-LABEL: @f1( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2:![0-9]+]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f1() { |
| return __sync_fetch_and_add(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f2( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw sub ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f2() { |
| return __sync_fetch_and_sub(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f3( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f3() { |
| return __sync_fetch_and_or(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f4( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw and ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f4() { |
| return __sync_fetch_and_and(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f5( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xor ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f5() { |
| return __sync_fetch_and_xor(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f6( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw nand ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f6() { |
| return __sync_fetch_and_nand(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f7( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: [[TMP2:%.*]] = add i128 [[TMP1]], [[TMP0]] |
| // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f7() { |
| return __sync_add_and_fetch(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f8( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw sub ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: [[TMP2:%.*]] = sub i128 [[TMP1]], [[TMP0]] |
| // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f8() { |
| return __sync_sub_and_fetch(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f9( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: [[TMP2:%.*]] = or i128 [[TMP1]], [[TMP0]] |
| // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f9() { |
| return __sync_or_and_fetch(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f10( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw and ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] |
| // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f10() { |
| return __sync_and_and_fetch(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f11( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xor ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: [[TMP2:%.*]] = xor i128 [[TMP1]], [[TMP0]] |
| // CHECK-NEXT: store i128 [[TMP2]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f11() { |
| return __sync_xor_and_fetch(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f12( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw nand ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: [[TMP2:%.*]] = and i128 [[TMP1]], [[TMP0]] |
| // CHECK-NEXT: [[TMP3:%.*]] = xor i128 [[TMP2]], -1 |
| // CHECK-NEXT: store i128 [[TMP3]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f12() { |
| return __sync_nand_and_fetch(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f13( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @OldVal, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr @Ptr, i128 [[TMP0]], i128 [[TMP1]] seq_cst seq_cst, align 16 |
| // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i128, i1 } [[TMP2]], 1 |
| // CHECK-NEXT: ret i1 [[TMP3]] |
| // |
| _Bool f13() { |
| return __sync_bool_compare_and_swap(&Ptr, OldVal, Val); |
| } |
| |
| // CHECK-LABEL: @f14( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @OldVal, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP2:%.*]] = cmpxchg ptr @Ptr, i128 [[TMP0]], i128 [[TMP1]] seq_cst seq_cst, align 16 |
| // CHECK-NEXT: [[TMP3:%.*]] = extractvalue { i128, i1 } [[TMP2]], 0 |
| // CHECK-NEXT: store i128 [[TMP3]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f14() { |
| return __sync_val_compare_and_swap(&Ptr, OldVal, Val); |
| } |
| |
| // CHECK-LABEL: @f15( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f15() { |
| return __sync_lock_test_and_set(&Ptr, Val); |
| } |
| |
| // CHECK-LABEL: @f16( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: store atomic i128 0, ptr @Ptr release, align 16 |
| // CHECK-NEXT: ret void |
| // |
| void f16() { |
| return __sync_lock_release(&Ptr); |
| } |
| |
| // CHECK-LABEL: @f17( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[TMP0:%.*]] = load i128, ptr @Val, align 16, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr @Ptr, i128 [[TMP0]] seq_cst, align 16 |
| // CHECK-NEXT: store i128 [[TMP1]], ptr [[AGG_RESULT:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: ret void |
| // |
| __int128 f17() { |
| return __sync_swap(&Ptr, Val); |
| } |
| |
| // Test that a statement expression compiles. |
| // CHECK-LABEL: @f18( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[T_ADDR:%.*]] = alloca i128, align 8 |
| // CHECK-NEXT: [[T:%.*]] = load i128, ptr [[TMP0:%.*]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: store i128 [[T]], ptr [[T_ADDR]], align 8, !tbaa [[TBAA2]] |
| // CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[T_ADDR]], i128 [[T]], i128 [[T]] seq_cst seq_cst, align 16 |
| // CHECK-NEXT: ret void |
| // |
| void f18(__int128 t) { |
| __sync_bool_compare_and_swap(({int x = 1; &t;}), t, t); |
| } |