883 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=aarch64 -aarch64-neon-syntax=apple | FileCheck %s --check-prefixes=CHECK,CHECK-SD3; RUN: llc < %s -mtriple=aarch64 -aarch64-neon-syntax=apple -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI4 5define i32 @test_rev_w(i32 %a) nounwind {6; CHECK-LABEL: test_rev_w:7; CHECK: // %bb.0: // %entry8; CHECK-NEXT: rev w0, w09; CHECK-NEXT: ret10entry:11 %0 = tail call i32 @llvm.bswap.i32(i32 %a)12 ret i32 %013}14 15define i64 @test_rev_x(i64 %a) nounwind {16; CHECK-LABEL: test_rev_x:17; CHECK: // %bb.0: // %entry18; CHECK-NEXT: rev x0, x019; CHECK-NEXT: ret20entry:21 %0 = tail call i64 @llvm.bswap.i64(i64 %a)22 ret i64 %023}24 25; Canonicalize (srl (bswap x), 16) to (rotr (bswap x), 16) if the high 16-bits26; of %a are zero. This optimizes rev + lsr 16 to rev16.27define i32 @test_rev_w_srl16(i16 %a) {28; CHECK-SD-LABEL: test_rev_w_srl16:29; CHECK-SD: // %bb.0: // %entry30; CHECK-SD-NEXT: rev w8, w031; CHECK-SD-NEXT: lsr w0, w8, #1632; CHECK-SD-NEXT: ret33;34; CHECK-GI-LABEL: test_rev_w_srl16:35; CHECK-GI: // %bb.0: // %entry36; CHECK-GI-NEXT: and w8, w0, #0xffff37; CHECK-GI-NEXT: rev16 w0, w838; CHECK-GI-NEXT: ret39entry:40 %0 = zext i16 %a to i3241 %1 = tail call i32 @llvm.bswap.i32(i32 %0)42 %2 = lshr i32 %1, 1643 ret i32 %244}45 46define i32 @test_rev_w_srl16_load(ptr %a) {47; CHECK-SD-LABEL: test_rev_w_srl16_load:48; CHECK-SD: // %bb.0: // %entry49; CHECK-SD-NEXT: ldrh w8, [x0]50; CHECK-SD-NEXT: rev w8, w851; CHECK-SD-NEXT: lsr w0, w8, #1652; CHECK-SD-NEXT: ret53;54; CHECK-GI-LABEL: test_rev_w_srl16_load:55; CHECK-GI: // %bb.0: // %entry56; CHECK-GI-NEXT: ldrh w8, [x0]57; CHECK-GI-NEXT: rev16 w0, w858; CHECK-GI-NEXT: ret59entry:60 %0 = load i16, ptr %a61 %1 = zext i16 %0 to i3262 %2 = tail call i32 @llvm.bswap.i32(i32 %1)63 %3 = lshr i32 %2, 1664 ret i32 %365}66 67define i32 @test_rev_w_srl16_add(i8 %a, i8 %b) {68; CHECK-SD-LABEL: test_rev_w_srl16_add:69; CHECK-SD: // %bb.0: // %entry70; CHECK-SD-NEXT: and w8, w0, #0xff71; CHECK-SD-NEXT: add w8, w8, w1, uxtb72; CHECK-SD-NEXT: rev16 w0, w873; CHECK-SD-NEXT: ret74;75; CHECK-GI-LABEL: test_rev_w_srl16_add:76; CHECK-GI: // %bb.0: // %entry77; CHECK-GI-NEXT: and w8, w1, #0xff78; CHECK-GI-NEXT: add w8, w8, w0, uxtb79; CHECK-GI-NEXT: rev16 w0, w880; CHECK-GI-NEXT: ret81entry:82 %0 = zext i8 %a to i3283 %1 = zext i8 %b to i3284 %2 = add i32 %0, %185 %3 = tail call i32 @llvm.bswap.i32(i32 %2)86 %4 = lshr i32 %3, 1687 ret i32 %488}89 90; Canonicalize (srl (bswap x), 32) to (rotr (bswap x), 32) if the high 32-bits91; of %a are zero. This optimizes rev + lsr 32 to rev32.92define i64 @test_rev_x_srl32(i32 %a) {93; CHECK-SD-LABEL: test_rev_x_srl32:94; CHECK-SD: // %bb.0: // %entry95; CHECK-SD-NEXT: // kill: def $w0 killed $w0 def $x096; CHECK-SD-NEXT: rev x8, x097; CHECK-SD-NEXT: lsr x0, x8, #3298; CHECK-SD-NEXT: ret99;100; CHECK-GI-LABEL: test_rev_x_srl32:101; CHECK-GI: // %bb.0: // %entry102; CHECK-GI-NEXT: mov w8, w0103; CHECK-GI-NEXT: rev32 x0, x8104; CHECK-GI-NEXT: ret105entry:106 %0 = zext i32 %a to i64107 %1 = tail call i64 @llvm.bswap.i64(i64 %0)108 %2 = lshr i64 %1, 32109 ret i64 %2110}111 112define i64 @test_rev_x_srl32_load(ptr %a) {113; CHECK-SD-LABEL: test_rev_x_srl32_load:114; CHECK-SD: // %bb.0: // %entry115; CHECK-SD-NEXT: ldr w8, [x0]116; CHECK-SD-NEXT: rev x8, x8117; CHECK-SD-NEXT: lsr x0, x8, #32118; CHECK-SD-NEXT: ret119;120; CHECK-GI-LABEL: test_rev_x_srl32_load:121; CHECK-GI: // %bb.0: // %entry122; CHECK-GI-NEXT: ldr w8, [x0]123; CHECK-GI-NEXT: rev32 x0, x8124; CHECK-GI-NEXT: ret125entry:126 %0 = load i32, ptr %a127 %1 = zext i32 %0 to i64128 %2 = tail call i64 @llvm.bswap.i64(i64 %1)129 %3 = lshr i64 %2, 32130 ret i64 %3131}132 133define i64 @test_rev_x_srl32_shift(i64 %a) {134; CHECK-LABEL: test_rev_x_srl32_shift:135; CHECK: // %bb.0: // %entry136; CHECK-NEXT: ubfx x8, x0, #2, #29137; CHECK-NEXT: rev32 x0, x8138; CHECK-NEXT: ret139entry:140 %0 = shl i64 %a, 33141 %1 = lshr i64 %0, 35142 %2 = tail call i64 @llvm.bswap.i64(i64 %1)143 %3 = lshr i64 %2, 32144 ret i64 %3145}146 147declare i32 @llvm.bswap.i32(i32) nounwind readnone148declare i64 @llvm.bswap.i64(i64) nounwind readnone149 150define i32 @test_rev16_w(i32 %X) nounwind {151; CHECK-SD-LABEL: test_rev16_w:152; CHECK-SD: // %bb.0: // %entry153; CHECK-SD-NEXT: rev16 w0, w0154; CHECK-SD-NEXT: ret155;156; CHECK-GI-LABEL: test_rev16_w:157; CHECK-GI: // %bb.0: // %entry158; CHECK-GI-NEXT: lsr w8, w0, #8159; CHECK-GI-NEXT: lsl w9, w0, #8160; CHECK-GI-NEXT: and w10, w8, #0xff0000161; CHECK-GI-NEXT: and w11, w9, #0xff000000162; CHECK-GI-NEXT: and w8, w8, #0xff163; CHECK-GI-NEXT: and w9, w9, #0xff00164; CHECK-GI-NEXT: orr w10, w11, w10165; CHECK-GI-NEXT: orr w8, w9, w8166; CHECK-GI-NEXT: orr w0, w10, w8167; CHECK-GI-NEXT: ret168entry:169 %tmp1 = lshr i32 %X, 8170 %X15 = bitcast i32 %X to i32171 %tmp4 = shl i32 %X15, 8172 %tmp2 = and i32 %tmp1, 16711680173 %tmp5 = and i32 %tmp4, -16777216174 %tmp9 = and i32 %tmp1, 255175 %tmp13 = and i32 %tmp4, 65280176 %tmp6 = or i32 %tmp5, %tmp2177 %tmp10 = or i32 %tmp6, %tmp13178 %tmp14 = or i32 %tmp10, %tmp9179 ret i32 %tmp14180}181 182; 64-bit REV16 is *not* a swap then a 16-bit rotation:183; 01234567 ->(bswap) 76543210 ->(rotr) 10765432184; 01234567 ->(rev16) 10325476185define i64 @test_rev16_x(i64 %a) nounwind {186; CHECK-LABEL: test_rev16_x:187; CHECK: // %bb.0: // %entry188; CHECK-NEXT: rev x8, x0189; CHECK-NEXT: ror x0, x8, #16190; CHECK-NEXT: ret191entry:192 %0 = tail call i64 @llvm.bswap.i64(i64 %a)193 %1 = lshr i64 %0, 16194 %2 = shl i64 %0, 48195 %3 = or i64 %1, %2196 ret i64 %3197}198 199define i64 @test_rev32_x(i64 %a) nounwind {200; CHECK-LABEL: test_rev32_x:201; CHECK: // %bb.0: // %entry202; CHECK-NEXT: rev32 x0, x0203; CHECK-NEXT: ret204entry:205 %0 = tail call i64 @llvm.bswap.i64(i64 %a)206 %1 = lshr i64 %0, 32207 %2 = shl i64 %0, 32208 %3 = or i64 %1, %2209 ret i64 %3210}211 212define <8 x i8> @test_vrev64D8(ptr %A) nounwind {213; CHECK-LABEL: test_vrev64D8:214; CHECK: // %bb.0:215; CHECK-NEXT: ldr d0, [x0]216; CHECK-NEXT: rev64.8b v0, v0217; CHECK-NEXT: ret218 %tmp1 = load <8 x i8>, ptr %A219 %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>220 ret <8 x i8> %tmp2221}222 223define <4 x i16> @test_vrev64D16(ptr %A) nounwind {224; CHECK-LABEL: test_vrev64D16:225; CHECK: // %bb.0:226; CHECK-NEXT: ldr d0, [x0]227; CHECK-NEXT: rev64.4h v0, v0228; CHECK-NEXT: ret229 %tmp1 = load <4 x i16>, ptr %A230 %tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> <i32 3, i32 2, i32 1, i32 0>231 ret <4 x i16> %tmp2232}233 234define <2 x i32> @test_vrev64D32(ptr %A) nounwind {235; CHECK-LABEL: test_vrev64D32:236; CHECK: // %bb.0:237; CHECK-NEXT: ldr d0, [x0]238; CHECK-NEXT: rev64.2s v0, v0239; CHECK-NEXT: ret240 %tmp1 = load <2 x i32>, ptr %A241 %tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <2 x i32> <i32 1, i32 0>242 ret <2 x i32> %tmp2243}244 245define <2 x float> @test_vrev64Df(ptr %A) nounwind {246; CHECK-LABEL: test_vrev64Df:247; CHECK: // %bb.0:248; CHECK-NEXT: ldr d0, [x0]249; CHECK-NEXT: rev64.2s v0, v0250; CHECK-NEXT: ret251 %tmp1 = load <2 x float>, ptr %A252 %tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <2 x i32> <i32 1, i32 0>253 ret <2 x float> %tmp2254}255 256define <16 x i8> @test_vrev64Q8(ptr %A) nounwind {257; CHECK-LABEL: test_vrev64Q8:258; CHECK: // %bb.0:259; CHECK-NEXT: ldr q0, [x0]260; CHECK-NEXT: rev64.16b v0, v0261; CHECK-NEXT: ret262 %tmp1 = load <16 x i8>, ptr %A263 %tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>264 ret <16 x i8> %tmp2265}266 267define <8 x i16> @test_vrev64Q16(ptr %A) nounwind {268; CHECK-LABEL: test_vrev64Q16:269; CHECK: // %bb.0:270; CHECK-NEXT: ldr q0, [x0]271; CHECK-NEXT: rev64.8h v0, v0272; CHECK-NEXT: ret273 %tmp1 = load <8 x i16>, ptr %A274 %tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>275 ret <8 x i16> %tmp2276}277 278define <4 x i32> @test_vrev64Q32(ptr %A) nounwind {279; CHECK-LABEL: test_vrev64Q32:280; CHECK: // %bb.0:281; CHECK-NEXT: ldr q0, [x0]282; CHECK-NEXT: rev64.4s v0, v0283; CHECK-NEXT: ret284 %tmp1 = load <4 x i32>, ptr %A285 %tmp2 = shufflevector <4 x i32> %tmp1, <4 x i32> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>286 ret <4 x i32> %tmp2287}288 289define <4 x float> @test_vrev64Qf(ptr %A) nounwind {290; CHECK-LABEL: test_vrev64Qf:291; CHECK: // %bb.0:292; CHECK-NEXT: ldr q0, [x0]293; CHECK-NEXT: rev64.4s v0, v0294; CHECK-NEXT: ret295 %tmp1 = load <4 x float>, ptr %A296 %tmp2 = shufflevector <4 x float> %tmp1, <4 x float> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>297 ret <4 x float> %tmp2298}299 300define <8 x i8> @test_vrev32D8(ptr %A) nounwind {301; CHECK-LABEL: test_vrev32D8:302; CHECK: // %bb.0:303; CHECK-NEXT: ldr d0, [x0]304; CHECK-NEXT: rev32.8b v0, v0305; CHECK-NEXT: ret306 %tmp1 = load <8 x i8>, ptr %A307 %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>308 ret <8 x i8> %tmp2309}310 311define <4 x i16> @test_vrev32D16(ptr %A) nounwind {312; CHECK-LABEL: test_vrev32D16:313; CHECK: // %bb.0:314; CHECK-NEXT: ldr d0, [x0]315; CHECK-NEXT: rev32.4h v0, v0316; CHECK-NEXT: ret317 %tmp1 = load <4 x i16>, ptr %A318 %tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> <i32 1, i32 0, i32 3, i32 2>319 ret <4 x i16> %tmp2320}321 322define <16 x i8> @test_vrev32Q8(ptr %A) nounwind {323; CHECK-LABEL: test_vrev32Q8:324; CHECK: // %bb.0:325; CHECK-NEXT: ldr q0, [x0]326; CHECK-NEXT: rev32.16b v0, v0327; CHECK-NEXT: ret328 %tmp1 = load <16 x i8>, ptr %A329 %tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>330 ret <16 x i8> %tmp2331}332 333define <8 x i16> @test_vrev32Q16(ptr %A) nounwind {334; CHECK-LABEL: test_vrev32Q16:335; CHECK: // %bb.0:336; CHECK-NEXT: ldr q0, [x0]337; CHECK-NEXT: rev32.8h v0, v0338; CHECK-NEXT: ret339 %tmp1 = load <8 x i16>, ptr %A340 %tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>341 ret <8 x i16> %tmp2342}343 344define <8 x i8> @test_vrev16D8(ptr %A) nounwind {345; CHECK-LABEL: test_vrev16D8:346; CHECK: // %bb.0:347; CHECK-NEXT: ldr d0, [x0]348; CHECK-NEXT: rev16.8b v0, v0349; CHECK-NEXT: ret350 %tmp1 = load <8 x i8>, ptr %A351 %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>352 ret <8 x i8> %tmp2353}354 355define <16 x i8> @test_vrev16Q8(ptr %A) nounwind {356; CHECK-LABEL: test_vrev16Q8:357; CHECK: // %bb.0:358; CHECK-NEXT: ldr q0, [x0]359; CHECK-NEXT: rev16.16b v0, v0360; CHECK-NEXT: ret361 %tmp1 = load <16 x i8>, ptr %A362 %tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>363 ret <16 x i8> %tmp2364}365 366define <4 x half> @test_vrev32Df16(<4 x half> %A) nounwind {367; CHECK-LABEL: test_vrev32Df16:368; CHECK: // %bb.0:369; CHECK-NEXT: rev32.4h v0, v0370; CHECK-NEXT: ret371 %tmp2 = shufflevector <4 x half> %A, <4 x half> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2>372 ret <4 x half> %tmp2373}374 375define <8 x half> @test_vrev32Qf16(<8 x half> %A) nounwind {376; CHECK-LABEL: test_vrev32Qf16:377; CHECK: // %bb.0:378; CHECK-NEXT: rev32.8h v0, v0379; CHECK-NEXT: ret380 %tmp2 = shufflevector <8 x half> %A, <8 x half> poison, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>381 ret <8 x half> %tmp2382}383 384define <4 x half> @test_vrev64Df16(<4 x half> %A) nounwind {385; CHECK-LABEL: test_vrev64Df16:386; CHECK: // %bb.0:387; CHECK-NEXT: rev64.4h v0, v0388; CHECK-NEXT: ret389 %tmp2 = shufflevector <4 x half> %A, <4 x half> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>390 ret <4 x half> %tmp2391}392 393define <8 x half> @test_vrev64Qf16(<8 x half> %A) nounwind {394; CHECK-LABEL: test_vrev64Qf16:395; CHECK: // %bb.0:396; CHECK-NEXT: rev64.8h v0, v0397; CHECK-NEXT: ret398 %tmp2 = shufflevector <8 x half> %A, <8 x half> poison, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>399 ret <8 x half> %tmp2400}401 402define <4 x bfloat> @test_vrev32Dbf16(<4 x bfloat> %A) nounwind {403; CHECK-LABEL: test_vrev32Dbf16:404; CHECK: // %bb.0:405; CHECK-NEXT: rev32.4h v0, v0406; CHECK-NEXT: ret407 %tmp2 = shufflevector <4 x bfloat> %A, <4 x bfloat> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2>408 ret <4 x bfloat> %tmp2409}410 411define <8 x bfloat> @test_vrev32Qbf16(<8 x bfloat> %A) nounwind {412; CHECK-LABEL: test_vrev32Qbf16:413; CHECK: // %bb.0:414; CHECK-NEXT: rev32.8h v0, v0415; CHECK-NEXT: ret416 %tmp2 = shufflevector <8 x bfloat> %A, <8 x bfloat> poison, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>417 ret <8 x bfloat> %tmp2418}419 420define <4 x bfloat> @test_vrev64Dbf16(<4 x bfloat> %A) nounwind {421; CHECK-LABEL: test_vrev64Dbf16:422; CHECK: // %bb.0:423; CHECK-NEXT: rev64.4h v0, v0424; CHECK-NEXT: ret425 %tmp2 = shufflevector <4 x bfloat> %A, <4 x bfloat> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>426 ret <4 x bfloat> %tmp2427}428 429define <8 x bfloat> @test_vrev64Qbf16(<8 x bfloat> %A) nounwind {430; CHECK-LABEL: test_vrev64Qbf16:431; CHECK: // %bb.0:432; CHECK-NEXT: rev64.8h v0, v0433; CHECK-NEXT: ret434 %tmp2 = shufflevector <8 x bfloat> %A, <8 x bfloat> poison, <8 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4>435 ret <8 x bfloat> %tmp2436}437 438; Undef shuffle indices should not prevent matching to VREV:439 440define <8 x i8> @test_vrev64D8_undef(ptr %A) nounwind {441; CHECK-LABEL: test_vrev64D8_undef:442; CHECK: // %bb.0:443; CHECK-NEXT: ldr d0, [x0]444; CHECK-NEXT: rev64.8b v0, v0445; CHECK-NEXT: ret446 %tmp1 = load <8 x i8>, ptr %A447 %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> <i32 7, i32 undef, i32 undef, i32 4, i32 3, i32 2, i32 1, i32 0>448 ret <8 x i8> %tmp2449}450 451define <8 x i16> @test_vrev32Q16_undef(ptr %A) nounwind {452; CHECK-LABEL: test_vrev32Q16_undef:453; CHECK: // %bb.0:454; CHECK-NEXT: ldr q0, [x0]455; CHECK-NEXT: rev32.8h v0, v0456; CHECK-NEXT: ret457 %tmp1 = load <8 x i16>, ptr %A458 %tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> <i32 undef, i32 0, i32 undef, i32 2, i32 5, i32 4, i32 7, i32 undef>459 ret <8 x i16> %tmp2460}461 462; vrev <4 x i16> should use REV32 and not REV64463define void @test_vrev64(ptr nocapture %source, ptr nocapture %dst) nounwind ssp {464; CHECK-SD-LABEL: test_vrev64:465; CHECK-SD: // %bb.0: // %entry466; CHECK-SD-NEXT: ldr q0, [x0]467; CHECK-SD-NEXT: mov h1, v0[5]468; CHECK-SD-NEXT: st1.h { v0 }[6], [x1]469; CHECK-SD-NEXT: str h1, [x1, #2]470; CHECK-SD-NEXT: ret471;472; CHECK-GI-LABEL: test_vrev64:473; CHECK-GI: // %bb.0: // %entry474; CHECK-GI-NEXT: ldr q0, [x0]475; CHECK-GI-NEXT: add x8, x1, #2476; CHECK-GI-NEXT: st1.h { v0 }[6], [x1]477; CHECK-GI-NEXT: st1.h { v0 }[5], [x8]478; CHECK-GI-NEXT: ret479entry:480 %tmp2 = load <8 x i16>, ptr %source, align 4481 %tmp3 = extractelement <8 x i16> %tmp2, i32 6482 %tmp5 = insertelement <2 x i16> undef, i16 %tmp3, i32 0483 %tmp9 = extractelement <8 x i16> %tmp2, i32 5484 %tmp11 = insertelement <2 x i16> %tmp5, i16 %tmp9, i32 1485 store <2 x i16> %tmp11, ptr %dst, align 4486 ret void487}488 489; Test vrev of float4490define void @float_vrev64(ptr nocapture %source, ptr nocapture %dest) nounwind noinline ssp {491; CHECK-SD-LABEL: float_vrev64:492; CHECK-SD: // %bb.0: // %entry493; CHECK-SD-NEXT: movi.2d v0, #0000000000000000494; CHECK-SD-NEXT: add x8, x0, #12495; CHECK-SD-NEXT: dup.4s v0, v0[0]496; CHECK-SD-NEXT: ld1.s { v0 }[1], [x8]497; CHECK-SD-NEXT: str q0, [x1, #176]498; CHECK-SD-NEXT: ret499;500; CHECK-GI-LABEL: float_vrev64:501; CHECK-GI: // %bb.0: // %entry502; CHECK-GI-NEXT: movi d0, #0000000000000000503; CHECK-GI-NEXT: adrp x8, .LCPI36_0504; CHECK-GI-NEXT: ldr q1, [x0]505; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI36_0]506; CHECK-GI-NEXT: tbl.16b v0, { v0, v1 }, v2507; CHECK-GI-NEXT: str q0, [x1, #176]508; CHECK-GI-NEXT: ret509entry:510 %tmp2 = load <4 x float>, ptr %source, align 4511 %tmp5 = shufflevector <4 x float> <float 0.000000e+00, float undef, float undef, float undef>, <4 x float> %tmp2, <4 x i32> <i32 0, i32 7, i32 0, i32 0>512 %arrayidx8 = getelementptr inbounds <4 x float>, ptr %dest, i32 11513 store <4 x float> %tmp5, ptr %arrayidx8, align 4514 ret void515}516 517 518define <4 x i32> @test_vrev32_bswap(<4 x i32> %source) nounwind {519; CHECK-LABEL: test_vrev32_bswap:520; CHECK: // %bb.0:521; CHECK-NEXT: rev32.16b v0, v0522; CHECK-NEXT: ret523 %bswap = call <4 x i32> @llvm.bswap.v4i32(<4 x i32> %source)524 ret <4 x i32> %bswap525}526 527declare <4 x i32> @llvm.bswap.v4i32(<4 x i32>) nounwind readnone528 529; Reduced regression from D114354530define void @test_rev16_truncstore() {531; CHECK-SD-LABEL: test_rev16_truncstore:532; CHECK-SD: // %bb.0: // %entry533; CHECK-SD-NEXT: cbnz wzr, .LBB38_2534; CHECK-SD-NEXT: .LBB38_1: // %cleanup535; CHECK-SD-NEXT: // =>This Inner Loop Header: Depth=1536; CHECK-SD-NEXT: ldrh w8, [x8]537; CHECK-SD-NEXT: rev16 w8, w8538; CHECK-SD-NEXT: strh w8, [x8]539; CHECK-SD-NEXT: cbz wzr, .LBB38_1540; CHECK-SD-NEXT: .LBB38_2: // %fail541; CHECK-SD-NEXT: ret542;543; CHECK-GI-LABEL: test_rev16_truncstore:544; CHECK-GI: // %bb.0: // %entry545; CHECK-GI-NEXT: tbnz wzr, #0, .LBB38_2546; CHECK-GI-NEXT: .LBB38_1: // %cleanup547; CHECK-GI-NEXT: // =>This Inner Loop Header: Depth=1548; CHECK-GI-NEXT: ldrh w8, [x8]549; CHECK-GI-NEXT: rev w8, w8550; CHECK-GI-NEXT: lsr w8, w8, #16551; CHECK-GI-NEXT: strh w8, [x8]552; CHECK-GI-NEXT: tbz wzr, #0, .LBB38_1553; CHECK-GI-NEXT: .LBB38_2: // %fail554; CHECK-GI-NEXT: ret555entry:556 br label %body557 558body:559 %out.6269.i = phi ptr [ undef, %cleanup ], [ undef, %entry ]560 %0 = load i16, ptr undef, align 2561 %1 = icmp eq i16 undef, -10240562 br i1 %1, label %fail, label %cleanup563 564cleanup:565 %or130.i = call i16 @llvm.bswap.i16(i16 %0)566 store i16 %or130.i, ptr %out.6269.i, align 2567 br label %body568 569fail:570 ret void571}572declare i16 @llvm.bswap.i16(i16)573 574; Reduced regression from D120192575define void @test_bswap32_narrow(ptr %p0, ptr %p1) nounwind {576; CHECK-SD-LABEL: test_bswap32_narrow:577; CHECK-SD: // %bb.0:578; CHECK-SD-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill579; CHECK-SD-NEXT: ldrh w8, [x0, #2]580; CHECK-SD-NEXT: mov x19, x1581; CHECK-SD-NEXT: rev16 w0, w8582; CHECK-SD-NEXT: bl gid_tbl_len583; CHECK-SD-NEXT: strh wzr, [x19]584; CHECK-SD-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload585; CHECK-SD-NEXT: ret586;587; CHECK-GI-LABEL: test_bswap32_narrow:588; CHECK-GI: // %bb.0:589; CHECK-GI-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill590; CHECK-GI-NEXT: ldr w8, [x0]591; CHECK-GI-NEXT: mov x19, x1592; CHECK-GI-NEXT: and w8, w8, #0xffff0000593; CHECK-GI-NEXT: rev w0, w8594; CHECK-GI-NEXT: bl gid_tbl_len595; CHECK-GI-NEXT: strh wzr, [x19]596; CHECK-GI-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload597; CHECK-GI-NEXT: ret598 %ld = load i32, ptr %p0, align 4599 %and = and i32 %ld, -65536600 %bswap = tail call i32 @llvm.bswap.i32(i32 %and)601 %and16 = zext i32 %bswap to i64602 %call17 = tail call i32 @gid_tbl_len(i64 %and16)603 store i16 0, ptr %p1, align 4604 ret void605}606declare i32 @gid_tbl_len(...)607 608; 64-bit REV16 is *not* a swap then a 16-bit rotation:609; 01234567 ->(bswap) 76543210 ->(rotr) 10765432610; 01234567 ->(rev16) 10325476611; Optimize patterns where rev16 can be generated for a 64-bit input.612define i64 @test_rev16_x_hwbyteswaps(i64 %a) nounwind {613; CHECK-LABEL: test_rev16_x_hwbyteswaps:614; CHECK: // %bb.0: // %entry615; CHECK-NEXT: rev16 x0, x0616; CHECK-NEXT: ret617entry:618 %0 = lshr i64 %a, 8619 %1 = and i64 %0, 71777214294589695620 %2 = shl i64 %a, 8621 %3 = and i64 %2, -71777214294589696622 %4 = or i64 %1, %3623 ret i64 %4624}625 626; Optimize pattern with multiple and/or to a simple pattern which can enable generation of rev16.627define i64 @test_rev16_x_hwbyteswaps_complex1(i64 %a) nounwind {628; CHECK-SD-LABEL: test_rev16_x_hwbyteswaps_complex1:629; CHECK-SD: // %bb.0: // %entry630; CHECK-SD-NEXT: lsr x8, x0, #8631; CHECK-SD-NEXT: lsr x9, x0, #48632; CHECK-SD-NEXT: and x10, x8, #0xff000000000000633; CHECK-SD-NEXT: and x11, x8, #0xff00000000634; CHECK-SD-NEXT: and x8, x8, #0xff0000635; CHECK-SD-NEXT: bfi x10, x9, #56, #8636; CHECK-SD-NEXT: lsr x9, x0, #32637; CHECK-SD-NEXT: orr x10, x10, x11638; CHECK-SD-NEXT: bfi x10, x9, #40, #8639; CHECK-SD-NEXT: lsr x9, x0, #16640; CHECK-SD-NEXT: orr x8, x10, x8641; CHECK-SD-NEXT: bfi x8, x9, #24, #8642; CHECK-SD-NEXT: ubfiz x9, x0, #8, #8643; CHECK-SD-NEXT: bfxil x8, x0, #8, #8644; CHECK-SD-NEXT: orr x0, x8, x9645; CHECK-SD-NEXT: ret646;647; CHECK-GI-LABEL: test_rev16_x_hwbyteswaps_complex1:648; CHECK-GI: // %bb.0: // %entry649; CHECK-GI-NEXT: lsr x8, x0, #8650; CHECK-GI-NEXT: lsl x9, x0, #8651; CHECK-GI-NEXT: and x10, x8, #0xff000000000000652; CHECK-GI-NEXT: and x11, x9, #0xff00000000000000653; CHECK-GI-NEXT: and x12, x8, #0xff00000000654; CHECK-GI-NEXT: and x13, x9, #0xff0000000000655; CHECK-GI-NEXT: and x14, x8, #0xff0000656; CHECK-GI-NEXT: orr x10, x10, x11657; CHECK-GI-NEXT: and x11, x9, #0xff000000658; CHECK-GI-NEXT: orr x12, x12, x13659; CHECK-GI-NEXT: and x8, x8, #0xff660; CHECK-GI-NEXT: orr x11, x14, x11661; CHECK-GI-NEXT: orr x10, x10, x12662; CHECK-GI-NEXT: and x9, x9, #0xff00663; CHECK-GI-NEXT: orr x8, x11, x8664; CHECK-GI-NEXT: orr x8, x10, x8665; CHECK-GI-NEXT: orr x0, x8, x9666; CHECK-GI-NEXT: ret667entry:668 %0 = lshr i64 %a, 8669 %1 = and i64 %0, 71776119061217280670 %2 = shl i64 %a, 8671 %3 = and i64 %2, -72057594037927936672 %4 = or i64 %1, %3673 %5 = and i64 %0, 1095216660480674 %6 = or i64 %4, %5675 %7 = and i64 %2, 280375465082880676 %8 = or i64 %6, %7677 %9 = and i64 %0, 16711680678 %10 = or i64 %8, %9679 %11 = and i64 %2, 4278190080680 %12 = or i64 %10, %11681 %13 = and i64 %0, 255682 %14 = or i64 %12, %13683 %15 = and i64 %2, 65280684 %16 = or i64 %14, %15685 ret i64 %16686}687 688define i64 @test_rev16_x_hwbyteswaps_complex2(i64 %a) nounwind {689; CHECK-SD-LABEL: test_rev16_x_hwbyteswaps_complex2:690; CHECK-SD: // %bb.0: // %entry691; CHECK-SD-NEXT: lsr x8, x0, #8692; CHECK-SD-NEXT: lsr x9, x0, #48693; CHECK-SD-NEXT: lsr x10, x0, #32694; CHECK-SD-NEXT: and x8, x8, #0xff00ff00ff00ff695; CHECK-SD-NEXT: bfi x8, x9, #56, #8696; CHECK-SD-NEXT: lsr x9, x0, #16697; CHECK-SD-NEXT: bfi x8, x10, #40, #8698; CHECK-SD-NEXT: bfi x8, x9, #24, #8699; CHECK-SD-NEXT: bfi x8, x0, #8, #8700; CHECK-SD-NEXT: mov x0, x8701; CHECK-SD-NEXT: ret702;703; CHECK-GI-LABEL: test_rev16_x_hwbyteswaps_complex2:704; CHECK-GI: // %bb.0: // %entry705; CHECK-GI-NEXT: lsr x8, x0, #8706; CHECK-GI-NEXT: lsl x9, x0, #8707; CHECK-GI-NEXT: and x10, x8, #0xff000000000000708; CHECK-GI-NEXT: and x11, x8, #0xff00000000709; CHECK-GI-NEXT: and x12, x8, #0xff0000710; CHECK-GI-NEXT: and x8, x8, #0xff711; CHECK-GI-NEXT: and x13, x9, #0xff00000000000000712; CHECK-GI-NEXT: orr x10, x10, x11713; CHECK-GI-NEXT: and x11, x9, #0xff0000000000714; CHECK-GI-NEXT: orr x8, x12, x8715; CHECK-GI-NEXT: and x12, x9, #0xff000000716; CHECK-GI-NEXT: orr x11, x13, x11717; CHECK-GI-NEXT: orr x8, x10, x8718; CHECK-GI-NEXT: and x9, x9, #0xff00719; CHECK-GI-NEXT: orr x10, x11, x12720; CHECK-GI-NEXT: orr x8, x8, x10721; CHECK-GI-NEXT: orr x0, x8, x9722; CHECK-GI-NEXT: ret723entry:724 %0 = lshr i64 %a, 8725 %1 = and i64 %0, 71776119061217280726 %2 = shl i64 %a, 8727 %3 = and i64 %0, 1095216660480728 %4 = or i64 %1, %3729 %5 = and i64 %0, 16711680730 %6 = or i64 %4, %5731 %7 = and i64 %0, 255732 %8 = or i64 %6, %7733 %9 = and i64 %2, -72057594037927936734 %10 = or i64 %8, %9735 %11 = and i64 %2, 280375465082880736 %12 = or i64 %10, %11737 %13 = and i64 %2, 4278190080738 %14 = or i64 %12, %13739 %15 = and i64 %2, 65280740 %16 = or i64 %14, %15741 ret i64 %16742}743 744; Optimize pattern with multiple and/or to a simple pattern which can enable generation of rev16.745define i64 @test_rev16_x_hwbyteswaps_complex3(i64 %a) nounwind {746; CHECK-SD-LABEL: test_rev16_x_hwbyteswaps_complex3:747; CHECK-SD: // %bb.0: // %entry748; CHECK-SD-NEXT: lsr x8, x0, #8749; CHECK-SD-NEXT: lsr x9, x0, #48750; CHECK-SD-NEXT: and x10, x8, #0xff000000000000751; CHECK-SD-NEXT: and x11, x8, #0xff00000000752; CHECK-SD-NEXT: and x8, x8, #0xff0000753; CHECK-SD-NEXT: bfi x10, x9, #56, #8754; CHECK-SD-NEXT: lsr x9, x0, #32755; CHECK-SD-NEXT: orr x10, x11, x10756; CHECK-SD-NEXT: bfi x10, x9, #40, #8757; CHECK-SD-NEXT: lsr x9, x0, #16758; CHECK-SD-NEXT: orr x8, x8, x10759; CHECK-SD-NEXT: bfi x8, x9, #24, #8760; CHECK-SD-NEXT: ubfiz x9, x0, #8, #8761; CHECK-SD-NEXT: bfxil x8, x0, #8, #8762; CHECK-SD-NEXT: orr x0, x9, x8763; CHECK-SD-NEXT: ret764;765; CHECK-GI-LABEL: test_rev16_x_hwbyteswaps_complex3:766; CHECK-GI: // %bb.0: // %entry767; CHECK-GI-NEXT: lsr x8, x0, #8768; CHECK-GI-NEXT: lsl x9, x0, #8769; CHECK-GI-NEXT: and x10, x8, #0xff000000000000770; CHECK-GI-NEXT: and x11, x9, #0xff00000000000000771; CHECK-GI-NEXT: and x12, x8, #0xff00000000772; CHECK-GI-NEXT: and x13, x9, #0xff0000000000773; CHECK-GI-NEXT: and x14, x8, #0xff0000774; CHECK-GI-NEXT: orr x10, x11, x10775; CHECK-GI-NEXT: and x11, x9, #0xff000000776; CHECK-GI-NEXT: orr x12, x13, x12777; CHECK-GI-NEXT: and x8, x8, #0xff778; CHECK-GI-NEXT: orr x11, x11, x14779; CHECK-GI-NEXT: orr x10, x12, x10780; CHECK-GI-NEXT: and x9, x9, #0xff00781; CHECK-GI-NEXT: orr x8, x8, x11782; CHECK-GI-NEXT: orr x8, x8, x10783; CHECK-GI-NEXT: orr x0, x9, x8784; CHECK-GI-NEXT: ret785entry:786 %0 = lshr i64 %a, 8787 %1 = and i64 %0, 71776119061217280788 %2 = shl i64 %a, 8789 %3 = and i64 %2, -72057594037927936790 %4 = or i64 %3, %1791 %5 = and i64 %0, 1095216660480792 %6 = or i64 %5, %4793 %7 = and i64 %2, 280375465082880794 %8 = or i64 %7, %6795 %9 = and i64 %0, 16711680796 %10 = or i64 %9, %8797 %11 = and i64 %2, 4278190080798 %12 = or i64 %11, %10799 %13 = and i64 %0, 255800 %14 = or i64 %13, %12801 %15 = and i64 %2, 65280802 %16 = or i64 %15, %14803 ret i64 %16804}805 806define i64 @test_or_and_combine1(i64 %a) nounwind {807; CHECK-SD-LABEL: test_or_and_combine1:808; CHECK-SD: // %bb.0: // %entry809; CHECK-SD-NEXT: lsr x8, x0, #8810; CHECK-SD-NEXT: lsr x9, x0, #24811; CHECK-SD-NEXT: and x10, x8, #0xff000000000000812; CHECK-SD-NEXT: and x8, x8, #0xff0000813; CHECK-SD-NEXT: bfi x10, x9, #32, #8814; CHECK-SD-NEXT: orr x0, x10, x8815; CHECK-SD-NEXT: ret816;817; CHECK-GI-LABEL: test_or_and_combine1:818; CHECK-GI: // %bb.0: // %entry819; CHECK-GI-NEXT: lsr x8, x0, #8820; CHECK-GI-NEXT: lsl x9, x0, #8821; CHECK-GI-NEXT: and x10, x8, #0xff000000000000822; CHECK-GI-NEXT: and x9, x9, #0xff00000000823; CHECK-GI-NEXT: and x8, x8, #0xff0000824; CHECK-GI-NEXT: orr x9, x10, x9825; CHECK-GI-NEXT: orr x0, x9, x8826; CHECK-GI-NEXT: ret827entry:828 %0 = lshr i64 %a, 8829 %1 = and i64 %0, 71776119061217280830 %2 = shl i64 %a, 8831 %3 = and i64 %2, 1095216660480832 %4 = or i64 %1, %3833 %5 = and i64 %0, 16711680834 %6 = or i64 %4, %5835 ret i64 %6836}837 838define i64 @test_or_and_combine2(i64 %a, i64 %b) nounwind {839; CHECK-LABEL: test_or_and_combine2:840; CHECK: // %bb.0: // %entry841; CHECK-NEXT: lsr x8, x0, #8842; CHECK-NEXT: lsl x9, x0, #8843; CHECK-NEXT: and x10, x8, #0xff000000000000844; CHECK-NEXT: and x11, x9, #0xff00000000845; CHECK-NEXT: and x8, x8, #0xff0000846; CHECK-NEXT: orr x9, x10, x9847; CHECK-NEXT: orr x8, x11, x8848; CHECK-NEXT: orr x0, x9, x8849; CHECK-NEXT: ret850entry:851 %0 = lshr i64 %a, 8852 %1 = and i64 %0, 71776119061217280853 %2 = shl i64 %a, 8854 %3 = or i64 %1, %2855 %4 = and i64 %2, 1095216660480856 %5 = or i64 %3, %4857 %6 = and i64 %0, 16711680858 %7 = or i64 %5, %6859 ret i64 %7860}861 862define i32 @pr55484(i32 %0) {863; CHECK-SD-LABEL: pr55484:864; CHECK-SD: // %bb.0:865; CHECK-SD-NEXT: lsr w8, w0, #8866; CHECK-SD-NEXT: orr w8, w8, w0, lsl #8867; CHECK-SD-NEXT: sxth w0, w8868; CHECK-SD-NEXT: ret869;870; CHECK-GI-LABEL: pr55484:871; CHECK-GI: // %bb.0:872; CHECK-GI-NEXT: lsl w8, w0, #8873; CHECK-GI-NEXT: orr w8, w8, w0, lsr #8874; CHECK-GI-NEXT: sxth w0, w8875; CHECK-GI-NEXT: ret876 %2 = lshr i32 %0, 8877 %3 = shl i32 %0, 8878 %4 = or i32 %2, %3879 %5 = trunc i32 %4 to i16880 %6 = sext i16 %5 to i32881 ret i32 %6882}883