419 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: opt -S -o - -mtriple=armv7-apple-ios7.0 -passes=atomic-expand -codegen-opt-level=1 %s | FileCheck %s3 4define i8 @test_atomic_xchg_i8(ptr %ptr, i8 %xchgend) {5; CHECK-LABEL: @test_atomic_xchg_i86; CHECK-NOT: dmb7; CHECK: br label %[[LOOP:.*]]8; CHECK: [[LOOP]]:9; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)10; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i811; CHECK: [[NEWVAL32:%.*]] = zext i8 %xchgend to i3212; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i8) %ptr)13; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 014; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]15; CHECK: [[END]]:16; CHECK-NOT: dmb17; CHECK: ret i8 [[OLDVAL]]18 %res = atomicrmw xchg ptr %ptr, i8 %xchgend monotonic19 ret i8 %res20}21 22define i16 @test_atomic_add_i16(ptr %ptr, i16 %addend) {23; CHECK-LABEL: @test_atomic_add_i1624; CHECK: call void @llvm.arm.dmb(i32 11)25; CHECK: br label %[[LOOP:.*]]26; CHECK: [[LOOP]]:27; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i16) %ptr)28; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i1629; CHECK: [[NEWVAL:%.*]] = add i16 [[OLDVAL]], %addend30; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i3231; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i16) %ptr)32; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 033; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]34; CHECK: [[END]]:35; CHECK: call void @llvm.arm.dmb(i32 11)36; CHECK: ret i16 [[OLDVAL]]37 %res = atomicrmw add ptr %ptr, i16 %addend seq_cst38 ret i16 %res39}40 41define i32 @test_atomic_sub_i32(ptr %ptr, i32 %subend) {42; CHECK-LABEL: @test_atomic_sub_i3243; CHECK-NOT: dmb44; CHECK: br label %[[LOOP:.*]]45; CHECK: [[LOOP]]:46; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %ptr)47; CHECK: [[NEWVAL:%.*]] = sub i32 [[OLDVAL]], %subend48; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL]], ptr elementtype(i32) %ptr)49; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 050; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]51; CHECK: [[END]]:52; CHECK: call void @llvm.arm.dmb(i32 11)53; CHECK: ret i32 [[OLDVAL]]54 %res = atomicrmw sub ptr %ptr, i32 %subend acquire55 ret i32 %res56}57 58define i8 @test_atomic_and_i8(ptr %ptr, i8 %andend) {59; CHECK-LABEL: @test_atomic_and_i860; CHECK: call void @llvm.arm.dmb(i32 11)61; CHECK: br label %[[LOOP:.*]]62; CHECK: [[LOOP]]:63; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)64; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i865; CHECK: [[NEWVAL:%.*]] = and i8 [[OLDVAL]], %andend66; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i3267; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i8) %ptr)68; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 069; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]70; CHECK: [[END]]:71; CHECK-NOT: dmb72; CHECK: ret i8 [[OLDVAL]]73 %res = atomicrmw and ptr %ptr, i8 %andend release74 ret i8 %res75}76 77define i16 @test_atomic_nand_i16(ptr %ptr, i16 %nandend) {78; CHECK-LABEL: @test_atomic_nand_i1679; CHECK: call void @llvm.arm.dmb(i32 11)80; CHECK: br label %[[LOOP:.*]]81; CHECK: [[LOOP]]:82; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i16) %ptr)83; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i1684; CHECK: [[NEWVAL_TMP:%.*]] = and i16 [[OLDVAL]], %nandend85; CHECK: [[NEWVAL:%.*]] = xor i16 [[NEWVAL_TMP]], -186; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i3287; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i16) %ptr)88; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 089; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]90; CHECK: [[END]]:91; CHECK: call void @llvm.arm.dmb(i32 11)92; CHECK: ret i16 [[OLDVAL]]93 %res = atomicrmw nand ptr %ptr, i16 %nandend seq_cst94 ret i16 %res95}96 97define i64 @test_atomic_or_i64(ptr %ptr, i64 %orend) {98; CHECK-LABEL: @test_atomic_or_i6499; CHECK: call void @llvm.arm.dmb(i32 11)100; CHECK: br label %[[LOOP:.*]]101; CHECK: [[LOOP]]:102; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(ptr %ptr)103; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0104; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1105; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64106; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64107; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32108; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]]109; CHECK: [[NEWVAL:%.*]] = or i64 [[OLDVAL]], %orend110; CHECK: [[NEWLO:%.*]] = trunc i64 [[NEWVAL]] to i32111; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 [[NEWVAL]], 32112; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32113; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], ptr %ptr)114; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0115; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]116; CHECK: [[END]]:117; CHECK: call void @llvm.arm.dmb(i32 11)118; CHECK: ret i64 [[OLDVAL]]119 %res = atomicrmw or ptr %ptr, i64 %orend seq_cst120 ret i64 %res121}122 123define i8 @test_atomic_xor_i8(ptr %ptr, i8 %xorend) {124; CHECK-LABEL: @test_atomic_xor_i8125; CHECK: call void @llvm.arm.dmb(i32 11)126; CHECK: br label %[[LOOP:.*]]127; CHECK: [[LOOP]]:128; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)129; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8130; CHECK: [[NEWVAL:%.*]] = xor i8 [[OLDVAL]], %xorend131; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32132; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i8) %ptr)133; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0134; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]135; CHECK: [[END]]:136; CHECK: call void @llvm.arm.dmb(i32 11)137; CHECK: ret i8 [[OLDVAL]]138 %res = atomicrmw xor ptr %ptr, i8 %xorend seq_cst139 ret i8 %res140}141 142define i8 @test_atomic_max_i8(ptr %ptr, i8 %maxend) {143; CHECK-LABEL: @test_atomic_max_i8144; CHECK: call void @llvm.arm.dmb(i32 11)145; CHECK: br label %[[LOOP:.*]]146; CHECK: [[LOOP]]:147; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)148; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8149; CHECK: [[WANT_OLD:%.*]] = icmp sgt i8 [[OLDVAL]], %maxend150; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %maxend151; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32152; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i8) %ptr)153; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0154; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]155; CHECK: [[END]]:156; CHECK: call void @llvm.arm.dmb(i32 11)157; CHECK: ret i8 [[OLDVAL]]158 %res = atomicrmw max ptr %ptr, i8 %maxend seq_cst159 ret i8 %res160}161 162define i8 @test_atomic_min_i8(ptr %ptr, i8 %minend) {163; CHECK-LABEL: @test_atomic_min_i8164; CHECK: call void @llvm.arm.dmb(i32 11)165; CHECK: br label %[[LOOP:.*]]166; CHECK: [[LOOP]]:167; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)168; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8169; CHECK: [[WANT_OLD:%.*]] = icmp sle i8 [[OLDVAL]], %minend170; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %minend171; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32172; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i8) %ptr)173; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0174; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]175; CHECK: [[END]]:176; CHECK: call void @llvm.arm.dmb(i32 11)177; CHECK: ret i8 [[OLDVAL]]178 %res = atomicrmw min ptr %ptr, i8 %minend seq_cst179 ret i8 %res180}181 182define i8 @test_atomic_umax_i8(ptr %ptr, i8 %umaxend) {183; CHECK-LABEL: @test_atomic_umax_i8184; CHECK: call void @llvm.arm.dmb(i32 11)185; CHECK: br label %[[LOOP:.*]]186; CHECK: [[LOOP]]:187; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)188; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8189; CHECK: [[WANT_OLD:%.*]] = icmp ugt i8 [[OLDVAL]], %umaxend190; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %umaxend191; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32192; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i8) %ptr)193; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0194; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]195; CHECK: [[END]]:196; CHECK: call void @llvm.arm.dmb(i32 11)197; CHECK: ret i8 [[OLDVAL]]198 %res = atomicrmw umax ptr %ptr, i8 %umaxend seq_cst199 ret i8 %res200}201 202define i8 @test_atomic_umin_i8(ptr %ptr, i8 %uminend) {203; CHECK-LABEL: @test_atomic_umin_i8204; CHECK: call void @llvm.arm.dmb(i32 11)205; CHECK: br label %[[LOOP:.*]]206; CHECK: [[LOOP]]:207; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)208; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8209; CHECK: [[WANT_OLD:%.*]] = icmp ule i8 [[OLDVAL]], %uminend210; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %uminend211; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32212; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i8) %ptr)213; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0214; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]]215; CHECK: [[END]]:216; CHECK: call void @llvm.arm.dmb(i32 11)217; CHECK: ret i8 [[OLDVAL]]218 %res = atomicrmw umin ptr %ptr, i8 %uminend seq_cst219 ret i8 %res220}221 222define i8 @test_cmpxchg_i8_seqcst_seqcst(ptr %ptr, i8 %desired, i8 %newval) {223; CHECK-LABEL: @test_cmpxchg_i8_seqcst_seqcst224; CHECK: br label %[[START:.*]]225; CHECK: [[START]]:226; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)227; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8228; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i8 [[OLDVAL]], %desired229; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]230; CHECK: [[FENCED_STORE]]:231; CHECK: call void @llvm.arm.dmb(i32 11)232; CHECK: br label %[[LOOP:.*]]233; CHECK: [[LOOP]]:234; CHECK: [[LOADED_LOOP:%.*]] = phi i8 [ [[OLDVAL]], %[[FENCED_STORE]] ], [ [[OLDVAL_LOOP:%.*]], %[[RELEASED_LOAD:.*]] ]235; CHECK: [[NEWVAL32:%.*]] = zext i8 %newval to i32236; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i8) %ptr)237; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0238; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[RELEASED_LOAD]]239; CHECK: [[RELEASED_LOAD]]:240; CHECK: [[OLDVAL32_LOOP:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %ptr)241; CHECK: [[OLDVAL_LOOP]] = trunc i32 [[OLDVAL32_LOOP]] to i8242; CHECK: [[SHOULD_STORE_LOOP:%.*]] = icmp eq i8 [[OLDVAL_LOOP]], %desired243; CHECK: br i1 [[SHOULD_STORE_LOOP]], label %[[LOOP]], label %[[NO_STORE_BB:cmpxchg\.nostore]]244; CHECK: [[SUCCESS_BB]]:245; CHECK: call void @llvm.arm.dmb(i32 11)246; CHECK: br label %[[DONE:.*]]247; CHECK: [[NO_STORE_BB]]:248; CHECK-NEXT: [[LOADED_NO_STORE:%.*]] = phi i8 [ [[OLDVAL]], %[[START]] ], [ [[OLDVAL_LOOP]], %[[RELEASED_LOAD]] ]249; CHECK-NEXT: call void @llvm.arm.clrex()250; CHECK-NEXT: br label %[[FAILURE_BB:.*]]251; CHECK: [[FAILURE_BB]]:252; CHECK: [[LOADED_FAILURE:%.*]] = phi i8 [ [[LOADED_NO_STORE]], %[[NO_STORE_BB]] ]253; CHECK: call void @llvm.arm.dmb(i32 11)254; CHECK: br label %[[DONE]]255; CHECK: [[DONE]]:256; CHECK: [[LOADED:%.*]] = phi i8 [ [[LOADED_LOOP]], %[[SUCCESS_BB]] ], [ [[LOADED_FAILURE]], %[[FAILURE_BB]] ]257; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]258; CHECK: ret i8 [[LOADED]]259 %pairold = cmpxchg ptr %ptr, i8 %desired, i8 %newval seq_cst seq_cst260 %old = extractvalue { i8, i1 } %pairold, 0261 ret i8 %old262}263 264define i16 @test_cmpxchg_i16_seqcst_monotonic(ptr %ptr, i16 %desired, i16 %newval) {265; CHECK-LABEL: @test_cmpxchg_i16_seqcst_monotonic266; CHECK: br label %[[LOOP:.*]]267; CHECK: [[LOOP]]:268; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i16) %ptr)269; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i16270; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i16 [[OLDVAL]], %desired271; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]]272; CHECK: [[FENCED_STORE]]:273; CHECK: call void @llvm.arm.dmb(i32 11)274; CHECK: br label %[[LOOP:.*]]275; CHECK: [[LOOP]]:276; CHECK: [[LOADED_LOOP:%.*]] = phi i16 [ [[OLDVAL]], %[[FENCED_STORE]] ], [ [[OLDVAL_LOOP:%.*]], %[[RELEASED_LOAD:.*]] ]277; CHECK: [[NEWVAL32:%.*]] = zext i16 %newval to i32278; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEWVAL32]], ptr elementtype(i16) %ptr)279; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0280; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[RELEASED_LOAD:cmpxchg\.releasedload]]281; CHECK: [[RELEASED_LOAD]]:282; CHECK: [[OLDVAL32_LOOP:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i16) %ptr)283; CHECK: [[OLDVAL_LOOP]] = trunc i32 [[OLDVAL32_LOOP]] to i16284; CHECK: [[SHOULD_STORE_LOOP:%.*]] = icmp eq i16 [[OLDVAL_LOOP]], %desired285; CHECK: br i1 [[SHOULD_STORE_LOOP]], label %[[LOOP]], label %[[NO_STORE_BB:cmpxchg\.nostore]]286; CHECK: [[SUCCESS_BB]]:287; CHECK: call void @llvm.arm.dmb(i32 11)288; CHECK: br label %[[DONE:.*]]289; CHECK: [[NO_STORE_BB]]:290; CHECK-NEXT: [[LOADED_NO_STORE:%.*]] = phi i16 [ [[OLDVAL]], %[[START]] ], [ [[OLDVAL_LOOP]], %[[RELEASED_LOAD]] ]291; CHECK-NEXT: call void @llvm.arm.clrex()292; CHECK-NEXT: br label %[[FAILURE_BB:.*]]293; CHECK: [[FAILURE_BB]]:294; CHECK-NEXT: [[LOADED_FAILURE:%.*]] = phi i16 [ [[LOADED_NO_STORE]], %[[NO_STORE_BB]] ]295; CHECK-NOT: dmb296; CHECK: br label %[[DONE]]297; CHECK: [[DONE]]:298; CHECK: [[LOADED:%.*]] = phi i16 [ [[LOADED_LOOP]], %[[SUCCESS_BB]] ], [ [[LOADED_FAILURE]], %[[FAILURE_BB]] ]299; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]300; CHECK: ret i16 [[LOADED]]301 %pairold = cmpxchg ptr %ptr, i16 %desired, i16 %newval seq_cst monotonic302 %old = extractvalue { i16, i1 } %pairold, 0303 ret i16 %old304}305 306define i32 @test_cmpxchg_i32_acquire_acquire(ptr %ptr, i32 %desired, i32 %newval) {307; CHECK-LABEL: @test_cmpxchg_i32_acquire_acquire308; CHECK-NOT: dmb309; CHECK: br label %[[LOOP:.*]]310; CHECK: [[LOOP]]:311; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %ptr)312; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[OLDVAL]], %desired313; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:cmpxchg\.nostore]]314; CHECK: [[FENCED_STORE]]:315; CHECK-NEXT: br label %[[TRY_STORE:.*]]316; CHECK: [[TRY_STORE]]:317; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[OLDVAL]], %[[FENCED_STORE]] ]318; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0(i32 %newval, ptr elementtype(i32) %ptr)319; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0320; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]321; CHECK: [[SUCCESS_BB]]:322; CHECK: call void @llvm.arm.dmb(i32 11)323; CHECK: br label %[[DONE:.*]]324; CHECK: [[NO_STORE_BB]]:325; CHECK-NEXT: [[LOADED_NO_STORE:%.*]] = phi i32 [ [[OLDVAL]], %[[LOOP]] ]326; CHECK-NEXT: call void @llvm.arm.clrex()327; CHECK-NEXT: br label %[[FAILURE_BB:.*]]328; CHECK: [[FAILURE_BB]]:329; CHECK: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NO_STORE]], %[[NO_STORE_BB]] ]330; CHECK: call void @llvm.arm.dmb(i32 11)331; CHECK: br label %[[DONE]]332; CHECK: [[DONE]]:333; CHECK: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[SUCCESS_BB]] ], [ [[LOADED_FAILURE]], %[[FAILURE_BB]] ]334; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]335; CHECK: ret i32 [[LOADED_EXIT]]336 %pairold = cmpxchg ptr %ptr, i32 %desired, i32 %newval acquire acquire337 %old = extractvalue { i32, i1 } %pairold, 0338 ret i32 %old339}340 341define i64 @test_cmpxchg_i64_monotonic_monotonic(ptr %ptr, i64 %desired, i64 %newval) {342; CHECK-LABEL: @test_cmpxchg_i64_monotonic_monotonic343; CHECK-NOT: dmb344; CHECK: br label %[[LOOP:.*]]345; CHECK: [[LOOP]]:346; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(ptr %ptr)347; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0348; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1349; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64350; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64351; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32352; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]]353; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i64 [[OLDVAL]], %desired354; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:cmpxchg\.nostore]]355; CHECK: [[FENCED_STORE]]:356; CHECK-NEXT: br label %[[TRY_STORE:.*]]357; CHECK: [[TRY_STORE]]:358; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i64 [ [[OLDVAL]], %[[FENCED_STORE]] ]359; CHECK: [[NEWLO:%.*]] = trunc i64 %newval to i32360; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 %newval, 32361; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32362; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], ptr %ptr)363; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0364; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]]365; CHECK: [[SUCCESS_BB]]:366; CHECK-NOT: dmb367; CHECK: br label %[[DONE:.*]]368; CHECK: [[NO_STORE_BB]]:369; CHECK-NEXT: [[LOADED_NO_STORE:%.*]] = phi i64 [ [[OLDVAL]], %[[LOOP]] ]370; CHECK-NEXT: call void @llvm.arm.clrex()371; CHECK-NEXT: br label %[[FAILURE_BB:.*]]372; CHECK: [[FAILURE_BB]]:373; CHECK-NEXT: [[LOADED_FAILURE:%.*]] = phi i64 [ [[LOADED_NO_STORE]], %[[NO_STORE_BB]] ]374; CHECK-NOT: dmb375; CHECK: br label %[[DONE]]376; CHECK: [[DONE]]:377; CHECK: [[LOADED_EXIT:%.*]] = phi i64 [ [[LOADED_TRYSTORE]], %[[SUCCESS_BB]] ], [ [[LOADED_FAILURE]], %[[FAILURE_BB]] ]378; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]379; CHECK: ret i64 [[LOADED_EXIT]]380 %pairold = cmpxchg ptr %ptr, i64 %desired, i64 %newval monotonic monotonic381 %old = extractvalue { i64, i1 } %pairold, 0382 ret i64 %old383}384 385define i32 @test_cmpxchg_minsize(ptr %addr, i32 %desired, i32 %new) minsize {386; CHECK-LABEL: @test_cmpxchg_minsize387; CHECK: call void @llvm.arm.dmb(i32 11)388; CHECK: br label %[[START:.*]]389; CHECK: [[START]]:390; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr)391; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired392; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:cmpxchg\.nostore]]393; CHECK: [[FENCED_STORE]]:394; CHECK-NEXT: br label %[[TRY_STORE:.*]]395; CHECK: [[TRY_STORE]]:396; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[LOADED]], %[[FENCED_STORE]] ]397; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0(i32 %new, ptr elementtype(i32) %addr)398; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0399; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[START]]400; CHECK: [[SUCCESS_BB]]:401; CHECK: call void @llvm.arm.dmb(i32 11)402; CHECK: br label %[[END:.*]]403; CHECK: [[NO_STORE_BB]]:404; CHECK: [[LOADED_NO_STORE:%.*]] = phi i32 [ [[LOADED]], %[[START]] ]405; CHECK: call void @llvm.arm.clrex()406; CHECK: br label %[[FAILURE_BB]]407; CHECK: [[FAILURE_BB]]:408; CHECK: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NO_STORE]], %[[NO_STORE_BB]] ]409; CHECK: call void @llvm.arm.dmb(i32 11)410; CHECK: br label %[[END]]411; CHECK: [[END]]:412; CHECK: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[SUCCESS_BB]] ], [ [[LOADED_FAILURE]], %[[FAILURE_BB]] ]413; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ]414; CHECK: ret i32 [[LOADED_EXIT]]415 %pair = cmpxchg ptr %addr, i32 %desired, i32 %new seq_cst seq_cst416 %oldval = extractvalue { i32, i1 } %pair, 0417 ret i32 %oldval418}419