338 lines · plain
1; Test loop tuning.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -disable-block-placement | FileCheck %s4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 -disable-block-placement \5; RUN: | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-Z136 7; Test that strength reduction is applied to addresses with a scale factor,8; but that indexed addressing can still be used.9define void @f1(ptr %dest, i32 %a) {10; CHECK-LABEL: f1:11; CHECK-NOT: sllg12; CHECK: st %r3, 400({{%r[1-5],%r[1-5]}})13; CHECK: br %r1414entry:15 br label %loop16 17loop:18 %index = phi i64 [ 0, %entry ], [ %next, %loop ]19 %ptr = getelementptr i32, ptr %dest, i64 %index20 store i32 %a, ptr %ptr21 %next = add i64 %index, 122 %cmp = icmp ne i64 %next, 10023 br i1 %cmp, label %loop, label %exit24 25exit:26 ret void27}28 29; Test a loop that should be converted into dbr form and then use BRCT.30define void @f2(ptr %src, ptr %dest) {31; CHECK-LABEL: f2:32; CHECK: lhi [[REG:%r[0-5]]], 10033; CHECK: [[LABEL:\.[^:]*]]:{{.*}} %loop34; CHECK: brct [[REG]], [[LABEL]]35; CHECK: br %r1436entry:37 br label %loop38 39loop:40 %count = phi i32 [ 0, %entry ], [ %next, %loop.next ]41 %next = add i32 %count, 142 %val = load volatile i32, ptr %src43 %cmp = icmp eq i32 %val, 044 br i1 %cmp, label %loop.next, label %loop.store45 46loop.store:47 %add = add i32 %val, 148 store volatile i32 %add, ptr %dest49 br label %loop.next50 51loop.next:52 %cont = icmp ne i32 %next, 10053 br i1 %cont, label %loop, label %exit54 55exit:56 ret void57}58 59; Like f2, but for BRCTG.60define void @f3(ptr %src, ptr %dest) {61; CHECK-LABEL: f3:62; CHECK: lghi [[REG:%r[0-5]]], 10063; CHECK: [[LABEL:\.[^:]*]]:{{.*}} %loop64; CHECK: brctg [[REG]], [[LABEL]]65; CHECK: br %r1466entry:67 br label %loop68 69loop:70 %count = phi i64 [ 0, %entry ], [ %next, %loop.next ]71 %next = add i64 %count, 172 %val = load volatile i64, ptr %src73 %cmp = icmp eq i64 %val, 074 br i1 %cmp, label %loop.next, label %loop.store75 76loop.store:77 %add = add i64 %val, 178 store volatile i64 %add, ptr %dest79 br label %loop.next80 81loop.next:82 %cont = icmp ne i64 %next, 10083 br i1 %cont, label %loop, label %exit84 85exit:86 ret void87}88 89; Test a loop with a 64-bit decremented counter in which the 32-bit90; low part of the counter is used after the decrement. This is an example91; of a subregister use being the only thing that blocks a conversion to BRCTG.92define void @f4(ptr %src, ptr %dest, ptr %dest2, i64 %count) {93; CHECK-LABEL: f4:94; CHECK: aghi [[REG:%r[0-5]]], -195; CHECK: lr [[REG2:%r[0-5]]], [[REG]]96; CHECK: stg [[REG2]],97; CHECK: jne {{\..*}}98; CHECK: br %r1499entry:100 br label %loop101 102loop:103 %left = phi i64 [ %count, %entry ], [ %next, %loop.next ]104 store volatile i64 %left, ptr %dest2105 %val = load volatile i32, ptr %src106 %cmp = icmp eq i32 %val, 0107 br i1 %cmp, label %loop.next, label %loop.store108 109loop.store:110 %add = add i32 %val, 1111 store volatile i32 %add, ptr %dest112 br label %loop.next113 114loop.next:115 %next = add i64 %left, -1116 %ext = zext i32 %val to i64117 %shl = shl i64 %ext, 32118 %and = and i64 %next, 4294967295119 %or = or i64 %shl, %and120 store volatile i64 %or, ptr %dest2121 %cont = icmp ne i64 %next, 0122 br i1 %cont, label %loop, label %exit123 124exit:125 ret void126}127 128; Test that negative offsets are avoided for loads of floating point.129%s.float = type { float, float, float }130define void @f5(ptr nocapture %a,131 ptr nocapture readonly %b,132 i32 zeroext %S) {133; CHECK-Z13-LABEL: f5:134; CHECK-Z13-NOT: -{{[0-9]+}}(%r135 136entry:137 %cmp9 = icmp eq i32 %S, 0138 br i1 %cmp9, label %for.cond.cleanup, label %for.body.preheader139 140for.body.preheader: ; preds = %entry141 br label %for.body142 143for.cond.cleanup.loopexit: ; preds = %for.body144 br label %for.cond.cleanup145 146for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry147 ret void148 149for.body: ; preds = %for.body.preheader, %for.body150 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]151 %a1 = getelementptr inbounds %s.float, ptr %b, i64 %indvars.iv, i32 0152 %tmp = load float, ptr %a1, align 4153 %b4 = getelementptr inbounds %s.float, ptr %b, i64 %indvars.iv, i32 1154 %tmp1 = load float, ptr %b4, align 4155 %add = fadd float %tmp, %tmp1156 %c = getelementptr inbounds %s.float, ptr %b, i64 %indvars.iv, i32 2157 %tmp2 = load float, ptr %c, align 4158 %add7 = fadd float %add, %tmp2159 %a10 = getelementptr inbounds %s.float, ptr %a, i64 %indvars.iv, i32 0160 store float %add7, ptr %a10, align 4161 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1162 %lftr.wideiv = trunc i64 %indvars.iv.next to i32163 %exitcond = icmp eq i32 %lftr.wideiv, %S164 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body165}166 167; Test that negative offsets are avoided for loads of double.168%s.double = type { double, double, double }169define void @f6(ptr nocapture %a,170 ptr nocapture readonly %b,171 i32 zeroext %S) {172; CHECK-Z13-LABEL: f6:173; CHECK-Z13-NOT: -{{[0-9]+}}(%r174entry:175 %cmp9 = icmp eq i32 %S, 0176 br i1 %cmp9, label %for.cond.cleanup, label %for.body.preheader177 178for.body.preheader: ; preds = %entry179 br label %for.body180 181for.cond.cleanup.loopexit: ; preds = %for.body182 br label %for.cond.cleanup183 184for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry185 ret void186 187for.body: ; preds = %for.body.preheader, %for.body188 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]189 %a1 = getelementptr inbounds %s.double, ptr %b, i64 %indvars.iv, i32 0190 %tmp = load double, ptr %a1, align 4191 %b4 = getelementptr inbounds %s.double, ptr %b, i64 %indvars.iv, i32 1192 %tmp1 = load double, ptr %b4, align 4193 %add = fadd double %tmp, %tmp1194 %c = getelementptr inbounds %s.double, ptr %b, i64 %indvars.iv, i32 2195 %tmp2 = load double, ptr %c, align 4196 %add7 = fadd double %add, %tmp2197 %a10 = getelementptr inbounds %s.double, ptr %a, i64 %indvars.iv, i32 0198 store double %add7, ptr %a10, align 4199 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1200 %lftr.wideiv = trunc i64 %indvars.iv.next to i32201 %exitcond = icmp eq i32 %lftr.wideiv, %S202 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body203}204 205; Test that negative offsets are avoided for memory accesses of vector type.206%s.vec = type { <4 x i32>, <4 x i32>, <4 x i32> }207define void @f7(ptr nocapture %a,208 ptr nocapture readonly %b,209 i32 zeroext %S) {210; CHECK-Z13-LABEL: f7:211; CHECK-Z13-NOT: -{{[0-9]+}}(%r212entry:213 %cmp9 = icmp eq i32 %S, 0214 br i1 %cmp9, label %for.cond.cleanup, label %for.body.preheader215 216for.body.preheader: ; preds = %entry217 br label %for.body218 219for.cond.cleanup.loopexit: ; preds = %for.body220 br label %for.cond.cleanup221 222for.cond.cleanup: ; preds = %for.cond.cleanup.loopexit, %entry223 ret void224 225for.body: ; preds = %for.body.preheader, %for.body226 %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ]227 %a1 = getelementptr inbounds %s.vec, ptr %b, i64 %indvars.iv, i32 0228 %tmp = load <4 x i32>, ptr %a1, align 4229 %b4 = getelementptr inbounds %s.vec, ptr %b, i64 %indvars.iv, i32 1230 %tmp1 = load <4 x i32>, ptr %b4, align 4231 %add = add <4 x i32> %tmp1, %tmp232 %c = getelementptr inbounds %s.vec, ptr %b, i64 %indvars.iv, i32 2233 %tmp2 = load <4 x i32>, ptr %c, align 4234 %add7 = add <4 x i32> %add, %tmp2235 %a10 = getelementptr inbounds %s.vec, ptr %a, i64 %indvars.iv, i32 0236 store <4 x i32> %add7, ptr %a10, align 4237 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1238 %lftr.wideiv = trunc i64 %indvars.iv.next to i32239 %exitcond = icmp eq i32 %lftr.wideiv, %S240 br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body241}242 243; Test that a memcpy loop does not get a lot of lays before each mvc (D12 and no index-reg).244%0 = type { %1, ptr }245%1 = type { ptr, ptr }246%2 = type <{ %3, i32, [4 x i8] }>247%3 = type { ptr, ptr, ptr }248 249declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1) #0250 251define void @f8() {252; CHECK-Z13-LABEL: f8:253; CHECK-Z13: mvc254; CHECK-Z13-NEXT: mvc255; CHECK-Z13-NEXT: mvc256; CHECK-Z13-NEXT: mvc257 258bb:259 %tmp = load ptr, ptr undef, align 8260 br i1 undef, label %bb2, label %bb1261 262bb1: ; preds = %bb263 br label %bb2264 265bb2: ; preds = %bb1, %bb266 %tmp3 = phi ptr [ %tmp, %bb ], [ undef, %bb1 ]267 %tmp4 = phi ptr [ undef, %bb ], [ undef, %bb1 ]268 br label %bb5269 270bb5: ; preds = %bb5, %bb2271 %tmp6 = phi ptr [ %tmp21, %bb5 ], [ %tmp3, %bb2 ]272 %tmp7 = phi ptr [ %tmp20, %bb5 ], [ %tmp4, %bb2 ]273 %tmp8 = getelementptr inbounds %0, ptr %tmp7, i64 -1274 %tmp9 = getelementptr inbounds %0, ptr %tmp6, i64 -1275 tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp9, ptr align 8 %tmp8, i64 24, i1 false)276 %tmp12 = getelementptr inbounds %0, ptr %tmp7, i64 -2277 %tmp13 = getelementptr inbounds %0, ptr %tmp6, i64 -2278 tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp13, ptr align 8 %tmp12, i64 24, i1 false)279 %tmp16 = getelementptr inbounds %0, ptr %tmp7, i64 -3280 %tmp17 = getelementptr inbounds %0, ptr %tmp6, i64 -3281 tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp17, ptr align 8 %tmp16, i64 24, i1 false)282 %tmp20 = getelementptr inbounds %0, ptr %tmp7, i64 -4283 %tmp21 = getelementptr inbounds %0, ptr %tmp6, i64 -4284 tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %tmp21, ptr align 8 %tmp20, i64 24, i1 false)285 br label %bb5286}287 288; Test that a chsi does not need an aghik inside the loop (no index reg)289define void @f9() {290; CHECK-Z13-LABEL: f9:291; CHECK-Z13: # =>This Inner Loop Header: Depth=1292; CHECK-Z13-NOT: aghik293; CHECK-Z13: chsi294 295entry:296 br label %for.body.i63297 298for.body.i63: ; preds = %for.inc.i, %entry299 %indvars.iv155.i = phi i64 [ 0, %entry ], [ %indvars.iv.next156.i.3, %for.inc.i ]300 %arrayidx.i62 = getelementptr inbounds i32, ptr undef, i64 %indvars.iv155.i301 %tmp = load i32, ptr %arrayidx.i62, align 4302 %cmp9.i = icmp eq i32 %tmp, 0303 br i1 %cmp9.i, label %for.inc.i, label %if.then10.i304 305if.then10.i: ; preds = %for.body.i63306 unreachable307 308for.inc.i: ; preds = %for.body.i63309 %indvars.iv.next156.i = or i64 %indvars.iv155.i, 1310 %arrayidx.i62.1 = getelementptr inbounds i32, ptr undef, i64 %indvars.iv.next156.i311 %tmp1 = load i32, ptr %arrayidx.i62.1, align 4312 %indvars.iv.next156.i.3 = add nsw i64 %indvars.iv155.i, 4313 br label %for.body.i63314}315 316; Test that offsets are in range for i128 memory accesses.317define void @fun10() {318; CHECK-Z13-LABEL: fun10:319; CHECK-Z13: # =>This Inner Loop Header: Depth=1320; CHECK-Z13-NOT: lay321entry:322 %A1 = alloca [3 x [7 x [10 x i128]]], align 8323 br label %for.body324 325for.body: ; preds = %for.body, %entry326 %IV = phi i64 [ 0, %entry ], [ %IV.next, %for.body ]327 %Addr1 = getelementptr inbounds [3 x [7 x [10 x i128]]], ptr %A1, i64 0, i64 %IV, i64 6, i64 6328 store i128 17174966165894859678, ptr %Addr1, align 8329 %Addr2 = getelementptr inbounds [3 x [7 x [10 x i128]]], ptr %A1, i64 0, i64 %IV, i64 6, i64 8330 store i128 17174966165894859678, ptr %Addr2, align 8331 %IV.next = add nuw nsw i64 %IV, 1332 %exitcond.not.i.i = icmp eq i64 %IV.next, 3333 br i1 %exitcond.not.i.i, label %exit, label %for.body334 335exit: ; preds = %for.body336 unreachable337}338