1759 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 X64 --check-prefix FAST_INC3; RUN: llc < %s -mtriple=i686-unknown-unknown -verify-machineinstrs | FileCheck %s --check-prefix X324; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=slow-incdec -verify-machineinstrs | FileCheck %s --check-prefix X64 --check-prefix SLOW_INC5 6; This file checks that atomic (non-seq_cst) stores of immediate values are7; done in one mov instruction and not 2. More precisely, it makes sure that the8; immediate is not first copied uselessly into a register.9 10; Similarily, it checks that a binary operation of an immediate with an atomic11; variable that is stored back in that variable is done as a single instruction.12; For example: x.store(42 + x.load(memory_order_acquire), memory_order_release)13; should be just an add instruction, instead of loading x into a register, doing14; an add and storing the result back.15; The binary operations supported are currently add, and, or, xor.16; sub is not supported because they are translated by an addition of the17; negated immediate.18;19; We also check the same patterns:20; - For inc/dec.21; - For register instead of immediate operands.22; - For floating point operations.23 24; seq_cst stores are left as (lock) xchgl, but we try to check every other25; attribute at least once.26 27; Please note that these operations do not require the lock prefix: only28; sequentially consistent stores require this kind of protection on X86.29; And even for seq_cst operations, llvm uses the xchg instruction which has30; an implicit lock prefix, so making it explicit is not required.31 32define void @store_atomic_imm_8(ptr %p) {33; X64-LABEL: store_atomic_imm_8:34; X64: # %bb.0:35; X64-NEXT: movb $42, (%rdi)36; X64-NEXT: retq37;38; X32-LABEL: store_atomic_imm_8:39; X32: # %bb.0:40; X32-NEXT: movl {{[0-9]+}}(%esp), %eax41; X32-NEXT: movb $42, (%eax)42; X32-NEXT: retl43 store atomic i8 42, ptr %p release, align 144 ret void45}46 47define void @store_atomic_imm_16(ptr %p) {48; X64-LABEL: store_atomic_imm_16:49; X64: # %bb.0:50; X64-NEXT: movw $42, (%rdi)51; X64-NEXT: retq52;53; X32-LABEL: store_atomic_imm_16:54; X32: # %bb.0:55; X32-NEXT: movl {{[0-9]+}}(%esp), %eax56; X32-NEXT: movw $42, (%eax)57; X32-NEXT: retl58 store atomic i16 42, ptr %p monotonic, align 259 ret void60}61 62define void @store_atomic_imm_32(ptr %p) {63; X64-LABEL: store_atomic_imm_32:64; X64: # %bb.0:65; X64-NEXT: movl $42, (%rdi)66; X64-NEXT: retq67;68; X32-LABEL: store_atomic_imm_32:69; X32: # %bb.0:70; X32-NEXT: movl {{[0-9]+}}(%esp), %eax71; X32-NEXT: movl $42, (%eax)72; X32-NEXT: retl73; On 32 bits, there is an extra movl for each of those functions74; (probably for alignment reasons).75 store atomic i32 42, ptr %p release, align 476 ret void77}78 79define void @store_atomic_imm_64(ptr %p) {80; X64-LABEL: store_atomic_imm_64:81; X64: # %bb.0:82; X64-NEXT: movq $42, (%rdi)83; X64-NEXT: retq84;85; X32-LABEL: store_atomic_imm_64:86; X32: # %bb.0:87; X32-NEXT: pushl %ebp88; X32-NEXT: .cfi_def_cfa_offset 889; X32-NEXT: .cfi_offset %ebp, -890; X32-NEXT: movl %esp, %ebp91; X32-NEXT: .cfi_def_cfa_register %ebp92; X32-NEXT: andl $-8, %esp93; X32-NEXT: subl $8, %esp94; X32-NEXT: movl 8(%ebp), %eax95; X32-NEXT: movl $0, {{[0-9]+}}(%esp)96; X32-NEXT: movl $42, (%esp)97; X32-NEXT: fildll (%esp)98; X32-NEXT: fistpll (%eax)99; X32-NEXT: movl %ebp, %esp100; X32-NEXT: popl %ebp101; X32-NEXT: .cfi_def_cfa %esp, 4102; X32-NEXT: retl103; These are implemented with a CAS loop on 32 bit architectures, and thus104; cannot be optimized in the same way as the others.105 store atomic i64 42, ptr %p release, align 8106 ret void107}108 109; If an immediate is too big to fit in 32 bits, it cannot be store in one mov,110; even on X64, one must use movabsq that can only target a register.111define void @store_atomic_imm_64_big(ptr %p) {112; X64-LABEL: store_atomic_imm_64_big:113; X64: # %bb.0:114; X64-NEXT: movabsq $100000000000, %rax # imm = 0x174876E800115; X64-NEXT: movq %rax, (%rdi)116; X64-NEXT: retq117;118; X32-LABEL: store_atomic_imm_64_big:119; X32: # %bb.0:120; X32-NEXT: pushl %ebp121; X32-NEXT: .cfi_def_cfa_offset 8122; X32-NEXT: .cfi_offset %ebp, -8123; X32-NEXT: movl %esp, %ebp124; X32-NEXT: .cfi_def_cfa_register %ebp125; X32-NEXT: andl $-8, %esp126; X32-NEXT: subl $8, %esp127; X32-NEXT: movl 8(%ebp), %eax128; X32-NEXT: movl $23, {{[0-9]+}}(%esp)129; X32-NEXT: movl $1215752192, (%esp) # imm = 0x4876E800130; X32-NEXT: fildll (%esp)131; X32-NEXT: fistpll (%eax)132; X32-NEXT: movl %ebp, %esp133; X32-NEXT: popl %ebp134; X32-NEXT: .cfi_def_cfa %esp, 4135; X32-NEXT: retl136 store atomic i64 100000000000, ptr %p monotonic, align 8137 ret void138}139 140; It would be incorrect to replace a lock xchgl by a movl141define void @store_atomic_imm_32_seq_cst(ptr %p) {142; X64-LABEL: store_atomic_imm_32_seq_cst:143; X64: # %bb.0:144; X64-NEXT: movl $42, %eax145; X64-NEXT: xchgl %eax, (%rdi)146; X64-NEXT: retq147;148; X32-LABEL: store_atomic_imm_32_seq_cst:149; X32: # %bb.0:150; X32-NEXT: movl {{[0-9]+}}(%esp), %eax151; X32-NEXT: movl $42, %ecx152; X32-NEXT: xchgl %ecx, (%eax)153; X32-NEXT: retl154 store atomic i32 42, ptr %p seq_cst, align 4155 ret void156}157 158; ----- ADD -----159 160define void @add_8i(ptr %p) {161; X64-LABEL: add_8i:162; X64: # %bb.0:163; X64-NEXT: addb $2, (%rdi)164; X64-NEXT: retq165;166; X32-LABEL: add_8i:167; X32: # %bb.0:168; X32-NEXT: movl {{[0-9]+}}(%esp), %eax169; X32-NEXT: addb $2, (%eax)170; X32-NEXT: retl171 %1 = load atomic i8, ptr %p seq_cst, align 1172 %2 = add i8 %1, 2173 store atomic i8 %2, ptr %p release, align 1174 ret void175}176 177define void @add_8r(ptr %p, i8 %v) {178; X64-LABEL: add_8r:179; X64: # %bb.0:180; X64-NEXT: addb %sil, (%rdi)181; X64-NEXT: retq182;183; X32-LABEL: add_8r:184; X32: # %bb.0:185; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax186; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx187; X32-NEXT: addb %al, (%ecx)188; X32-NEXT: retl189 %1 = load atomic i8, ptr %p seq_cst, align 1190 %2 = add i8 %1, %v191 store atomic i8 %2, ptr %p release, align 1192 ret void193}194 195define void @add_16i(ptr %p) {196; X64-LABEL: add_16i:197; X64: # %bb.0:198; X64-NEXT: addw $2, (%rdi)199; X64-NEXT: retq200;201; X32-LABEL: add_16i:202; X32: # %bb.0:203; X32-NEXT: movl {{[0-9]+}}(%esp), %eax204; X32-NEXT: addw $2, (%eax)205; X32-NEXT: retl206 %1 = load atomic i16, ptr %p acquire, align 2207 %2 = add i16 %1, 2208 store atomic i16 %2, ptr %p release, align 2209 ret void210}211 212define void @add_16r(ptr %p, i16 %v) {213; X64-LABEL: add_16r:214; X64: # %bb.0:215; X64-NEXT: addw %si, (%rdi)216; X64-NEXT: retq217;218; X32-LABEL: add_16r:219; X32: # %bb.0:220; X32-NEXT: movzwl {{[0-9]+}}(%esp), %eax221; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx222; X32-NEXT: addw %ax, (%ecx)223; X32-NEXT: retl224 %1 = load atomic i16, ptr %p acquire, align 2225 %2 = add i16 %1, %v226 store atomic i16 %2, ptr %p release, align 2227 ret void228}229 230define void @add_32i(ptr %p) {231; X64-LABEL: add_32i:232; X64: # %bb.0:233; X64-NEXT: addl $2, (%rdi)234; X64-NEXT: retq235;236; X32-LABEL: add_32i:237; X32: # %bb.0:238; X32-NEXT: movl {{[0-9]+}}(%esp), %eax239; X32-NEXT: addl $2, (%eax)240; X32-NEXT: retl241 %1 = load atomic i32, ptr %p acquire, align 4242 %2 = add i32 %1, 2243 store atomic i32 %2, ptr %p monotonic, align 4244 ret void245}246 247define void @add_32r(ptr %p, i32 %v) {248; X64-LABEL: add_32r:249; X64: # %bb.0:250; X64-NEXT: addl %esi, (%rdi)251; X64-NEXT: retq252;253; X32-LABEL: add_32r:254; X32: # %bb.0:255; X32-NEXT: movl {{[0-9]+}}(%esp), %eax256; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx257; X32-NEXT: addl %eax, (%ecx)258; X32-NEXT: retl259 %1 = load atomic i32, ptr %p acquire, align 4260 %2 = add i32 %1, %v261 store atomic i32 %2, ptr %p monotonic, align 4262 ret void263}264 265; The following is a corner case where the load is added to itself. The pattern266; matching should not fold this. We only test with 32-bit add, but the same267; applies to other sizes and operations.268define void @add_32r_self(ptr %p) {269; X64-LABEL: add_32r_self:270; X64: # %bb.0:271; X64-NEXT: movl (%rdi), %eax272; X64-NEXT: addl %eax, %eax273; X64-NEXT: movl %eax, (%rdi)274; X64-NEXT: retq275;276; X32-LABEL: add_32r_self:277; X32: # %bb.0:278; X32-NEXT: movl {{[0-9]+}}(%esp), %eax279; X32-NEXT: movl (%eax), %ecx280; X32-NEXT: addl %ecx, %ecx281; X32-NEXT: movl %ecx, (%eax)282; X32-NEXT: retl283 %1 = load atomic i32, ptr %p acquire, align 4284 %2 = add i32 %1, %1285 store atomic i32 %2, ptr %p monotonic, align 4286 ret void287}288 289; The following is a corner case where the load's result is returned. The290; optimizer isn't allowed to duplicate the load because it's atomic.291define i32 @add_32r_ret_load(ptr %p, i32 %v) {292; X64-LABEL: add_32r_ret_load:293; X64: # %bb.0:294; X64-NEXT: movl (%rdi), %eax295; X64-NEXT: addl %eax, %esi296; X64-NEXT: movl %esi, (%rdi)297; X64-NEXT: retq298;299; X32-LABEL: add_32r_ret_load:300; X32: # %bb.0:301; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx302; X32-NEXT: movl (%ecx), %eax303; X32-NEXT: movl {{[0-9]+}}(%esp), %edx304; X32-NEXT: addl %eax, %edx305; X32-NEXT: movl %edx, (%ecx)306; X32-NEXT: retl307; More code here, we just don't want it to load from P.308 %1 = load atomic i32, ptr %p acquire, align 4309 %2 = add i32 %1, %v310 store atomic i32 %2, ptr %p monotonic, align 4311 ret i32 %1312}313 314define void @add_64i(ptr %p) {315; X64-LABEL: add_64i:316; X64: # %bb.0:317; X64-NEXT: addq $2, (%rdi)318; X64-NEXT: retq319;320; X32-LABEL: add_64i:321; X32: # %bb.0:322; X32-NEXT: pushl %ebp323; X32-NEXT: .cfi_def_cfa_offset 8324; X32-NEXT: .cfi_offset %ebp, -8325; X32-NEXT: movl %esp, %ebp326; X32-NEXT: .cfi_def_cfa_register %ebp327; X32-NEXT: andl $-8, %esp328; X32-NEXT: subl $16, %esp329; X32-NEXT: movl 8(%ebp), %eax330; X32-NEXT: fildll (%eax)331; X32-NEXT: fistpll {{[0-9]+}}(%esp)332; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx333; X32-NEXT: movl {{[0-9]+}}(%esp), %edx334; X32-NEXT: addl $2, %ecx335; X32-NEXT: adcl $0, %edx336; X32-NEXT: movl %ecx, (%esp)337; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)338; X32-NEXT: fildll (%esp)339; X32-NEXT: fistpll (%eax)340; X32-NEXT: movl %ebp, %esp341; X32-NEXT: popl %ebp342; X32-NEXT: .cfi_def_cfa %esp, 4343; X32-NEXT: retl344; We do not check X86-32 as it cannot do 'addq'.345 %1 = load atomic i64, ptr %p acquire, align 8346 %2 = add i64 %1, 2347 store atomic i64 %2, ptr %p release, align 8348 ret void349}350 351define void @add_64r(ptr %p, i64 %v) {352; X64-LABEL: add_64r:353; X64: # %bb.0:354; X64-NEXT: addq %rsi, (%rdi)355; X64-NEXT: retq356;357; X32-LABEL: add_64r:358; X32: # %bb.0:359; X32-NEXT: pushl %ebp360; X32-NEXT: .cfi_def_cfa_offset 8361; X32-NEXT: .cfi_offset %ebp, -8362; X32-NEXT: movl %esp, %ebp363; X32-NEXT: .cfi_def_cfa_register %ebp364; X32-NEXT: andl $-8, %esp365; X32-NEXT: subl $16, %esp366; X32-NEXT: movl 8(%ebp), %eax367; X32-NEXT: fildll (%eax)368; X32-NEXT: fistpll {{[0-9]+}}(%esp)369; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx370; X32-NEXT: movl {{[0-9]+}}(%esp), %edx371; X32-NEXT: addl 12(%ebp), %ecx372; X32-NEXT: adcl 16(%ebp), %edx373; X32-NEXT: movl %ecx, (%esp)374; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)375; X32-NEXT: fildll (%esp)376; X32-NEXT: fistpll (%eax)377; X32-NEXT: movl %ebp, %esp378; X32-NEXT: popl %ebp379; X32-NEXT: .cfi_def_cfa %esp, 4380; X32-NEXT: retl381; We do not check X86-32 as it cannot do 'addq'.382 %1 = load atomic i64, ptr %p acquire, align 8383 %2 = add i64 %1, %v384 store atomic i64 %2, ptr %p release, align 8385 ret void386}387 388define void @add_32i_seq_cst(ptr %p) {389; X64-LABEL: add_32i_seq_cst:390; X64: # %bb.0:391; X64-NEXT: movl (%rdi), %eax392; X64-NEXT: addl $2, %eax393; X64-NEXT: xchgl %eax, (%rdi)394; X64-NEXT: retq395;396; X32-LABEL: add_32i_seq_cst:397; X32: # %bb.0:398; X32-NEXT: movl {{[0-9]+}}(%esp), %eax399; X32-NEXT: movl (%eax), %ecx400; X32-NEXT: addl $2, %ecx401; X32-NEXT: xchgl %ecx, (%eax)402; X32-NEXT: retl403 %1 = load atomic i32, ptr %p monotonic, align 4404 %2 = add i32 %1, 2405 store atomic i32 %2, ptr %p seq_cst, align 4406 ret void407}408 409define void @add_32r_seq_cst(ptr %p, i32 %v) {410; X64-LABEL: add_32r_seq_cst:411; X64: # %bb.0:412; X64-NEXT: movl (%rdi), %eax413; X64-NEXT: addl %esi, %eax414; X64-NEXT: xchgl %eax, (%rdi)415; X64-NEXT: retq416;417; X32-LABEL: add_32r_seq_cst:418; X32: # %bb.0:419; X32-NEXT: movl {{[0-9]+}}(%esp), %eax420; X32-NEXT: movl (%eax), %ecx421; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx422; X32-NEXT: xchgl %ecx, (%eax)423; X32-NEXT: retl424 %1 = load atomic i32, ptr %p monotonic, align 4425 %2 = add i32 %1, %v426 store atomic i32 %2, ptr %p seq_cst, align 4427 ret void428}429 430; ----- SUB -----431 432define void @sub_8r(ptr %p, i8 %v) {433; X64-LABEL: sub_8r:434; X64: # %bb.0:435; X64-NEXT: subb %sil, (%rdi)436; X64-NEXT: retq437;438; X32-LABEL: sub_8r:439; X32: # %bb.0:440; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax441; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx442; X32-NEXT: subb %al, (%ecx)443; X32-NEXT: retl444 %1 = load atomic i8, ptr %p seq_cst, align 1445 %2 = sub i8 %1, %v446 store atomic i8 %2, ptr %p release, align 1447 ret void448}449 450define void @sub_16r(ptr %p, i16 %v) {451; X64-LABEL: sub_16r:452; X64: # %bb.0:453; X64-NEXT: subw %si, (%rdi)454; X64-NEXT: retq455;456; X32-LABEL: sub_16r:457; X32: # %bb.0:458; X32-NEXT: movzwl {{[0-9]+}}(%esp), %eax459; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx460; X32-NEXT: subw %ax, (%ecx)461; X32-NEXT: retl462 %1 = load atomic i16, ptr %p acquire, align 2463 %2 = sub i16 %1, %v464 store atomic i16 %2, ptr %p release, align 2465 ret void466}467 468define void @sub_32r(ptr %p, i32 %v) {469; X64-LABEL: sub_32r:470; X64: # %bb.0:471; X64-NEXT: subl %esi, (%rdi)472; X64-NEXT: retq473;474; X32-LABEL: sub_32r:475; X32: # %bb.0:476; X32-NEXT: movl {{[0-9]+}}(%esp), %eax477; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx478; X32-NEXT: subl %eax, (%ecx)479; X32-NEXT: retl480 %1 = load atomic i32, ptr %p acquire, align 4481 %2 = sub i32 %1, %v482 store atomic i32 %2, ptr %p monotonic, align 4483 ret void484}485 486; The following is a corner case where the load is subed to itself. The pattern487; matching should not fold this. We only test with 32-bit sub, but the same488; applies to other sizes and operations.489define void @sub_32r_self(ptr %p) {490; X64-LABEL: sub_32r_self:491; X64: # %bb.0:492; X64-NEXT: movl (%rdi), %eax493; X64-NEXT: movl $0, (%rdi)494; X64-NEXT: retq495;496; X32-LABEL: sub_32r_self:497; X32: # %bb.0:498; X32-NEXT: movl {{[0-9]+}}(%esp), %eax499; X32-NEXT: movl (%eax), %ecx500; X32-NEXT: movl $0, (%eax)501; X32-NEXT: retl502 %1 = load atomic i32, ptr %p acquire, align 4503 %2 = sub i32 %1, %1504 store atomic i32 %2, ptr %p monotonic, align 4505 ret void506}507 508; The following is a corner case where the load's result is returned. The509; optimizer isn't allowed to duplicate the load because it's atomic.510define i32 @sub_32r_ret_load(ptr %p, i32 %v) {511; X64-LABEL: sub_32r_ret_load:512; X64: # %bb.0:513; X64-NEXT: movl (%rdi), %eax514; X64-NEXT: movl %eax, %ecx515; X64-NEXT: subl %esi, %ecx516; X64-NEXT: movl %ecx, (%rdi)517; X64-NEXT: retq518;519; X32-LABEL: sub_32r_ret_load:520; X32: # %bb.0:521; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx522; X32-NEXT: movl (%ecx), %eax523; X32-NEXT: movl %eax, %edx524; X32-NEXT: subl {{[0-9]+}}(%esp), %edx525; X32-NEXT: movl %edx, (%ecx)526; X32-NEXT: retl527; More code here, we just don't want it to load from P.528 %1 = load atomic i32, ptr %p acquire, align 4529 %2 = sub i32 %1, %v530 store atomic i32 %2, ptr %p monotonic, align 4531 ret i32 %1532}533 534define void @sub_64r(ptr %p, i64 %v) {535; X64-LABEL: sub_64r:536; X64: # %bb.0:537; X64-NEXT: subq %rsi, (%rdi)538; X64-NEXT: retq539;540; X32-LABEL: sub_64r:541; X32: # %bb.0:542; X32-NEXT: pushl %ebp543; X32-NEXT: .cfi_def_cfa_offset 8544; X32-NEXT: .cfi_offset %ebp, -8545; X32-NEXT: movl %esp, %ebp546; X32-NEXT: .cfi_def_cfa_register %ebp547; X32-NEXT: andl $-8, %esp548; X32-NEXT: subl $16, %esp549; X32-NEXT: movl 8(%ebp), %eax550; X32-NEXT: fildll (%eax)551; X32-NEXT: fistpll {{[0-9]+}}(%esp)552; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx553; X32-NEXT: movl {{[0-9]+}}(%esp), %edx554; X32-NEXT: subl 12(%ebp), %ecx555; X32-NEXT: sbbl 16(%ebp), %edx556; X32-NEXT: movl %ecx, (%esp)557; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)558; X32-NEXT: fildll (%esp)559; X32-NEXT: fistpll (%eax)560; X32-NEXT: movl %ebp, %esp561; X32-NEXT: popl %ebp562; X32-NEXT: .cfi_def_cfa %esp, 4563; X32-NEXT: retl564; We do not check X86-32 as it cannot do 'subq'.565 %1 = load atomic i64, ptr %p acquire, align 8566 %2 = sub i64 %1, %v567 store atomic i64 %2, ptr %p release, align 8568 ret void569}570 571define void @sub_32r_seq_cst(ptr %p, i32 %v) {572; X64-LABEL: sub_32r_seq_cst:573; X64: # %bb.0:574; X64-NEXT: movl (%rdi), %eax575; X64-NEXT: subl %esi, %eax576; X64-NEXT: xchgl %eax, (%rdi)577; X64-NEXT: retq578;579; X32-LABEL: sub_32r_seq_cst:580; X32: # %bb.0:581; X32-NEXT: movl {{[0-9]+}}(%esp), %eax582; X32-NEXT: movl (%eax), %ecx583; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx584; X32-NEXT: xchgl %ecx, (%eax)585; X32-NEXT: retl586 %1 = load atomic i32, ptr %p monotonic, align 4587 %2 = sub i32 %1, %v588 store atomic i32 %2, ptr %p seq_cst, align 4589 ret void590}591 592; ----- AND -----593 594define void @and_8i(ptr %p) {595; X64-LABEL: and_8i:596; X64: # %bb.0:597; X64-NEXT: andb $2, (%rdi)598; X64-NEXT: retq599;600; X32-LABEL: and_8i:601; X32: # %bb.0:602; X32-NEXT: movl {{[0-9]+}}(%esp), %eax603; X32-NEXT: andb $2, (%eax)604; X32-NEXT: retl605 %1 = load atomic i8, ptr %p monotonic, align 1606 %2 = and i8 %1, 2607 store atomic i8 %2, ptr %p release, align 1608 ret void609}610 611define void @and_8r(ptr %p, i8 %v) {612; X64-LABEL: and_8r:613; X64: # %bb.0:614; X64-NEXT: andb %sil, (%rdi)615; X64-NEXT: retq616;617; X32-LABEL: and_8r:618; X32: # %bb.0:619; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax620; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx621; X32-NEXT: andb %al, (%ecx)622; X32-NEXT: retl623 %1 = load atomic i8, ptr %p monotonic, align 1624 %2 = and i8 %1, %v625 store atomic i8 %2, ptr %p release, align 1626 ret void627}628 629define void @and_16i(ptr %p) {630; X64-LABEL: and_16i:631; X64: # %bb.0:632; X64-NEXT: andw $2, (%rdi)633; X64-NEXT: retq634;635; X32-LABEL: and_16i:636; X32: # %bb.0:637; X32-NEXT: movl {{[0-9]+}}(%esp), %eax638; X32-NEXT: andw $2, (%eax)639; X32-NEXT: retl640 %1 = load atomic i16, ptr %p acquire, align 2641 %2 = and i16 %1, 2642 store atomic i16 %2, ptr %p release, align 2643 ret void644}645 646define void @and_16r(ptr %p, i16 %v) {647; X64-LABEL: and_16r:648; X64: # %bb.0:649; X64-NEXT: andw %si, (%rdi)650; X64-NEXT: retq651;652; X32-LABEL: and_16r:653; X32: # %bb.0:654; X32-NEXT: movzwl {{[0-9]+}}(%esp), %eax655; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx656; X32-NEXT: andw %ax, (%ecx)657; X32-NEXT: retl658 %1 = load atomic i16, ptr %p acquire, align 2659 %2 = and i16 %1, %v660 store atomic i16 %2, ptr %p release, align 2661 ret void662}663 664define void @and_32i(ptr %p) {665; X64-LABEL: and_32i:666; X64: # %bb.0:667; X64-NEXT: andl $2, (%rdi)668; X64-NEXT: retq669;670; X32-LABEL: and_32i:671; X32: # %bb.0:672; X32-NEXT: movl {{[0-9]+}}(%esp), %eax673; X32-NEXT: andl $2, (%eax)674; X32-NEXT: retl675 %1 = load atomic i32, ptr %p acquire, align 4676 %2 = and i32 %1, 2677 store atomic i32 %2, ptr %p release, align 4678 ret void679}680 681define void @and_32r(ptr %p, i32 %v) {682; X64-LABEL: and_32r:683; X64: # %bb.0:684; X64-NEXT: andl %esi, (%rdi)685; X64-NEXT: retq686;687; X32-LABEL: and_32r:688; X32: # %bb.0:689; X32-NEXT: movl {{[0-9]+}}(%esp), %eax690; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx691; X32-NEXT: andl %eax, (%ecx)692; X32-NEXT: retl693 %1 = load atomic i32, ptr %p acquire, align 4694 %2 = and i32 %1, %v695 store atomic i32 %2, ptr %p release, align 4696 ret void697}698 699define void @and_64i(ptr %p) {700; X64-LABEL: and_64i:701; X64: # %bb.0:702; X64-NEXT: andq $2, (%rdi)703; X64-NEXT: retq704;705; X32-LABEL: and_64i:706; X32: # %bb.0:707; X32-NEXT: pushl %ebp708; X32-NEXT: .cfi_def_cfa_offset 8709; X32-NEXT: .cfi_offset %ebp, -8710; X32-NEXT: movl %esp, %ebp711; X32-NEXT: .cfi_def_cfa_register %ebp712; X32-NEXT: andl $-8, %esp713; X32-NEXT: subl $16, %esp714; X32-NEXT: movl 8(%ebp), %eax715; X32-NEXT: fildll (%eax)716; X32-NEXT: fistpll {{[0-9]+}}(%esp)717; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx718; X32-NEXT: andl $2, %ecx719; X32-NEXT: movl %ecx, (%esp)720; X32-NEXT: movl $0, {{[0-9]+}}(%esp)721; X32-NEXT: fildll (%esp)722; X32-NEXT: fistpll (%eax)723; X32-NEXT: movl %ebp, %esp724; X32-NEXT: popl %ebp725; X32-NEXT: .cfi_def_cfa %esp, 4726; X32-NEXT: retl727; We do not check X86-32 as it cannot do 'andq'.728 %1 = load atomic i64, ptr %p acquire, align 8729 %2 = and i64 %1, 2730 store atomic i64 %2, ptr %p release, align 8731 ret void732}733 734define void @and_64r(ptr %p, i64 %v) {735; X64-LABEL: and_64r:736; X64: # %bb.0:737; X64-NEXT: andq %rsi, (%rdi)738; X64-NEXT: retq739;740; X32-LABEL: and_64r:741; X32: # %bb.0:742; X32-NEXT: pushl %ebp743; X32-NEXT: .cfi_def_cfa_offset 8744; X32-NEXT: .cfi_offset %ebp, -8745; X32-NEXT: movl %esp, %ebp746; X32-NEXT: .cfi_def_cfa_register %ebp747; X32-NEXT: andl $-8, %esp748; X32-NEXT: subl $16, %esp749; X32-NEXT: movl 8(%ebp), %eax750; X32-NEXT: fildll (%eax)751; X32-NEXT: fistpll {{[0-9]+}}(%esp)752; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx753; X32-NEXT: movl {{[0-9]+}}(%esp), %edx754; X32-NEXT: andl 16(%ebp), %edx755; X32-NEXT: andl 12(%ebp), %ecx756; X32-NEXT: movl %ecx, (%esp)757; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)758; X32-NEXT: fildll (%esp)759; X32-NEXT: fistpll (%eax)760; X32-NEXT: movl %ebp, %esp761; X32-NEXT: popl %ebp762; X32-NEXT: .cfi_def_cfa %esp, 4763; X32-NEXT: retl764; We do not check X86-32 as it cannot do 'andq'.765 %1 = load atomic i64, ptr %p acquire, align 8766 %2 = and i64 %1, %v767 store atomic i64 %2, ptr %p release, align 8768 ret void769}770 771define void @and_32i_seq_cst(ptr %p) {772; X64-LABEL: and_32i_seq_cst:773; X64: # %bb.0:774; X64-NEXT: movl (%rdi), %eax775; X64-NEXT: andl $2, %eax776; X64-NEXT: xchgl %eax, (%rdi)777; X64-NEXT: retq778;779; X32-LABEL: and_32i_seq_cst:780; X32: # %bb.0:781; X32-NEXT: movl {{[0-9]+}}(%esp), %eax782; X32-NEXT: movl (%eax), %ecx783; X32-NEXT: andl $2, %ecx784; X32-NEXT: xchgl %ecx, (%eax)785; X32-NEXT: retl786 %1 = load atomic i32, ptr %p monotonic, align 4787 %2 = and i32 %1, 2788 store atomic i32 %2, ptr %p seq_cst, align 4789 ret void790}791 792define void @and_32r_seq_cst(ptr %p, i32 %v) {793; X64-LABEL: and_32r_seq_cst:794; X64: # %bb.0:795; X64-NEXT: movl (%rdi), %eax796; X64-NEXT: andl %esi, %eax797; X64-NEXT: xchgl %eax, (%rdi)798; X64-NEXT: retq799;800; X32-LABEL: and_32r_seq_cst:801; X32: # %bb.0:802; X32-NEXT: movl {{[0-9]+}}(%esp), %eax803; X32-NEXT: movl (%eax), %ecx804; X32-NEXT: andl {{[0-9]+}}(%esp), %ecx805; X32-NEXT: xchgl %ecx, (%eax)806; X32-NEXT: retl807 %1 = load atomic i32, ptr %p monotonic, align 4808 %2 = and i32 %1, %v809 store atomic i32 %2, ptr %p seq_cst, align 4810 ret void811}812 813; ----- OR -----814 815define void @or_8i(ptr %p) {816; X64-LABEL: or_8i:817; X64: # %bb.0:818; X64-NEXT: orb $2, (%rdi)819; X64-NEXT: retq820;821; X32-LABEL: or_8i:822; X32: # %bb.0:823; X32-NEXT: movl {{[0-9]+}}(%esp), %eax824; X32-NEXT: orb $2, (%eax)825; X32-NEXT: retl826 %1 = load atomic i8, ptr %p acquire, align 1827 %2 = or i8 %1, 2828 store atomic i8 %2, ptr %p release, align 1829 ret void830}831 832define void @or_8r(ptr %p, i8 %v) {833; X64-LABEL: or_8r:834; X64: # %bb.0:835; X64-NEXT: orb %sil, (%rdi)836; X64-NEXT: retq837;838; X32-LABEL: or_8r:839; X32: # %bb.0:840; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax841; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx842; X32-NEXT: orb %al, (%ecx)843; X32-NEXT: retl844 %1 = load atomic i8, ptr %p acquire, align 1845 %2 = or i8 %1, %v846 store atomic i8 %2, ptr %p release, align 1847 ret void848}849 850define void @or_16i(ptr %p) {851; X64-LABEL: or_16i:852; X64: # %bb.0:853; X64-NEXT: orw $2, (%rdi)854; X64-NEXT: retq855;856; X32-LABEL: or_16i:857; X32: # %bb.0:858; X32-NEXT: movl {{[0-9]+}}(%esp), %eax859; X32-NEXT: orw $2, (%eax)860; X32-NEXT: retl861 %1 = load atomic i16, ptr %p acquire, align 2862 %2 = or i16 %1, 2863 store atomic i16 %2, ptr %p release, align 2864 ret void865}866 867define void @or_16r(ptr %p, i16 %v) {868; X64-LABEL: or_16r:869; X64: # %bb.0:870; X64-NEXT: orw %si, (%rdi)871; X64-NEXT: retq872;873; X32-LABEL: or_16r:874; X32: # %bb.0:875; X32-NEXT: movzwl {{[0-9]+}}(%esp), %eax876; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx877; X32-NEXT: orw %ax, (%ecx)878; X32-NEXT: retl879 %1 = load atomic i16, ptr %p acquire, align 2880 %2 = or i16 %1, %v881 store atomic i16 %2, ptr %p release, align 2882 ret void883}884 885define void @or_32i(ptr %p) {886; X64-LABEL: or_32i:887; X64: # %bb.0:888; X64-NEXT: orl $2, (%rdi)889; X64-NEXT: retq890;891; X32-LABEL: or_32i:892; X32: # %bb.0:893; X32-NEXT: movl {{[0-9]+}}(%esp), %eax894; X32-NEXT: orl $2, (%eax)895; X32-NEXT: retl896 %1 = load atomic i32, ptr %p acquire, align 4897 %2 = or i32 %1, 2898 store atomic i32 %2, ptr %p release, align 4899 ret void900}901 902define void @or_32r(ptr %p, i32 %v) {903; X64-LABEL: or_32r:904; X64: # %bb.0:905; X64-NEXT: orl %esi, (%rdi)906; X64-NEXT: retq907;908; X32-LABEL: or_32r:909; X32: # %bb.0:910; X32-NEXT: movl {{[0-9]+}}(%esp), %eax911; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx912; X32-NEXT: orl %eax, (%ecx)913; X32-NEXT: retl914 %1 = load atomic i32, ptr %p acquire, align 4915 %2 = or i32 %1, %v916 store atomic i32 %2, ptr %p release, align 4917 ret void918}919 920define void @or_64i(ptr %p) {921; X64-LABEL: or_64i:922; X64: # %bb.0:923; X64-NEXT: orq $2, (%rdi)924; X64-NEXT: retq925;926; X32-LABEL: or_64i:927; X32: # %bb.0:928; X32-NEXT: pushl %ebp929; X32-NEXT: .cfi_def_cfa_offset 8930; X32-NEXT: .cfi_offset %ebp, -8931; X32-NEXT: movl %esp, %ebp932; X32-NEXT: .cfi_def_cfa_register %ebp933; X32-NEXT: andl $-8, %esp934; X32-NEXT: subl $16, %esp935; X32-NEXT: movl 8(%ebp), %eax936; X32-NEXT: fildll (%eax)937; X32-NEXT: fistpll {{[0-9]+}}(%esp)938; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx939; X32-NEXT: movl {{[0-9]+}}(%esp), %edx940; X32-NEXT: orl $2, %ecx941; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)942; X32-NEXT: movl %ecx, (%esp)943; X32-NEXT: fildll (%esp)944; X32-NEXT: fistpll (%eax)945; X32-NEXT: movl %ebp, %esp946; X32-NEXT: popl %ebp947; X32-NEXT: .cfi_def_cfa %esp, 4948; X32-NEXT: retl949; We do not check X86-32 as it cannot do 'orq'.950 %1 = load atomic i64, ptr %p acquire, align 8951 %2 = or i64 %1, 2952 store atomic i64 %2, ptr %p release, align 8953 ret void954}955 956define void @or_64r(ptr %p, i64 %v) {957; X64-LABEL: or_64r:958; X64: # %bb.0:959; X64-NEXT: orq %rsi, (%rdi)960; X64-NEXT: retq961;962; X32-LABEL: or_64r:963; X32: # %bb.0:964; X32-NEXT: pushl %ebp965; X32-NEXT: .cfi_def_cfa_offset 8966; X32-NEXT: .cfi_offset %ebp, -8967; X32-NEXT: movl %esp, %ebp968; X32-NEXT: .cfi_def_cfa_register %ebp969; X32-NEXT: andl $-8, %esp970; X32-NEXT: subl $16, %esp971; X32-NEXT: movl 8(%ebp), %eax972; X32-NEXT: fildll (%eax)973; X32-NEXT: fistpll {{[0-9]+}}(%esp)974; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx975; X32-NEXT: movl {{[0-9]+}}(%esp), %edx976; X32-NEXT: orl 16(%ebp), %edx977; X32-NEXT: orl 12(%ebp), %ecx978; X32-NEXT: movl %ecx, (%esp)979; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)980; X32-NEXT: fildll (%esp)981; X32-NEXT: fistpll (%eax)982; X32-NEXT: movl %ebp, %esp983; X32-NEXT: popl %ebp984; X32-NEXT: .cfi_def_cfa %esp, 4985; X32-NEXT: retl986; We do not check X86-32 as it cannot do 'orq'.987 %1 = load atomic i64, ptr %p acquire, align 8988 %2 = or i64 %1, %v989 store atomic i64 %2, ptr %p release, align 8990 ret void991}992 993define void @or_32i_seq_cst(ptr %p) {994; X64-LABEL: or_32i_seq_cst:995; X64: # %bb.0:996; X64-NEXT: movl (%rdi), %eax997; X64-NEXT: orl $2, %eax998; X64-NEXT: xchgl %eax, (%rdi)999; X64-NEXT: retq1000;1001; X32-LABEL: or_32i_seq_cst:1002; X32: # %bb.0:1003; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1004; X32-NEXT: movl (%eax), %ecx1005; X32-NEXT: orl $2, %ecx1006; X32-NEXT: xchgl %ecx, (%eax)1007; X32-NEXT: retl1008 %1 = load atomic i32, ptr %p monotonic, align 41009 %2 = or i32 %1, 21010 store atomic i32 %2, ptr %p seq_cst, align 41011 ret void1012}1013 1014define void @or_32r_seq_cst(ptr %p, i32 %v) {1015; X64-LABEL: or_32r_seq_cst:1016; X64: # %bb.0:1017; X64-NEXT: movl (%rdi), %eax1018; X64-NEXT: orl %esi, %eax1019; X64-NEXT: xchgl %eax, (%rdi)1020; X64-NEXT: retq1021;1022; X32-LABEL: or_32r_seq_cst:1023; X32: # %bb.0:1024; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1025; X32-NEXT: movl (%eax), %ecx1026; X32-NEXT: orl {{[0-9]+}}(%esp), %ecx1027; X32-NEXT: xchgl %ecx, (%eax)1028; X32-NEXT: retl1029 %1 = load atomic i32, ptr %p monotonic, align 41030 %2 = or i32 %1, %v1031 store atomic i32 %2, ptr %p seq_cst, align 41032 ret void1033}1034 1035; ----- XOR -----1036 1037define void @xor_8i(ptr %p) {1038; X64-LABEL: xor_8i:1039; X64: # %bb.0:1040; X64-NEXT: xorb $2, (%rdi)1041; X64-NEXT: retq1042;1043; X32-LABEL: xor_8i:1044; X32: # %bb.0:1045; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1046; X32-NEXT: xorb $2, (%eax)1047; X32-NEXT: retl1048 %1 = load atomic i8, ptr %p acquire, align 11049 %2 = xor i8 %1, 21050 store atomic i8 %2, ptr %p release, align 11051 ret void1052}1053 1054define void @xor_8r(ptr %p, i8 %v) {1055; X64-LABEL: xor_8r:1056; X64: # %bb.0:1057; X64-NEXT: xorb %sil, (%rdi)1058; X64-NEXT: retq1059;1060; X32-LABEL: xor_8r:1061; X32: # %bb.0:1062; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax1063; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx1064; X32-NEXT: xorb %al, (%ecx)1065; X32-NEXT: retl1066 %1 = load atomic i8, ptr %p acquire, align 11067 %2 = xor i8 %1, %v1068 store atomic i8 %2, ptr %p release, align 11069 ret void1070}1071 1072define void @xor_16i(ptr %p) {1073; X64-LABEL: xor_16i:1074; X64: # %bb.0:1075; X64-NEXT: xorw $2, (%rdi)1076; X64-NEXT: retq1077;1078; X32-LABEL: xor_16i:1079; X32: # %bb.0:1080; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1081; X32-NEXT: xorw $2, (%eax)1082; X32-NEXT: retl1083 %1 = load atomic i16, ptr %p acquire, align 21084 %2 = xor i16 %1, 21085 store atomic i16 %2, ptr %p release, align 21086 ret void1087}1088 1089define void @xor_16r(ptr %p, i16 %v) {1090; X64-LABEL: xor_16r:1091; X64: # %bb.0:1092; X64-NEXT: xorw %si, (%rdi)1093; X64-NEXT: retq1094;1095; X32-LABEL: xor_16r:1096; X32: # %bb.0:1097; X32-NEXT: movzwl {{[0-9]+}}(%esp), %eax1098; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx1099; X32-NEXT: xorw %ax, (%ecx)1100; X32-NEXT: retl1101 %1 = load atomic i16, ptr %p acquire, align 21102 %2 = xor i16 %1, %v1103 store atomic i16 %2, ptr %p release, align 21104 ret void1105}1106 1107define void @xor_32i(ptr %p) {1108; X64-LABEL: xor_32i:1109; X64: # %bb.0:1110; X64-NEXT: xorl $2, (%rdi)1111; X64-NEXT: retq1112;1113; X32-LABEL: xor_32i:1114; X32: # %bb.0:1115; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1116; X32-NEXT: xorl $2, (%eax)1117; X32-NEXT: retl1118 %1 = load atomic i32, ptr %p acquire, align 41119 %2 = xor i32 %1, 21120 store atomic i32 %2, ptr %p release, align 41121 ret void1122}1123 1124define void @xor_32r(ptr %p, i32 %v) {1125; X64-LABEL: xor_32r:1126; X64: # %bb.0:1127; X64-NEXT: xorl %esi, (%rdi)1128; X64-NEXT: retq1129;1130; X32-LABEL: xor_32r:1131; X32: # %bb.0:1132; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1133; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx1134; X32-NEXT: xorl %eax, (%ecx)1135; X32-NEXT: retl1136 %1 = load atomic i32, ptr %p acquire, align 41137 %2 = xor i32 %1, %v1138 store atomic i32 %2, ptr %p release, align 41139 ret void1140}1141 1142define void @xor_64i(ptr %p) {1143; X64-LABEL: xor_64i:1144; X64: # %bb.0:1145; X64-NEXT: xorq $2, (%rdi)1146; X64-NEXT: retq1147;1148; X32-LABEL: xor_64i:1149; X32: # %bb.0:1150; X32-NEXT: pushl %ebp1151; X32-NEXT: .cfi_def_cfa_offset 81152; X32-NEXT: .cfi_offset %ebp, -81153; X32-NEXT: movl %esp, %ebp1154; X32-NEXT: .cfi_def_cfa_register %ebp1155; X32-NEXT: andl $-8, %esp1156; X32-NEXT: subl $16, %esp1157; X32-NEXT: movl 8(%ebp), %eax1158; X32-NEXT: fildll (%eax)1159; X32-NEXT: fistpll {{[0-9]+}}(%esp)1160; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx1161; X32-NEXT: movl {{[0-9]+}}(%esp), %edx1162; X32-NEXT: xorl $2, %ecx1163; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)1164; X32-NEXT: movl %ecx, (%esp)1165; X32-NEXT: fildll (%esp)1166; X32-NEXT: fistpll (%eax)1167; X32-NEXT: movl %ebp, %esp1168; X32-NEXT: popl %ebp1169; X32-NEXT: .cfi_def_cfa %esp, 41170; X32-NEXT: retl1171; We do not check X86-32 as it cannot do 'xorq'.1172 %1 = load atomic i64, ptr %p acquire, align 81173 %2 = xor i64 %1, 21174 store atomic i64 %2, ptr %p release, align 81175 ret void1176}1177 1178define void @xor_64r(ptr %p, i64 %v) {1179; X64-LABEL: xor_64r:1180; X64: # %bb.0:1181; X64-NEXT: xorq %rsi, (%rdi)1182; X64-NEXT: retq1183;1184; X32-LABEL: xor_64r:1185; X32: # %bb.0:1186; X32-NEXT: pushl %ebp1187; X32-NEXT: .cfi_def_cfa_offset 81188; X32-NEXT: .cfi_offset %ebp, -81189; X32-NEXT: movl %esp, %ebp1190; X32-NEXT: .cfi_def_cfa_register %ebp1191; X32-NEXT: andl $-8, %esp1192; X32-NEXT: subl $16, %esp1193; X32-NEXT: movl 8(%ebp), %eax1194; X32-NEXT: fildll (%eax)1195; X32-NEXT: fistpll {{[0-9]+}}(%esp)1196; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx1197; X32-NEXT: movl {{[0-9]+}}(%esp), %edx1198; X32-NEXT: xorl 16(%ebp), %edx1199; X32-NEXT: xorl 12(%ebp), %ecx1200; X32-NEXT: movl %ecx, (%esp)1201; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)1202; X32-NEXT: fildll (%esp)1203; X32-NEXT: fistpll (%eax)1204; X32-NEXT: movl %ebp, %esp1205; X32-NEXT: popl %ebp1206; X32-NEXT: .cfi_def_cfa %esp, 41207; X32-NEXT: retl1208; We do not check X86-32 as it cannot do 'xorq'.1209 %1 = load atomic i64, ptr %p acquire, align 81210 %2 = xor i64 %1, %v1211 store atomic i64 %2, ptr %p release, align 81212 ret void1213}1214 1215define void @xor_32i_seq_cst(ptr %p) {1216; X64-LABEL: xor_32i_seq_cst:1217; X64: # %bb.0:1218; X64-NEXT: movl (%rdi), %eax1219; X64-NEXT: xorl $2, %eax1220; X64-NEXT: xchgl %eax, (%rdi)1221; X64-NEXT: retq1222;1223; X32-LABEL: xor_32i_seq_cst:1224; X32: # %bb.0:1225; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1226; X32-NEXT: movl (%eax), %ecx1227; X32-NEXT: xorl $2, %ecx1228; X32-NEXT: xchgl %ecx, (%eax)1229; X32-NEXT: retl1230 %1 = load atomic i32, ptr %p monotonic, align 41231 %2 = xor i32 %1, 21232 store atomic i32 %2, ptr %p seq_cst, align 41233 ret void1234}1235 1236define void @xor_32r_seq_cst(ptr %p, i32 %v) {1237; X64-LABEL: xor_32r_seq_cst:1238; X64: # %bb.0:1239; X64-NEXT: movl (%rdi), %eax1240; X64-NEXT: xorl %esi, %eax1241; X64-NEXT: xchgl %eax, (%rdi)1242; X64-NEXT: retq1243;1244; X32-LABEL: xor_32r_seq_cst:1245; X32: # %bb.0:1246; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1247; X32-NEXT: movl (%eax), %ecx1248; X32-NEXT: xorl {{[0-9]+}}(%esp), %ecx1249; X32-NEXT: xchgl %ecx, (%eax)1250; X32-NEXT: retl1251 %1 = load atomic i32, ptr %p monotonic, align 41252 %2 = xor i32 %1, %v1253 store atomic i32 %2, ptr %p seq_cst, align 41254 ret void1255}1256 1257; ----- INC -----1258 1259define void @inc_8(ptr %p) {1260; FAST_INC-LABEL: inc_8:1261; FAST_INC: # %bb.0:1262; FAST_INC-NEXT: incb (%rdi)1263; FAST_INC-NEXT: retq1264;1265; X32-LABEL: inc_8:1266; X32: # %bb.0:1267; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1268; X32-NEXT: incb (%eax)1269; X32-NEXT: retl1270;1271; SLOW_INC-LABEL: inc_8:1272; SLOW_INC: # %bb.0:1273; SLOW_INC-NEXT: addb $1, (%rdi)1274; SLOW_INC-NEXT: retq1275 %1 = load atomic i8, ptr %p seq_cst, align 11276 %2 = add i8 %1, 11277 store atomic i8 %2, ptr %p release, align 11278 ret void1279}1280 1281define void @inc_16(ptr %p) {1282; FAST_INC-LABEL: inc_16:1283; FAST_INC: # %bb.0:1284; FAST_INC-NEXT: incw (%rdi)1285; FAST_INC-NEXT: retq1286;1287; X32-LABEL: inc_16:1288; X32: # %bb.0:1289; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1290; X32-NEXT: incw (%eax)1291; X32-NEXT: retl1292;1293; SLOW_INC-LABEL: inc_16:1294; SLOW_INC: # %bb.0:1295; SLOW_INC-NEXT: addw $1, (%rdi)1296; SLOW_INC-NEXT: retq1297 %1 = load atomic i16, ptr %p acquire, align 21298 %2 = add i16 %1, 11299 store atomic i16 %2, ptr %p release, align 21300 ret void1301}1302 1303define void @inc_32(ptr %p) {1304; FAST_INC-LABEL: inc_32:1305; FAST_INC: # %bb.0:1306; FAST_INC-NEXT: incl (%rdi)1307; FAST_INC-NEXT: retq1308;1309; X32-LABEL: inc_32:1310; X32: # %bb.0:1311; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1312; X32-NEXT: incl (%eax)1313; X32-NEXT: retl1314;1315; SLOW_INC-LABEL: inc_32:1316; SLOW_INC: # %bb.0:1317; SLOW_INC-NEXT: addl $1, (%rdi)1318; SLOW_INC-NEXT: retq1319 %1 = load atomic i32, ptr %p acquire, align 41320 %2 = add i32 %1, 11321 store atomic i32 %2, ptr %p monotonic, align 41322 ret void1323}1324 1325define void @inc_64(ptr %p) {1326; FAST_INC-LABEL: inc_64:1327; FAST_INC: # %bb.0:1328; FAST_INC-NEXT: incq (%rdi)1329; FAST_INC-NEXT: retq1330;1331; X32-LABEL: inc_64:1332; X32: # %bb.0:1333; X32-NEXT: pushl %ebp1334; X32-NEXT: .cfi_def_cfa_offset 81335; X32-NEXT: .cfi_offset %ebp, -81336; X32-NEXT: movl %esp, %ebp1337; X32-NEXT: .cfi_def_cfa_register %ebp1338; X32-NEXT: andl $-8, %esp1339; X32-NEXT: subl $16, %esp1340; X32-NEXT: movl 8(%ebp), %eax1341; X32-NEXT: fildll (%eax)1342; X32-NEXT: fistpll {{[0-9]+}}(%esp)1343; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx1344; X32-NEXT: movl {{[0-9]+}}(%esp), %edx1345; X32-NEXT: addl $1, %ecx1346; X32-NEXT: adcl $0, %edx1347; X32-NEXT: movl %ecx, (%esp)1348; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)1349; X32-NEXT: fildll (%esp)1350; X32-NEXT: fistpll (%eax)1351; X32-NEXT: movl %ebp, %esp1352; X32-NEXT: popl %ebp1353; X32-NEXT: .cfi_def_cfa %esp, 41354; X32-NEXT: retl1355;1356; SLOW_INC-LABEL: inc_64:1357; SLOW_INC: # %bb.0:1358; SLOW_INC-NEXT: addq $1, (%rdi)1359; SLOW_INC-NEXT: retq1360; We do not check X86-32 as it cannot do 'incq'.1361 %1 = load atomic i64, ptr %p acquire, align 81362 %2 = add i64 %1, 11363 store atomic i64 %2, ptr %p release, align 81364 ret void1365}1366 1367define void @inc_32_seq_cst(ptr %p) {1368; FAST_INC-LABEL: inc_32_seq_cst:1369; FAST_INC: # %bb.0:1370; FAST_INC-NEXT: movl (%rdi), %eax1371; FAST_INC-NEXT: incl %eax1372; FAST_INC-NEXT: xchgl %eax, (%rdi)1373; FAST_INC-NEXT: retq1374;1375; X32-LABEL: inc_32_seq_cst:1376; X32: # %bb.0:1377; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1378; X32-NEXT: movl (%eax), %ecx1379; X32-NEXT: incl %ecx1380; X32-NEXT: xchgl %ecx, (%eax)1381; X32-NEXT: retl1382;1383; SLOW_INC-LABEL: inc_32_seq_cst:1384; SLOW_INC: # %bb.0:1385; SLOW_INC-NEXT: movl (%rdi), %eax1386; SLOW_INC-NEXT: addl $1, %eax1387; SLOW_INC-NEXT: xchgl %eax, (%rdi)1388; SLOW_INC-NEXT: retq1389 %1 = load atomic i32, ptr %p monotonic, align 41390 %2 = add i32 %1, 11391 store atomic i32 %2, ptr %p seq_cst, align 41392 ret void1393}1394 1395; ----- DEC -----1396 1397define void @dec_8(ptr %p) {1398; FAST_INC-LABEL: dec_8:1399; FAST_INC: # %bb.0:1400; FAST_INC-NEXT: decb (%rdi)1401; FAST_INC-NEXT: retq1402;1403; X32-LABEL: dec_8:1404; X32: # %bb.0:1405; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1406; X32-NEXT: decb (%eax)1407; X32-NEXT: retl1408;1409; SLOW_INC-LABEL: dec_8:1410; SLOW_INC: # %bb.0:1411; SLOW_INC-NEXT: addb $-1, (%rdi)1412; SLOW_INC-NEXT: retq1413 %1 = load atomic i8, ptr %p seq_cst, align 11414 %2 = sub i8 %1, 11415 store atomic i8 %2, ptr %p release, align 11416 ret void1417}1418 1419define void @dec_16(ptr %p) {1420; FAST_INC-LABEL: dec_16:1421; FAST_INC: # %bb.0:1422; FAST_INC-NEXT: decw (%rdi)1423; FAST_INC-NEXT: retq1424;1425; X32-LABEL: dec_16:1426; X32: # %bb.0:1427; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1428; X32-NEXT: decw (%eax)1429; X32-NEXT: retl1430;1431; SLOW_INC-LABEL: dec_16:1432; SLOW_INC: # %bb.0:1433; SLOW_INC-NEXT: addw $-1, (%rdi)1434; SLOW_INC-NEXT: retq1435 %1 = load atomic i16, ptr %p acquire, align 21436 %2 = sub i16 %1, 11437 store atomic i16 %2, ptr %p release, align 21438 ret void1439}1440 1441define void @dec_32(ptr %p) {1442; FAST_INC-LABEL: dec_32:1443; FAST_INC: # %bb.0:1444; FAST_INC-NEXT: decl (%rdi)1445; FAST_INC-NEXT: retq1446;1447; X32-LABEL: dec_32:1448; X32: # %bb.0:1449; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1450; X32-NEXT: decl (%eax)1451; X32-NEXT: retl1452;1453; SLOW_INC-LABEL: dec_32:1454; SLOW_INC: # %bb.0:1455; SLOW_INC-NEXT: addl $-1, (%rdi)1456; SLOW_INC-NEXT: retq1457 %1 = load atomic i32, ptr %p acquire, align 41458 %2 = sub i32 %1, 11459 store atomic i32 %2, ptr %p monotonic, align 41460 ret void1461}1462 1463define void @dec_64(ptr %p) {1464; FAST_INC-LABEL: dec_64:1465; FAST_INC: # %bb.0:1466; FAST_INC-NEXT: decq (%rdi)1467; FAST_INC-NEXT: retq1468;1469; X32-LABEL: dec_64:1470; X32: # %bb.0:1471; X32-NEXT: pushl %ebp1472; X32-NEXT: .cfi_def_cfa_offset 81473; X32-NEXT: .cfi_offset %ebp, -81474; X32-NEXT: movl %esp, %ebp1475; X32-NEXT: .cfi_def_cfa_register %ebp1476; X32-NEXT: andl $-8, %esp1477; X32-NEXT: subl $16, %esp1478; X32-NEXT: movl 8(%ebp), %eax1479; X32-NEXT: fildll (%eax)1480; X32-NEXT: fistpll {{[0-9]+}}(%esp)1481; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx1482; X32-NEXT: movl {{[0-9]+}}(%esp), %edx1483; X32-NEXT: addl $-1, %ecx1484; X32-NEXT: adcl $-1, %edx1485; X32-NEXT: movl %ecx, (%esp)1486; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)1487; X32-NEXT: fildll (%esp)1488; X32-NEXT: fistpll (%eax)1489; X32-NEXT: movl %ebp, %esp1490; X32-NEXT: popl %ebp1491; X32-NEXT: .cfi_def_cfa %esp, 41492; X32-NEXT: retl1493;1494; SLOW_INC-LABEL: dec_64:1495; SLOW_INC: # %bb.0:1496; SLOW_INC-NEXT: addq $-1, (%rdi)1497; SLOW_INC-NEXT: retq1498; We do not check X86-32 as it cannot do 'decq'.1499 %1 = load atomic i64, ptr %p acquire, align 81500 %2 = sub i64 %1, 11501 store atomic i64 %2, ptr %p release, align 81502 ret void1503}1504 1505define void @dec_32_seq_cst(ptr %p) {1506; FAST_INC-LABEL: dec_32_seq_cst:1507; FAST_INC: # %bb.0:1508; FAST_INC-NEXT: movl (%rdi), %eax1509; FAST_INC-NEXT: decl %eax1510; FAST_INC-NEXT: xchgl %eax, (%rdi)1511; FAST_INC-NEXT: retq1512;1513; X32-LABEL: dec_32_seq_cst:1514; X32: # %bb.0:1515; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1516; X32-NEXT: movl (%eax), %ecx1517; X32-NEXT: decl %ecx1518; X32-NEXT: xchgl %ecx, (%eax)1519; X32-NEXT: retl1520;1521; SLOW_INC-LABEL: dec_32_seq_cst:1522; SLOW_INC: # %bb.0:1523; SLOW_INC-NEXT: movl (%rdi), %eax1524; SLOW_INC-NEXT: addl $-1, %eax1525; SLOW_INC-NEXT: xchgl %eax, (%rdi)1526; SLOW_INC-NEXT: retq1527 %1 = load atomic i32, ptr %p monotonic, align 41528 %2 = sub i32 %1, 11529 store atomic i32 %2, ptr %p seq_cst, align 41530 ret void1531}1532 1533; ----- NOT -----1534 1535define void @not_8(ptr %p) {1536; X64-LABEL: not_8:1537; X64: # %bb.0:1538; X64-NEXT: notb (%rdi)1539; X64-NEXT: retq1540;1541; X32-LABEL: not_8:1542; X32: # %bb.0:1543; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1544; X32-NEXT: notb (%eax)1545; X32-NEXT: retl1546 %1 = load atomic i8, ptr %p seq_cst, align 11547 %2 = xor i8 %1, -11548 store atomic i8 %2, ptr %p release, align 11549 ret void1550}1551 1552define void @not_16(ptr %p) {1553; X64-LABEL: not_16:1554; X64: # %bb.0:1555; X64-NEXT: notw (%rdi)1556; X64-NEXT: retq1557;1558; X32-LABEL: not_16:1559; X32: # %bb.0:1560; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1561; X32-NEXT: notw (%eax)1562; X32-NEXT: retl1563 %1 = load atomic i16, ptr %p acquire, align 21564 %2 = xor i16 %1, -11565 store atomic i16 %2, ptr %p release, align 21566 ret void1567}1568 1569define void @not_32(ptr %p) {1570; X64-LABEL: not_32:1571; X64: # %bb.0:1572; X64-NEXT: notl (%rdi)1573; X64-NEXT: retq1574;1575; X32-LABEL: not_32:1576; X32: # %bb.0:1577; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1578; X32-NEXT: notl (%eax)1579; X32-NEXT: retl1580 %1 = load atomic i32, ptr %p acquire, align 41581 %2 = xor i32 %1, -11582 store atomic i32 %2, ptr %p monotonic, align 41583 ret void1584}1585 1586define void @not_64(ptr %p) {1587; X64-LABEL: not_64:1588; X64: # %bb.0:1589; X64-NEXT: notq (%rdi)1590; X64-NEXT: retq1591;1592; X32-LABEL: not_64:1593; X32: # %bb.0:1594; X32-NEXT: pushl %ebp1595; X32-NEXT: .cfi_def_cfa_offset 81596; X32-NEXT: .cfi_offset %ebp, -81597; X32-NEXT: movl %esp, %ebp1598; X32-NEXT: .cfi_def_cfa_register %ebp1599; X32-NEXT: andl $-8, %esp1600; X32-NEXT: subl $16, %esp1601; X32-NEXT: movl 8(%ebp), %eax1602; X32-NEXT: fildll (%eax)1603; X32-NEXT: fistpll {{[0-9]+}}(%esp)1604; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx1605; X32-NEXT: movl {{[0-9]+}}(%esp), %edx1606; X32-NEXT: notl %edx1607; X32-NEXT: notl %ecx1608; X32-NEXT: movl %ecx, (%esp)1609; X32-NEXT: movl %edx, {{[0-9]+}}(%esp)1610; X32-NEXT: fildll (%esp)1611; X32-NEXT: fistpll (%eax)1612; X32-NEXT: movl %ebp, %esp1613; X32-NEXT: popl %ebp1614; X32-NEXT: .cfi_def_cfa %esp, 41615; X32-NEXT: retl1616; We do not check X86-32 as it cannot do 'notq'.1617 %1 = load atomic i64, ptr %p acquire, align 81618 %2 = xor i64 %1, -11619 store atomic i64 %2, ptr %p release, align 81620 ret void1621}1622 1623define void @not_32_seq_cst(ptr %p) {1624; X64-LABEL: not_32_seq_cst:1625; X64: # %bb.0:1626; X64-NEXT: movl (%rdi), %eax1627; X64-NEXT: notl %eax1628; X64-NEXT: xchgl %eax, (%rdi)1629; X64-NEXT: retq1630;1631; X32-LABEL: not_32_seq_cst:1632; X32: # %bb.0:1633; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1634; X32-NEXT: movl (%eax), %ecx1635; X32-NEXT: notl %ecx1636; X32-NEXT: xchgl %ecx, (%eax)1637; X32-NEXT: retl1638 %1 = load atomic i32, ptr %p monotonic, align 41639 %2 = xor i32 %1, -11640 store atomic i32 %2, ptr %p seq_cst, align 41641 ret void1642}1643 1644; ----- NEG -----1645 1646define void @neg_8(ptr %p) {1647; X64-LABEL: neg_8:1648; X64: # %bb.0:1649; X64-NEXT: negb (%rdi)1650; X64-NEXT: retq1651;1652; X32-LABEL: neg_8:1653; X32: # %bb.0:1654; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1655; X32-NEXT: negb (%eax)1656; X32-NEXT: retl1657 %1 = load atomic i8, ptr %p seq_cst, align 11658 %2 = sub i8 0, %11659 store atomic i8 %2, ptr %p release, align 11660 ret void1661}1662 1663define void @neg_16(ptr %p) {1664; X64-LABEL: neg_16:1665; X64: # %bb.0:1666; X64-NEXT: movzwl (%rdi), %eax1667; X64-NEXT: negl %eax1668; X64-NEXT: movw %ax, (%rdi)1669; X64-NEXT: retq1670;1671; X32-LABEL: neg_16:1672; X32: # %bb.0:1673; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1674; X32-NEXT: movzwl (%eax), %ecx1675; X32-NEXT: negl %ecx1676; X32-NEXT: movw %cx, (%eax)1677; X32-NEXT: retl1678 %1 = load atomic i16, ptr %p acquire, align 21679 %2 = sub i16 0, %11680 store atomic i16 %2, ptr %p release, align 21681 ret void1682}1683 1684define void @neg_32(ptr %p) {1685; X64-LABEL: neg_32:1686; X64: # %bb.0:1687; X64-NEXT: negl (%rdi)1688; X64-NEXT: retq1689;1690; X32-LABEL: neg_32:1691; X32: # %bb.0:1692; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1693; X32-NEXT: negl (%eax)1694; X32-NEXT: retl1695 %1 = load atomic i32, ptr %p acquire, align 41696 %2 = sub i32 0, %11697 store atomic i32 %2, ptr %p monotonic, align 41698 ret void1699}1700 1701define void @neg_64(ptr %p) {1702; X64-LABEL: neg_64:1703; X64: # %bb.0:1704; X64-NEXT: negq (%rdi)1705; X64-NEXT: retq1706;1707; X32-LABEL: neg_64:1708; X32: # %bb.0:1709; X32-NEXT: pushl %ebp1710; X32-NEXT: .cfi_def_cfa_offset 81711; X32-NEXT: .cfi_offset %ebp, -81712; X32-NEXT: movl %esp, %ebp1713; X32-NEXT: .cfi_def_cfa_register %ebp1714; X32-NEXT: andl $-8, %esp1715; X32-NEXT: subl $16, %esp1716; X32-NEXT: movl 8(%ebp), %eax1717; X32-NEXT: fildll (%eax)1718; X32-NEXT: fistpll {{[0-9]+}}(%esp)1719; X32-NEXT: xorl %ecx, %ecx1720; X32-NEXT: xorl %edx, %edx1721; X32-NEXT: subl {{[0-9]+}}(%esp), %edx1722; X32-NEXT: sbbl {{[0-9]+}}(%esp), %ecx1723; X32-NEXT: movl %edx, (%esp)1724; X32-NEXT: movl %ecx, {{[0-9]+}}(%esp)1725; X32-NEXT: fildll (%esp)1726; X32-NEXT: fistpll (%eax)1727; X32-NEXT: movl %ebp, %esp1728; X32-NEXT: popl %ebp1729; X32-NEXT: .cfi_def_cfa %esp, 41730; X32-NEXT: retl1731; We do neg check X86-32 as it canneg do 'negq'.1732 %1 = load atomic i64, ptr %p acquire, align 81733 %2 = sub i64 0, %11734 store atomic i64 %2, ptr %p release, align 81735 ret void1736}1737 1738define void @neg_32_seq_cst(ptr %p) {1739; X64-LABEL: neg_32_seq_cst:1740; X64: # %bb.0:1741; X64-NEXT: movl (%rdi), %eax1742; X64-NEXT: negl %eax1743; X64-NEXT: xchgl %eax, (%rdi)1744; X64-NEXT: retq1745;1746; X32-LABEL: neg_32_seq_cst:1747; X32: # %bb.0:1748; X32-NEXT: movl {{[0-9]+}}(%esp), %eax1749; X32-NEXT: movl (%eax), %ecx1750; X32-NEXT: negl %ecx1751; X32-NEXT: xchgl %ecx, (%eax)1752; X32-NEXT: retl1753 %1 = load atomic i32, ptr %p monotonic, align 41754 %2 = sub i32 0, %11755 store atomic i32 %2, ptr %p seq_cst, align 41756 ret void1757}1758 1759