129 lines · plain
1; RUN: llc -verify-machineinstrs -mtriple=armv7-linux-gnu -O0 %s -o - | FileCheck %s2; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnu -O0 %s -o - | FileCheck %s3; RUN: llc -verify-machineinstrs -mtriple=thumbv6m-none-eabi -O0 %s -o - | FileCheck %s --check-prefix=CHECK-T14 5; CHECK-T1-NOT: ldrex6; CHECK-T1-NOT: strex7 8define { i8, i1 } @test_cmpxchg_8(ptr %addr, i8 %desired, i8 %new) nounwind {9; CHECK-LABEL: test_cmpxchg_8:10; CHECK-DAG: mov [[ADDR:r[0-9]+]], r011; CHECK-DAG: mov [[NEW:r[0-9]+]], r212; CHECK: dmb ish13; CHECK: uxtb [[DESIRED:r[0-9]+]], [[DESIRED]]14; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:15; CHECK: ldrexb [[OLD:[lr0-9]+]], [[[ADDR]]]16; CHECK: cmp [[OLD]], [[DESIRED]]17; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]]18; CHECK: strexb [[STATUS:r[0-9]+]], [[NEW]], [[[ADDR]]]19; CHECK: cmp{{(\.w)?}} [[STATUS]], #020; CHECK: bne [[RETRY]]21; CHECK: [[DONE]]:22; Materialisation of a boolean is done with sub/clz/lsr23; CHECK: uxtb [[CMP1:r[0-9]+]], [[DESIRED]]24; CHECK: sub{{(\.w|s)?}} [[CMP1]], [[OLD]], [[CMP1]]25; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]]26; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #527; CHECK: dmb ish28 %res = cmpxchg ptr %addr, i8 %desired, i8 %new seq_cst monotonic29 ret { i8, i1 } %res30}31 32define { i16, i1 } @test_cmpxchg_16(ptr %addr, i16 %desired, i16 %new) nounwind {33; CHECK-LABEL: test_cmpxchg_16:34; CHECK-DAG: mov [[ADDR:r[0-9]+]], r035; CHECK-DAG: mov [[NEW:r[0-9]+]], r236; CHECK: dmb ish37; CHECK: uxth [[DESIRED:r[0-9]+]], [[DESIRED]]38; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:39; CHECK: ldrexh [[OLD:[lr0-9]+]], [[[ADDR]]]40; CHECK: cmp [[OLD]], [[DESIRED]]41; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]]42; CHECK: strexh [[STATUS:r[0-9]+]], [[NEW]], [[[ADDR]]]43; CHECK: cmp{{(\.w)?}} [[STATUS]], #044; CHECK: bne [[RETRY]]45; CHECK: [[DONE]]:46; Materialisation of a boolean is done with sub/clz/lsr47; CHECK: uxth [[CMP1:r[0-9]+]], [[DESIRED]]48; CHECK: sub{{(\.w|s)?}} [[CMP1]], [[OLD]], [[CMP1]]49; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]]50; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #551; CHECK: dmb ish52 %res = cmpxchg ptr %addr, i16 %desired, i16 %new seq_cst monotonic53 ret { i16, i1 } %res54}55 56define { i32, i1 } @test_cmpxchg_32(ptr %addr, i32 %desired, i32 %new) nounwind {57; CHECK-LABEL: test_cmpxchg_32:58; CHECK-DAG: mov [[ADDR:r[0-9]+]], r059; CHECK-DAG: mov [[NEW:r[0-9]+]], r260; CHECK: dmb ish61; CHECK-NOT: uxt62; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:63; CHECK: ldrex [[OLD:r[0-9]+]], [[[ADDR]]]64; CHECK: cmp [[OLD]], [[DESIRED]]65; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]]66; CHECK: strex [[STATUS:r[0-9]+]], [[NEW]], [[[ADDR]]]67; CHECK: cmp{{(\.w)?}} [[STATUS]], #068; CHECK: bne [[RETRY]]69; CHECK: [[DONE]]:70; Materialisation of a boolean is done with sub/clz/lsr71; CHECK: sub{{(s)?}} [[CMP1:r[0-9]+]], [[OLD]], [[DESIRED]]72; CHECK: clz [[CMP2:r[0-9]+]], [[CMP1]]73; CHECK: lsr{{(s)?}} {{r[0-9]+}}, [[CMP2]], #574; CHECK: dmb ish75 %res = cmpxchg ptr %addr, i32 %desired, i32 %new seq_cst monotonic76 ret { i32, i1 } %res77}78 79define { i64, i1 } @test_cmpxchg_64(ptr %addr, i64 %desired, i64 %new) nounwind {80; CHECK-LABEL: test_cmpxchg_64:81; CHECK: dmb ish82; CHECK-NOT: uxt83; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:84; CHECK: ldrexd [[OLDLO:r[0-9]+]], [[OLDHI:r[0-9]+]], [r0]85; CHECK: cmp [[OLDLO]], r686; CHECK: cmpeq [[OLDHI]], r787; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]]88; CHECK: strexd [[STATUS:[lr0-9]+]], r8, r9, [r0]89; CHECK: cmp{{(\.w)?}} [[STATUS]], #090; CHECK: bne [[RETRY]]91; CHECK: [[DONE]]:92; CHECK: dmb ish93 %res = cmpxchg ptr %addr, i64 %desired, i64 %new seq_cst monotonic94 ret { i64, i1 } %res95}96 97define { i64, i1 } @test_nontrivial_args(ptr %addr, i64 %desired, i64 %new) {98; CHECK-LABEL: test_nontrivial_args:99; CHECK: mov [[ADDR:r[0-9]+]], r0100; CHECK: dmb ish101; CHECK-NOT: uxt102; CHECK: [[RETRY:.LBB[0-9]+_[0-9]+]]:103; CHECK: ldrexd [[OLDLO:r[0-9]+]], [[OLDHI:r[0-9]+]], [[[ADDR]]]104; CHECK: cmp [[OLDLO]], {{r[0-9]+}}105; CHECK: cmpeq [[OLDHI]], {{r[0-9]+}}106; CHECK: bne [[DONE:.LBB[0-9]+_[0-9]+]]107; CHECK: strexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [[[ADDR]]]108; CHECK: cmp{{(\.w)?}} [[STATUS]], #0109; CHECK: bne [[RETRY]]110; CHECK: [[DONE]]:111; CHECK: dmb ish112 113 %desired1 = add i64 %desired, 1114 %new1 = add i64 %new, 1115 %res = cmpxchg ptr %addr, i64 %desired1, i64 %new1 seq_cst seq_cst116 ret { i64, i1 } %res117}118 119; The following used to trigger an assertion when creating a spill on thumb2120; for a physreg with RC==GPRPairRegClass.121; CHECK-LABEL: test_cmpxchg_spillbug:122; CHECK: ldrexd123; CHECK: strexd124; CHECK: bne125define void @test_cmpxchg_spillbug() {126 %v = cmpxchg ptr undef, i64 undef, i64 undef seq_cst seq_cst127 ret void128}129