393 lines · plain
1; Test load/store pairs that act as memcpys.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s4 5@g1src = dso_local global i8 16@g1dst = dso_local global i8 17@g2src = dso_local global i16 28@g2dst = dso_local global i16 29@g3 = dso_local global i32 310@g4 = dso_local global i64 411@g5src = external dso_local global fp128, align 1612@g5dst = external dso_local global fp128, align 1613 14; Test the simple i8 case.15define dso_local void @f1(ptr %ptr1) {16; CHECK-LABEL: f1:17; CHECK: mvc 1(1,%r2), 0(%r2)18; CHECK: br %r1419 %ptr2 = getelementptr i8, ptr %ptr1, i64 120 %val = load i8, ptr %ptr121 store i8 %val, ptr %ptr222 ret void23}24 25; Test i8 cases where the value is zero-extended to 32 bits.26define dso_local void @f2(ptr %ptr1) {27; CHECK-LABEL: f2:28; CHECK: mvc 1(1,%r2), 0(%r2)29; CHECK: br %r1430 %ptr2 = getelementptr i8, ptr %ptr1, i64 131 %val = load i8, ptr %ptr132 %ext = zext i8 %val to i3233 %trunc = trunc i32 %ext to i834 store i8 %trunc, ptr %ptr235 ret void36}37 38; Test i8 cases where the value is zero-extended to 64 bits.39define dso_local void @f3(ptr %ptr1) {40; CHECK-LABEL: f3:41; CHECK: mvc 1(1,%r2), 0(%r2)42; CHECK: br %r1443 %ptr2 = getelementptr i8, ptr %ptr1, i64 144 %val = load i8, ptr %ptr145 %ext = zext i8 %val to i6446 %trunc = trunc i64 %ext to i847 store i8 %trunc, ptr %ptr248 ret void49}50 51; Test i8 cases where the value is sign-extended to 32 bits.52define dso_local void @f4(ptr %ptr1) {53; CHECK-LABEL: f4:54; CHECK: mvc 1(1,%r2), 0(%r2)55; CHECK: br %r1456 %ptr2 = getelementptr i8, ptr %ptr1, i64 157 %val = load i8, ptr %ptr158 %ext = sext i8 %val to i3259 %trunc = trunc i32 %ext to i860 store i8 %trunc, ptr %ptr261 ret void62}63 64; Test i8 cases where the value is sign-extended to 64 bits.65define dso_local void @f5(ptr %ptr1) {66; CHECK-LABEL: f5:67; CHECK: mvc 1(1,%r2), 0(%r2)68; CHECK: br %r1469 %ptr2 = getelementptr i8, ptr %ptr1, i64 170 %val = load i8, ptr %ptr171 %ext = sext i8 %val to i6472 %trunc = trunc i64 %ext to i873 store i8 %trunc, ptr %ptr274 ret void75}76 77; Test the simple i16 case.78define dso_local void @f6(ptr %ptr1) {79; CHECK-LABEL: f6:80; CHECK: mvc 2(2,%r2), 0(%r2)81; CHECK: br %r1482 %ptr2 = getelementptr i16, ptr %ptr1, i64 183 %val = load i16, ptr %ptr184 store i16 %val, ptr %ptr285 ret void86}87 88; Test i16 cases where the value is zero-extended to 32 bits.89define dso_local void @f7(ptr %ptr1) {90; CHECK-LABEL: f7:91; CHECK: mvc 2(2,%r2), 0(%r2)92; CHECK: br %r1493 %ptr2 = getelementptr i16, ptr %ptr1, i64 194 %val = load i16, ptr %ptr195 %ext = zext i16 %val to i3296 %trunc = trunc i32 %ext to i1697 store i16 %trunc, ptr %ptr298 ret void99}100 101; Test i16 cases where the value is zero-extended to 64 bits.102define dso_local void @f8(ptr %ptr1) {103; CHECK-LABEL: f8:104; CHECK: mvc 2(2,%r2), 0(%r2)105; CHECK: br %r14106 %ptr2 = getelementptr i16, ptr %ptr1, i64 1107 %val = load i16, ptr %ptr1108 %ext = zext i16 %val to i64109 %trunc = trunc i64 %ext to i16110 store i16 %trunc, ptr %ptr2111 ret void112}113 114; Test i16 cases where the value is sign-extended to 32 bits.115define dso_local void @f9(ptr %ptr1) {116; CHECK-LABEL: f9:117; CHECK: mvc 2(2,%r2), 0(%r2)118; CHECK: br %r14119 %ptr2 = getelementptr i16, ptr %ptr1, i64 1120 %val = load i16, ptr %ptr1121 %ext = sext i16 %val to i32122 %trunc = trunc i32 %ext to i16123 store i16 %trunc, ptr %ptr2124 ret void125}126 127; Test i16 cases where the value is sign-extended to 64 bits.128define dso_local void @f10(ptr %ptr1) {129; CHECK-LABEL: f10:130; CHECK: mvc 2(2,%r2), 0(%r2)131; CHECK: br %r14132 %ptr2 = getelementptr i16, ptr %ptr1, i64 1133 %val = load i16, ptr %ptr1134 %ext = sext i16 %val to i64135 %trunc = trunc i64 %ext to i16136 store i16 %trunc, ptr %ptr2137 ret void138}139 140; Test the simple i32 case.141define dso_local void @f11(ptr %ptr1) {142; CHECK-LABEL: f11:143; CHECK: mvc 4(4,%r2), 0(%r2)144; CHECK: br %r14145 %ptr2 = getelementptr i32, ptr %ptr1, i64 1146 %val = load i32, ptr %ptr1147 store i32 %val, ptr %ptr2148 ret void149}150 151; Test i32 cases where the value is zero-extended to 64 bits.152define dso_local void @f12(ptr %ptr1) {153; CHECK-LABEL: f12:154; CHECK: mvc 4(4,%r2), 0(%r2)155; CHECK: br %r14156 %ptr2 = getelementptr i32, ptr %ptr1, i64 1157 %val = load i32, ptr %ptr1158 %ext = zext i32 %val to i64159 %trunc = trunc i64 %ext to i32160 store i32 %trunc, ptr %ptr2161 ret void162}163 164; Test i32 cases where the value is sign-extended to 64 bits.165define dso_local void @f13(ptr %ptr1) {166; CHECK-LABEL: f13:167; CHECK: mvc 4(4,%r2), 0(%r2)168; CHECK: br %r14169 %ptr2 = getelementptr i32, ptr %ptr1, i64 1170 %val = load i32, ptr %ptr1171 %ext = sext i32 %val to i64172 %trunc = trunc i64 %ext to i32173 store i32 %trunc, ptr %ptr2174 ret void175}176 177; Test the i64 case.178define dso_local void @f14(ptr %ptr1) {179; CHECK-LABEL: f14:180; CHECK: mvc 8(8,%r2), 0(%r2)181; CHECK: br %r14182 %ptr2 = getelementptr i64, ptr %ptr1, i64 1183 %val = load i64, ptr %ptr1184 store i64 %val, ptr %ptr2185 ret void186}187 188; Test the f32 case.189define dso_local void @f15(ptr %ptr1) {190; CHECK-LABEL: f15:191; CHECK: mvc 4(4,%r2), 0(%r2)192; CHECK: br %r14193 %ptr2 = getelementptr float, ptr %ptr1, i64 1194 %val = load float, ptr %ptr1195 store float %val, ptr %ptr2196 ret void197}198 199; Test the f64 case.200define dso_local void @f16(ptr %ptr1) {201; CHECK-LABEL: f16:202; CHECK: mvc 8(8,%r2), 0(%r2)203; CHECK: br %r14204 %ptr2 = getelementptr double, ptr %ptr1, i64 1205 %val = load double, ptr %ptr1206 store double %val, ptr %ptr2207 ret void208}209 210; Test the f128 case.211define dso_local void @f17(ptr %ptr1) {212; CHECK-LABEL: f17:213; CHECK: mvc 16(16,%r2), 0(%r2)214; CHECK: br %r14215 %ptr2 = getelementptr fp128, ptr %ptr1, i64 1216 %val = load fp128, ptr %ptr1217 store fp128 %val, ptr %ptr2218 ret void219}220 221; Make sure that we don't use MVC if the load is volatile.222define dso_local void @f18(ptr %ptr1) {223; CHECK-LABEL: f18:224; CHECK-NOT: mvc225; CHECK: br %r14226 %ptr2 = getelementptr i64, ptr %ptr1, i64 1227 %val = load volatile i64, ptr %ptr1228 store i64 %val, ptr %ptr2229 ret void230}231 232; ...likewise the store.233define dso_local void @f19(ptr %ptr1) {234; CHECK-LABEL: f19:235; CHECK-NOT: mvc236; CHECK: br %r14237 %ptr2 = getelementptr i64, ptr %ptr1, i64 1238 %val = load i64, ptr %ptr1239 store volatile i64 %val, ptr %ptr2240 ret void241}242 243; Test that MVC is not used for aligned loads and stores if there is244; no way of telling whether they alias. We don't want to use MVC in245; cases where the addresses could be equal.246define dso_local void @f20(ptr %ptr1, ptr %ptr2) {247; CHECK-LABEL: f20:248; CHECK-NOT: mvc249; CHECK: br %r14250 %val = load i64, ptr %ptr1251 store i64 %val, ptr %ptr2252 ret void253}254 255; ...and again for unaligned loads and stores.256define dso_local void @f21(ptr %ptr1, ptr %ptr2) {257; CHECK-LABEL: f21:258; CHECK-NOT: mvc259; CHECK: br %r14260 %val = load i64, ptr %ptr1, align 2261 store i64 %val, ptr %ptr2, align 2262 ret void263}264 265; Test a case where there is definite overlap.266define dso_local void @f22(i64 %base) {267; CHECK-LABEL: f22:268; CHECK-NOT: mvc269; CHECK: br %r14270 %add = add i64 %base, 1271 %ptr1 = inttoptr i64 %base to ptr272 %ptr2 = inttoptr i64 %add to ptr273 %val = load i64, ptr %ptr1, align 1274 store i64 %val, ptr %ptr2, align 1275 ret void276}277 278; Test that we can use MVC for global addresses for i8.279define dso_local void @f23(ptr %ptr) {280; CHECK-LABEL: f23:281; CHECK-DAG: larl [[SRC:%r[0-5]]], g1src282; CHECK-DAG: larl [[DST:%r[0-5]]], g1dst283; CHECK: mvc 0(1,[[DST]]), 0([[SRC]])284; CHECK: br %r14285 %val = load i8, ptr@g1src286 store i8 %val, ptr@g1dst287 ret void288}289 290; Test that we use LHRL and STHRL for i16.291define dso_local void @f24(ptr %ptr) {292; CHECK-LABEL: f24:293; CHECK: lhrl [[REG:%r[0-5]]], g2src294; CHECK: sthrl [[REG]], g2dst295; CHECK: br %r14296 %val = load i16, ptr@g2src297 store i16 %val, ptr@g2dst298 ret void299}300 301; Test that we use LRL for i32.302define dso_local void @f25(ptr %ptr) {303; CHECK-LABEL: f25:304; CHECK: lrl [[REG:%r[0-5]]], g3305; CHECK: st [[REG]], 0(%r2)306; CHECK: br %r14307 %val = load i32, ptr@g3308 store i32 %val, ptr %ptr309 ret void310}311 312; ...likewise STRL.313define dso_local void @f26(ptr %ptr) {314; CHECK-LABEL: f26:315; CHECK: l [[REG:%r[0-5]]], 0(%r2)316; CHECK: strl [[REG]], g3317; CHECK: br %r14318 %val = load i32, ptr %ptr319 store i32 %val, ptr@g3320 ret void321}322 323; Test that we use LGRL for i64.324define dso_local void @f27(ptr %ptr) {325; CHECK-LABEL: f27:326; CHECK: lgrl [[REG:%r[0-5]]], g4327; CHECK: stg [[REG]], 0(%r2)328; CHECK: br %r14329 %val = load i64, ptr@g4330 store i64 %val, ptr %ptr331 ret void332}333 334; ...likewise STGRL.335define dso_local void @f28(ptr %ptr) {336; CHECK-LABEL: f28:337; CHECK: lg [[REG:%r[0-5]]], 0(%r2)338; CHECK: stgrl [[REG]], g4339; CHECK: br %r14340 %val = load i64, ptr %ptr341 store i64 %val, ptr@g4342 ret void343}344 345; Test that we can use MVC for global addresses for fp128.346define dso_local void @f29(ptr %ptr) {347; CHECK-LABEL: f29:348; CHECK-DAG: larl [[SRC:%r[0-5]]], g5src349; CHECK-DAG: larl [[DST:%r[0-5]]], g5dst350; CHECK: mvc 0(16,[[DST]]), 0([[SRC]])351; CHECK: br %r14352 %val = load fp128, ptr@g5src, align 16353 store fp128 %val, ptr@g5dst, align 16354 ret void355}356 357; Test a case where offset disambiguation is enough.358define dso_local void @f30(ptr %ptr1) {359; CHECK-LABEL: f30:360; CHECK: mvc 8(8,%r2), 0(%r2)361; CHECK: br %r14362 %ptr2 = getelementptr i64, ptr %ptr1, i64 1363 %val = load i64, ptr %ptr1, align 1364 store i64 %val, ptr %ptr2, align 1365 ret void366}367 368; Test f21 in cases where TBAA tells us there is no alias.369define dso_local void @f31(ptr %ptr1, ptr %ptr2) {370; CHECK-LABEL: f31:371; CHECK: mvc 0(8,%r3), 0(%r2)372; CHECK: br %r14373 %val = load i64, ptr %ptr1, align 2, !tbaa !1374 store i64 %val, ptr %ptr2, align 2, !tbaa !2375 ret void376}377 378; Test f21 in cases where TBAA is present but doesn't help.379define dso_local void @f32(ptr %ptr1, ptr %ptr2) {380; CHECK-LABEL: f32:381; CHECK-NOT: mvc382; CHECK: br %r14383 %val = load i64, ptr %ptr1, align 2, !tbaa !1384 store i64 %val, ptr %ptr2, align 2, !tbaa !1385 ret void386}387 388!0 = !{ !"root" }389!1 = !{ !3, !3, i64 0 }390!2 = !{ !4, !4, i64 0 }391!3 = !{ !"set1", !0 }392!4 = !{ !"set2", !0 }393