| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s |
| |
| ;;; Test atomicrmw operations |
| |
| @c = common global i8 0, align 4 |
| @s = common global i16 0, align 4 |
| @i = common global i32 0, align 4 |
| @l = common global i64 0, align 4 |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i8 @test_atomic_fetch_add_1() { |
| ; CHECK-LABEL: test_atomic_fetch_add_1: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, c@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s0, c@hi(, %s0) |
| ; CHECK-NEXT: and %s0, -4, %s0 |
| ; CHECK-NEXT: ldl.sx %s2, (, %s0) |
| ; CHECK-NEXT: lea %s1, -256 |
| ; CHECK-NEXT: and %s1, %s1, (32)0 |
| ; CHECK-NEXT: .LBB0_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s3, 0, %s2 |
| ; CHECK-NEXT: adds.w.sx %s2, 1, %s2 |
| ; CHECK-NEXT: and %s2, %s2, (56)0 |
| ; CHECK-NEXT: and %s4, %s3, %s1 |
| ; CHECK-NEXT: or %s2, %s4, %s2 |
| ; CHECK-NEXT: cas.w %s2, (%s0), %s3 |
| ; CHECK-NEXT: brne.w %s2, %s3, .LBB0_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: sll %s0, %s2, 56 |
| ; CHECK-NEXT: sra.l %s0, %s0, 56 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw add ptr @c, i8 1 seq_cst |
| ret i8 %0 |
| } |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i16 @test_atomic_fetch_sub_2() { |
| ; CHECK-LABEL: test_atomic_fetch_sub_2: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, s@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s0, s@hi(, %s0) |
| ; CHECK-NEXT: and %s0, -4, %s0 |
| ; CHECK-NEXT: ldl.sx %s2, (, %s0) |
| ; CHECK-NEXT: lea %s1, -65536 |
| ; CHECK-NEXT: and %s1, %s1, (32)0 |
| ; CHECK-NEXT: .LBB1_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s3, 0, %s2 |
| ; CHECK-NEXT: adds.w.sx %s2, -1, %s2 |
| ; CHECK-NEXT: and %s2, %s2, (48)0 |
| ; CHECK-NEXT: and %s4, %s3, %s1 |
| ; CHECK-NEXT: or %s2, %s4, %s2 |
| ; CHECK-NEXT: cas.w %s2, (%s0), %s3 |
| ; CHECK-NEXT: brne.w %s2, %s3, .LBB1_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: sll %s0, %s2, 48 |
| ; CHECK-NEXT: sra.l %s0, %s0, 48 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw sub ptr @s, i16 1 seq_cst |
| ret i16 %0 |
| } |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i32 @test_atomic_fetch_and_4() { |
| ; CHECK-LABEL: test_atomic_fetch_and_4: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, i@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s0, i@hi(, %s0) |
| ; CHECK-NEXT: ldl.sx %s1, (, %s0) |
| ; CHECK-NEXT: .LBB2_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s2, 0, %s1 |
| ; CHECK-NEXT: and %s1, 1, %s2 |
| ; CHECK-NEXT: cas.w %s1, (%s0), %s2 |
| ; CHECK-NEXT: brne.w %s1, %s2, .LBB2_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: adds.w.sx %s0, %s1, (0)1 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw and ptr @i, i32 1 seq_cst |
| ret i32 %0 |
| } |
| ; Function Attrs: norecurse nounwind |
| define i64 @test_atomic_fetch_or_8() { |
| ; CHECK-LABEL: test_atomic_fetch_or_8: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, l@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s1, l@hi(, %s0) |
| ; CHECK-NEXT: ld %s0, (, %s1) |
| ; CHECK-NEXT: .LBB3_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s2, 0, %s0 |
| ; CHECK-NEXT: or %s0, 1, %s0 |
| ; CHECK-NEXT: cas.l %s0, (%s1), %s2 |
| ; CHECK-NEXT: brne.l %s0, %s2, .LBB3_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw or ptr @l, i64 1 seq_cst |
| ret i64 %0 |
| } |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i8 @test_atomic_fetch_xor_1() { |
| ; CHECK-LABEL: test_atomic_fetch_xor_1: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, c@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s0, c@hi(, %s0) |
| ; CHECK-NEXT: and %s1, -4, %s0 |
| ; CHECK-NEXT: ldl.sx %s0, (, %s1) |
| ; CHECK-NEXT: .LBB4_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s2, 0, %s0 |
| ; CHECK-NEXT: xor %s0, 1, %s2 |
| ; CHECK-NEXT: cas.w %s0, (%s1), %s2 |
| ; CHECK-NEXT: brne.w %s0, %s2, .LBB4_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: sll %s0, %s0, 56 |
| ; CHECK-NEXT: sra.l %s0, %s0, 56 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw xor ptr @c, i8 1 seq_cst |
| ret i8 %0 |
| } |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i16 @test_atomic_fetch_nand_2() { |
| ; CHECK-LABEL: test_atomic_fetch_nand_2: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, s@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s0, s@hi(, %s0) |
| ; CHECK-NEXT: and %s0, -4, %s0 |
| ; CHECK-NEXT: ldl.sx %s2, (, %s0) |
| ; CHECK-NEXT: lea %s1, 65534 |
| ; CHECK-NEXT: lea %s3, -65536 |
| ; CHECK-NEXT: and %s3, %s3, (32)0 |
| ; CHECK-NEXT: .LBB5_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s4, 0, %s2 |
| ; CHECK-NEXT: xor %s2, -1, %s4 |
| ; CHECK-NEXT: or %s2, %s2, %s1 |
| ; CHECK-NEXT: and %s2, %s2, (48)0 |
| ; CHECK-NEXT: and %s5, %s4, %s3 |
| ; CHECK-NEXT: or %s2, %s5, %s2 |
| ; CHECK-NEXT: cas.w %s2, (%s0), %s4 |
| ; CHECK-NEXT: brne.w %s2, %s4, .LBB5_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: sll %s0, %s2, 48 |
| ; CHECK-NEXT: sra.l %s0, %s0, 48 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw nand ptr @s, i16 1 seq_cst |
| ret i16 %0 |
| } |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i32 @test_atomic_fetch_max_4() { |
| ; CHECK-LABEL: test_atomic_fetch_max_4: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, i@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s1, i@hi(, %s0) |
| ; CHECK-NEXT: ldl.sx %s0, (, %s1) |
| ; CHECK-NEXT: .LBB6_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s2, 0, %s0 |
| ; CHECK-NEXT: maxs.w.sx %s0, 1, %s0 |
| ; CHECK-NEXT: cas.w %s0, (%s1), %s2 |
| ; CHECK-NEXT: brne.w %s0, %s2, .LBB6_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw max ptr @i, i32 1 seq_cst |
| ret i32 %0 |
| } |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i32 @test_atomic_fetch_min_4() { |
| ; CHECK-LABEL: test_atomic_fetch_min_4: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, i@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s1, i@hi(, %s0) |
| ; CHECK-NEXT: ldl.sx %s0, (, %s1) |
| ; CHECK-NEXT: .LBB7_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s2, 0, %s0 |
| ; CHECK-NEXT: mins.w.sx %s0, 1, %s0 |
| ; CHECK-NEXT: cas.w %s0, (%s1), %s2 |
| ; CHECK-NEXT: brne.w %s0, %s2, .LBB7_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw min ptr @i, i32 1 seq_cst |
| ret i32 %0 |
| } |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i32 @test_atomic_fetch_umax_4() { |
| ; CHECK-LABEL: test_atomic_fetch_umax_4: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, i@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s0, i@hi(, %s0) |
| ; CHECK-NEXT: ldl.sx %s1, (, %s0) |
| ; CHECK-NEXT: .LBB8_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s2, 0, %s1 |
| ; CHECK-NEXT: cmpu.w %s3, %s1, (63)0 |
| ; CHECK-NEXT: or %s1, 0, %s2 |
| ; CHECK-NEXT: cmov.w.le %s1, (63)0, %s3 |
| ; CHECK-NEXT: cas.w %s1, (%s0), %s2 |
| ; CHECK-NEXT: brne.w %s1, %s2, .LBB8_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: adds.w.sx %s0, %s1, (0)1 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw umax ptr @i, i32 1 seq_cst |
| ret i32 %0 |
| } |
| |
| ; Function Attrs: norecurse nounwind |
| define signext i32 @test_atomic_fetch_umin_4() { |
| ; CHECK-LABEL: test_atomic_fetch_umin_4: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: lea %s0, i@lo |
| ; CHECK-NEXT: and %s0, %s0, (32)0 |
| ; CHECK-NEXT: lea.sl %s0, i@hi(, %s0) |
| ; CHECK-NEXT: ldl.sx %s1, (, %s0) |
| ; CHECK-NEXT: .LBB9_1: # %atomicrmw.start |
| ; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; CHECK-NEXT: or %s2, 0, %s1 |
| ; CHECK-NEXT: cmpu.w %s3, 2, %s1 |
| ; CHECK-NEXT: or %s1, 0, %s2 |
| ; CHECK-NEXT: cmov.w.le %s1, (63)0, %s3 |
| ; CHECK-NEXT: cas.w %s1, (%s0), %s2 |
| ; CHECK-NEXT: brne.w %s1, %s2, .LBB9_1 |
| ; CHECK-NEXT: # %bb.2: # %atomicrmw.end |
| ; CHECK-NEXT: adds.w.sx %s0, %s1, (0)1 |
| ; CHECK-NEXT: fencem 3 |
| ; CHECK-NEXT: b.l.t (, %s10) |
| entry: |
| %0 = atomicrmw umin ptr @i, i32 1 seq_cst |
| ret i32 %0 |
| } |