301 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=thumbv8.1m.main -mattr=+lob --verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOMVE3; RUN: llc -mtriple=thumbv8.1m.main -mattr=+lob,+mve --verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-MVE4 5; Check that loop strength reduction understands that it can fold a sub into an6; le instruction and reduces the cost appropriately, causing it to do this no7; matter the preferred addressing mode.8 9define void @test(ptr %dst, i32 %n) {10; CHECK-NOMVE-LABEL: test:11; CHECK-NOMVE: @ %bb.0: @ %entry12; CHECK-NOMVE-NEXT: push {r7, lr}13; CHECK-NOMVE-NEXT: add.w r0, r0, r1, lsl #114; CHECK-NOMVE-NEXT: movs r2, #015; CHECK-NOMVE-NEXT: sub.w r12, r0, #216; CHECK-NOMVE-NEXT: movs r3, #017; CHECK-NOMVE-NEXT: .LBB0_1: @ %outer_loop18; CHECK-NOMVE-NEXT: @ =>This Loop Header: Depth=119; CHECK-NOMVE-NEXT: @ Child Loop BB0_2 Depth 220; CHECK-NOMVE-NEXT: dls lr, r121; CHECK-NOMVE-NEXT: mov r0, r1222; CHECK-NOMVE-NEXT: .LBB0_2: @ %inner_loop23; CHECK-NOMVE-NEXT: @ Parent Loop BB0_1 Depth=124; CHECK-NOMVE-NEXT: @ => This Inner Loop Header: Depth=225; CHECK-NOMVE-NEXT: strh r2, [r0, #2]!26; CHECK-NOMVE-NEXT: le lr, .LBB0_227; CHECK-NOMVE-NEXT: @ %bb.3: @ %outer_loop_end28; CHECK-NOMVE-NEXT: @ in Loop: Header=BB0_1 Depth=129; CHECK-NOMVE-NEXT: adds r3, #130; CHECK-NOMVE-NEXT: cmp r3, r131; CHECK-NOMVE-NEXT: it eq32; CHECK-NOMVE-NEXT: popeq {r7, pc}33; CHECK-NOMVE-NEXT: b .LBB0_134;35; CHECK-MVE-LABEL: test:36; CHECK-MVE: @ %bb.0: @ %entry37; CHECK-MVE-NEXT: push {r7, lr}38; CHECK-MVE-NEXT: add.w r12, r0, r1, lsl #139; CHECK-MVE-NEXT: movs r2, #040; CHECK-MVE-NEXT: movs r3, #041; CHECK-MVE-NEXT: .LBB0_1: @ %outer_loop42; CHECK-MVE-NEXT: @ =>This Loop Header: Depth=143; CHECK-MVE-NEXT: @ Child Loop BB0_2 Depth 244; CHECK-MVE-NEXT: dls lr, r145; CHECK-MVE-NEXT: mov r0, r1246; CHECK-MVE-NEXT: .LBB0_2: @ %inner_loop47; CHECK-MVE-NEXT: @ Parent Loop BB0_1 Depth=148; CHECK-MVE-NEXT: @ => This Inner Loop Header: Depth=249; CHECK-MVE-NEXT: strh r2, [r0], #250; CHECK-MVE-NEXT: le lr, .LBB0_251; CHECK-MVE-NEXT: @ %bb.3: @ %outer_loop_end52; CHECK-MVE-NEXT: @ in Loop: Header=BB0_1 Depth=153; CHECK-MVE-NEXT: adds r3, #154; CHECK-MVE-NEXT: cmp r3, r155; CHECK-MVE-NEXT: it eq56; CHECK-MVE-NEXT: popeq {r7, pc}57; CHECK-MVE-NEXT: b .LBB0_158entry:59 br label %outer_loop60 61outer_loop:62 %idx_outer = phi i32 [ %idx_outer.inc, %outer_loop_end ], [ 0, %entry ]63 br label %inner_loop64 65inner_loop:66 %idx_inner = phi i32 [ 0, %outer_loop ], [ %idx_inner.inc, %inner_loop ]67 %add = add i32 %idx_inner, %n68 %gep = getelementptr inbounds i16, ptr %dst, i32 %add69 store i16 0, ptr %gep, align 270 %idx_inner.inc = add nuw nsw i32 %idx_inner, 171 %cond_inner = icmp eq i32 %idx_inner.inc, %n72 br i1 %cond_inner, label %outer_loop_end, label %inner_loop73 74outer_loop_end:75 %idx_outer.inc = add nuw i32 %idx_outer, 176 %cond_outer = icmp eq i32 %idx_outer.inc, %n77 br i1 %cond_outer, label %exit, label %outer_loop78 79exit:80 ret void81}82 83define void @test_optsize(ptr %dst, i32 %n) optsize {84; CHECK-LABEL: test_optsize:85; CHECK: @ %bb.0: @ %entry86; CHECK-NEXT: push {r7, lr}87; CHECK-NEXT: add.w r12, r0, r1, lsl #188; CHECK-NEXT: movs r2, #089; CHECK-NEXT: movs r3, #090; CHECK-NEXT: .LBB1_1: @ %outer_loop91; CHECK-NEXT: @ =>This Loop Header: Depth=192; CHECK-NEXT: @ Child Loop BB1_2 Depth 293; CHECK-NEXT: dls lr, r194; CHECK-NEXT: mov r0, r1295; CHECK-NEXT: .LBB1_2: @ %inner_loop96; CHECK-NEXT: @ Parent Loop BB1_1 Depth=197; CHECK-NEXT: @ => This Inner Loop Header: Depth=298; CHECK-NEXT: strh r2, [r0], #299; CHECK-NEXT: le lr, .LBB1_2100; CHECK-NEXT: @ %bb.3: @ %outer_loop_end101; CHECK-NEXT: @ in Loop: Header=BB1_1 Depth=1102; CHECK-NEXT: adds r3, #1103; CHECK-NEXT: cmp r3, r1104; CHECK-NEXT: it eq105; CHECK-NEXT: popeq {r7, pc}106; CHECK-NEXT: b .LBB1_1107entry:108 br label %outer_loop109 110outer_loop:111 %idx_outer = phi i32 [ %idx_outer.inc, %outer_loop_end ], [ 0, %entry ]112 br label %inner_loop113 114inner_loop:115 %idx_inner = phi i32 [ 0, %outer_loop ], [ %idx_inner.inc, %inner_loop ]116 %add = add i32 %idx_inner, %n117 %gep = getelementptr inbounds i16, ptr %dst, i32 %add118 store i16 0, ptr %gep, align 2119 %idx_inner.inc = add nuw nsw i32 %idx_inner, 1120 %cond_inner = icmp eq i32 %idx_inner.inc, %n121 br i1 %cond_inner, label %outer_loop_end, label %inner_loop122 123outer_loop_end:124 %idx_outer.inc = add nuw i32 %idx_outer, 1125 %cond_outer = icmp eq i32 %idx_outer.inc, %n126 br i1 %cond_outer, label %exit, label %outer_loop127 128exit:129 ret void130}131 132; Check that when we can't use LE we don't discount the cost of a sub133; instruction, so we only get it when postincrement is the preferred addressing134; mode (i.e. when we have mve).135 136declare void @otherfn()137 138define void @test_no_le(ptr %dst, i32 %n) {139; CHECK-NOMVE-LABEL: test_no_le:140; CHECK-NOMVE: @ %bb.0: @ %entry141; CHECK-NOMVE-NEXT: push.w {r4, r5, r6, r7, r8, lr}142; CHECK-NOMVE-NEXT: add.w r5, r0, r1, lsl #1143; CHECK-NOMVE-NEXT: mov r4, r1144; CHECK-NOMVE-NEXT: movs r6, #0145; CHECK-NOMVE-NEXT: mov.w r8, #0146; CHECK-NOMVE-NEXT: .LBB2_1: @ %outer_loop147; CHECK-NOMVE-NEXT: @ =>This Loop Header: Depth=1148; CHECK-NOMVE-NEXT: @ Child Loop BB2_2 Depth 2149; CHECK-NOMVE-NEXT: movs r7, #0150; CHECK-NOMVE-NEXT: .LBB2_2: @ %inner_loop151; CHECK-NOMVE-NEXT: @ Parent Loop BB2_1 Depth=1152; CHECK-NOMVE-NEXT: @ => This Inner Loop Header: Depth=2153; CHECK-NOMVE-NEXT: bl otherfn154; CHECK-NOMVE-NEXT: strh.w r6, [r5, r7, lsl #1]155; CHECK-NOMVE-NEXT: adds r7, #1156; CHECK-NOMVE-NEXT: cmp r4, r7157; CHECK-NOMVE-NEXT: bne .LBB2_2158; CHECK-NOMVE-NEXT: @ %bb.3: @ %outer_loop_end159; CHECK-NOMVE-NEXT: @ in Loop: Header=BB2_1 Depth=1160; CHECK-NOMVE-NEXT: add.w r8, r8, #1161; CHECK-NOMVE-NEXT: cmp r8, r4162; CHECK-NOMVE-NEXT: bne .LBB2_1163; CHECK-NOMVE-NEXT: @ %bb.4: @ %exit164; CHECK-NOMVE-NEXT: pop.w {r4, r5, r6, r7, r8, pc}165;166; CHECK-MVE-LABEL: test_no_le:167; CHECK-MVE: @ %bb.0: @ %entry168; CHECK-MVE-NEXT: push.w {r4, r5, r6, r7, r8, r9, lr}169; CHECK-MVE-NEXT: sub sp, #4170; CHECK-MVE-NEXT: add.w r8, r0, r1, lsl #1171; CHECK-MVE-NEXT: mov r9, r1172; CHECK-MVE-NEXT: movs r6, #0173; CHECK-MVE-NEXT: movs r7, #0174; CHECK-MVE-NEXT: .LBB2_1: @ %outer_loop175; CHECK-MVE-NEXT: @ =>This Loop Header: Depth=1176; CHECK-MVE-NEXT: @ Child Loop BB2_2 Depth 2177; CHECK-MVE-NEXT: mov r5, r8178; CHECK-MVE-NEXT: mov r4, r9179; CHECK-MVE-NEXT: .LBB2_2: @ %inner_loop180; CHECK-MVE-NEXT: @ Parent Loop BB2_1 Depth=1181; CHECK-MVE-NEXT: @ => This Inner Loop Header: Depth=2182; CHECK-MVE-NEXT: bl otherfn183; CHECK-MVE-NEXT: strh r6, [r5], #2184; CHECK-MVE-NEXT: subs r4, #1185; CHECK-MVE-NEXT: bne .LBB2_2186; CHECK-MVE-NEXT: @ %bb.3: @ %outer_loop_end187; CHECK-MVE-NEXT: @ in Loop: Header=BB2_1 Depth=1188; CHECK-MVE-NEXT: adds r7, #1189; CHECK-MVE-NEXT: cmp r7, r9190; CHECK-MVE-NEXT: bne .LBB2_1191; CHECK-MVE-NEXT: @ %bb.4: @ %exit192; CHECK-MVE-NEXT: add sp, #4193; CHECK-MVE-NEXT: pop.w {r4, r5, r6, r7, r8, r9, pc}194entry:195 br label %outer_loop196 197outer_loop:198 %idx_outer = phi i32 [ %idx_outer.inc, %outer_loop_end ], [ 0, %entry ]199 br label %inner_loop200 201inner_loop:202 %idx_inner = phi i32 [ 0, %outer_loop ], [ %idx_inner.inc, %inner_loop ]203 call void @otherfn()204 %add = add i32 %idx_inner, %n205 %gep = getelementptr inbounds i16, ptr %dst, i32 %add206 store i16 0, ptr %gep, align 2207 %idx_inner.inc = add nuw nsw i32 %idx_inner, 1208 %cond_inner = icmp eq i32 %idx_inner.inc, %n209 br i1 %cond_inner, label %outer_loop_end, label %inner_loop210 211outer_loop_end:212 %idx_outer.inc = add nuw i32 %idx_outer, 1213 %cond_outer = icmp eq i32 %idx_outer.inc, %n214 br i1 %cond_outer, label %exit, label %outer_loop215 216exit:217 ret void218}219 220define void @test_no_le_optsize(ptr %dst, i32 %n) optsize {221; CHECK-NOMVE-LABEL: test_no_le_optsize:222; CHECK-NOMVE: @ %bb.0: @ %entry223; CHECK-NOMVE-NEXT: push.w {r4, r5, r6, r7, r8, lr}224; CHECK-NOMVE-NEXT: add.w r5, r0, r1, lsl #1225; CHECK-NOMVE-NEXT: mov r4, r1226; CHECK-NOMVE-NEXT: movs r6, #0227; CHECK-NOMVE-NEXT: mov.w r8, #0228; CHECK-NOMVE-NEXT: .LBB3_1: @ %outer_loop229; CHECK-NOMVE-NEXT: @ =>This Loop Header: Depth=1230; CHECK-NOMVE-NEXT: @ Child Loop BB3_2 Depth 2231; CHECK-NOMVE-NEXT: movs r7, #0232; CHECK-NOMVE-NEXT: .LBB3_2: @ %inner_loop233; CHECK-NOMVE-NEXT: @ Parent Loop BB3_1 Depth=1234; CHECK-NOMVE-NEXT: @ => This Inner Loop Header: Depth=2235; CHECK-NOMVE-NEXT: bl otherfn236; CHECK-NOMVE-NEXT: strh.w r6, [r5, r7, lsl #1]237; CHECK-NOMVE-NEXT: adds r7, #1238; CHECK-NOMVE-NEXT: cmp r4, r7239; CHECK-NOMVE-NEXT: bne .LBB3_2240; CHECK-NOMVE-NEXT: @ %bb.3: @ %outer_loop_end241; CHECK-NOMVE-NEXT: @ in Loop: Header=BB3_1 Depth=1242; CHECK-NOMVE-NEXT: add.w r8, r8, #1243; CHECK-NOMVE-NEXT: cmp r8, r4244; CHECK-NOMVE-NEXT: bne .LBB3_1245; CHECK-NOMVE-NEXT: @ %bb.4: @ %exit246; CHECK-NOMVE-NEXT: pop.w {r4, r5, r6, r7, r8, pc}247;248; CHECK-MVE-LABEL: test_no_le_optsize:249; CHECK-MVE: @ %bb.0: @ %entry250; CHECK-MVE-NEXT: push.w {r4, r5, r6, r7, r8, r9, lr}251; CHECK-MVE-NEXT: sub sp, #4252; CHECK-MVE-NEXT: add.w r8, r0, r1, lsl #1253; CHECK-MVE-NEXT: mov r9, r1254; CHECK-MVE-NEXT: movs r6, #0255; CHECK-MVE-NEXT: movs r7, #0256; CHECK-MVE-NEXT: .LBB3_1: @ %outer_loop257; CHECK-MVE-NEXT: @ =>This Loop Header: Depth=1258; CHECK-MVE-NEXT: @ Child Loop BB3_2 Depth 2259; CHECK-MVE-NEXT: mov r5, r8260; CHECK-MVE-NEXT: mov r4, r9261; CHECK-MVE-NEXT: .LBB3_2: @ %inner_loop262; CHECK-MVE-NEXT: @ Parent Loop BB3_1 Depth=1263; CHECK-MVE-NEXT: @ => This Inner Loop Header: Depth=2264; CHECK-MVE-NEXT: bl otherfn265; CHECK-MVE-NEXT: strh r6, [r5], #2266; CHECK-MVE-NEXT: subs r4, #1267; CHECK-MVE-NEXT: bne .LBB3_2268; CHECK-MVE-NEXT: @ %bb.3: @ %outer_loop_end269; CHECK-MVE-NEXT: @ in Loop: Header=BB3_1 Depth=1270; CHECK-MVE-NEXT: adds r7, #1271; CHECK-MVE-NEXT: cmp r7, r9272; CHECK-MVE-NEXT: bne .LBB3_1273; CHECK-MVE-NEXT: @ %bb.4: @ %exit274; CHECK-MVE-NEXT: add sp, #4275; CHECK-MVE-NEXT: pop.w {r4, r5, r6, r7, r8, r9, pc}276entry:277 br label %outer_loop278 279outer_loop:280 %idx_outer = phi i32 [ %idx_outer.inc, %outer_loop_end ], [ 0, %entry ]281 br label %inner_loop282 283inner_loop:284 %idx_inner = phi i32 [ 0, %outer_loop ], [ %idx_inner.inc, %inner_loop ]285 call void @otherfn()286 %add = add i32 %idx_inner, %n287 %gep = getelementptr inbounds i16, ptr %dst, i32 %add288 store i16 0, ptr %gep, align 2289 %idx_inner.inc = add nuw nsw i32 %idx_inner, 1290 %cond_inner = icmp eq i32 %idx_inner.inc, %n291 br i1 %cond_inner, label %outer_loop_end, label %inner_loop292 293outer_loop_end:294 %idx_outer.inc = add nuw i32 %idx_outer, 1295 %cond_outer = icmp eq i32 %idx_outer.inc, %n296 br i1 %cond_outer, label %exit, label %outer_loop297 298exit:299 ret void300}301