374 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=i386-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK323; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK644 5; The peephole optimizer can elide some physical register copies such as6; EFLAGS. Make sure the flags are used directly, instead of needlessly using7; saving and restoring specific conditions.8 9@L = external dso_local global i3210@M = external dso_local global i811 12declare i32 @bar(i64)13 14define i1 @plus_one() nounwind {15; CHECK32-LABEL: plus_one:16; CHECK32: # %bb.0: # %entry17; CHECK32-NEXT: movzbl M, %eax18; CHECK32-NEXT: incl L19; CHECK32-NEXT: jne .LBB0_220; CHECK32-NEXT: # %bb.1: # %entry21; CHECK32-NEXT: andb $8, %al22; CHECK32-NEXT: je .LBB0_223; CHECK32-NEXT: # %bb.3: # %exit224; CHECK32-NEXT: xorl %eax, %eax25; CHECK32-NEXT: retl26; CHECK32-NEXT: .LBB0_2: # %exit27; CHECK32-NEXT: movb $1, %al28; CHECK32-NEXT: retl29;30; CHECK64-LABEL: plus_one:31; CHECK64: # %bb.0: # %entry32; CHECK64-NEXT: movzbl M(%rip), %eax33; CHECK64-NEXT: incl L(%rip)34; CHECK64-NEXT: jne .LBB0_235; CHECK64-NEXT: # %bb.1: # %entry36; CHECK64-NEXT: andb $8, %al37; CHECK64-NEXT: je .LBB0_238; CHECK64-NEXT: # %bb.3: # %exit239; CHECK64-NEXT: xorl %eax, %eax40; CHECK64-NEXT: retq41; CHECK64-NEXT: .LBB0_2: # %exit42; CHECK64-NEXT: movb $1, %al43; CHECK64-NEXT: retq44entry:45 %loaded_L = load i32, ptr @L46 %val = add nsw i32 %loaded_L, 1 ; N.B. will emit inc.47 store i32 %val, ptr @L48 %loaded_M = load i8, ptr @M49 %masked = and i8 %loaded_M, 850 %M_is_true = icmp ne i8 %masked, 051 %L_is_false = icmp eq i32 %val, 052 %cond = and i1 %L_is_false, %M_is_true53 br i1 %cond, label %exit2, label %exit54 55exit:56 ret i1 true57 58exit2:59 ret i1 false60}61 62define i1 @plus_forty_two() nounwind {63; CHECK32-LABEL: plus_forty_two:64; CHECK32: # %bb.0: # %entry65; CHECK32-NEXT: movzbl M, %eax66; CHECK32-NEXT: addl $42, L67; CHECK32-NEXT: jne .LBB1_268; CHECK32-NEXT: # %bb.1: # %entry69; CHECK32-NEXT: andb $8, %al70; CHECK32-NEXT: je .LBB1_271; CHECK32-NEXT: # %bb.3: # %exit272; CHECK32-NEXT: xorl %eax, %eax73; CHECK32-NEXT: retl74; CHECK32-NEXT: .LBB1_2: # %exit75; CHECK32-NEXT: movb $1, %al76; CHECK32-NEXT: retl77;78; CHECK64-LABEL: plus_forty_two:79; CHECK64: # %bb.0: # %entry80; CHECK64-NEXT: movzbl M(%rip), %eax81; CHECK64-NEXT: addl $42, L(%rip)82; CHECK64-NEXT: jne .LBB1_283; CHECK64-NEXT: # %bb.1: # %entry84; CHECK64-NEXT: andb $8, %al85; CHECK64-NEXT: je .LBB1_286; CHECK64-NEXT: # %bb.3: # %exit287; CHECK64-NEXT: xorl %eax, %eax88; CHECK64-NEXT: retq89; CHECK64-NEXT: .LBB1_2: # %exit90; CHECK64-NEXT: movb $1, %al91; CHECK64-NEXT: retq92entry:93 %loaded_L = load i32, ptr @L94 %val = add nsw i32 %loaded_L, 42 ; N.B. won't emit inc.95 store i32 %val, ptr @L96 %loaded_M = load i8, ptr @M97 %masked = and i8 %loaded_M, 898 %M_is_true = icmp ne i8 %masked, 099 %L_is_false = icmp eq i32 %val, 0100 %cond = and i1 %L_is_false, %M_is_true101 br i1 %cond, label %exit2, label %exit102 103exit:104 ret i1 true105 106exit2:107 ret i1 false108}109 110define i1 @minus_one() nounwind {111; CHECK32-LABEL: minus_one:112; CHECK32: # %bb.0: # %entry113; CHECK32-NEXT: movzbl M, %eax114; CHECK32-NEXT: decl L115; CHECK32-NEXT: jne .LBB2_2116; CHECK32-NEXT: # %bb.1: # %entry117; CHECK32-NEXT: andb $8, %al118; CHECK32-NEXT: je .LBB2_2119; CHECK32-NEXT: # %bb.3: # %exit2120; CHECK32-NEXT: xorl %eax, %eax121; CHECK32-NEXT: retl122; CHECK32-NEXT: .LBB2_2: # %exit123; CHECK32-NEXT: movb $1, %al124; CHECK32-NEXT: retl125;126; CHECK64-LABEL: minus_one:127; CHECK64: # %bb.0: # %entry128; CHECK64-NEXT: movzbl M(%rip), %eax129; CHECK64-NEXT: decl L(%rip)130; CHECK64-NEXT: jne .LBB2_2131; CHECK64-NEXT: # %bb.1: # %entry132; CHECK64-NEXT: andb $8, %al133; CHECK64-NEXT: je .LBB2_2134; CHECK64-NEXT: # %bb.3: # %exit2135; CHECK64-NEXT: xorl %eax, %eax136; CHECK64-NEXT: retq137; CHECK64-NEXT: .LBB2_2: # %exit138; CHECK64-NEXT: movb $1, %al139; CHECK64-NEXT: retq140entry:141 %loaded_L = load i32, ptr @L142 %val = add nsw i32 %loaded_L, -1 ; N.B. will emit dec.143 store i32 %val, ptr @L144 %loaded_M = load i8, ptr @M145 %masked = and i8 %loaded_M, 8146 %M_is_true = icmp ne i8 %masked, 0147 %L_is_false = icmp eq i32 %val, 0148 %cond = and i1 %L_is_false, %M_is_true149 br i1 %cond, label %exit2, label %exit150 151exit:152 ret i1 true153 154exit2:155 ret i1 false156}157 158define i1 @minus_forty_two() nounwind {159; CHECK32-LABEL: minus_forty_two:160; CHECK32: # %bb.0: # %entry161; CHECK32-NEXT: movzbl M, %eax162; CHECK32-NEXT: addl $-42, L163; CHECK32-NEXT: jne .LBB3_2164; CHECK32-NEXT: # %bb.1: # %entry165; CHECK32-NEXT: andb $8, %al166; CHECK32-NEXT: je .LBB3_2167; CHECK32-NEXT: # %bb.3: # %exit2168; CHECK32-NEXT: xorl %eax, %eax169; CHECK32-NEXT: retl170; CHECK32-NEXT: .LBB3_2: # %exit171; CHECK32-NEXT: movb $1, %al172; CHECK32-NEXT: retl173;174; CHECK64-LABEL: minus_forty_two:175; CHECK64: # %bb.0: # %entry176; CHECK64-NEXT: movzbl M(%rip), %eax177; CHECK64-NEXT: addl $-42, L(%rip)178; CHECK64-NEXT: jne .LBB3_2179; CHECK64-NEXT: # %bb.1: # %entry180; CHECK64-NEXT: andb $8, %al181; CHECK64-NEXT: je .LBB3_2182; CHECK64-NEXT: # %bb.3: # %exit2183; CHECK64-NEXT: xorl %eax, %eax184; CHECK64-NEXT: retq185; CHECK64-NEXT: .LBB3_2: # %exit186; CHECK64-NEXT: movb $1, %al187; CHECK64-NEXT: retq188entry:189 %loaded_L = load i32, ptr @L190 %val = add nsw i32 %loaded_L, -42 ; N.B. won't emit dec.191 store i32 %val, ptr @L192 %loaded_M = load i8, ptr @M193 %masked = and i8 %loaded_M, 8194 %M_is_true = icmp ne i8 %masked, 0195 %L_is_false = icmp eq i32 %val, 0196 %cond = and i1 %L_is_false, %M_is_true197 br i1 %cond, label %exit2, label %exit198 199exit:200 ret i1 true201 202exit2:203 ret i1 false204}205 206define i64 @test_intervening_call(ptr %foo, i64 %bar, i64 %baz) nounwind {207; CHECK32-LABEL: test_intervening_call:208; CHECK32: # %bb.0: # %entry209; CHECK32-NEXT: pushl %ebx210; CHECK32-NEXT: pushl %esi211; CHECK32-NEXT: pushl %eax212; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax213; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %edx214; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ebx215; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ecx216; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %esi217; CHECK32-NEXT: lock cmpxchg8b (%esi)218; CHECK32-NEXT: setne %bl219; CHECK32-NEXT: subl $8, %esp220; CHECK32-NEXT: pushl %edx221; CHECK32-NEXT: pushl %eax222; CHECK32-NEXT: calll bar@PLT223; CHECK32-NEXT: addl $16, %esp224; CHECK32-NEXT: testb %bl, %bl225; CHECK32-NEXT: jne .LBB4_3226; CHECK32-NEXT: # %bb.1: # %t227; CHECK32-NEXT: movl $42, %eax228; CHECK32-NEXT: jmp .LBB4_2229; CHECK32-NEXT: .LBB4_3: # %f230; CHECK32-NEXT: xorl %eax, %eax231; CHECK32-NEXT: .LBB4_2: # %t232; CHECK32-NEXT: xorl %edx, %edx233; CHECK32-NEXT: addl $4, %esp234; CHECK32-NEXT: popl %esi235; CHECK32-NEXT: popl %ebx236; CHECK32-NEXT: retl237;238; CHECK64-LABEL: test_intervening_call:239; CHECK64: # %bb.0: # %entry240; CHECK64-NEXT: pushq %rbx241; CHECK64-NEXT: movq %rsi, %rax242; CHECK64-NEXT: lock cmpxchgq %rdx, (%rdi)243; CHECK64-NEXT: setne %bl244; CHECK64-NEXT: movq %rax, %rdi245; CHECK64-NEXT: callq bar@PLT246; CHECK64-NEXT: testb %bl, %bl247; CHECK64-NEXT: jne .LBB4_2248; CHECK64-NEXT: # %bb.1: # %t249; CHECK64-NEXT: movl $42, %eax250; CHECK64-NEXT: popq %rbx251; CHECK64-NEXT: retq252; CHECK64-NEXT: .LBB4_2: # %f253; CHECK64-NEXT: xorl %eax, %eax254; CHECK64-NEXT: popq %rbx255; CHECK64-NEXT: retq256entry:257 ; cmpxchg sets EFLAGS, call clobbers it, then br uses EFLAGS.258 %cx = cmpxchg ptr %foo, i64 %bar, i64 %baz seq_cst seq_cst259 %v = extractvalue { i64, i1 } %cx, 0260 %p = extractvalue { i64, i1 } %cx, 1261 call i32 @bar(i64 %v)262 br i1 %p, label %t, label %f263 264t:265 ret i64 42266 267f:268 ret i64 0269}270 271define i64 @test_two_live_flags(ptr %foo0, i64 %bar0, i64 %baz0, ptr %foo1, i64 %bar1, i64 %baz1) nounwind {272; CHECK32-LABEL: test_two_live_flags:273; CHECK32: # %bb.0: # %entry274; CHECK32-NEXT: pushl %ebp275; CHECK32-NEXT: pushl %ebx276; CHECK32-NEXT: pushl %edi277; CHECK32-NEXT: pushl %esi278; CHECK32-NEXT: pushl %eax279; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ebp280; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %edi281; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax282; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %edx283; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ebx284; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ecx285; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %esi286; CHECK32-NEXT: lock cmpxchg8b (%esi)287; CHECK32-NEXT: sete {{[-0-9]+}}(%e{{[sb]}}p) # 1-byte Folded Spill288; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %eax289; CHECK32-NEXT: movl %ebp, %edx290; CHECK32-NEXT: movl %edi, %ecx291; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ebx292; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %esi293; CHECK32-NEXT: lock cmpxchg8b (%esi)294; CHECK32-NEXT: sete %al295; CHECK32-NEXT: andb {{[-0-9]+}}(%e{{[sb]}}p), %al # 1-byte Folded Reload296; CHECK32-NEXT: cmpb $1, %al297; CHECK32-NEXT: jne .LBB5_3298; CHECK32-NEXT: # %bb.1: # %t299; CHECK32-NEXT: movl $42, %eax300; CHECK32-NEXT: jmp .LBB5_2301; CHECK32-NEXT: .LBB5_3: # %f302; CHECK32-NEXT: xorl %eax, %eax303; CHECK32-NEXT: .LBB5_2: # %t304; CHECK32-NEXT: xorl %edx, %edx305; CHECK32-NEXT: addl $4, %esp306; CHECK32-NEXT: popl %esi307; CHECK32-NEXT: popl %edi308; CHECK32-NEXT: popl %ebx309; CHECK32-NEXT: popl %ebp310; CHECK32-NEXT: retl311;312; CHECK64-LABEL: test_two_live_flags:313; CHECK64: # %bb.0: # %entry314; CHECK64-NEXT: movq %rsi, %rax315; CHECK64-NEXT: lock cmpxchgq %rdx, (%rdi)316; CHECK64-NEXT: sete %dl317; CHECK64-NEXT: movq %r8, %rax318; CHECK64-NEXT: lock cmpxchgq %r9, (%rcx)319; CHECK64-NEXT: sete %al320; CHECK64-NEXT: andb %dl, %al321; CHECK64-NEXT: cmpb $1, %al322; CHECK64-NEXT: jne .LBB5_2323; CHECK64-NEXT: # %bb.1: # %t324; CHECK64-NEXT: movl $42, %eax325; CHECK64-NEXT: retq326; CHECK64-NEXT: .LBB5_2: # %f327; CHECK64-NEXT: xorl %eax, %eax328; CHECK64-NEXT: retq329entry:330 %cx0 = cmpxchg ptr %foo0, i64 %bar0, i64 %baz0 seq_cst seq_cst331 %p0 = extractvalue { i64, i1 } %cx0, 1332 %cx1 = cmpxchg ptr %foo1, i64 %bar1, i64 %baz1 seq_cst seq_cst333 %p1 = extractvalue { i64, i1 } %cx1, 1334 %flag = and i1 %p0, %p1335 br i1 %flag, label %t, label %f336 337t:338 ret i64 42339 340f:341 ret i64 0342}343 344define i1 @asm_clobbering_flags(ptr %mem) nounwind {345; CHECK32-LABEL: asm_clobbering_flags:346; CHECK32: # %bb.0: # %entry347; CHECK32-NEXT: movl {{[0-9]+}}(%esp), %ecx348; CHECK32-NEXT: movl (%ecx), %edx349; CHECK32-NEXT: testl %edx, %edx350; CHECK32-NEXT: setg %al351; CHECK32-NEXT: #APP352; CHECK32-NEXT: bsfl %edx, %edx353; CHECK32-NEXT: #NO_APP354; CHECK32-NEXT: movl %edx, (%ecx)355; CHECK32-NEXT: retl356;357; CHECK64-LABEL: asm_clobbering_flags:358; CHECK64: # %bb.0: # %entry359; CHECK64-NEXT: movl (%rdi), %ecx360; CHECK64-NEXT: testl %ecx, %ecx361; CHECK64-NEXT: setg %al362; CHECK64-NEXT: #APP363; CHECK64-NEXT: bsfl %ecx, %ecx364; CHECK64-NEXT: #NO_APP365; CHECK64-NEXT: movl %ecx, (%rdi)366; CHECK64-NEXT: retq367entry:368 %val = load i32, ptr %mem, align 4369 %cmp = icmp sgt i32 %val, 0370 %res = tail call i32 asm "bsfl $1,$0", "=r,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i32 %val)371 store i32 %res, ptr %mem, align 4372 ret i1 %cmp373}374