| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s |
| |
| ; PR37025 |
| ; |
| ;#include <stdatomic.h> |
| ;#include <stdbool.h> |
| ; |
| ;void func2(); |
| ; |
| ;void func(_Atomic(unsigned long) * obj, void * obj2) |
| ;{ |
| ; if (atomic_fetch_sub(obj, 1) == 1 && obj2) |
| ; func2(); |
| ;} |
| |
| define void @test_dec_select(i64* nocapture %0, i8* readnone %1) { |
| ; CHECK-LABEL: test_dec_select: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lock decq (%rdi) |
| ; CHECK-NEXT: jne .LBB0_2 |
| ; CHECK-NEXT: # %bb.1: |
| ; CHECK-NEXT: testq %rsi, %rsi |
| ; CHECK-NEXT: je .LBB0_2 |
| ; CHECK-NEXT: # %bb.3: |
| ; CHECK-NEXT: jmp func2 # TAILCALL |
| ; CHECK-NEXT: .LBB0_2: |
| ; CHECK-NEXT: retq |
| %3 = atomicrmw sub i64* %0, i64 1 seq_cst |
| %4 = icmp eq i64 %3, 1 |
| %5 = icmp ne i8* %1, null |
| %6 = select i1 %4, i1 %5, i1 false |
| br i1 %6, label %7, label %8 |
| |
| 7: ; preds = %2 |
| tail call void @func2() |
| br label %8 |
| |
| 8: ; preds = %7, %2 |
| ret void |
| } |
| |
| define void @test_dec_select_commute(i64* nocapture %0, i8* readnone %1) { |
| ; CHECK-LABEL: test_dec_select_commute: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq $-1, %rax |
| ; CHECK-NEXT: lock xaddq %rax, (%rdi) |
| ; CHECK-NEXT: testq %rsi, %rsi |
| ; CHECK-NEXT: je .LBB1_2 |
| ; CHECK-NEXT: # %bb.1: |
| ; CHECK-NEXT: cmpq $1, %rax |
| ; CHECK-NEXT: jne .LBB1_2 |
| ; CHECK-NEXT: # %bb.3: |
| ; CHECK-NEXT: jmp func2 # TAILCALL |
| ; CHECK-NEXT: .LBB1_2: |
| ; CHECK-NEXT: retq |
| %3 = atomicrmw sub i64* %0, i64 1 seq_cst |
| %4 = icmp eq i64 %3, 1 |
| %5 = icmp ne i8* %1, null |
| %6 = select i1 %5, i1 %4, i1 false |
| br i1 %6, label %7, label %8 |
| |
| 7: ; preds = %2 |
| tail call void @func2() |
| br label %8 |
| |
| 8: ; preds = %7, %2 |
| ret void |
| } |
| |
| define void @test_dec_and(i64* nocapture %0, i8* readnone %1) { |
| ; CHECK-LABEL: test_dec_and: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: movq $-1, %rax |
| ; CHECK-NEXT: lock xaddq %rax, (%rdi) |
| ; CHECK-NEXT: testq %rsi, %rsi |
| ; CHECK-NEXT: je .LBB2_2 |
| ; CHECK-NEXT: # %bb.1: |
| ; CHECK-NEXT: cmpq $1, %rax |
| ; CHECK-NEXT: jne .LBB2_2 |
| ; CHECK-NEXT: # %bb.3: |
| ; CHECK-NEXT: jmp func2 # TAILCALL |
| ; CHECK-NEXT: .LBB2_2: |
| ; CHECK-NEXT: retq |
| %3 = atomicrmw sub i64* %0, i64 1 seq_cst |
| %4 = icmp eq i64 %3, 1 |
| %5 = icmp ne i8* %1, null |
| %6 = and i1 %5, %4 |
| br i1 %6, label %7, label %8 |
| |
| 7: ; preds = %2 |
| tail call void @func2() |
| br label %8 |
| |
| 8: ; preds = %7, %2 |
| ret void |
| } |
| |
| define void @test_dec_and_commute(i64* nocapture %0, i8* readnone %1) { |
| ; CHECK-LABEL: test_dec_and_commute: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lock decq (%rdi) |
| ; CHECK-NEXT: jne .LBB3_2 |
| ; CHECK-NEXT: # %bb.1: |
| ; CHECK-NEXT: testq %rsi, %rsi |
| ; CHECK-NEXT: je .LBB3_2 |
| ; CHECK-NEXT: # %bb.3: |
| ; CHECK-NEXT: jmp func2 # TAILCALL |
| ; CHECK-NEXT: .LBB3_2: |
| ; CHECK-NEXT: retq |
| %3 = atomicrmw sub i64* %0, i64 1 seq_cst |
| %4 = icmp eq i64 %3, 1 |
| %5 = icmp ne i8* %1, null |
| %6 = and i1 %4, %5 |
| br i1 %6, label %7, label %8 |
| |
| 7: ; preds = %2 |
| tail call void @func2() |
| br label %8 |
| |
| 8: ; preds = %7, %2 |
| ret void |
| } |
| |
| declare dso_local void @func2() |