232 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs | FileCheck %s --check-prefix=X643; RUN: llc < %s -mtriple=i686-unknown-unknown -verify-machineinstrs | FileCheck %s --check-prefix=X864 5; Make sure that flags are properly preserved despite atomic optimizations.6 7define i32 @atomic_and_flags_1(ptr %p, i32 %a, i32 %b) {8; X64-LABEL: atomic_and_flags_1:9; X64: # %bb.0:10; X64-NEXT: cmpl %edx, %esi11; X64-NEXT: jne .LBB0_312; X64-NEXT: # %bb.1: # %L113; X64-NEXT: incb (%rdi)14; X64-NEXT: cmpl %edx, %esi15; X64-NEXT: jne .LBB0_216; X64-NEXT: # %bb.4: # %L317; X64-NEXT: movl $3, %eax18; X64-NEXT: retq19; X64-NEXT: .LBB0_3: # %L220; X64-NEXT: movl $2, %eax21; X64-NEXT: retq22; X64-NEXT: .LBB0_2: # %L423; X64-NEXT: movl $4, %eax24; X64-NEXT: retq25;26; X86-LABEL: atomic_and_flags_1:27; X86: # %bb.0:28; X86-NEXT: movl {{[0-9]+}}(%esp), %eax29; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx30; X86-NEXT: cmpl %eax, %ecx31; X86-NEXT: jne .LBB0_332; X86-NEXT: # %bb.1: # %L133; X86-NEXT: movl {{[0-9]+}}(%esp), %edx34; X86-NEXT: incb (%edx)35; X86-NEXT: cmpl %eax, %ecx36; X86-NEXT: jne .LBB0_237; X86-NEXT: # %bb.4: # %L338; X86-NEXT: movl $3, %eax39; X86-NEXT: retl40; X86-NEXT: .LBB0_3: # %L241; X86-NEXT: movl $2, %eax42; X86-NEXT: retl43; X86-NEXT: .LBB0_2: # %L444; X86-NEXT: movl $4, %eax45; X86-NEXT: retl46 ; Generate flags value, and use it.47 %cmp = icmp eq i32 %a, %b48 br i1 %cmp, label %L1, label %L249 50L1:51 ; The following pattern will get folded.52 %1 = load atomic i8, ptr %p seq_cst, align 153 %2 = add i8 %1, 1 ; This forces the INC instruction to be generated.54 store atomic i8 %2, ptr %p release, align 155 56 ; Use the comparison result again. We need to rematerialize the comparison57 ; somehow. This test checks that cmpl gets emitted again, but any58 ; rematerialization would work (the optimizer used to clobber the flags with59 ; the add).60 br i1 %cmp, label %L3, label %L461 62L2:63 ret i32 264 65L3:66 ret i32 367 68L4:69 ret i32 470}71 72; Same as above, but using 2 as immediate to avoid the INC instruction.73define i32 @atomic_and_flags_2(ptr %p, i32 %a, i32 %b) {74; X64-LABEL: atomic_and_flags_2:75; X64: # %bb.0:76; X64-NEXT: cmpl %edx, %esi77; X64-NEXT: jne .LBB1_378; X64-NEXT: # %bb.1: # %L179; X64-NEXT: addb $2, (%rdi)80; X64-NEXT: cmpl %edx, %esi81; X64-NEXT: jne .LBB1_282; X64-NEXT: # %bb.4: # %L383; X64-NEXT: movl $3, %eax84; X64-NEXT: retq85; X64-NEXT: .LBB1_3: # %L286; X64-NEXT: movl $2, %eax87; X64-NEXT: retq88; X64-NEXT: .LBB1_2: # %L489; X64-NEXT: movl $4, %eax90; X64-NEXT: retq91;92; X86-LABEL: atomic_and_flags_2:93; X86: # %bb.0:94; X86-NEXT: movl {{[0-9]+}}(%esp), %eax95; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx96; X86-NEXT: cmpl %eax, %ecx97; X86-NEXT: jne .LBB1_398; X86-NEXT: # %bb.1: # %L199; X86-NEXT: movl {{[0-9]+}}(%esp), %edx100; X86-NEXT: addb $2, (%edx)101; X86-NEXT: cmpl %eax, %ecx102; X86-NEXT: jne .LBB1_2103; X86-NEXT: # %bb.4: # %L3104; X86-NEXT: movl $3, %eax105; X86-NEXT: retl106; X86-NEXT: .LBB1_3: # %L2107; X86-NEXT: movl $2, %eax108; X86-NEXT: retl109; X86-NEXT: .LBB1_2: # %L4110; X86-NEXT: movl $4, %eax111; X86-NEXT: retl112 %cmp = icmp eq i32 %a, %b113 br i1 %cmp, label %L1, label %L2114L1:115 %1 = load atomic i8, ptr %p seq_cst, align 1116 %2 = add i8 %1, 2117 store atomic i8 %2, ptr %p release, align 1118 br i1 %cmp, label %L3, label %L4119L2:120 ret i32 2121L3:122 ret i32 3123L4:124 ret i32 4125}126 127; PR20841 - ensure we don't reuse the ZF flag from XADD for compares with zero,128; the flags are set for the result of the add result (the value stored to memory),129; not the value returned by the atomicrmw add.130 131define zeroext i1 @xadd_cmp0_i64(ptr %x) nounwind {132; X64-LABEL: xadd_cmp0_i64:133; X64: # %bb.0:134; X64-NEXT: movl $1, %eax135; X64-NEXT: lock xaddq %rax, (%rdi)136; X64-NEXT: testq %rax, %rax137; X64-NEXT: sete %al138; X64-NEXT: retq139;140; X86-LABEL: xadd_cmp0_i64:141; X86: # %bb.0:142; X86-NEXT: pushl %ebx143; X86-NEXT: pushl %esi144; X86-NEXT: movl {{[0-9]+}}(%esp), %esi145; X86-NEXT: movl (%esi), %eax146; X86-NEXT: movl 4(%esi), %edx147; X86-NEXT: .p2align 4148; X86-NEXT: .LBB2_1: # %atomicrmw.start149; X86-NEXT: # =>This Inner Loop Header: Depth=1150; X86-NEXT: movl %eax, %ebx151; X86-NEXT: addl $1, %ebx152; X86-NEXT: movl %edx, %ecx153; X86-NEXT: adcl $0, %ecx154; X86-NEXT: lock cmpxchg8b (%esi)155; X86-NEXT: jne .LBB2_1156; X86-NEXT: # %bb.2: # %atomicrmw.end157; X86-NEXT: orl %edx, %eax158; X86-NEXT: sete %al159; X86-NEXT: popl %esi160; X86-NEXT: popl %ebx161; X86-NEXT: retl162 %add = atomicrmw add ptr %x, i64 1 seq_cst163 %cmp = icmp eq i64 %add, 0164 ret i1 %cmp165}166 167define zeroext i1 @xadd_cmp0_i32(ptr %x) nounwind {168; X64-LABEL: xadd_cmp0_i32:169; X64: # %bb.0:170; X64-NEXT: movl $1, %eax171; X64-NEXT: lock xaddl %eax, (%rdi)172; X64-NEXT: testl %eax, %eax173; X64-NEXT: setne %al174; X64-NEXT: retq175;176; X86-LABEL: xadd_cmp0_i32:177; X86: # %bb.0:178; X86-NEXT: movl {{[0-9]+}}(%esp), %eax179; X86-NEXT: movl $1, %ecx180; X86-NEXT: lock xaddl %ecx, (%eax)181; X86-NEXT: testl %ecx, %ecx182; X86-NEXT: setne %al183; X86-NEXT: retl184 %add = atomicrmw add ptr %x, i32 1 seq_cst185 %cmp = icmp ne i32 %add, 0186 ret i1 %cmp187}188 189define zeroext i1 @xadd_cmp0_i16(ptr %x) nounwind {190; X64-LABEL: xadd_cmp0_i16:191; X64: # %bb.0:192; X64-NEXT: movw $1, %ax193; X64-NEXT: lock xaddw %ax, (%rdi)194; X64-NEXT: testw %ax, %ax195; X64-NEXT: sete %al196; X64-NEXT: retq197;198; X86-LABEL: xadd_cmp0_i16:199; X86: # %bb.0:200; X86-NEXT: movl {{[0-9]+}}(%esp), %eax201; X86-NEXT: movw $1, %cx202; X86-NEXT: lock xaddw %cx, (%eax)203; X86-NEXT: testw %cx, %cx204; X86-NEXT: sete %al205; X86-NEXT: retl206 %add = atomicrmw add ptr %x, i16 1 seq_cst207 %cmp = icmp eq i16 %add, 0208 ret i1 %cmp209}210 211define zeroext i1 @xadd_cmp0_i8(ptr %x) nounwind {212; X64-LABEL: xadd_cmp0_i8:213; X64: # %bb.0:214; X64-NEXT: movb $1, %al215; X64-NEXT: lock xaddb %al, (%rdi)216; X64-NEXT: testb %al, %al217; X64-NEXT: setne %al218; X64-NEXT: retq219;220; X86-LABEL: xadd_cmp0_i8:221; X86: # %bb.0:222; X86-NEXT: movl {{[0-9]+}}(%esp), %eax223; X86-NEXT: movb $1, %cl224; X86-NEXT: lock xaddb %cl, (%eax)225; X86-NEXT: testb %cl, %cl226; X86-NEXT: setne %al227; X86-NEXT: retl228 %add = atomicrmw add ptr %x, i8 1 seq_cst229 %cmp = icmp ne i8 %add, 0230 ret i1 %cmp231}232