1; RUN: llc -mtriple=thumbv7-none-eabi -mcpu=cortex-m33 -verify-machineinstrs -o - %s | FileCheck %s 2 3define i8 @test_atomic_load_add_i8(i8 %offset) nounwind { 4; CHECK-LABEL: test_atomic_load_add_i8: 5 %old = atomicrmw add ptr @var8, i8 %offset seq_cst 6; CHECK-NOT: dmb 7; CHECK-NOT: mcr 8; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8 9; CHECK: movt r[[ADDR]], :upper16:var8 10 11; CHECK: .LBB{{[0-9]+}}_1: 12; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]] 13 ; r0 below is a reasonable guess but could change: it certainly comes into the 14 ; function there. 15; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0 16; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]] 17; CHECK-NEXT: cmp [[STATUS]], #0 18; CHECK-NEXT: bne .LBB{{[0-9]+}}_1 19; CHECK-NOT: dmb 20; CHECK-NOT: mcr 21 22; CHECK: mov r0, r[[OLD]] 23 ret i8 %old 24} 25 26define i16 @test_atomic_load_add_i16(i16 %offset) nounwind { 27; CHECK-LABEL: test_atomic_load_add_i16: 28 %old = atomicrmw add ptr @var16, i16 %offset acquire 29; CHECK-NOT: dmb 30; CHECK-NOT: mcr 31; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16 32; CHECK: movt r[[ADDR]], :upper16:var16 33 34; CHECK: .LBB{{[0-9]+}}_1: 35; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]] 36 ; r0 below is a reasonable guess but could change: it certainly comes into the 37 ; function there. 38; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0 39; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]] 40; CHECK-NEXT: cmp [[STATUS]], #0 41; CHECK-NEXT: bne .LBB{{[0-9]+}}_1 42; CHECK-NOT: dmb 43; CHECK-NOT: mcr 44 45; CHECK: mov r0, r[[OLD]] 46 ret i16 %old 47} 48 49define i32 @test_atomic_load_add_i32(i32 %offset) nounwind { 50; CHECK-LABEL: test_atomic_load_add_i32: 51 %old = atomicrmw add ptr @var32, i32 %offset release 52; CHECK-NOT: dmb 53; CHECK-NOT: mcr 54; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32 55; CHECK: movt r[[ADDR]], :upper16:var32 56 57; CHECK: .LBB{{[0-9]+}}_1: 58; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]] 59 ; r0 below is a reasonable guess but could change: it certainly comes into the 60 ; function there. 61; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0 62; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]] 63; CHECK-NEXT: cmp [[STATUS]], #0 64; CHECK-NEXT: bne .LBB{{[0-9]+}}_1 65; CHECK-NOT: dmb 66; CHECK-NOT: mcr 67 68; CHECK: mov r0, r[[OLD]] 69 ret i32 %old 70} 71 72define void @test_atomic_load_add_i64(i64 %offset) nounwind { 73; CHECK-LABEL: test_atomic_load_add_i64: 74; CHECK: bl __atomic_fetch_add_8 75 %old = atomicrmw add ptr @var64, i64 %offset monotonic 76 store i64 %old, ptr @var64 77 ret void 78} 79 80define i8 @test_load_acquire_i8(ptr %ptr) { 81; CHECK-LABEL: test_load_acquire_i8: 82; CHECK: ldab r0, [r0] 83 %val = load atomic i8, ptr %ptr seq_cst, align 1 84 ret i8 %val 85} 86 87define i16 @test_load_acquire_i16(ptr %ptr) { 88; CHECK-LABEL: test_load_acquire_i16: 89; CHECK: ldah r0, [r0] 90 %val = load atomic i16, ptr %ptr acquire, align 2 91 ret i16 %val 92} 93 94define i32 @test_load_acquire_i32(ptr %ptr) { 95; CHECK-LABEL: test_load_acquire_i32: 96; CHECK: lda r0, [r0] 97 %val = load atomic i32, ptr %ptr acquire, align 4 98 ret i32 %val 99} 100 101define i64 @test_load_acquire_i64(ptr %ptr) { 102; CHECK-LABEL: test_load_acquire_i64: 103; CHECK: bl __atomic_load 104 %val = load atomic i64, ptr %ptr acquire, align 4 105 ret i64 %val 106} 107 108define void @test_store_release_i8(i8 %val, ptr %ptr) { 109; CHECK-LABEL: test_store_release_i8: 110; CHECK: stlb r0, [r1] 111 store atomic i8 %val, ptr %ptr seq_cst, align 1 112 ret void 113} 114 115define void @test_store_release_i16(i16 %val, ptr %ptr) { 116; CHECK-LABEL: test_store_release_i16: 117; CHECK: stlh r0, [r1] 118 store atomic i16 %val, ptr %ptr release, align 2 119 ret void 120} 121 122define void @test_store_release_i32(i32 %val, ptr %ptr) { 123; CHECK-LABEL: test_store_release_i32: 124; CHECK: stl r0, [r1] 125 store atomic i32 %val, ptr %ptr seq_cst, align 4 126 ret void 127} 128 129define void @test_store_release_i64(i64 %val, ptr %ptr) { 130; CHECK-LABEL: test_store_release_i64: 131; CHECK: bl __atomic_store 132 store atomic i64 %val, ptr %ptr seq_cst, align 4 133 ret void 134} 135 136 137@var8 = global i8 0 138@var16 = global i16 0 139@var32 = global i32 0 140@var64 = global i64 0 141