1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=i686-unknown -verify-machineinstrs < %s | FileCheck %s 3; RUN: opt < %s -codegenprepare -S -mtriple=x86_64-unknown-unknown | FileCheck --check-prefix=CHECK-CGP %s 4 5@A = global i32 zeroinitializer 6@B = global i32 zeroinitializer 7@C = global i32 zeroinitializer 8 9; Test that 'and' is sunk into bb0. 10define i32 @and_sink1(i32 %a, i1 %c) { 11; CHECK-LABEL: and_sink1: 12; CHECK: # %bb.0: 13; CHECK-NEXT: testb $1, {{[0-9]+}}(%esp) 14; CHECK-NEXT: je .LBB0_3 15; CHECK-NEXT: # %bb.1: # %bb0 16; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 17; CHECK-NEXT: testb $4, %al 18; CHECK-NEXT: movl $0, A 19; CHECK-NEXT: jne .LBB0_3 20; CHECK-NEXT: # %bb.2: # %bb1 21; CHECK-NEXT: movl $1, %eax 22; CHECK-NEXT: retl 23; CHECK-NEXT: .LBB0_3: # %bb2 24; CHECK-NEXT: xorl %eax, %eax 25; CHECK-NEXT: retl 26 27; CHECK-CGP-LABEL: @and_sink1( 28; CHECK-CGP-NOT: and i32 29 %and = and i32 %a, 4 30 br i1 %c, label %bb0, label %bb2 31bb0: 32; CHECK-CGP-LABEL: bb0: 33; CHECK-CGP: and i32 34; CHECK-CGP-NEXT: icmp eq i32 35; CHECK-CGP-NEXT: store 36; CHECK-CGP-NEXT: br 37 %cmp = icmp eq i32 %and, 0 38 store i32 0, i32* @A 39 br i1 %cmp, label %bb1, label %bb2 40bb1: 41 ret i32 1 42bb2: 43 ret i32 0 44} 45 46; Test that both 'and' and cmp get sunk to bb1. 47define i32 @and_sink2(i32 %a, i1 %c, i1 %c2) { 48; CHECK-LABEL: and_sink2: 49; CHECK: # %bb.0: 50; CHECK-NEXT: movl $0, A 51; CHECK-NEXT: testb $1, {{[0-9]+}}(%esp) 52; CHECK-NEXT: je .LBB1_5 53; CHECK-NEXT: # %bb.1: # %bb0.preheader 54; CHECK-NEXT: movb {{[0-9]+}}(%esp), %al 55; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx 56; CHECK-NEXT: .p2align 4, 0x90 57; CHECK-NEXT: .LBB1_2: # %bb0 58; CHECK-NEXT: # =>This Inner Loop Header: Depth=1 59; CHECK-NEXT: movl $0, B 60; CHECK-NEXT: testb $1, %al 61; CHECK-NEXT: je .LBB1_5 62; CHECK-NEXT: # %bb.3: # %bb1 63; CHECK-NEXT: # in Loop: Header=BB1_2 Depth=1 64; CHECK-NEXT: testb $4, %cl 65; CHECK-NEXT: movl $0, C 66; CHECK-NEXT: jne .LBB1_2 67; CHECK-NEXT: # %bb.4: # %bb2 68; CHECK-NEXT: movl $1, %eax 69; CHECK-NEXT: retl 70; CHECK-NEXT: .LBB1_5: # %bb3 71; CHECK-NEXT: xorl %eax, %eax 72; CHECK-NEXT: retl 73 74; CHECK-CGP-LABEL: @and_sink2( 75; CHECK-CGP-NOT: and i32 76 %and = and i32 %a, 4 77 store i32 0, i32* @A 78 br i1 %c, label %bb0, label %bb3 79bb0: 80; CHECK-CGP-LABEL: bb0: 81; CHECK-CGP-NOT: and i32 82; CHECK-CGP-NOT: icmp 83 %cmp = icmp eq i32 %and, 0 84 store i32 0, i32* @B 85 br i1 %c2, label %bb1, label %bb3 86bb1: 87; CHECK-CGP-LABEL: bb1: 88; CHECK-CGP: and i32 89; CHECK-CGP-NEXT: icmp eq i32 90; CHECK-CGP-NEXT: store 91; CHECK-CGP-NEXT: br 92 store i32 0, i32* @C 93 br i1 %cmp, label %bb2, label %bb0 94bb2: 95 ret i32 1 96bb3: 97 ret i32 0 98} 99 100; Test that CodeGenPrepare doesn't get stuck in a loop sinking and hoisting a masked load. 101define i32 @and_sink3(i1 %c, i32* %p) { 102; CHECK-LABEL: and_sink3: 103; CHECK: # %bb.0: 104; CHECK-NEXT: testb $1, {{[0-9]+}}(%esp) 105; CHECK-NEXT: je .LBB2_3 106; CHECK-NEXT: # %bb.1: # %bb0 107; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 108; CHECK-NEXT: movzbl (%eax), %eax 109; CHECK-NEXT: testl %eax, %eax 110; CHECK-NEXT: movl $0, A 111; CHECK-NEXT: je .LBB2_2 112; CHECK-NEXT: .LBB2_3: # %bb2 113; CHECK-NEXT: xorl %eax, %eax 114; CHECK-NEXT: retl 115; CHECK-NEXT: .LBB2_2: # %bb1 116; CHECK-NEXT: movl $1, %eax 117; CHECK-NEXT: retl 118 119; CHECK-CGP-LABEL: @and_sink3( 120; CHECK-CGP: load i32 121; CHECK-CGP-NEXT: and i32 122 %load = load i32, i32* %p 123 %and = and i32 %load, 255 124 br i1 %c, label %bb0, label %bb2 125bb0: 126; CHECK-CGP-LABEL: bb0: 127; CHECK-CGP-NOT: and i32 128; CHECK-CGP: icmp eq i32 129 %cmp = icmp eq i32 %and, 0 130 store i32 0, i32* @A 131 br i1 %cmp, label %bb1, label %bb2 132bb1: 133 ret i32 1 134bb2: 135 ret i32 0 136} 137 138; Test that CodeGenPrepare sinks/duplicates non-immediate 'and'. 139define i32 @and_sink4(i32 %a, i32 %b, i1 %c) { 140; CHECK-LABEL: and_sink4: 141; CHECK: # %bb.0: 142; CHECK-NEXT: testb $1, {{[0-9]+}}(%esp) 143; CHECK-NEXT: je .LBB3_4 144; CHECK-NEXT: # %bb.1: # %bb0 145; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 146; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx 147; CHECK-NEXT: testl %eax, %ecx 148; CHECK-NEXT: movl $0, A 149; CHECK-NEXT: jne .LBB3_4 150; CHECK-NEXT: # %bb.2: # %bb1 151; CHECK-NEXT: leal (%ecx,%eax), %edx 152; CHECK-NEXT: testl %eax, %ecx 153; CHECK-NEXT: movl %edx, B 154; CHECK-NEXT: je .LBB3_3 155; CHECK-NEXT: .LBB3_4: # %bb3 156; CHECK-NEXT: xorl %eax, %eax 157; CHECK-NEXT: retl 158; CHECK-NEXT: .LBB3_3: # %bb2 159; CHECK-NEXT: movl $1, %eax 160; CHECK-NEXT: retl 161 162; CHECK-CGP-LABEL: @and_sink4( 163; CHECK-CGP-NOT: and i32 164; CHECK-CGP-NOT: icmp 165 %and = and i32 %a, %b 166 %cmp = icmp eq i32 %and, 0 167 br i1 %c, label %bb0, label %bb3 168bb0: 169; CHECK-CGP-LABEL: bb0: 170; CHECK-CGP: and i32 171; CHECK-CGP-NEXT: icmp eq i32 172 store i32 0, i32* @A 173 br i1 %cmp, label %bb1, label %bb3 174bb1: 175; CHECK-CGP-LABEL: bb1: 176; CHECK-CGP: and i32 177; CHECK-CGP-NEXT: icmp eq i32 178 %add = add i32 %a, %b 179 store i32 %add, i32* @B 180 br i1 %cmp, label %bb2, label %bb3 181bb2: 182 ret i32 1 183bb3: 184 ret i32 0 185} 186 187 188; Test that CodeGenPrepare doesn't sink/duplicate non-immediate 'and' 189; when it would increase register pressure. 190define i32 @and_sink5(i32 %a, i32 %b, i32 %a2, i32 %b2, i1 %c) { 191; CHECK-LABEL: and_sink5: 192; CHECK: # %bb.0: 193; CHECK-NEXT: testb $1, {{[0-9]+}}(%esp) 194; CHECK-NEXT: je .LBB4_4 195; CHECK-NEXT: # %bb.1: # %bb0 196; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 197; CHECK-NEXT: andl {{[0-9]+}}(%esp), %eax 198; CHECK-NEXT: movl $0, A 199; CHECK-NEXT: jne .LBB4_4 200; CHECK-NEXT: # %bb.2: # %bb1 201; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx 202; CHECK-NEXT: addl {{[0-9]+}}(%esp), %ecx 203; CHECK-NEXT: testl %eax, %eax 204; CHECK-NEXT: movl %ecx, B 205; CHECK-NEXT: je .LBB4_3 206; CHECK-NEXT: .LBB4_4: # %bb3 207; CHECK-NEXT: xorl %eax, %eax 208; CHECK-NEXT: retl 209; CHECK-NEXT: .LBB4_3: # %bb2 210; CHECK-NEXT: movl $1, %eax 211; CHECK-NEXT: retl 212 213; CHECK-CGP-LABEL: @and_sink5( 214; CHECK-CGP: and i32 215; CHECK-CGP-NOT: icmp 216 %and = and i32 %a, %b 217 %cmp = icmp eq i32 %and, 0 218 br i1 %c, label %bb0, label %bb3 219bb0: 220; CHECK-CGP-LABEL: bb0: 221; CHECK-CGP-NOT: and i32 222; CHECK-CGP: icmp eq i32 223 store i32 0, i32* @A 224 br i1 %cmp, label %bb1, label %bb3 225bb1: 226; CHECK-CGP-LABEL: bb1: 227; CHECK-CGP-NOT: and i32 228; CHECK-CGP: icmp eq i32 229 %add = add i32 %a2, %b2 230 store i32 %add, i32* @B 231 br i1 %cmp, label %bb2, label %bb3 232bb2: 233 ret i32 1 234bb3: 235 ret i32 0 236} 237