1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=thumbv7m-eabi %s -o - | FileCheck %s --check-prefix V7M 3; RUN: llc -mtriple=armv7a-eabi %s -o - | FileCheck %s --check-prefix V7A 4; RUN: llc -mtriple=thumbv7a-eabi %s -o - | FileCheck %s --check-prefix V7A-T 5; RUN: llc -mtriple=armv6m-eabi %s -o - | FileCheck %s --check-prefix V6M 6 7target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" 8 9; Test sink of `and` instructions to fold in to `tst`, `lsls`, do cmov-bfi combine, etc. 10define void @f(i32 %v, ptr noalias %outp) { 11; V7M-LABEL: f: 12; V7M: @ %bb.0: @ %entry 13; V7M-NEXT: movs r2, #0 14; V7M-NEXT: str r2, [r1] 15; V7M-NEXT: lsls r2, r0, #31 16; V7M-NEXT: bne .LBB0_3 17; V7M-NEXT: @ %bb.1: @ %if.then 18; V7M-NEXT: tst.w r0, #14 19; V7M-NEXT: beq .LBB0_6 20; V7M-NEXT: @ %bb.2: 21; V7M-NEXT: lsls r2, r0, #30 22; V7M-NEXT: mov.w r3, #33024 23; V7M-NEXT: and.w r2, r3, r2, asr #31 24; V7M-NEXT: lsrs r0, r0, #2 25; V7M-NEXT: bfi r2, r0, #7, #1 26; V7M-NEXT: bfi r2, r0, #14, #1 27; V7M-NEXT: b .LBB0_5 28; V7M-NEXT: .LBB0_3: @ %if.else 29; V7M-NEXT: tst.w r0, #14 30; V7M-NEXT: it eq 31; V7M-NEXT: bxeq lr 32; V7M-NEXT: .LBB0_4: 33; V7M-NEXT: lsls r2, r0, #30 34; V7M-NEXT: mov.w r3, #8256 35; V7M-NEXT: and.w r2, r3, r2, asr #31 36; V7M-NEXT: lsrs r0, r0, #2 37; V7M-NEXT: bfi r2, r0, #5, #1 38; V7M-NEXT: bfi r2, r0, #12, #1 39; V7M-NEXT: .LBB0_5: @ %if.end 40; V7M-NEXT: str r2, [r1] 41; V7M-NEXT: .LBB0_6: @ %exit 42; V7M-NEXT: bx lr 43; 44; V7A-LABEL: f: 45; V7A: @ %bb.0: @ %entry 46; V7A-NEXT: mov r2, #0 47; V7A-NEXT: tst r0, #1 48; V7A-NEXT: str r2, [r1] 49; V7A-NEXT: bne .LBB0_3 50; V7A-NEXT: @ %bb.1: @ %if.then 51; V7A-NEXT: tst r0, #14 52; V7A-NEXT: beq .LBB0_6 53; V7A-NEXT: @ %bb.2: 54; V7A-NEXT: lsl r2, r0, #30 55; V7A-NEXT: mov r3, #33024 56; V7A-NEXT: and r2, r3, r2, asr #31 57; V7A-NEXT: lsr r0, r0, #2 58; V7A-NEXT: bfi r2, r0, #7, #1 59; V7A-NEXT: bfi r2, r0, #14, #1 60; V7A-NEXT: b .LBB0_5 61; V7A-NEXT: .LBB0_3: @ %if.else 62; V7A-NEXT: tst r0, #14 63; V7A-NEXT: bxeq lr 64; V7A-NEXT: .LBB0_4: 65; V7A-NEXT: lsl r2, r0, #30 66; V7A-NEXT: mov r3, #8256 67; V7A-NEXT: and r2, r3, r2, asr #31 68; V7A-NEXT: lsr r0, r0, #2 69; V7A-NEXT: bfi r2, r0, #5, #1 70; V7A-NEXT: bfi r2, r0, #12, #1 71; V7A-NEXT: .LBB0_5: @ %if.end 72; V7A-NEXT: str r2, [r1] 73; V7A-NEXT: .LBB0_6: @ %exit 74; V7A-NEXT: bx lr 75; 76; V7A-T-LABEL: f: 77; V7A-T: @ %bb.0: @ %entry 78; V7A-T-NEXT: movs r2, #0 79; V7A-T-NEXT: str r2, [r1] 80; V7A-T-NEXT: lsls r2, r0, #31 81; V7A-T-NEXT: bne .LBB0_3 82; V7A-T-NEXT: @ %bb.1: @ %if.then 83; V7A-T-NEXT: tst.w r0, #14 84; V7A-T-NEXT: beq .LBB0_6 85; V7A-T-NEXT: @ %bb.2: 86; V7A-T-NEXT: lsls r2, r0, #30 87; V7A-T-NEXT: mov.w r3, #33024 88; V7A-T-NEXT: and.w r2, r3, r2, asr #31 89; V7A-T-NEXT: lsrs r0, r0, #2 90; V7A-T-NEXT: bfi r2, r0, #7, #1 91; V7A-T-NEXT: bfi r2, r0, #14, #1 92; V7A-T-NEXT: b .LBB0_5 93; V7A-T-NEXT: .LBB0_3: @ %if.else 94; V7A-T-NEXT: tst.w r0, #14 95; V7A-T-NEXT: it eq 96; V7A-T-NEXT: bxeq lr 97; V7A-T-NEXT: .LBB0_4: 98; V7A-T-NEXT: lsls r2, r0, #30 99; V7A-T-NEXT: mov.w r3, #8256 100; V7A-T-NEXT: and.w r2, r3, r2, asr #31 101; V7A-T-NEXT: lsrs r0, r0, #2 102; V7A-T-NEXT: bfi r2, r0, #5, #1 103; V7A-T-NEXT: bfi r2, r0, #12, #1 104; V7A-T-NEXT: .LBB0_5: @ %if.end 105; V7A-T-NEXT: str r2, [r1] 106; V7A-T-NEXT: .LBB0_6: @ %exit 107; V7A-T-NEXT: bx lr 108; 109; V6M-LABEL: f: 110; V6M: @ %bb.0: @ %entry 111; V6M-NEXT: .save {r4, lr} 112; V6M-NEXT: push {r4, lr} 113; V6M-NEXT: movs r2, #0 114; V6M-NEXT: str r2, [r1] 115; V6M-NEXT: movs r3, #14 116; V6M-NEXT: ands r3, r0 117; V6M-NEXT: movs r4, #4 118; V6M-NEXT: ands r4, r0 119; V6M-NEXT: movs r2, #2 120; V6M-NEXT: ands r2, r0 121; V6M-NEXT: lsls r0, r0, #31 122; V6M-NEXT: bne .LBB0_5 123; V6M-NEXT: @ %bb.1: @ %if.then 124; V6M-NEXT: movs r0, #129 125; V6M-NEXT: cmp r2, #0 126; V6M-NEXT: beq .LBB0_3 127; V6M-NEXT: @ %bb.2: 128; V6M-NEXT: lsls r2, r0, #8 129; V6M-NEXT: .LBB0_3: @ %if.then 130; V6M-NEXT: cmp r4, #0 131; V6M-NEXT: beq .LBB0_10 132; V6M-NEXT: @ %bb.4: @ %if.then 133; V6M-NEXT: lsls r0, r0, #7 134; V6M-NEXT: b .LBB0_9 135; V6M-NEXT: .LBB0_5: @ %if.else 136; V6M-NEXT: movs r0, #129 137; V6M-NEXT: cmp r2, #0 138; V6M-NEXT: beq .LBB0_7 139; V6M-NEXT: @ %bb.6: 140; V6M-NEXT: lsls r2, r0, #6 141; V6M-NEXT: .LBB0_7: @ %if.else 142; V6M-NEXT: cmp r4, #0 143; V6M-NEXT: beq .LBB0_10 144; V6M-NEXT: @ %bb.8: @ %if.else 145; V6M-NEXT: lsls r0, r0, #5 146; V6M-NEXT: .LBB0_9: @ %if.else 147; V6M-NEXT: adds r2, r2, r0 148; V6M-NEXT: .LBB0_10: @ %if.else 149; V6M-NEXT: cmp r3, #0 150; V6M-NEXT: beq .LBB0_12 151; V6M-NEXT: @ %bb.11: @ %if.end 152; V6M-NEXT: str r2, [r1] 153; V6M-NEXT: .LBB0_12: @ %exit 154; V6M-NEXT: pop {r4, pc} 155entry: 156 store i32 0, ptr %outp, align 4 157 %and = and i32 %v, 1 158 %cmp = icmp eq i32 %and, 0 159 %and1 = and i32 %v, 2 160 %tobool.not = icmp eq i32 %and1, 0 161 %and2 = and i32 %v, 4 162 %tobool1.not = icmp eq i32 %and2, 0 163 %and3 = and i32 %v, 14 164 %tobool2.not = icmp eq i32 %and3, 0 165 br i1 %cmp, label %if.then, label %if.else 166 167if.then: 168 %select = select i1 %tobool.not, i32 0, i32 33024 169 %or = or i32 %select, 16512 170 %spec.select = select i1 %tobool1.not, i32 %select, i32 %or 171 br i1 %tobool2.not, label %exit, label %if.end 172 173if.else: 174 %select1 = select i1 %tobool.not, i32 0, i32 8256 175 %or1 = or i32 %select1, 4128 176 %spec.select1 = select i1 %tobool1.not, i32 %select1, i32 %or1 177 br i1 %tobool2.not, label %exit, label %if.end 178 179if.end: 180 %spec.select.sink = phi i32 [ %spec.select, %if.then ], [ %spec.select1, %if.else ] 181 store i32 %spec.select.sink, ptr %outp, align 4 182 br label %exit 183 184exit: 185 ret void 186} 187 188; Test with a mask that can be encoded with T32 instruction set, but not with A32. 189define i32 @f0(i1 %c0, i32 %v, ptr %p) { 190; V7M-LABEL: f0: 191; V7M: @ %bb.0: @ %E 192; V7M-NEXT: lsls r0, r0, #31 193; V7M-NEXT: beq .LBB1_2 194; V7M-NEXT: @ %bb.1: @ %A 195; V7M-NEXT: tst.w r1, #16843009 196; V7M-NEXT: itt eq 197; V7M-NEXT: moveq r0, #0 198; V7M-NEXT: bxeq lr 199; V7M-NEXT: b .LBB1_3 200; V7M-NEXT: .LBB1_2: @ %B 201; V7M-NEXT: movs r0, #1 202; V7M-NEXT: tst.w r1, #16843009 203; V7M-NEXT: str r0, [r2] 204; V7M-NEXT: itt ne 205; V7M-NEXT: movne r0, #0 206; V7M-NEXT: bxne lr 207; V7M-NEXT: .LBB1_3: @ %D 208; V7M-NEXT: movs r0, #1 209; V7M-NEXT: bx lr 210; 211; V7A-LABEL: f0: 212; V7A: @ %bb.0: @ %E 213; V7A-NEXT: movw r3, #257 214; V7A-NEXT: tst r0, #1 215; V7A-NEXT: movt r3, #257 216; V7A-NEXT: and r1, r1, r3 217; V7A-NEXT: beq .LBB1_3 218; V7A-NEXT: @ %bb.1: @ %A 219; V7A-NEXT: cmp r1, #0 220; V7A-NEXT: moveq r0, #0 221; V7A-NEXT: bxeq lr 222; V7A-NEXT: .LBB1_2: @ %D 223; V7A-NEXT: mov r0, #1 224; V7A-NEXT: bx lr 225; V7A-NEXT: .LBB1_3: @ %B 226; V7A-NEXT: mov r0, #1 227; V7A-NEXT: cmp r1, #0 228; V7A-NEXT: str r0, [r2] 229; V7A-NEXT: mov r0, #0 230; V7A-NEXT: moveq r0, #1 231; V7A-NEXT: bx lr 232; 233; V7A-T-LABEL: f0: 234; V7A-T: @ %bb.0: @ %E 235; V7A-T-NEXT: lsls r0, r0, #31 236; V7A-T-NEXT: beq .LBB1_2 237; V7A-T-NEXT: @ %bb.1: @ %A 238; V7A-T-NEXT: tst.w r1, #16843009 239; V7A-T-NEXT: itt eq 240; V7A-T-NEXT: moveq r0, #0 241; V7A-T-NEXT: bxeq lr 242; V7A-T-NEXT: b .LBB1_3 243; V7A-T-NEXT: .LBB1_2: @ %B 244; V7A-T-NEXT: movs r0, #1 245; V7A-T-NEXT: tst.w r1, #16843009 246; V7A-T-NEXT: str r0, [r2] 247; V7A-T-NEXT: itt ne 248; V7A-T-NEXT: movne r0, #0 249; V7A-T-NEXT: bxne lr 250; V7A-T-NEXT: .LBB1_3: @ %D 251; V7A-T-NEXT: movs r0, #1 252; V7A-T-NEXT: bx lr 253; 254; V6M-LABEL: f0: 255; V6M: @ %bb.0: @ %E 256; V6M-NEXT: ldr r3, .LCPI1_0 257; V6M-NEXT: ands r3, r1 258; V6M-NEXT: lsls r0, r0, #31 259; V6M-NEXT: beq .LBB1_3 260; V6M-NEXT: @ %bb.1: @ %A 261; V6M-NEXT: cmp r3, #0 262; V6M-NEXT: bne .LBB1_5 263; V6M-NEXT: @ %bb.2: 264; V6M-NEXT: movs r0, #0 265; V6M-NEXT: bx lr 266; V6M-NEXT: .LBB1_3: @ %B 267; V6M-NEXT: movs r0, #1 268; V6M-NEXT: str r0, [r2] 269; V6M-NEXT: cmp r3, #0 270; V6M-NEXT: beq .LBB1_5 271; V6M-NEXT: @ %bb.4: 272; V6M-NEXT: movs r0, #0 273; V6M-NEXT: bx lr 274; V6M-NEXT: .LBB1_5: @ %D 275; V6M-NEXT: movs r0, #1 276; V6M-NEXT: bx lr 277; V6M-NEXT: .p2align 2 278; V6M-NEXT: @ %bb.6: 279; V6M-NEXT: .LCPI1_0: 280; V6M-NEXT: .long 16843009 @ 0x1010101 281E: 282 %a = and i32 %v, 16843009 283 br i1 %c0, label %A, label %B 284 285A: 286 %c1 = icmp eq i32 %a, 0 287 br i1 %c1, label %C, label %D 288 289B: 290 %c2 = icmp eq i32 %a, 0 291 store i32 1, ptr %p, align 4 292 br i1 %c2, label %D, label %C 293 294C: 295 br label %X 296 297D: 298 br label %X 299 300X: 301 %x = phi i32 [0, %C], [1, %D] 302 ret i32 %x 303} 304 305; Test with a mask that can be encoded both with T32 and A32 instruction sets. 306define i32 @f1(i1 %c0, i32 %v, ptr %p) { 307; V7M-LABEL: f1: 308; V7M: @ %bb.0: @ %E 309; V7M-NEXT: lsls r0, r0, #31 310; V7M-NEXT: beq .LBB2_2 311; V7M-NEXT: @ %bb.1: @ %A 312; V7M-NEXT: tst.w r1, #100663296 313; V7M-NEXT: itt eq 314; V7M-NEXT: moveq r0, #0 315; V7M-NEXT: bxeq lr 316; V7M-NEXT: b .LBB2_3 317; V7M-NEXT: .LBB2_2: @ %B 318; V7M-NEXT: movs r0, #1 319; V7M-NEXT: tst.w r1, #100663296 320; V7M-NEXT: str r0, [r2] 321; V7M-NEXT: itt ne 322; V7M-NEXT: movne r0, #0 323; V7M-NEXT: bxne lr 324; V7M-NEXT: .LBB2_3: @ %D 325; V7M-NEXT: movs r0, #1 326; V7M-NEXT: bx lr 327; 328; V7A-LABEL: f1: 329; V7A: @ %bb.0: @ %E 330; V7A-NEXT: tst r0, #1 331; V7A-NEXT: beq .LBB2_3 332; V7A-NEXT: @ %bb.1: @ %A 333; V7A-NEXT: tst r1, #100663296 334; V7A-NEXT: moveq r0, #0 335; V7A-NEXT: bxeq lr 336; V7A-NEXT: .LBB2_2: @ %D 337; V7A-NEXT: mov r0, #1 338; V7A-NEXT: bx lr 339; V7A-NEXT: .LBB2_3: @ %B 340; V7A-NEXT: mov r0, #1 341; V7A-NEXT: tst r1, #100663296 342; V7A-NEXT: str r0, [r2] 343; V7A-NEXT: mov r0, #0 344; V7A-NEXT: moveq r0, #1 345; V7A-NEXT: bx lr 346; 347; V7A-T-LABEL: f1: 348; V7A-T: @ %bb.0: @ %E 349; V7A-T-NEXT: lsls r0, r0, #31 350; V7A-T-NEXT: beq .LBB2_2 351; V7A-T-NEXT: @ %bb.1: @ %A 352; V7A-T-NEXT: tst.w r1, #100663296 353; V7A-T-NEXT: itt eq 354; V7A-T-NEXT: moveq r0, #0 355; V7A-T-NEXT: bxeq lr 356; V7A-T-NEXT: b .LBB2_3 357; V7A-T-NEXT: .LBB2_2: @ %B 358; V7A-T-NEXT: movs r0, #1 359; V7A-T-NEXT: tst.w r1, #100663296 360; V7A-T-NEXT: str r0, [r2] 361; V7A-T-NEXT: itt ne 362; V7A-T-NEXT: movne r0, #0 363; V7A-T-NEXT: bxne lr 364; V7A-T-NEXT: .LBB2_3: @ %D 365; V7A-T-NEXT: movs r0, #1 366; V7A-T-NEXT: bx lr 367; 368; V6M-LABEL: f1: 369; V6M: @ %bb.0: @ %E 370; V6M-NEXT: movs r3, #3 371; V6M-NEXT: lsls r3, r3, #25 372; V6M-NEXT: ands r3, r1 373; V6M-NEXT: lsls r0, r0, #31 374; V6M-NEXT: beq .LBB2_3 375; V6M-NEXT: @ %bb.1: @ %A 376; V6M-NEXT: cmp r3, #0 377; V6M-NEXT: bne .LBB2_5 378; V6M-NEXT: @ %bb.2: 379; V6M-NEXT: movs r0, #0 380; V6M-NEXT: bx lr 381; V6M-NEXT: .LBB2_3: @ %B 382; V6M-NEXT: movs r0, #1 383; V6M-NEXT: str r0, [r2] 384; V6M-NEXT: cmp r3, #0 385; V6M-NEXT: beq .LBB2_5 386; V6M-NEXT: @ %bb.4: 387; V6M-NEXT: movs r0, #0 388; V6M-NEXT: bx lr 389; V6M-NEXT: .LBB2_5: @ %D 390; V6M-NEXT: movs r0, #1 391; V6M-NEXT: bx lr 392E: 393 %a = and i32 %v, 100663296 394 br i1 %c0, label %A, label %B 395 396A: 397 %c1 = icmp eq i32 %a, 0 398 br i1 %c1, label %C, label %D 399 400B: 401 %c2 = icmp eq i32 %a, 0 402 store i32 1, ptr %p, align 4 403 br i1 %c2, label %D, label %C 404 405C: 406 br label %X 407 408D: 409 br label %X 410 411X: 412 %x = phi i32 [0, %C], [1, %D] 413 ret i32 %x 414} 415