529 lines · plain
1; REQUIRES: asserts2; The regression tests need to test for order of emitted instructions, and3; therefore, the tests are a bit fragile/reliant on instruction scheduling. The4; test cases have been minimized as much as possible, but still most of the test5; cases could break if instruction scheduling heuristics for cortex-a53 change6; RUN: llc < %s -mcpu=cortex-a53 -mattr=+fix-cortex-a53-835769 -frame-pointer=non-leaf -stats 2>&1 \7; RUN: | FileCheck %s8; RUN: llc < %s -mcpu=cortex-a53 -mattr=-fix-cortex-a53-835769 -frame-pointer=non-leaf -stats 2>&1 \9; RUN: | FileCheck %s --check-prefix CHECK-NOWORKAROUND10; The following run lines are just to verify whether or not this pass runs by11; default for given CPUs. Given the fragility of the tests, this is only run on12; a test case where the scheduler has not freedom at all to reschedule the13; instructions, so the potentially massively different scheduling heuristics14; will not break the test case.15; RUN: llc < %s -mcpu=generic -frame-pointer=non-leaf | FileCheck %s --check-prefix CHECK-BASIC-PASS-DISABLED16; RUN: llc < %s -mcpu=cortex-a53 -frame-pointer=non-leaf | FileCheck %s --check-prefix CHECK-BASIC-PASS-DISABLED17; RUN: llc < %s -mcpu=cortex-a57 -frame-pointer=non-leaf | FileCheck %s --check-prefix CHECK-BASIC-PASS-DISABLED18; RUN: llc < %s -mcpu=cyclone -frame-pointer=non-leaf | FileCheck %s --check-prefix CHECK-BASIC-PASS-DISABLED19 20target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"21target triple = "aarch64--linux-gnu"22 23define i64 @f_load_madd_64(i64 %a, i64 %b, ptr nocapture readonly %c) #0 {24entry:25 %0 = load i64, ptr %c, align 826 %mul = mul nsw i64 %0, %b27 %add = add nsw i64 %mul, %a28 ret i64 %add29}30; CHECK-LABEL: f_load_madd_64:31; CHECK: ldr32; CHECK-NEXT: nop33; CHECK-NEXT: madd34; CHECK-NOWORKAROUND-LABEL: f_load_madd_64:35; CHECK-NOWORKAROUND: ldr36; CHECK-NOWORKAROUND-NEXT: madd37; CHECK-BASIC-PASS-DISABLED-LABEL: f_load_madd_64:38; CHECK-BASIC-PASS-DISABLED: ldr39; CHECK-BASIC-PASS-DISABLED-NEXT: madd40 41 42define i32 @f_load_madd_32(i32 %a, i32 %b, ptr nocapture readonly %c) #0 {43entry:44 %0 = load i32, ptr %c, align 445 %mul = mul nsw i32 %0, %b46 %add = add nsw i32 %mul, %a47 ret i32 %add48}49; CHECK-LABEL: f_load_madd_32:50; CHECK: ldr51; CHECK-NEXT: madd52; CHECK-NOWORKAROUND-LABEL: f_load_madd_32:53; CHECK-NOWORKAROUND: ldr54; CHECK-NOWORKAROUND-NEXT: madd55 56 57define i64 @f_load_msub_64(i64 %a, i64 %b, ptr nocapture readonly %c) #0 {58entry:59 %0 = load i64, ptr %c, align 860 %mul = mul nsw i64 %0, %b61 %sub = sub nsw i64 %a, %mul62 ret i64 %sub63}64; CHECK-LABEL: f_load_msub_64:65; CHECK: ldr66; CHECK-NEXT: nop67; CHECK-NEXT: msub68; CHECK-NOWORKAROUND-LABEL: f_load_msub_64:69; CHECK-NOWORKAROUND: ldr70; CHECK-NOWORKAROUND-NEXT: msub71 72 73define i32 @f_load_msub_32(i32 %a, i32 %b, ptr nocapture readonly %c) #0 {74entry:75 %0 = load i32, ptr %c, align 476 %mul = mul nsw i32 %0, %b77 %sub = sub nsw i32 %a, %mul78 ret i32 %sub79}80; CHECK-LABEL: f_load_msub_32:81; CHECK: ldr82; CHECK-NEXT: msub83; CHECK-NOWORKAROUND-LABEL: f_load_msub_32:84; CHECK-NOWORKAROUND: ldr85; CHECK-NOWORKAROUND-NEXT: msub86 87 88define i64 @f_load_mul_64(i64 %a, i64 %b, ptr nocapture readonly %c) #0 {89entry:90 %0 = load i64, ptr %c, align 891 %mul = mul nsw i64 %0, %b92 ret i64 %mul93}94; CHECK-LABEL: f_load_mul_64:95; CHECK: ldr96; CHECK-NEXT: mul97; CHECK-NOWORKAROUND-LABEL: f_load_mul_64:98; CHECK-NOWORKAROUND: ldr99; CHECK-NOWORKAROUND-NEXT: mul100 101 102define i32 @f_load_mul_32(i32 %a, i32 %b, ptr nocapture readonly %c) #0 {103entry:104 %0 = load i32, ptr %c, align 4105 %mul = mul nsw i32 %0, %b106 ret i32 %mul107}108; CHECK-LABEL: f_load_mul_32:109; CHECK: ldr110; CHECK-NEXT: mul111; CHECK-NOWORKAROUND-LABEL: f_load_mul_32:112; CHECK-NOWORKAROUND: ldr113; CHECK-NOWORKAROUND-NEXT: mul114 115 116define i64 @f_load_mneg_64(i64 %a, i64 %b, ptr nocapture readonly %c) #0 {117entry:118 %0 = load i64, ptr %c, align 8119 %mul = sub i64 0, %b120 %sub = mul i64 %0, %mul121 ret i64 %sub122}123; CHECK-LABEL: f_load_mneg_64:124; CHECK-NOWORKAROUND-LABEL: f_load_mneg_64:125; FIXME: only add further checks here once LLVM actually produces126; neg instructions127; FIXME-CHECK: ldr128; FIXME-CHECK-NEXT: nop129; FIXME-CHECK-NEXT: mneg130; FIXME-CHECK-NOWORKAROUND: ldr131; FIXME-CHECK-NOWORKAROUND-NEXT: mneg132 133 134define i32 @f_load_mneg_32(i32 %a, i32 %b, ptr nocapture readonly %c) #0 {135entry:136 %0 = load i32, ptr %c, align 4137 %mul = sub i32 0, %b138 %sub = mul i32 %0, %mul139 ret i32 %sub140}141; CHECK-LABEL: f_load_mneg_32:142; CHECK-NOWORKAROUND-LABEL: f_load_mneg_32:143; FIXME: only add further checks here once LLVM actually produces144; neg instructions145; FIXME-CHECK: ldr146; FIXME-CHECK-NEXT: mneg147; FIXME-CHECK-NOWORKAROUND: ldr148; FIXME-CHECK-NOWORKAROUND-NEXT: mneg149 150 151define i64 @f_load_smaddl(i64 %a, i32 %b, i32 %c, ptr nocapture readonly %d) #0 {152entry:153 %conv = sext i32 %b to i64154 %conv1 = sext i32 %c to i64155 %mul = mul nsw i64 %conv1, %conv156 %add = add nsw i64 %mul, %a157 %0 = load i32, ptr %d, align 4158 %conv2 = sext i32 %0 to i64159 %add3 = add nsw i64 %add, %conv2160 ret i64 %add3161}162; CHECK-LABEL: f_load_smaddl:163; CHECK: ldrsw164; CHECK-NEXT: nop165; CHECK-NEXT: smaddl166; CHECK-NOWORKAROUND-LABEL: f_load_smaddl:167; CHECK-NOWORKAROUND: ldrsw168; CHECK-NOWORKAROUND-NEXT: smaddl169 170 171define i64 @f_load_smsubl_64(i64 %a, i32 %b, i32 %c, ptr nocapture readonly %d) #0 {172entry:173 %conv = sext i32 %b to i64174 %conv1 = sext i32 %c to i64175 %mul = mul nsw i64 %conv1, %conv176 %sub = sub i64 %a, %mul177 %0 = load i32, ptr %d, align 4178 %conv2 = sext i32 %0 to i64179 %add = add nsw i64 %sub, %conv2180 ret i64 %add181}182; CHECK-LABEL: f_load_smsubl_64:183; CHECK: ldrsw184; CHECK-NEXT: nop185; CHECK-NEXT: smsubl186; CHECK-NOWORKAROUND-LABEL: f_load_smsubl_64:187; CHECK-NOWORKAROUND: ldrsw188; CHECK-NOWORKAROUND-NEXT: smsubl189 190 191define i64 @f_load_smull(i64 %a, i32 %b, i32 %c, ptr nocapture readonly %d) #0 {192entry:193 %conv = sext i32 %b to i64194 %conv1 = sext i32 %c to i64195 %mul = mul nsw i64 %conv1, %conv196 %0 = load i32, ptr %d, align 4197 %conv2 = sext i32 %0 to i64198 %div = sdiv i64 %mul, %conv2199 ret i64 %div200}201; CHECK-LABEL: f_load_smull:202; CHECK: ldrsw203; CHECK-NEXT: smull204; CHECK-NOWORKAROUND-LABEL: f_load_smull:205; CHECK-NOWORKAROUND: ldrsw206; CHECK-NOWORKAROUND-NEXT: smull207 208 209define i64 @f_load_smnegl_64(i64 %a, i32 %b, i32 %c, ptr nocapture readonly %d) #0 {210entry:211 %conv = sext i32 %b to i64212 %conv1 = sext i32 %c to i64213 %mul = sub nsw i64 0, %conv214 %sub = mul i64 %conv1, %mul215 %0 = load i32, ptr %d, align 4216 %conv2 = sext i32 %0 to i64217 %div = sdiv i64 %sub, %conv2218 ret i64 %div219}220; CHECK-LABEL: f_load_smnegl_64:221; CHECK-NOWORKAROUND-LABEL: f_load_smnegl_64:222; FIXME: only add further checks here once LLVM actually produces223; smnegl instructions224 225 226define i64 @f_load_umaddl(i64 %a, i32 %b, i32 %c, ptr nocapture readonly %d) #0 {227entry:228 %conv = zext i32 %b to i64229 %conv1 = zext i32 %c to i64230 %mul = mul i64 %conv1, %conv231 %add = add i64 %mul, %a232 %0 = load i32, ptr %d, align 4233 %conv2 = zext i32 %0 to i64234 %add3 = add i64 %add, %conv2235 ret i64 %add3236}237; CHECK-LABEL: f_load_umaddl:238; CHECK: ldr239; CHECK-NEXT: nop240; CHECK-NEXT: umaddl241; CHECK-NOWORKAROUND-LABEL: f_load_umaddl:242; CHECK-NOWORKAROUND: ldr243; CHECK-NOWORKAROUND-NEXT: umaddl244 245 246define i64 @f_load_umsubl_64(i64 %a, i32 %b, i32 %c, ptr nocapture readonly %d) #0 {247entry:248 %conv = zext i32 %b to i64249 %conv1 = zext i32 %c to i64250 %mul = mul i64 %conv1, %conv251 %sub = sub i64 %a, %mul252 %0 = load i32, ptr %d, align 4253 %conv2 = zext i32 %0 to i64254 %add = add i64 %sub, %conv2255 ret i64 %add256}257; CHECK-LABEL: f_load_umsubl_64:258; CHECK: ldr259; CHECK-NEXT: nop260; CHECK-NEXT: umsubl261; CHECK-NOWORKAROUND-LABEL: f_load_umsubl_64:262; CHECK-NOWORKAROUND: ldr263; CHECK-NOWORKAROUND-NEXT: umsubl264 265 266define i64 @f_load_umull(i64 %a, i32 %b, i32 %c, ptr nocapture readonly %d) #0 {267entry:268 %conv = zext i32 %b to i64269 %conv1 = zext i32 %c to i64270 %mul = mul i64 %conv1, %conv271 %0 = load i32, ptr %d, align 4272 %conv2 = zext i32 %0 to i64273 %div = udiv i64 %mul, %conv2274 ret i64 %div275}276; CHECK-LABEL: f_load_umull:277; CHECK: ldr278; CHECK-NEXT: umull279; CHECK-NOWORKAROUND-LABEL: f_load_umull:280; CHECK-NOWORKAROUND: ldr281; CHECK-NOWORKAROUND-NEXT: umull282 283 284define i64 @f_load_umnegl_64(i64 %a, i32 %b, i32 %c, ptr nocapture readonly %d) #0 {285entry:286 %conv = zext i32 %b to i64287 %conv1 = zext i32 %c to i64288 %mul = sub nsw i64 0, %conv289 %sub = mul i64 %conv1, %mul290 %0 = load i32, ptr %d, align 4291 %conv2 = zext i32 %0 to i64292 %div = udiv i64 %sub, %conv2293 ret i64 %div294}295; CHECK-LABEL: f_load_umnegl_64:296; CHECK-NOWORKAROUND-LABEL: f_load_umnegl_64:297; FIXME: only add further checks here once LLVM actually produces298; umnegl instructions299 300 301define i64 @f_store_madd_64(i64 %a, i64 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {302entry:303 %0 = load i64, ptr %cp, align 8304 store i64 %a, ptr %e, align 8305 %mul = mul nsw i64 %0, %b306 %add = add nsw i64 %mul, %a307 ret i64 %add308}309; CHECK-LABEL: f_store_madd_64:310; CHECK: str311; CHECK-NEXT: nop312; CHECK-NEXT: madd313; CHECK-NOWORKAROUND-LABEL: f_store_madd_64:314; CHECK-NOWORKAROUND: str315; CHECK-NOWORKAROUND-NEXT: madd316 317 318define i32 @f_store_madd_32(i32 %a, i32 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {319entry:320 %0 = load i32, ptr %cp, align 4321 store i32 %a, ptr %e, align 4322 %mul = mul nsw i32 %0, %b323 %add = add nsw i32 %mul, %a324 ret i32 %add325}326; CHECK-LABEL: f_store_madd_32:327; CHECK: str328; CHECK-NEXT: madd329; CHECK-NOWORKAROUND-LABEL: f_store_madd_32:330; CHECK-NOWORKAROUND: str331; CHECK-NOWORKAROUND-NEXT: madd332 333 334define i64 @f_store_msub_64(i64 %a, i64 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {335entry:336 %0 = load i64, ptr %cp, align 8337 store i64 %a, ptr %e, align 8338 %mul = mul nsw i64 %0, %b339 %sub = sub nsw i64 %a, %mul340 ret i64 %sub341}342; CHECK-LABEL: f_store_msub_64:343; CHECK: str344; CHECK-NEXT: nop345; CHECK-NEXT: msub346; CHECK-NOWORKAROUND-LABEL: f_store_msub_64:347; CHECK-NOWORKAROUND: str348; CHECK-NOWORKAROUND-NEXT: msub349 350 351define i32 @f_store_msub_32(i32 %a, i32 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {352entry:353 %0 = load i32, ptr %cp, align 4354 store i32 %a, ptr %e, align 4355 %mul = mul nsw i32 %0, %b356 %sub = sub nsw i32 %a, %mul357 ret i32 %sub358}359; CHECK-LABEL: f_store_msub_32:360; CHECK: str361; CHECK-NEXT: msub362; CHECK-NOWORKAROUND-LABEL: f_store_msub_32:363; CHECK-NOWORKAROUND: str364; CHECK-NOWORKAROUND-NEXT: msub365 366 367define i64 @f_store_mul_64(i64 %a, i64 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {368entry:369 %0 = load i64, ptr %cp, align 8370 store i64 %a, ptr %e, align 8371 %mul = mul nsw i64 %0, %b372 ret i64 %mul373}374; CHECK-LABEL: f_store_mul_64:375; CHECK: str376; CHECK-NEXT: mul377; CHECK-NOWORKAROUND-LABEL: f_store_mul_64:378; CHECK-NOWORKAROUND: str379; CHECK-NOWORKAROUND-NEXT: mul380 381 382define i32 @f_store_mul_32(i32 %a, i32 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {383entry:384 %0 = load i32, ptr %cp, align 4385 store i32 %a, ptr %e, align 4386 %mul = mul nsw i32 %0, %b387 ret i32 %mul388}389; CHECK-LABEL: f_store_mul_32:390; CHECK: str391; CHECK-NEXT: mul392; CHECK-NOWORKAROUND-LABEL: f_store_mul_32:393; CHECK-NOWORKAROUND: str394; CHECK-NOWORKAROUND-NEXT: mul395 396 397define i64 @f_prefetch_madd_64(i64 %a, i64 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {398entry:399 %0 = load i64, ptr %cp, align 8400 tail call void @llvm.prefetch(ptr %e, i32 0, i32 0, i32 1)401 %mul = mul nsw i64 %0, %b402 %add = add nsw i64 %mul, %a403 ret i64 %add404}405; CHECK-LABEL: f_prefetch_madd_64:406; CHECK: prfm407; CHECK-NEXT: nop408; CHECK-NEXT: madd409; CHECK-NOWORKAROUND-LABEL: f_prefetch_madd_64:410; CHECK-NOWORKAROUND: prfm411; CHECK-NOWORKAROUND-NEXT: madd412 413declare void @llvm.prefetch(ptr nocapture, i32, i32, i32) #2414 415define i32 @f_prefetch_madd_32(i32 %a, i32 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {416entry:417 %0 = load i32, ptr %cp, align 4418 tail call void @llvm.prefetch(ptr %e, i32 1, i32 0, i32 1)419 %mul = mul nsw i32 %0, %b420 %add = add nsw i32 %mul, %a421 ret i32 %add422}423; CHECK-LABEL: f_prefetch_madd_32:424; CHECK: prfm425; CHECK-NEXT: madd426; CHECK-NOWORKAROUND-LABEL: f_prefetch_madd_32:427; CHECK-NOWORKAROUND: prfm428; CHECK-NOWORKAROUND-NEXT: madd429 430define i64 @f_prefetch_msub_64(i64 %a, i64 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {431entry:432 %0 = load i64, ptr %cp, align 8433 tail call void @llvm.prefetch(ptr %e, i32 0, i32 1, i32 1)434 %mul = mul nsw i64 %0, %b435 %sub = sub nsw i64 %a, %mul436 ret i64 %sub437}438; CHECK-LABEL: f_prefetch_msub_64:439; CHECK: prfm440; CHECK-NEXT: nop441; CHECK-NEXT: msub442; CHECK-NOWORKAROUND-LABEL: f_prefetch_msub_64:443; CHECK-NOWORKAROUND: prfm444; CHECK-NOWORKAROUND-NEXT: msub445 446define i32 @f_prefetch_msub_32(i32 %a, i32 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {447entry:448 %0 = load i32, ptr %cp, align 4449 tail call void @llvm.prefetch(ptr %e, i32 1, i32 1, i32 1)450 %mul = mul nsw i32 %0, %b451 %sub = sub nsw i32 %a, %mul452 ret i32 %sub453}454; CHECK-LABEL: f_prefetch_msub_32:455; CHECK: prfm456; CHECK-NEXT: msub457; CHECK-NOWORKAROUND-LABEL: f_prefetch_msub_32:458; CHECK-NOWORKAROUND: prfm459; CHECK-NOWORKAROUND-NEXT: msub460 461define i64 @f_prefetch_mul_64(i64 %a, i64 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {462entry:463 %0 = load i64, ptr %cp, align 8464 tail call void @llvm.prefetch(ptr %e, i32 0, i32 3, i32 1)465 %mul = mul nsw i64 %0, %b466 ret i64 %mul467}468; CHECK-LABEL: f_prefetch_mul_64:469; CHECK: prfm470; CHECK-NEXT: mul471; CHECK-NOWORKAROUND-LABEL: f_prefetch_mul_64:472; CHECK-NOWORKAROUND: prfm473; CHECK-NOWORKAROUND-NEXT: mul474 475define i32 @f_prefetch_mul_32(i32 %a, i32 %b, ptr nocapture readonly %cp, ptr nocapture %e) #1 {476entry:477 %0 = load i32, ptr %cp, align 4478 tail call void @llvm.prefetch(ptr %e, i32 1, i32 3, i32 1)479 %mul = mul nsw i32 %0, %b480 ret i32 %mul481}482; CHECK-LABEL: f_prefetch_mul_32:483; CHECK: prfm484; CHECK-NEXT: mul485; CHECK-NOWORKAROUND-LABEL: f_prefetch_mul_32:486; CHECK-NOWORKAROUND: prfm487; CHECK-NOWORKAROUND-NEXT: mul488 489define i64 @fall_through(i64 %a, i64 %b, ptr nocapture readonly %c) #0 {490entry:491 %0 = load i64, ptr %c, align 8492 br label %block1493 494block1:495 %mul = mul nsw i64 %0, %b496 %add = add nsw i64 %mul, %a497 %tmp = ptrtoint ptr blockaddress(@fall_through, %block1) to i64498 %ret = add nsw i64 %tmp, %add499 ret i64 %ret500}501; CHECK-LABEL: fall_through502; CHECK: ldr503; CHECK-NEXT: nop504; CHECK-NEXT: .Ltmp505; CHECK-NEXT: %bb.506; CHECK-NEXT: madd507; CHECK-NOWORKAROUND-LABEL: fall_through508; CHECK-NOWORKAROUND: ldr509; CHECK-NOWORKAROUND-NEXT: .Ltmp510; CHECK-NOWORKAROUND-NEXT: %bb.511; CHECK-NOWORKAROUND-NEXT: madd512 513; No checks for this, just check it doesn't crash514define i32 @crash_check(ptr nocapture readnone %data) #0 {515entry:516 br label %while.cond517 518while.cond:519 br label %while.cond520}521 522attributes #0 = { nounwind readonly "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "use-soft-float"="false" }523attributes #1 = { nounwind "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "use-soft-float"="false" }524attributes #2 = { nounwind }525 526 527; CHECK-LABEL: ... Statistics Collected ...528; CHECK: 11 aarch64-fix-cortex-a53-835769 - Number of Nops added to work around erratum 835769529