371 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=arm-eabi -arm-atomic-cfg-tidy=0 %s -o - | FileCheck -check-prefix=ARM %s3; RUN: llc -mtriple=thumb-eabi -arm-atomic-cfg-tidy=0 %s -o - | FileCheck -check-prefix=THUMB %s4; RUN: llc -mtriple=thumb-eabi -arm-atomic-cfg-tidy=0 -mcpu=arm1156t2-s -mattr=+thumb2 %s -o - | FileCheck -check-prefix=T2 %s5; RUN: llc -mtriple=thumbv8-eabi -arm-atomic-cfg-tidy=0 %s -o - | FileCheck -check-prefix=V8 %s6 7; FIXME: The -mtriple=thumb test doesn't change if -disable-peephole is specified.8 9%struct.Foo = type { ptr }10 11define ptr @foo(ptr %this, i32 %acc) nounwind readonly align 2 {12; ARM-LABEL: foo:13; ARM: @ %bb.0: @ %entry14; ARM-NEXT: add r2, r0, #415; ARM-NEXT: mov r12, #116; ARM-NEXT: b .LBB0_317; ARM-NEXT: .LBB0_1: @ %tailrecurse.switch18; ARM-NEXT: @ in Loop: Header=BB0_3 Depth=119; ARM-NEXT: cmp r3, #120; ARM-NEXT: movne pc, lr21; ARM-NEXT: .LBB0_2: @ %sw.bb22; ARM-NEXT: @ in Loop: Header=BB0_3 Depth=123; ARM-NEXT: orr r1, r3, r1, lsl #124; ARM-NEXT: add r2, r2, #425; ARM-NEXT: add r12, r12, #126; ARM-NEXT: .LBB0_3: @ %tailrecurse27; ARM-NEXT: @ =>This Inner Loop Header: Depth=128; ARM-NEXT: ldr r3, [r2, #-4]29; ARM-NEXT: ands r3, r3, #330; ARM-NEXT: beq .LBB0_231; ARM-NEXT: @ %bb.4: @ %tailrecurse.switch32; ARM-NEXT: @ in Loop: Header=BB0_3 Depth=133; ARM-NEXT: cmp r3, #334; ARM-NEXT: moveq r0, r235; ARM-NEXT: moveq pc, lr36; ARM-NEXT: .LBB0_5: @ %tailrecurse.switch37; ARM-NEXT: @ in Loop: Header=BB0_3 Depth=138; ARM-NEXT: cmp r3, #239; ARM-NEXT: bne .LBB0_140; ARM-NEXT: @ %bb.6: @ %sw.bb841; ARM-NEXT: add r1, r1, r1242; ARM-NEXT: add r0, r0, r1, lsl #243; ARM-NEXT: mov pc, lr44;45; THUMB-LABEL: foo:46; THUMB: @ %bb.0: @ %entry47; THUMB-NEXT: .save {r4, r5, r7, lr}48; THUMB-NEXT: push {r4, r5, r7, lr}49; THUMB-NEXT: movs r2, #150; THUMB-NEXT: movs r3, r051; THUMB-NEXT: .LBB0_1: @ %tailrecurse52; THUMB-NEXT: @ =>This Inner Loop Header: Depth=153; THUMB-NEXT: ldr r5, [r3]54; THUMB-NEXT: movs r4, #355; THUMB-NEXT: ands r4, r556; THUMB-NEXT: beq .LBB0_557; THUMB-NEXT: @ %bb.2: @ %tailrecurse.switch58; THUMB-NEXT: @ in Loop: Header=BB0_1 Depth=159; THUMB-NEXT: cmp r4, #360; THUMB-NEXT: beq .LBB0_661; THUMB-NEXT: @ %bb.3: @ %tailrecurse.switch62; THUMB-NEXT: @ in Loop: Header=BB0_1 Depth=163; THUMB-NEXT: cmp r4, #264; THUMB-NEXT: beq .LBB0_765; THUMB-NEXT: @ %bb.4: @ %tailrecurse.switch66; THUMB-NEXT: @ in Loop: Header=BB0_1 Depth=167; THUMB-NEXT: cmp r4, #168; THUMB-NEXT: bne .LBB0_969; THUMB-NEXT: .LBB0_5: @ %sw.bb70; THUMB-NEXT: @ in Loop: Header=BB0_1 Depth=171; THUMB-NEXT: lsls r1, r1, #172; THUMB-NEXT: orrs r4, r173; THUMB-NEXT: adds r3, r3, #474; THUMB-NEXT: adds r2, r2, #175; THUMB-NEXT: movs r1, r476; THUMB-NEXT: b .LBB0_177; THUMB-NEXT: .LBB0_6: @ %sw.bb678; THUMB-NEXT: adds r0, r3, #479; THUMB-NEXT: b .LBB0_880; THUMB-NEXT: .LBB0_7: @ %sw.bb881; THUMB-NEXT: adds r1, r1, r282; THUMB-NEXT: lsls r1, r1, #283; THUMB-NEXT: adds r0, r0, r184; THUMB-NEXT: .LBB0_8: @ %sw.bb685; THUMB-NEXT: pop {r4, r5, r7}86; THUMB-NEXT: pop {r1}87; THUMB-NEXT: bx r188; THUMB-NEXT: .LBB0_9: @ %sw.epilog89; THUMB-NEXT: pop {r4, r5, r7}90; THUMB-NEXT: pop {r0}91; THUMB-NEXT: bx r092;93; T2-LABEL: foo:94; T2: @ %bb.0: @ %entry95; T2-NEXT: adds r2, r0, #496; T2-NEXT: mov.w r12, #197; T2-NEXT: b .LBB0_398; T2-NEXT: .LBB0_1: @ %tailrecurse.switch99; T2-NEXT: @ in Loop: Header=BB0_3 Depth=1100; T2-NEXT: cmp r3, #1101; T2-NEXT: it ne102; T2-NEXT: bxne lr103; T2-NEXT: .LBB0_2: @ %sw.bb104; T2-NEXT: @ in Loop: Header=BB0_3 Depth=1105; T2-NEXT: orr.w r1, r3, r1, lsl #1106; T2-NEXT: adds r2, #4107; T2-NEXT: add.w r12, r12, #1108; T2-NEXT: .LBB0_3: @ %tailrecurse109; T2-NEXT: @ =>This Inner Loop Header: Depth=1110; T2-NEXT: ldr r3, [r2, #-4]111; T2-NEXT: ands r3, r3, #3112; T2-NEXT: beq .LBB0_2113; T2-NEXT: @ %bb.4: @ %tailrecurse.switch114; T2-NEXT: @ in Loop: Header=BB0_3 Depth=1115; T2-NEXT: cmp r3, #3116; T2-NEXT: itt eq117; T2-NEXT: moveq r0, r2118; T2-NEXT: bxeq lr119; T2-NEXT: .LBB0_5: @ %tailrecurse.switch120; T2-NEXT: @ in Loop: Header=BB0_3 Depth=1121; T2-NEXT: cmp r3, #2122; T2-NEXT: bne .LBB0_1123; T2-NEXT: @ %bb.6: @ %sw.bb8124; T2-NEXT: add r1, r12125; T2-NEXT: add.w r0, r0, r1, lsl #2126; T2-NEXT: bx lr127;128; V8-LABEL: foo:129; V8: @ %bb.0: @ %entry130; V8-NEXT: adds r2, r0, #4131; V8-NEXT: mov.w r12, #1132; V8-NEXT: b .LBB0_3133; V8-NEXT: .LBB0_1: @ %tailrecurse.switch134; V8-NEXT: @ in Loop: Header=BB0_3 Depth=1135; V8-NEXT: cmp r3, #1136; V8-NEXT: it ne137; V8-NEXT: bxne lr138; V8-NEXT: .LBB0_2: @ %sw.bb139; V8-NEXT: @ in Loop: Header=BB0_3 Depth=1140; V8-NEXT: orr.w r1, r3, r1, lsl #1141; V8-NEXT: adds r2, #4142; V8-NEXT: add.w r12, r12, #1143; V8-NEXT: .LBB0_3: @ %tailrecurse144; V8-NEXT: @ =>This Inner Loop Header: Depth=1145; V8-NEXT: ldr r3, [r2, #-4]146; V8-NEXT: ands r3, r3, #3147; V8-NEXT: beq .LBB0_2148; V8-NEXT: @ %bb.4: @ %tailrecurse.switch149; V8-NEXT: @ in Loop: Header=BB0_3 Depth=1150; V8-NEXT: cmp r3, #3151; V8-NEXT: itt eq152; V8-NEXT: moveq r0, r2153; V8-NEXT: bxeq lr154; V8-NEXT: .LBB0_5: @ %tailrecurse.switch155; V8-NEXT: @ in Loop: Header=BB0_3 Depth=1156; V8-NEXT: cmp r3, #2157; V8-NEXT: bne .LBB0_1158; V8-NEXT: @ %bb.6: @ %sw.bb8159; V8-NEXT: add r1, r12160; V8-NEXT: add.w r0, r0, r1, lsl #2161; V8-NEXT: bx lr162entry:163 %scevgep = getelementptr %struct.Foo, ptr %this, i32 1164 br label %tailrecurse165 166tailrecurse: ; preds = %sw.bb, %entry167 %lsr.iv2 = phi ptr [ %scevgep3, %sw.bb ], [ %scevgep, %entry ]168 %lsr.iv = phi i32 [ %lsr.iv.next, %sw.bb ], [ 1, %entry ]169 %acc.tr = phi i32 [ %or, %sw.bb ], [ %acc, %entry ]170 %scevgep5 = getelementptr ptr, ptr %lsr.iv2, i32 -1171 %tmp2 = load ptr, ptr %scevgep5172 %0 = ptrtoint ptr %tmp2 to i32173 174 175 176 177 %and = and i32 %0, 3178 %tst = icmp eq i32 %and, 0179 br i1 %tst, label %sw.bb, label %tailrecurse.switch180 181tailrecurse.switch: ; preds = %tailrecurse182 183 switch i32 %and, label %sw.epilog [184 i32 1, label %sw.bb185 i32 3, label %sw.bb6186 i32 2, label %sw.bb8187 ], !prof !1188 189sw.bb: ; preds = %tailrecurse.switch, %tailrecurse190 %shl = shl i32 %acc.tr, 1191 %or = or i32 %and, %shl192 %lsr.iv.next = add i32 %lsr.iv, 1193 %scevgep3 = getelementptr %struct.Foo, ptr %lsr.iv2, i32 1194 br label %tailrecurse195 196sw.bb6: ; preds = %tailrecurse.switch197 ret ptr %lsr.iv2198 199sw.bb8: ; preds = %tailrecurse.switch200 %tmp1 = add i32 %acc.tr, %lsr.iv201 %add.ptr11 = getelementptr inbounds %struct.Foo, ptr %this, i32 %tmp1202 ret ptr %add.ptr11203 204sw.epilog: ; preds = %tailrecurse.switch205 ret ptr undef206}207 208; Another test that exercises the AND/TST peephole optimization and also209; generates a predicated ANDS instruction. Check that the predicate is printed210; after the "S" modifier on the instruction.211 212%struct.S = type { ptr, [1 x i8] }213 214define internal zeroext i8 @bar(ptr %x, ptr nocapture %y) nounwind readonly {215; ARM-LABEL: bar:216; ARM: @ %bb.0: @ %entry217; ARM-NEXT: ldrb r2, [r0, #4]218; ARM-NEXT: ands r2, r2, #112219; ARM-NEXT: ldrbne r1, [r1, #4]220; ARM-NEXT: andsne r1, r1, #112221; ARM-NEXT: beq .LBB1_2222; ARM-NEXT: @ %bb.1: @ %bb2223; ARM-NEXT: cmp r2, #16224; ARM-NEXT: cmpne r1, #16225; ARM-NEXT: andeq r0, r0, #255226; ARM-NEXT: moveq pc, lr227; ARM-NEXT: .LBB1_2: @ %return228; ARM-NEXT: mov r0, #1229; ARM-NEXT: mov pc, lr230;231; THUMB-LABEL: bar:232; THUMB: @ %bb.0: @ %entry233; THUMB-NEXT: ldrb r2, [r0, #4]234; THUMB-NEXT: movs r3, #112235; THUMB-NEXT: ands r2, r3236; THUMB-NEXT: beq .LBB1_4237; THUMB-NEXT: @ %bb.1: @ %bb238; THUMB-NEXT: ldrb r1, [r1, #4]239; THUMB-NEXT: ands r1, r3240; THUMB-NEXT: beq .LBB1_4241; THUMB-NEXT: @ %bb.2: @ %bb2242; THUMB-NEXT: cmp r2, #16243; THUMB-NEXT: beq .LBB1_5244; THUMB-NEXT: @ %bb.3: @ %bb2245; THUMB-NEXT: cmp r1, #16246; THUMB-NEXT: beq .LBB1_5247; THUMB-NEXT: .LBB1_4: @ %return248; THUMB-NEXT: movs r0, #1249; THUMB-NEXT: bx lr250; THUMB-NEXT: .LBB1_5: @ %bb4251; THUMB-NEXT: movs r1, #255252; THUMB-NEXT: ands r0, r1253; THUMB-NEXT: bx lr254;255; T2-LABEL: bar:256; T2: @ %bb.0: @ %entry257; T2-NEXT: ldrb r2, [r0, #4]258; T2-NEXT: ands r2, r2, #112259; T2-NEXT: itt ne260; T2-NEXT: ldrbne r1, [r1, #4]261; T2-NEXT: andsne r1, r1, #112262; T2-NEXT: beq .LBB1_2263; T2-NEXT: @ %bb.1: @ %bb2264; T2-NEXT: cmp r2, #16265; T2-NEXT: itee ne266; T2-NEXT: cmpne r1, #16267; T2-NEXT: uxtbeq r0, r0268; T2-NEXT: bxeq lr269; T2-NEXT: .LBB1_2: @ %return270; T2-NEXT: movs r0, #1271; T2-NEXT: bx lr272;273; V8-LABEL: bar:274; V8: @ %bb.0: @ %entry275; V8-NEXT: ldrb r2, [r0, #4]276; V8-NEXT: ands r2, r2, #112277; V8-NEXT: itt ne278; V8-NEXT: ldrbne r1, [r1, #4]279; V8-NEXT: andsne r1, r1, #112280; V8-NEXT: beq .LBB1_2281; V8-NEXT: @ %bb.1: @ %bb2282; V8-NEXT: cmp r2, #16283; V8-NEXT: itee ne284; V8-NEXT: cmpne r1, #16285; V8-NEXT: uxtbeq r0, r0286; V8-NEXT: bxeq lr287; V8-NEXT: .LBB1_2: @ %return288; V8-NEXT: movs r0, #1289; V8-NEXT: bx lr290entry:291 %0 = getelementptr inbounds %struct.S, ptr %x, i32 0, i32 1, i32 0292 %1 = load i8, ptr %0, align 1293 %2 = zext i8 %1 to i32294 %3 = and i32 %2, 112295 %4 = icmp eq i32 %3, 0296 br i1 %4, label %return, label %bb297 298bb: ; preds = %entry299 %5 = getelementptr inbounds %struct.S, ptr %y, i32 0, i32 1, i32 0300 %6 = load i8, ptr %5, align 1301 %7 = zext i8 %6 to i32302 %8 = and i32 %7, 112303 %9 = icmp eq i32 %8, 0304 br i1 %9, label %return, label %bb2305 306bb2: ; preds = %bb307 %10 = icmp eq i32 %3, 16308 %11 = icmp eq i32 %8, 16309 %or.cond = or i1 %10, %11310 br i1 %or.cond, label %bb4, label %return311 312bb4: ; preds = %bb2313 %12 = ptrtoint ptr %x to i32314 %phitmp = trunc i32 %12 to i8315 ret i8 %phitmp316 317return: ; preds = %bb2, %bb, %entry318 ret i8 1319}320 321 322; We were looking through multiple COPY instructions to find an AND we might323; fold into a TST, but in doing so we changed the register being tested allowing324; folding of unrelated tests (in this case, a TST against r1 was eliminated in325; favour of an AND of r0).326 327define i32 @test_tst_assessment(i32 %a, i32 %b) {328; ARM-LABEL: test_tst_assessment:329; ARM: @ %bb.0:330; ARM-NEXT: and r0, r0, #1331; ARM-NEXT: tst r1, #1332; ARM-NEXT: subne r0, r0, #1333; ARM-NEXT: mov pc, lr334;335; THUMB-LABEL: test_tst_assessment:336; THUMB: @ %bb.0:337; THUMB-NEXT: movs r2, r0338; THUMB-NEXT: movs r0, #1339; THUMB-NEXT: ands r0, r2340; THUMB-NEXT: lsls r1, r1, #31341; THUMB-NEXT: beq .LBB2_2342; THUMB-NEXT: @ %bb.1:343; THUMB-NEXT: subs r0, r0, #1344; THUMB-NEXT: .LBB2_2:345; THUMB-NEXT: bx lr346;347; T2-LABEL: test_tst_assessment:348; T2: @ %bb.0:349; T2-NEXT: and r0, r0, #1350; T2-NEXT: lsls r1, r1, #31351; T2-NEXT: it ne352; T2-NEXT: subne r0, #1353; T2-NEXT: bx lr354;355; V8-LABEL: test_tst_assessment:356; V8: @ %bb.0:357; V8-NEXT: and r0, r0, #1358; V8-NEXT: lsls r1, r1, #31359; V8-NEXT: it ne360; V8-NEXT: subne r0, #1361; V8-NEXT: bx lr362 %and1 = and i32 %a, 1363 %sub = sub i32 %and1, 1364 %and2 = and i32 %b, 1365 %cmp = icmp eq i32 %and2, 0366 %sel = select i1 %cmp, i32 %and1, i32 %sub367 ret i32 %sel368}369 370!1 = !{!"branch_weights", i32 1, i32 1, i32 3, i32 2 }371