1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -verify-machineinstrs -mattr=+simd128 | FileCheck %s 3 4; Test loads and stores with custom alignment values. 5 6target triple = "wasm32-unknown-unknown" 7 8; ============================================================================== 9; 16 x i8 10; ============================================================================== 11 12define <16 x i8> @load_v16i8_a1(<16 x i8> *%p) { 13; CHECK-LABEL: load_v16i8_a1: 14; CHECK: .functype load_v16i8_a1 (i32) -> (v128) 15; CHECK-NEXT: # %bb.0: 16; CHECK-NEXT: local.get 0 17; CHECK-NEXT: v128.load 0:p2align=0 18; CHECK-NEXT: # fallthrough-return 19 %v = load <16 x i8>, <16 x i8>* %p, align 1 20 ret <16 x i8> %v 21} 22 23define <16 x i8> @load_v16i8_a4(<16 x i8> *%p) { 24; CHECK-LABEL: load_v16i8_a4: 25; CHECK: .functype load_v16i8_a4 (i32) -> (v128) 26; CHECK-NEXT: # %bb.0: 27; CHECK-NEXT: local.get 0 28; CHECK-NEXT: v128.load 0:p2align=2 29; CHECK-NEXT: # fallthrough-return 30 %v = load <16 x i8>, <16 x i8>* %p, align 4 31 ret <16 x i8> %v 32} 33 34; 16 is the default alignment for v128 so no attribute is needed. 35define <16 x i8> @load_v16i8_a16(<16 x i8> *%p) { 36; CHECK-LABEL: load_v16i8_a16: 37; CHECK: .functype load_v16i8_a16 (i32) -> (v128) 38; CHECK-NEXT: # %bb.0: 39; CHECK-NEXT: local.get 0 40; CHECK-NEXT: v128.load 0 41; CHECK-NEXT: # fallthrough-return 42 %v = load <16 x i8>, <16 x i8>* %p, align 16 43 ret <16 x i8> %v 44} 45 46; 32 is greater than the default alignment so it is ignored. 47define <16 x i8> @load_v16i8_a32(<16 x i8> *%p) { 48; CHECK-LABEL: load_v16i8_a32: 49; CHECK: .functype load_v16i8_a32 (i32) -> (v128) 50; CHECK-NEXT: # %bb.0: 51; CHECK-NEXT: local.get 0 52; CHECK-NEXT: v128.load 0 53; CHECK-NEXT: # fallthrough-return 54 %v = load <16 x i8>, <16 x i8>* %p, align 32 55 ret <16 x i8> %v 56} 57 58define void @store_v16i8_a1(<16 x i8> *%p, <16 x i8> %v) { 59; CHECK-LABEL: store_v16i8_a1: 60; CHECK: .functype store_v16i8_a1 (i32, v128) -> () 61; CHECK-NEXT: # %bb.0: 62; CHECK-NEXT: local.get 0 63; CHECK-NEXT: local.get 1 64; CHECK-NEXT: v128.store 0:p2align=0 65; CHECK-NEXT: # fallthrough-return 66 store <16 x i8> %v, <16 x i8>* %p, align 1 67 ret void 68} 69 70define void @store_v16i8_a4(<16 x i8> *%p, <16 x i8> %v) { 71; CHECK-LABEL: store_v16i8_a4: 72; CHECK: .functype store_v16i8_a4 (i32, v128) -> () 73; CHECK-NEXT: # %bb.0: 74; CHECK-NEXT: local.get 0 75; CHECK-NEXT: local.get 1 76; CHECK-NEXT: v128.store 0:p2align=2 77; CHECK-NEXT: # fallthrough-return 78 store <16 x i8> %v, <16 x i8>* %p, align 4 79 ret void 80} 81 82; 16 is the default alignment for v128 so no attribute is needed. 83define void @store_v16i8_a16(<16 x i8> *%p, <16 x i8> %v) { 84; CHECK-LABEL: store_v16i8_a16: 85; CHECK: .functype store_v16i8_a16 (i32, v128) -> () 86; CHECK-NEXT: # %bb.0: 87; CHECK-NEXT: local.get 0 88; CHECK-NEXT: local.get 1 89; CHECK-NEXT: v128.store 0 90; CHECK-NEXT: # fallthrough-return 91 store <16 x i8> %v, <16 x i8>* %p, align 16 92 ret void 93} 94 95; 32 is greater than the default alignment so it is ignored. 96define void @store_v16i8_a32(<16 x i8> *%p, <16 x i8> %v) { 97; CHECK-LABEL: store_v16i8_a32: 98; CHECK: .functype store_v16i8_a32 (i32, v128) -> () 99; CHECK-NEXT: # %bb.0: 100; CHECK-NEXT: local.get 0 101; CHECK-NEXT: local.get 1 102; CHECK-NEXT: v128.store 0 103; CHECK-NEXT: # fallthrough-return 104 store <16 x i8> %v, <16 x i8>* %p, align 32 105 ret void 106} 107 108; 1 is the default alignment for v128.load8_splat so no attribute is needed. 109define <16 x i8> @load_splat_v16i8_a1(i8* %p) { 110; CHECK-LABEL: load_splat_v16i8_a1: 111; CHECK: .functype load_splat_v16i8_a1 (i32) -> (v128) 112; CHECK-NEXT: # %bb.0: 113; CHECK-NEXT: local.get 0 114; CHECK-NEXT: v128.load8_splat 0 115; CHECK-NEXT: # fallthrough-return 116 %e = load i8, i8* %p, align 1 117 %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 118 %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer 119 ret <16 x i8> %v2 120} 121 122; 2 is greater than the default alignment so it is ignored. 123define <16 x i8> @load_splat_v16i8_a2(i8* %p) { 124; CHECK-LABEL: load_splat_v16i8_a2: 125; CHECK: .functype load_splat_v16i8_a2 (i32) -> (v128) 126; CHECK-NEXT: # %bb.0: 127; CHECK-NEXT: local.get 0 128; CHECK-NEXT: v128.load8_splat 0 129; CHECK-NEXT: # fallthrough-return 130 %e = load i8, i8* %p, align 2 131 %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 132 %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer 133 ret <16 x i8> %v2 134} 135 136; 1 is the default alignment for v128.load8_lane so no attribute is needed. 137define <16 x i8> @load_lane_i8_a1(i8* %p, <16 x i8> %v) { 138; CHECK-LABEL: load_lane_i8_a1: 139; CHECK: .functype load_lane_i8_a1 (i32, v128) -> (v128) 140; CHECK-NEXT: # %bb.0: 141; CHECK-NEXT: local.get 0 142; CHECK-NEXT: local.get 1 143; CHECK-NEXT: v128.load8_lane 0, 0 144; CHECK-NEXT: # fallthrough-return 145 %e = load i8, i8* %p, align 1 146 %v1 = insertelement <16 x i8> %v, i8 %e, i32 0 147 ret <16 x i8> %v1 148} 149 150; 2 is greater than the default alignment so it is ignored. 151define <16 x i8> @load_lane_i8_a2(i8* %p, <16 x i8> %v) { 152; CHECK-LABEL: load_lane_i8_a2: 153; CHECK: .functype load_lane_i8_a2 (i32, v128) -> (v128) 154; CHECK-NEXT: # %bb.0: 155; CHECK-NEXT: local.get 0 156; CHECK-NEXT: local.get 1 157; CHECK-NEXT: v128.load8_lane 0, 0 158; CHECK-NEXT: # fallthrough-return 159 %e = load i8, i8* %p, align 2 160 %v1 = insertelement <16 x i8> %v, i8 %e, i32 0 161 ret <16 x i8> %v1 162} 163 164; 1 is the default alignment for v128.store8_lane so no attribute is needed. 165define void @store_lane_i8_a1(<16 x i8> %v, i8* %p) { 166; CHECK-LABEL: store_lane_i8_a1: 167; CHECK: .functype store_lane_i8_a1 (v128, i32) -> () 168; CHECK-NEXT: # %bb.0: 169; CHECK-NEXT: local.get 1 170; CHECK-NEXT: local.get 0 171; CHECK-NEXT: v128.store8_lane 0, 0 172; CHECK-NEXT: # fallthrough-return 173 %x = extractelement <16 x i8> %v, i32 0 174 store i8 %x, i8* %p, align 1 175 ret void 176} 177 178; 2 is greater than the default alignment so it is ignored. 179define void @store_lane_i8_a2(<16 x i8> %v, i8* %p) { 180; CHECK-LABEL: store_lane_i8_a2: 181; CHECK: .functype store_lane_i8_a2 (v128, i32) -> () 182; CHECK-NEXT: # %bb.0: 183; CHECK-NEXT: local.get 1 184; CHECK-NEXT: local.get 0 185; CHECK-NEXT: v128.store8_lane 0, 0 186; CHECK-NEXT: # fallthrough-return 187 %x = extractelement <16 x i8> %v, i32 0 188 store i8 %x, i8* %p, align 2 189 ret void 190} 191 192; ============================================================================== 193; 8 x i16 194; ============================================================================== 195 196define <8 x i16> @load_v8i16_a1(<8 x i16> *%p) { 197; CHECK-LABEL: load_v8i16_a1: 198; CHECK: .functype load_v8i16_a1 (i32) -> (v128) 199; CHECK-NEXT: # %bb.0: 200; CHECK-NEXT: local.get 0 201; CHECK-NEXT: v128.load 0:p2align=0 202; CHECK-NEXT: # fallthrough-return 203 %v = load <8 x i16>, <8 x i16>* %p, align 1 204 ret <8 x i16> %v 205} 206 207define <8 x i16> @load_v8i16_a4(<8 x i16> *%p) { 208; CHECK-LABEL: load_v8i16_a4: 209; CHECK: .functype load_v8i16_a4 (i32) -> (v128) 210; CHECK-NEXT: # %bb.0: 211; CHECK-NEXT: local.get 0 212; CHECK-NEXT: v128.load 0:p2align=2 213; CHECK-NEXT: # fallthrough-return 214 %v = load <8 x i16>, <8 x i16>* %p, align 4 215 ret <8 x i16> %v 216} 217 218; 8 is the default alignment for v128 so no attribute is needed. 219define <8 x i16> @load_v8i16_a16(<8 x i16> *%p) { 220; CHECK-LABEL: load_v8i16_a16: 221; CHECK: .functype load_v8i16_a16 (i32) -> (v128) 222; CHECK-NEXT: # %bb.0: 223; CHECK-NEXT: local.get 0 224; CHECK-NEXT: v128.load 0 225; CHECK-NEXT: # fallthrough-return 226 %v = load <8 x i16>, <8 x i16>* %p, align 16 227 ret <8 x i16> %v 228} 229 230; 32 is greater than the default alignment so it is ignored. 231define <8 x i16> @load_v8i16_a32(<8 x i16> *%p) { 232; CHECK-LABEL: load_v8i16_a32: 233; CHECK: .functype load_v8i16_a32 (i32) -> (v128) 234; CHECK-NEXT: # %bb.0: 235; CHECK-NEXT: local.get 0 236; CHECK-NEXT: v128.load 0 237; CHECK-NEXT: # fallthrough-return 238 %v = load <8 x i16>, <8 x i16>* %p, align 32 239 ret <8 x i16> %v 240} 241 242define void @store_v8i16_a1(<8 x i16> *%p, <8 x i16> %v) { 243; CHECK-LABEL: store_v8i16_a1: 244; CHECK: .functype store_v8i16_a1 (i32, v128) -> () 245; CHECK-NEXT: # %bb.0: 246; CHECK-NEXT: local.get 0 247; CHECK-NEXT: local.get 1 248; CHECK-NEXT: v128.store 0:p2align=0 249; CHECK-NEXT: # fallthrough-return 250 store <8 x i16> %v, <8 x i16>* %p, align 1 251 ret void 252} 253 254define void @store_v8i16_a4(<8 x i16> *%p, <8 x i16> %v) { 255; CHECK-LABEL: store_v8i16_a4: 256; CHECK: .functype store_v8i16_a4 (i32, v128) -> () 257; CHECK-NEXT: # %bb.0: 258; CHECK-NEXT: local.get 0 259; CHECK-NEXT: local.get 1 260; CHECK-NEXT: v128.store 0:p2align=2 261; CHECK-NEXT: # fallthrough-return 262 store <8 x i16> %v, <8 x i16>* %p, align 4 263 ret void 264} 265 266; 16 is the default alignment for v128 so no attribute is needed. 267define void @store_v8i16_a16(<8 x i16> *%p, <8 x i16> %v) { 268; CHECK-LABEL: store_v8i16_a16: 269; CHECK: .functype store_v8i16_a16 (i32, v128) -> () 270; CHECK-NEXT: # %bb.0: 271; CHECK-NEXT: local.get 0 272; CHECK-NEXT: local.get 1 273; CHECK-NEXT: v128.store 0 274; CHECK-NEXT: # fallthrough-return 275 store <8 x i16> %v, <8 x i16>* %p, align 16 276 ret void 277} 278 279; 32 is greater than the default alignment so it is ignored. 280define void @store_v8i16_a32(<8 x i16> *%p, <8 x i16> %v) { 281; CHECK-LABEL: store_v8i16_a32: 282; CHECK: .functype store_v8i16_a32 (i32, v128) -> () 283; CHECK-NEXT: # %bb.0: 284; CHECK-NEXT: local.get 0 285; CHECK-NEXT: local.get 1 286; CHECK-NEXT: v128.store 0 287; CHECK-NEXT: # fallthrough-return 288 store <8 x i16> %v, <8 x i16>* %p, align 32 289 ret void 290} 291 292define <8 x i8> @load_ext_v8i16_a1(<8 x i8>* %p) { 293; CHECK-LABEL: load_ext_v8i16_a1: 294; CHECK: .functype load_ext_v8i16_a1 (i32) -> (v128) 295; CHECK-NEXT: # %bb.0: 296; CHECK-NEXT: local.get 0 297; CHECK-NEXT: i16x8.load8x8_u 0:p2align=0 298; CHECK-NEXT: # fallthrough-return 299 %v = load <8 x i8>, <8 x i8>* %p, align 1 300 ret <8 x i8> %v 301} 302 303define <8 x i8> @load_ext_v8i16_a2(<8 x i8>* %p) { 304; CHECK-LABEL: load_ext_v8i16_a2: 305; CHECK: .functype load_ext_v8i16_a2 (i32) -> (v128) 306; CHECK-NEXT: # %bb.0: 307; CHECK-NEXT: local.get 0 308; CHECK-NEXT: i16x8.load8x8_u 0:p2align=1 309; CHECK-NEXT: # fallthrough-return 310 %v = load <8 x i8>, <8 x i8>* %p, align 2 311 ret <8 x i8> %v 312} 313 314define <8 x i8> @load_ext_v8i16_a4(<8 x i8>* %p) { 315; CHECK-LABEL: load_ext_v8i16_a4: 316; CHECK: .functype load_ext_v8i16_a4 (i32) -> (v128) 317; CHECK-NEXT: # %bb.0: 318; CHECK-NEXT: local.get 0 319; CHECK-NEXT: i16x8.load8x8_u 0:p2align=2 320; CHECK-NEXT: # fallthrough-return 321 %v = load <8 x i8>, <8 x i8>* %p, align 4 322 ret <8 x i8> %v 323} 324 325; 8 is the default alignment for v128 extending load so no attribute is needed. 326define <8 x i8> @load_ext_v8i16_a8(<8 x i8>* %p) { 327; CHECK-LABEL: load_ext_v8i16_a8: 328; CHECK: .functype load_ext_v8i16_a8 (i32) -> (v128) 329; CHECK-NEXT: # %bb.0: 330; CHECK-NEXT: local.get 0 331; CHECK-NEXT: i16x8.load8x8_u 0 332; CHECK-NEXT: # fallthrough-return 333 %v = load <8 x i8>, <8 x i8>* %p, align 8 334 ret <8 x i8> %v 335} 336 337; 16 is greater than the default alignment so it is ignored. 338define <8 x i8> @load_ext_v8i16_a16(<8 x i8>* %p) { 339; CHECK-LABEL: load_ext_v8i16_a16: 340; CHECK: .functype load_ext_v8i16_a16 (i32) -> (v128) 341; CHECK-NEXT: # %bb.0: 342; CHECK-NEXT: local.get 0 343; CHECK-NEXT: i16x8.load8x8_u 0 344; CHECK-NEXT: # fallthrough-return 345 %v = load <8 x i8>, <8 x i8>* %p, align 16 346 ret <8 x i8> %v 347} 348 349define <8 x i16> @load_sext_v8i16_a1(<8 x i8>* %p) { 350; CHECK-LABEL: load_sext_v8i16_a1: 351; CHECK: .functype load_sext_v8i16_a1 (i32) -> (v128) 352; CHECK-NEXT: # %bb.0: 353; CHECK-NEXT: local.get 0 354; CHECK-NEXT: i16x8.load8x8_s 0:p2align=0 355; CHECK-NEXT: # fallthrough-return 356 %v = load <8 x i8>, <8 x i8>* %p, align 1 357 %v2 = sext <8 x i8> %v to <8 x i16> 358 ret <8 x i16> %v2 359} 360 361define <8 x i16> @load_sext_v8i16_a2(<8 x i8>* %p) { 362; CHECK-LABEL: load_sext_v8i16_a2: 363; CHECK: .functype load_sext_v8i16_a2 (i32) -> (v128) 364; CHECK-NEXT: # %bb.0: 365; CHECK-NEXT: local.get 0 366; CHECK-NEXT: i16x8.load8x8_s 0:p2align=1 367; CHECK-NEXT: # fallthrough-return 368 %v = load <8 x i8>, <8 x i8>* %p, align 2 369 %v2 = sext <8 x i8> %v to <8 x i16> 370 ret <8 x i16> %v2 371} 372 373define <8 x i16> @load_sext_v8i16_a4(<8 x i8>* %p) { 374; CHECK-LABEL: load_sext_v8i16_a4: 375; CHECK: .functype load_sext_v8i16_a4 (i32) -> (v128) 376; CHECK-NEXT: # %bb.0: 377; CHECK-NEXT: local.get 0 378; CHECK-NEXT: i16x8.load8x8_s 0:p2align=2 379; CHECK-NEXT: # fallthrough-return 380 %v = load <8 x i8>, <8 x i8>* %p, align 4 381 %v2 = sext <8 x i8> %v to <8 x i16> 382 ret <8 x i16> %v2 383} 384 385; 8 is the default alignment for v128 extending load so no attribute is needed. 386define <8 x i16> @load_sext_v8i16_a8(<8 x i8>* %p) { 387; CHECK-LABEL: load_sext_v8i16_a8: 388; CHECK: .functype load_sext_v8i16_a8 (i32) -> (v128) 389; CHECK-NEXT: # %bb.0: 390; CHECK-NEXT: local.get 0 391; CHECK-NEXT: i16x8.load8x8_s 0 392; CHECK-NEXT: # fallthrough-return 393 %v = load <8 x i8>, <8 x i8>* %p, align 8 394 %v2 = sext <8 x i8> %v to <8 x i16> 395 ret <8 x i16> %v2 396} 397 398; 16 is greater than the default alignment so it is ignored. 399define <8 x i16> @load_sext_v8i16_a16(<8 x i8>* %p) { 400; CHECK-LABEL: load_sext_v8i16_a16: 401; CHECK: .functype load_sext_v8i16_a16 (i32) -> (v128) 402; CHECK-NEXT: # %bb.0: 403; CHECK-NEXT: local.get 0 404; CHECK-NEXT: i16x8.load8x8_s 0 405; CHECK-NEXT: # fallthrough-return 406 %v = load <8 x i8>, <8 x i8>* %p, align 16 407 %v2 = sext <8 x i8> %v to <8 x i16> 408 ret <8 x i16> %v2 409} 410 411define <8 x i16> @load_splat_v8i16_a1(i16* %p) { 412; CHECK-LABEL: load_splat_v8i16_a1: 413; CHECK: .functype load_splat_v8i16_a1 (i32) -> (v128) 414; CHECK-NEXT: # %bb.0: 415; CHECK-NEXT: local.get 0 416; CHECK-NEXT: v128.load16_splat 0:p2align=0 417; CHECK-NEXT: # fallthrough-return 418 %e = load i16, i16* %p, align 1 419 %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 420 %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer 421 ret <8 x i16> %v2 422} 423 424; 2 is the default alignment for v128.load16_splat so no attribute is needed. 425define <8 x i16> @load_splat_v8i16_a2(i16* %p) { 426; CHECK-LABEL: load_splat_v8i16_a2: 427; CHECK: .functype load_splat_v8i16_a2 (i32) -> (v128) 428; CHECK-NEXT: # %bb.0: 429; CHECK-NEXT: local.get 0 430; CHECK-NEXT: v128.load16_splat 0 431; CHECK-NEXT: # fallthrough-return 432 %e = load i16, i16* %p, align 2 433 %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 434 %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer 435 ret <8 x i16> %v2 436} 437 438; 4 is greater than the default alignment so it is ignored. 439define <8 x i16> @load_splat_v8i16_a4(i16* %p) { 440; CHECK-LABEL: load_splat_v8i16_a4: 441; CHECK: .functype load_splat_v8i16_a4 (i32) -> (v128) 442; CHECK-NEXT: # %bb.0: 443; CHECK-NEXT: local.get 0 444; CHECK-NEXT: v128.load16_splat 0 445; CHECK-NEXT: # fallthrough-return 446 %e = load i16, i16* %p, align 4 447 %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 448 %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer 449 ret <8 x i16> %v2 450} 451 452define <8 x i16> @load_lane_i16_a1(i16* %p, <8 x i16> %v) { 453; CHECK-LABEL: load_lane_i16_a1: 454; CHECK: .functype load_lane_i16_a1 (i32, v128) -> (v128) 455; CHECK-NEXT: # %bb.0: 456; CHECK-NEXT: local.get 0 457; CHECK-NEXT: local.get 1 458; CHECK-NEXT: v128.load16_lane 0:p2align=0, 0 459; CHECK-NEXT: # fallthrough-return 460 %e = load i16, i16* %p, align 1 461 %v1 = insertelement <8 x i16> %v, i16 %e, i32 0 462 ret <8 x i16> %v1 463} 464 465; 2 is the default alignment for v128.load16_lane so no attribute is needed. 466define <8 x i16> @load_lane_i16_a2(i16* %p, <8 x i16> %v) { 467; CHECK-LABEL: load_lane_i16_a2: 468; CHECK: .functype load_lane_i16_a2 (i32, v128) -> (v128) 469; CHECK-NEXT: # %bb.0: 470; CHECK-NEXT: local.get 0 471; CHECK-NEXT: local.get 1 472; CHECK-NEXT: v128.load16_lane 0, 0 473; CHECK-NEXT: # fallthrough-return 474 %e = load i16, i16* %p, align 2 475 %v1 = insertelement <8 x i16> %v, i16 %e, i32 0 476 ret <8 x i16> %v1 477} 478 479; 4 is greater than the default alignment so it is ignored. 480define <8 x i16> @load_lane_i16_a4(i16* %p, <8 x i16> %v) { 481; CHECK-LABEL: load_lane_i16_a4: 482; CHECK: .functype load_lane_i16_a4 (i32, v128) -> (v128) 483; CHECK-NEXT: # %bb.0: 484; CHECK-NEXT: local.get 0 485; CHECK-NEXT: local.get 1 486; CHECK-NEXT: v128.load16_lane 0, 0 487; CHECK-NEXT: # fallthrough-return 488 %e = load i16, i16* %p, align 4 489 %v1 = insertelement <8 x i16> %v, i16 %e, i32 0 490 ret <8 x i16> %v1 491} 492 493define void @store_lane_i16_a1(<8 x i16> %v, i16* %p) { 494; CHECK-LABEL: store_lane_i16_a1: 495; CHECK: .functype store_lane_i16_a1 (v128, i32) -> () 496; CHECK-NEXT: # %bb.0: 497; CHECK-NEXT: local.get 1 498; CHECK-NEXT: local.get 0 499; CHECK-NEXT: v128.store16_lane 0:p2align=0, 0 500; CHECK-NEXT: # fallthrough-return 501 %x = extractelement <8 x i16> %v, i32 0 502 store i16 %x, i16* %p, align 1 503 ret void 504} 505 506; 2 is the default alignment for v128.store16_lane so no attribute is needed. 507define void @store_lane_i16_a2(<8 x i16> %v, i16* %p) { 508; CHECK-LABEL: store_lane_i16_a2: 509; CHECK: .functype store_lane_i16_a2 (v128, i32) -> () 510; CHECK-NEXT: # %bb.0: 511; CHECK-NEXT: local.get 1 512; CHECK-NEXT: local.get 0 513; CHECK-NEXT: v128.store16_lane 0, 0 514; CHECK-NEXT: # fallthrough-return 515 %x = extractelement <8 x i16> %v, i32 0 516 store i16 %x, i16* %p, align 2 517 ret void 518} 519 520; 4 is greater than the default alignment so it is ignored. 521define void @store_lane_i16_a4(<8 x i16> %v, i16* %p) { 522; CHECK-LABEL: store_lane_i16_a4: 523; CHECK: .functype store_lane_i16_a4 (v128, i32) -> () 524; CHECK-NEXT: # %bb.0: 525; CHECK-NEXT: local.get 1 526; CHECK-NEXT: local.get 0 527; CHECK-NEXT: v128.store16_lane 0, 0 528; CHECK-NEXT: # fallthrough-return 529 %x = extractelement <8 x i16> %v, i32 0 530 store i16 %x, i16* %p, align 4 531 ret void 532} 533 534; ============================================================================== 535; 4 x i32 536; ============================================================================== 537 538define <4 x i32> @load_v4i32_a1(<4 x i32> *%p) { 539; CHECK-LABEL: load_v4i32_a1: 540; CHECK: .functype load_v4i32_a1 (i32) -> (v128) 541; CHECK-NEXT: # %bb.0: 542; CHECK-NEXT: local.get 0 543; CHECK-NEXT: v128.load 0:p2align=0 544; CHECK-NEXT: # fallthrough-return 545 %v = load <4 x i32>, <4 x i32>* %p, align 1 546 ret <4 x i32> %v 547} 548 549define <4 x i32> @load_v4i32_a4(<4 x i32> *%p) { 550; CHECK-LABEL: load_v4i32_a4: 551; CHECK: .functype load_v4i32_a4 (i32) -> (v128) 552; CHECK-NEXT: # %bb.0: 553; CHECK-NEXT: local.get 0 554; CHECK-NEXT: v128.load 0:p2align=2 555; CHECK-NEXT: # fallthrough-return 556 %v = load <4 x i32>, <4 x i32>* %p, align 4 557 ret <4 x i32> %v 558} 559 560; 4 is the default alignment for v128 so no attribute is needed. 561define <4 x i32> @load_v4i32_a16(<4 x i32> *%p) { 562; CHECK-LABEL: load_v4i32_a16: 563; CHECK: .functype load_v4i32_a16 (i32) -> (v128) 564; CHECK-NEXT: # %bb.0: 565; CHECK-NEXT: local.get 0 566; CHECK-NEXT: v128.load 0 567; CHECK-NEXT: # fallthrough-return 568 %v = load <4 x i32>, <4 x i32>* %p, align 16 569 ret <4 x i32> %v 570} 571 572; 32 is greater than the default alignment so it is ignored. 573define <4 x i32> @load_v4i32_a32(<4 x i32> *%p) { 574; CHECK-LABEL: load_v4i32_a32: 575; CHECK: .functype load_v4i32_a32 (i32) -> (v128) 576; CHECK-NEXT: # %bb.0: 577; CHECK-NEXT: local.get 0 578; CHECK-NEXT: v128.load 0 579; CHECK-NEXT: # fallthrough-return 580 %v = load <4 x i32>, <4 x i32>* %p, align 32 581 ret <4 x i32> %v 582} 583 584define void @store_v4i32_a1(<4 x i32> *%p, <4 x i32> %v) { 585; CHECK-LABEL: store_v4i32_a1: 586; CHECK: .functype store_v4i32_a1 (i32, v128) -> () 587; CHECK-NEXT: # %bb.0: 588; CHECK-NEXT: local.get 0 589; CHECK-NEXT: local.get 1 590; CHECK-NEXT: v128.store 0:p2align=0 591; CHECK-NEXT: # fallthrough-return 592 store <4 x i32> %v, <4 x i32>* %p, align 1 593 ret void 594} 595 596define void @store_v4i32_a4(<4 x i32> *%p, <4 x i32> %v) { 597; CHECK-LABEL: store_v4i32_a4: 598; CHECK: .functype store_v4i32_a4 (i32, v128) -> () 599; CHECK-NEXT: # %bb.0: 600; CHECK-NEXT: local.get 0 601; CHECK-NEXT: local.get 1 602; CHECK-NEXT: v128.store 0:p2align=2 603; CHECK-NEXT: # fallthrough-return 604 store <4 x i32> %v, <4 x i32>* %p, align 4 605 ret void 606} 607 608; 16 is the default alignment for v128 so no attribute is needed. 609define void @store_v4i32_a16(<4 x i32> *%p, <4 x i32> %v) { 610; CHECK-LABEL: store_v4i32_a16: 611; CHECK: .functype store_v4i32_a16 (i32, v128) -> () 612; CHECK-NEXT: # %bb.0: 613; CHECK-NEXT: local.get 0 614; CHECK-NEXT: local.get 1 615; CHECK-NEXT: v128.store 0 616; CHECK-NEXT: # fallthrough-return 617 store <4 x i32> %v, <4 x i32>* %p, align 16 618 ret void 619} 620 621; 32 is greater than the default alignment so it is ignored. 622define void @store_v4i32_a32(<4 x i32> *%p, <4 x i32> %v) { 623; CHECK-LABEL: store_v4i32_a32: 624; CHECK: .functype store_v4i32_a32 (i32, v128) -> () 625; CHECK-NEXT: # %bb.0: 626; CHECK-NEXT: local.get 0 627; CHECK-NEXT: local.get 1 628; CHECK-NEXT: v128.store 0 629; CHECK-NEXT: # fallthrough-return 630 store <4 x i32> %v, <4 x i32>* %p, align 32 631 ret void 632} 633 634define <4 x i16> @load_ext_v4i32_a1(<4 x i16>* %p) { 635; CHECK-LABEL: load_ext_v4i32_a1: 636; CHECK: .functype load_ext_v4i32_a1 (i32) -> (v128) 637; CHECK-NEXT: # %bb.0: 638; CHECK-NEXT: local.get 0 639; CHECK-NEXT: i32x4.load16x4_u 0:p2align=0 640; CHECK-NEXT: # fallthrough-return 641 %v = load <4 x i16>, <4 x i16>* %p, align 1 642 ret <4 x i16> %v 643} 644 645define <4 x i16> @load_ext_v4i32_a2(<4 x i16>* %p) { 646; CHECK-LABEL: load_ext_v4i32_a2: 647; CHECK: .functype load_ext_v4i32_a2 (i32) -> (v128) 648; CHECK-NEXT: # %bb.0: 649; CHECK-NEXT: local.get 0 650; CHECK-NEXT: i32x4.load16x4_u 0:p2align=1 651; CHECK-NEXT: # fallthrough-return 652 %v = load <4 x i16>, <4 x i16>* %p, align 2 653 ret <4 x i16> %v 654} 655 656define <4 x i16> @load_ext_v4i32_a4(<4 x i16>* %p) { 657; CHECK-LABEL: load_ext_v4i32_a4: 658; CHECK: .functype load_ext_v4i32_a4 (i32) -> (v128) 659; CHECK-NEXT: # %bb.0: 660; CHECK-NEXT: local.get 0 661; CHECK-NEXT: i32x4.load16x4_u 0:p2align=2 662; CHECK-NEXT: # fallthrough-return 663 %v = load <4 x i16>, <4 x i16>* %p, align 4 664 ret <4 x i16> %v 665} 666 667; 8 is the default alignment for v128 extending load so no attribute is needed. 668define <4 x i16> @load_ext_v4i32_a8(<4 x i16>* %p) { 669; CHECK-LABEL: load_ext_v4i32_a8: 670; CHECK: .functype load_ext_v4i32_a8 (i32) -> (v128) 671; CHECK-NEXT: # %bb.0: 672; CHECK-NEXT: local.get 0 673; CHECK-NEXT: i32x4.load16x4_u 0 674; CHECK-NEXT: # fallthrough-return 675 %v = load <4 x i16>, <4 x i16>* %p, align 8 676 ret <4 x i16> %v 677} 678 679; 16 is greater than the default alignment so it is ignored. 680define <4 x i16> @load_ext_v4i32_a16(<4 x i16>* %p) { 681; CHECK-LABEL: load_ext_v4i32_a16: 682; CHECK: .functype load_ext_v4i32_a16 (i32) -> (v128) 683; CHECK-NEXT: # %bb.0: 684; CHECK-NEXT: local.get 0 685; CHECK-NEXT: i32x4.load16x4_u 0 686; CHECK-NEXT: # fallthrough-return 687 %v = load <4 x i16>, <4 x i16>* %p, align 16 688 ret <4 x i16> %v 689} 690 691define <4 x i32> @load_sext_v4i32_a1(<4 x i16>* %p) { 692; CHECK-LABEL: load_sext_v4i32_a1: 693; CHECK: .functype load_sext_v4i32_a1 (i32) -> (v128) 694; CHECK-NEXT: # %bb.0: 695; CHECK-NEXT: local.get 0 696; CHECK-NEXT: i32x4.load16x4_s 0:p2align=0 697; CHECK-NEXT: # fallthrough-return 698 %v = load <4 x i16>, <4 x i16>* %p, align 1 699 %v2 = sext <4 x i16> %v to <4 x i32> 700 ret <4 x i32> %v2 701} 702 703define <4 x i32> @load_sext_v4i32_a2(<4 x i16>* %p) { 704; CHECK-LABEL: load_sext_v4i32_a2: 705; CHECK: .functype load_sext_v4i32_a2 (i32) -> (v128) 706; CHECK-NEXT: # %bb.0: 707; CHECK-NEXT: local.get 0 708; CHECK-NEXT: i32x4.load16x4_s 0:p2align=1 709; CHECK-NEXT: # fallthrough-return 710 %v = load <4 x i16>, <4 x i16>* %p, align 2 711 %v2 = sext <4 x i16> %v to <4 x i32> 712 ret <4 x i32> %v2 713} 714 715define <4 x i32> @load_sext_v4i32_a4(<4 x i16>* %p) { 716; CHECK-LABEL: load_sext_v4i32_a4: 717; CHECK: .functype load_sext_v4i32_a4 (i32) -> (v128) 718; CHECK-NEXT: # %bb.0: 719; CHECK-NEXT: local.get 0 720; CHECK-NEXT: i32x4.load16x4_s 0:p2align=2 721; CHECK-NEXT: # fallthrough-return 722 %v = load <4 x i16>, <4 x i16>* %p, align 4 723 %v2 = sext <4 x i16> %v to <4 x i32> 724 ret <4 x i32> %v2 725} 726 727; 8 is the default alignment for v128 extending load so no attribute is needed. 728define <4 x i32> @load_sext_v4i32_a8(<4 x i16>* %p) { 729; CHECK-LABEL: load_sext_v4i32_a8: 730; CHECK: .functype load_sext_v4i32_a8 (i32) -> (v128) 731; CHECK-NEXT: # %bb.0: 732; CHECK-NEXT: local.get 0 733; CHECK-NEXT: i32x4.load16x4_s 0 734; CHECK-NEXT: # fallthrough-return 735 %v = load <4 x i16>, <4 x i16>* %p, align 8 736 %v2 = sext <4 x i16> %v to <4 x i32> 737 ret <4 x i32> %v2 738} 739 740; 16 is greater than the default alignment so it is ignored. 741define <4 x i32> @load_sext_v4i32_a16(<4 x i16>* %p) { 742; CHECK-LABEL: load_sext_v4i32_a16: 743; CHECK: .functype load_sext_v4i32_a16 (i32) -> (v128) 744; CHECK-NEXT: # %bb.0: 745; CHECK-NEXT: local.get 0 746; CHECK-NEXT: i32x4.load16x4_s 0 747; CHECK-NEXT: # fallthrough-return 748 %v = load <4 x i16>, <4 x i16>* %p, align 16 749 %v2 = sext <4 x i16> %v to <4 x i32> 750 ret <4 x i32> %v2 751} 752 753define <4 x i32> @load_splat_v4i32_a1(i32* %addr) { 754; CHECK-LABEL: load_splat_v4i32_a1: 755; CHECK: .functype load_splat_v4i32_a1 (i32) -> (v128) 756; CHECK-NEXT: # %bb.0: 757; CHECK-NEXT: local.get 0 758; CHECK-NEXT: v128.load32_splat 0:p2align=0 759; CHECK-NEXT: # fallthrough-return 760 %e = load i32, i32* %addr, align 1 761 %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 762 %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer 763 ret <4 x i32> %v2 764} 765 766define <4 x i32> @load_splat_v4i32_a2(i32* %addr) { 767; CHECK-LABEL: load_splat_v4i32_a2: 768; CHECK: .functype load_splat_v4i32_a2 (i32) -> (v128) 769; CHECK-NEXT: # %bb.0: 770; CHECK-NEXT: local.get 0 771; CHECK-NEXT: v128.load32_splat 0:p2align=1 772; CHECK-NEXT: # fallthrough-return 773 %e = load i32, i32* %addr, align 2 774 %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 775 %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer 776 ret <4 x i32> %v2 777} 778 779; 4 is the default alignment for v128.load32_splat so no attribute is needed. 780define <4 x i32> @load_splat_v4i32_a4(i32* %addr) { 781; CHECK-LABEL: load_splat_v4i32_a4: 782; CHECK: .functype load_splat_v4i32_a4 (i32) -> (v128) 783; CHECK-NEXT: # %bb.0: 784; CHECK-NEXT: local.get 0 785; CHECK-NEXT: v128.load32_splat 0 786; CHECK-NEXT: # fallthrough-return 787 %e = load i32, i32* %addr, align 4 788 %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 789 %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer 790 ret <4 x i32> %v2 791} 792 793; 8 is greater than the default alignment so it is ignored. 794define <4 x i32> @load_splat_v4i32_a8(i32* %addr) { 795; CHECK-LABEL: load_splat_v4i32_a8: 796; CHECK: .functype load_splat_v4i32_a8 (i32) -> (v128) 797; CHECK-NEXT: # %bb.0: 798; CHECK-NEXT: local.get 0 799; CHECK-NEXT: v128.load32_splat 0 800; CHECK-NEXT: # fallthrough-return 801 %e = load i32, i32* %addr, align 8 802 %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 803 %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer 804 ret <4 x i32> %v2 805} 806 807define <4 x i32> @load_lane_i32_a1(i32* %p, <4 x i32> %v) { 808; CHECK-LABEL: load_lane_i32_a1: 809; CHECK: .functype load_lane_i32_a1 (i32, v128) -> (v128) 810; CHECK-NEXT: # %bb.0: 811; CHECK-NEXT: local.get 0 812; CHECK-NEXT: local.get 1 813; CHECK-NEXT: v128.load32_lane 0:p2align=0, 0 814; CHECK-NEXT: # fallthrough-return 815 %e = load i32, i32* %p, align 1 816 %v1 = insertelement <4 x i32> %v, i32 %e, i32 0 817 ret <4 x i32> %v1 818} 819 820define <4 x i32> @load_lane_i32_a2(i32* %p, <4 x i32> %v) { 821; CHECK-LABEL: load_lane_i32_a2: 822; CHECK: .functype load_lane_i32_a2 (i32, v128) -> (v128) 823; CHECK-NEXT: # %bb.0: 824; CHECK-NEXT: local.get 0 825; CHECK-NEXT: local.get 1 826; CHECK-NEXT: v128.load32_lane 0:p2align=1, 0 827; CHECK-NEXT: # fallthrough-return 828 %e = load i32, i32* %p, align 2 829 %v1 = insertelement <4 x i32> %v, i32 %e, i32 0 830 ret <4 x i32> %v1 831} 832 833; 4 is the default alignment for v128.load32_lane so no attribute is needed. 834define <4 x i32> @load_lane_i32_a4(i32* %p, <4 x i32> %v) { 835; CHECK-LABEL: load_lane_i32_a4: 836; CHECK: .functype load_lane_i32_a4 (i32, v128) -> (v128) 837; CHECK-NEXT: # %bb.0: 838; CHECK-NEXT: local.get 0 839; CHECK-NEXT: local.get 1 840; CHECK-NEXT: v128.load32_lane 0, 0 841; CHECK-NEXT: # fallthrough-return 842 %e = load i32, i32* %p, align 4 843 %v1 = insertelement <4 x i32> %v, i32 %e, i32 0 844 ret <4 x i32> %v1 845} 846 847; 8 is greater than the default alignment so it is ignored. 848define <4 x i32> @load_lane_i32_a8(i32* %p, <4 x i32> %v) { 849; CHECK-LABEL: load_lane_i32_a8: 850; CHECK: .functype load_lane_i32_a8 (i32, v128) -> (v128) 851; CHECK-NEXT: # %bb.0: 852; CHECK-NEXT: local.get 0 853; CHECK-NEXT: local.get 1 854; CHECK-NEXT: v128.load32_lane 0, 0 855; CHECK-NEXT: # fallthrough-return 856 %e = load i32, i32* %p, align 8 857 %v1 = insertelement <4 x i32> %v, i32 %e, i32 0 858 ret <4 x i32> %v1 859} 860 861define void @store_lane_i32_a1(<4 x i32> %v, i32* %p) { 862; CHECK-LABEL: store_lane_i32_a1: 863; CHECK: .functype store_lane_i32_a1 (v128, i32) -> () 864; CHECK-NEXT: # %bb.0: 865; CHECK-NEXT: local.get 1 866; CHECK-NEXT: local.get 0 867; CHECK-NEXT: v128.store32_lane 0:p2align=0, 0 868; CHECK-NEXT: # fallthrough-return 869 %x = extractelement <4 x i32> %v, i32 0 870 store i32 %x, i32* %p, align 1 871 ret void 872} 873 874define void @store_lane_i32_a2(<4 x i32> %v, i32* %p) { 875; CHECK-LABEL: store_lane_i32_a2: 876; CHECK: .functype store_lane_i32_a2 (v128, i32) -> () 877; CHECK-NEXT: # %bb.0: 878; CHECK-NEXT: local.get 1 879; CHECK-NEXT: local.get 0 880; CHECK-NEXT: v128.store32_lane 0:p2align=1, 0 881; CHECK-NEXT: # fallthrough-return 882 %x = extractelement <4 x i32> %v, i32 0 883 store i32 %x, i32* %p, align 2 884 ret void 885} 886 887; 4 is the default alignment for v128.store32_lane so no attribute is needed. 888define void @store_lane_i32_a4(<4 x i32> %v, i32* %p) { 889; CHECK-LABEL: store_lane_i32_a4: 890; CHECK: .functype store_lane_i32_a4 (v128, i32) -> () 891; CHECK-NEXT: # %bb.0: 892; CHECK-NEXT: local.get 1 893; CHECK-NEXT: local.get 0 894; CHECK-NEXT: v128.store32_lane 0, 0 895; CHECK-NEXT: # fallthrough-return 896 %x = extractelement <4 x i32> %v, i32 0 897 store i32 %x, i32* %p, align 4 898 ret void 899} 900 901; 8 is greater than the default alignment so it is ignored. 902define void @store_lane_i32_a8(<4 x i32> %v, i32* %p) { 903; CHECK-LABEL: store_lane_i32_a8: 904; CHECK: .functype store_lane_i32_a8 (v128, i32) -> () 905; CHECK-NEXT: # %bb.0: 906; CHECK-NEXT: local.get 1 907; CHECK-NEXT: local.get 0 908; CHECK-NEXT: v128.store32_lane 0, 0 909; CHECK-NEXT: # fallthrough-return 910 %x = extractelement <4 x i32> %v, i32 0 911 store i32 %x, i32* %p, align 8 912 ret void 913} 914 915; ============================================================================== 916; 2 x i64 917; ============================================================================== 918 919define <2 x i64> @load_v2i64_a1(<2 x i64> *%p) { 920; CHECK-LABEL: load_v2i64_a1: 921; CHECK: .functype load_v2i64_a1 (i32) -> (v128) 922; CHECK-NEXT: # %bb.0: 923; CHECK-NEXT: local.get 0 924; CHECK-NEXT: v128.load 0:p2align=0 925; CHECK-NEXT: # fallthrough-return 926 %v = load <2 x i64>, <2 x i64>* %p, align 1 927 ret <2 x i64> %v 928} 929 930define <2 x i64> @load_v2i64_a4(<2 x i64> *%p) { 931; CHECK-LABEL: load_v2i64_a4: 932; CHECK: .functype load_v2i64_a4 (i32) -> (v128) 933; CHECK-NEXT: # %bb.0: 934; CHECK-NEXT: local.get 0 935; CHECK-NEXT: v128.load 0:p2align=2 936; CHECK-NEXT: # fallthrough-return 937 %v = load <2 x i64>, <2 x i64>* %p, align 4 938 ret <2 x i64> %v 939} 940 941; 2 is the default alignment for v128 so no attribute is needed. 942define <2 x i64> @load_v2i64_a16(<2 x i64> *%p) { 943; CHECK-LABEL: load_v2i64_a16: 944; CHECK: .functype load_v2i64_a16 (i32) -> (v128) 945; CHECK-NEXT: # %bb.0: 946; CHECK-NEXT: local.get 0 947; CHECK-NEXT: v128.load 0 948; CHECK-NEXT: # fallthrough-return 949 %v = load <2 x i64>, <2 x i64>* %p, align 16 950 ret <2 x i64> %v 951} 952 953; 32 is greater than the default alignment so it is ignored. 954define <2 x i64> @load_v2i64_a32(<2 x i64> *%p) { 955; CHECK-LABEL: load_v2i64_a32: 956; CHECK: .functype load_v2i64_a32 (i32) -> (v128) 957; CHECK-NEXT: # %bb.0: 958; CHECK-NEXT: local.get 0 959; CHECK-NEXT: v128.load 0 960; CHECK-NEXT: # fallthrough-return 961 %v = load <2 x i64>, <2 x i64>* %p, align 32 962 ret <2 x i64> %v 963} 964 965define void @store_v2i64_a1(<2 x i64> *%p, <2 x i64> %v) { 966; CHECK-LABEL: store_v2i64_a1: 967; CHECK: .functype store_v2i64_a1 (i32, v128) -> () 968; CHECK-NEXT: # %bb.0: 969; CHECK-NEXT: local.get 0 970; CHECK-NEXT: local.get 1 971; CHECK-NEXT: v128.store 0:p2align=0 972; CHECK-NEXT: # fallthrough-return 973 store <2 x i64> %v, <2 x i64>* %p, align 1 974 ret void 975} 976 977define void @store_v2i64_a4(<2 x i64> *%p, <2 x i64> %v) { 978; CHECK-LABEL: store_v2i64_a4: 979; CHECK: .functype store_v2i64_a4 (i32, v128) -> () 980; CHECK-NEXT: # %bb.0: 981; CHECK-NEXT: local.get 0 982; CHECK-NEXT: local.get 1 983; CHECK-NEXT: v128.store 0:p2align=2 984; CHECK-NEXT: # fallthrough-return 985 store <2 x i64> %v, <2 x i64>* %p, align 4 986 ret void 987} 988 989; 16 is the default alignment for v128 so no attribute is needed. 990define void @store_v2i64_a16(<2 x i64> *%p, <2 x i64> %v) { 991; CHECK-LABEL: store_v2i64_a16: 992; CHECK: .functype store_v2i64_a16 (i32, v128) -> () 993; CHECK-NEXT: # %bb.0: 994; CHECK-NEXT: local.get 0 995; CHECK-NEXT: local.get 1 996; CHECK-NEXT: v128.store 0 997; CHECK-NEXT: # fallthrough-return 998 store <2 x i64> %v, <2 x i64>* %p, align 16 999 ret void 1000} 1001 1002; 32 is greater than the default alignment so it is ignored. 1003define void @store_v2i64_a32(<2 x i64> *%p, <2 x i64> %v) { 1004; CHECK-LABEL: store_v2i64_a32: 1005; CHECK: .functype store_v2i64_a32 (i32, v128) -> () 1006; CHECK-NEXT: # %bb.0: 1007; CHECK-NEXT: local.get 0 1008; CHECK-NEXT: local.get 1 1009; CHECK-NEXT: v128.store 0 1010; CHECK-NEXT: # fallthrough-return 1011 store <2 x i64> %v, <2 x i64>* %p, align 32 1012 ret void 1013} 1014 1015define <2 x i64> @load_splat_v2i64_a1(i64* %p) { 1016; CHECK-LABEL: load_splat_v2i64_a1: 1017; CHECK: .functype load_splat_v2i64_a1 (i32) -> (v128) 1018; CHECK-NEXT: # %bb.0: 1019; CHECK-NEXT: local.get 0 1020; CHECK-NEXT: v128.load64_splat 0:p2align=0 1021; CHECK-NEXT: # fallthrough-return 1022 %e = load i64, i64* %p, align 1 1023 %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 1024 %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer 1025 ret <2 x i64> %v2 1026} 1027 1028define <2 x i64> @load_splat_v2i64_a2(i64* %p) { 1029; CHECK-LABEL: load_splat_v2i64_a2: 1030; CHECK: .functype load_splat_v2i64_a2 (i32) -> (v128) 1031; CHECK-NEXT: # %bb.0: 1032; CHECK-NEXT: local.get 0 1033; CHECK-NEXT: v128.load64_splat 0:p2align=1 1034; CHECK-NEXT: # fallthrough-return 1035 %e = load i64, i64* %p, align 2 1036 %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 1037 %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer 1038 ret <2 x i64> %v2 1039} 1040 1041define <2 x i64> @load_splat_v2i64_a4(i64* %p) { 1042; CHECK-LABEL: load_splat_v2i64_a4: 1043; CHECK: .functype load_splat_v2i64_a4 (i32) -> (v128) 1044; CHECK-NEXT: # %bb.0: 1045; CHECK-NEXT: local.get 0 1046; CHECK-NEXT: v128.load64_splat 0:p2align=2 1047; CHECK-NEXT: # fallthrough-return 1048 %e = load i64, i64* %p, align 4 1049 %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 1050 %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer 1051 ret <2 x i64> %v2 1052} 1053 1054; 8 is the default alignment for v128.load64_splat so no attribute is needed. 1055define <2 x i64> @load_splat_v2i64_a8(i64* %p) { 1056; CHECK-LABEL: load_splat_v2i64_a8: 1057; CHECK: .functype load_splat_v2i64_a8 (i32) -> (v128) 1058; CHECK-NEXT: # %bb.0: 1059; CHECK-NEXT: local.get 0 1060; CHECK-NEXT: v128.load64_splat 0 1061; CHECK-NEXT: # fallthrough-return 1062 %e = load i64, i64* %p, align 8 1063 %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 1064 %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer 1065 ret <2 x i64> %v2 1066} 1067 1068; 16 is greater than the default alignment so it is ignored. 1069define <2 x i64> @load_splat_v2i64_a16(i64* %p) { 1070; CHECK-LABEL: load_splat_v2i64_a16: 1071; CHECK: .functype load_splat_v2i64_a16 (i32) -> (v128) 1072; CHECK-NEXT: # %bb.0: 1073; CHECK-NEXT: local.get 0 1074; CHECK-NEXT: v128.load64_splat 0 1075; CHECK-NEXT: # fallthrough-return 1076 %e = load i64, i64* %p, align 16 1077 %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 1078 %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer 1079 ret <2 x i64> %v2 1080} 1081 1082define <2 x i64> @load_lane_i64_a1(i64* %p, <2 x i64> %v) { 1083; CHECK-LABEL: load_lane_i64_a1: 1084; CHECK: .functype load_lane_i64_a1 (i32, v128) -> (v128) 1085; CHECK-NEXT: # %bb.0: 1086; CHECK-NEXT: local.get 0 1087; CHECK-NEXT: local.get 1 1088; CHECK-NEXT: v128.load64_lane 0:p2align=0, 0 1089; CHECK-NEXT: # fallthrough-return 1090 %e = load i64, i64* %p, align 1 1091 %v1 = insertelement <2 x i64> %v, i64 %e, i32 0 1092 ret <2 x i64> %v1 1093} 1094 1095define <2 x i64> @load_lane_i64_a2(i64* %p, <2 x i64> %v) { 1096; CHECK-LABEL: load_lane_i64_a2: 1097; CHECK: .functype load_lane_i64_a2 (i32, v128) -> (v128) 1098; CHECK-NEXT: # %bb.0: 1099; CHECK-NEXT: local.get 0 1100; CHECK-NEXT: local.get 1 1101; CHECK-NEXT: v128.load64_lane 0:p2align=1, 0 1102; CHECK-NEXT: # fallthrough-return 1103 %e = load i64, i64* %p, align 2 1104 %v1 = insertelement <2 x i64> %v, i64 %e, i32 0 1105 ret <2 x i64> %v1 1106} 1107 1108define <2 x i64> @load_lane_i64_a4(i64* %p, <2 x i64> %v) { 1109; CHECK-LABEL: load_lane_i64_a4: 1110; CHECK: .functype load_lane_i64_a4 (i32, v128) -> (v128) 1111; CHECK-NEXT: # %bb.0: 1112; CHECK-NEXT: local.get 0 1113; CHECK-NEXT: local.get 1 1114; CHECK-NEXT: v128.load64_lane 0:p2align=2, 0 1115; CHECK-NEXT: # fallthrough-return 1116 %e = load i64, i64* %p, align 4 1117 %v1 = insertelement <2 x i64> %v, i64 %e, i32 0 1118 ret <2 x i64> %v1 1119} 1120 1121; 8 is the default alignment for v128.load64_lane so no attribute is needed. 1122define <2 x i64> @load_lane_i64_a8(i64* %p, <2 x i64> %v) { 1123; CHECK-LABEL: load_lane_i64_a8: 1124; CHECK: .functype load_lane_i64_a8 (i32, v128) -> (v128) 1125; CHECK-NEXT: # %bb.0: 1126; CHECK-NEXT: local.get 0 1127; CHECK-NEXT: local.get 1 1128; CHECK-NEXT: v128.load64_lane 0, 0 1129; CHECK-NEXT: # fallthrough-return 1130 %e = load i64, i64* %p, align 8 1131 %v1 = insertelement <2 x i64> %v, i64 %e, i32 0 1132 ret <2 x i64> %v1 1133} 1134 1135; 16 is greater than the default alignment so it is ignored. 1136define <2 x i64> @load_lane_i64_a16(i64* %p, <2 x i64> %v) { 1137; CHECK-LABEL: load_lane_i64_a16: 1138; CHECK: .functype load_lane_i64_a16 (i32, v128) -> (v128) 1139; CHECK-NEXT: # %bb.0: 1140; CHECK-NEXT: local.get 0 1141; CHECK-NEXT: local.get 1 1142; CHECK-NEXT: v128.load64_lane 0, 0 1143; CHECK-NEXT: # fallthrough-return 1144 %e = load i64, i64* %p, align 16 1145 %v1 = insertelement <2 x i64> %v, i64 %e, i32 0 1146 ret <2 x i64> %v1 1147} 1148 1149define void @store_lane_i64_a1(<2 x i64> %v, i64* %p) { 1150; CHECK-LABEL: store_lane_i64_a1: 1151; CHECK: .functype store_lane_i64_a1 (v128, i32) -> () 1152; CHECK-NEXT: # %bb.0: 1153; CHECK-NEXT: local.get 1 1154; CHECK-NEXT: local.get 0 1155; CHECK-NEXT: v128.store64_lane 0:p2align=0, 0 1156; CHECK-NEXT: # fallthrough-return 1157 %x = extractelement <2 x i64> %v, i32 0 1158 store i64 %x, i64* %p, align 1 1159 ret void 1160} 1161 1162define void @store_lane_i64_a2(<2 x i64> %v, i64* %p) { 1163; CHECK-LABEL: store_lane_i64_a2: 1164; CHECK: .functype store_lane_i64_a2 (v128, i32) -> () 1165; CHECK-NEXT: # %bb.0: 1166; CHECK-NEXT: local.get 1 1167; CHECK-NEXT: local.get 0 1168; CHECK-NEXT: v128.store64_lane 0:p2align=1, 0 1169; CHECK-NEXT: # fallthrough-return 1170 %x = extractelement <2 x i64> %v, i32 0 1171 store i64 %x, i64* %p, align 2 1172 ret void 1173} 1174 1175define void @store_lane_i64_a4(<2 x i64> %v, i64* %p) { 1176; CHECK-LABEL: store_lane_i64_a4: 1177; CHECK: .functype store_lane_i64_a4 (v128, i32) -> () 1178; CHECK-NEXT: # %bb.0: 1179; CHECK-NEXT: local.get 1 1180; CHECK-NEXT: local.get 0 1181; CHECK-NEXT: v128.store64_lane 0:p2align=2, 0 1182; CHECK-NEXT: # fallthrough-return 1183 %x = extractelement <2 x i64> %v, i32 0 1184 store i64 %x, i64* %p, align 4 1185 ret void 1186} 1187 1188; 8 is the default alignment for v128.store64_lane so no attribute is needed. 1189define void @store_lane_i64_a8(<2 x i64> %v, i64* %p) { 1190; CHECK-LABEL: store_lane_i64_a8: 1191; CHECK: .functype store_lane_i64_a8 (v128, i32) -> () 1192; CHECK-NEXT: # %bb.0: 1193; CHECK-NEXT: local.get 1 1194; CHECK-NEXT: local.get 0 1195; CHECK-NEXT: v128.store64_lane 0, 0 1196; CHECK-NEXT: # fallthrough-return 1197 %x = extractelement <2 x i64> %v, i32 0 1198 store i64 %x, i64* %p, align 8 1199 ret void 1200} 1201 1202; 16 is greater than the default alignment so it is ignored. 1203define void @store_lane_i64_a16(<2 x i64> %v, i64* %p) { 1204; CHECK-LABEL: store_lane_i64_a16: 1205; CHECK: .functype store_lane_i64_a16 (v128, i32) -> () 1206; CHECK-NEXT: # %bb.0: 1207; CHECK-NEXT: local.get 1 1208; CHECK-NEXT: local.get 0 1209; CHECK-NEXT: v128.store64_lane 0, 0 1210; CHECK-NEXT: # fallthrough-return 1211 %x = extractelement <2 x i64> %v, i32 0 1212 store i64 %x, i64* %p, align 16 1213 ret void 1214} 1215 1216; ============================================================================== 1217; 4 x float 1218; ============================================================================== 1219 1220define <4 x float> @load_v4f32_a1(<4 x float> *%p) { 1221; CHECK-LABEL: load_v4f32_a1: 1222; CHECK: .functype load_v4f32_a1 (i32) -> (v128) 1223; CHECK-NEXT: # %bb.0: 1224; CHECK-NEXT: local.get 0 1225; CHECK-NEXT: v128.load 0:p2align=0 1226; CHECK-NEXT: # fallthrough-return 1227 %v = load <4 x float>, <4 x float>* %p, align 1 1228 ret <4 x float> %v 1229} 1230 1231define <4 x float> @load_v4f32_a4(<4 x float> *%p) { 1232; CHECK-LABEL: load_v4f32_a4: 1233; CHECK: .functype load_v4f32_a4 (i32) -> (v128) 1234; CHECK-NEXT: # %bb.0: 1235; CHECK-NEXT: local.get 0 1236; CHECK-NEXT: v128.load 0:p2align=2 1237; CHECK-NEXT: # fallthrough-return 1238 %v = load <4 x float>, <4 x float>* %p, align 4 1239 ret <4 x float> %v 1240} 1241 1242; 4 is the default alignment for v128 so no attribute is needed. 1243define <4 x float> @load_v4f32_a16(<4 x float> *%p) { 1244; CHECK-LABEL: load_v4f32_a16: 1245; CHECK: .functype load_v4f32_a16 (i32) -> (v128) 1246; CHECK-NEXT: # %bb.0: 1247; CHECK-NEXT: local.get 0 1248; CHECK-NEXT: v128.load 0 1249; CHECK-NEXT: # fallthrough-return 1250 %v = load <4 x float>, <4 x float>* %p, align 16 1251 ret <4 x float> %v 1252} 1253 1254; 32 is greater than the default alignment so it is ignored. 1255define <4 x float> @load_v4f32_a32(<4 x float> *%p) { 1256; CHECK-LABEL: load_v4f32_a32: 1257; CHECK: .functype load_v4f32_a32 (i32) -> (v128) 1258; CHECK-NEXT: # %bb.0: 1259; CHECK-NEXT: local.get 0 1260; CHECK-NEXT: v128.load 0 1261; CHECK-NEXT: # fallthrough-return 1262 %v = load <4 x float>, <4 x float>* %p, align 32 1263 ret <4 x float> %v 1264} 1265 1266define void @store_v4f32_a1(<4 x float> *%p, <4 x float> %v) { 1267; CHECK-LABEL: store_v4f32_a1: 1268; CHECK: .functype store_v4f32_a1 (i32, v128) -> () 1269; CHECK-NEXT: # %bb.0: 1270; CHECK-NEXT: local.get 0 1271; CHECK-NEXT: local.get 1 1272; CHECK-NEXT: v128.store 0:p2align=0 1273; CHECK-NEXT: # fallthrough-return 1274 store <4 x float> %v, <4 x float>* %p, align 1 1275 ret void 1276} 1277 1278define void @store_v4f32_a4(<4 x float> *%p, <4 x float> %v) { 1279; CHECK-LABEL: store_v4f32_a4: 1280; CHECK: .functype store_v4f32_a4 (i32, v128) -> () 1281; CHECK-NEXT: # %bb.0: 1282; CHECK-NEXT: local.get 0 1283; CHECK-NEXT: local.get 1 1284; CHECK-NEXT: v128.store 0:p2align=2 1285; CHECK-NEXT: # fallthrough-return 1286 store <4 x float> %v, <4 x float>* %p, align 4 1287 ret void 1288} 1289 1290; 16 is the default alignment for v128 so no attribute is needed. 1291define void @store_v4f32_a16(<4 x float> *%p, <4 x float> %v) { 1292; CHECK-LABEL: store_v4f32_a16: 1293; CHECK: .functype store_v4f32_a16 (i32, v128) -> () 1294; CHECK-NEXT: # %bb.0: 1295; CHECK-NEXT: local.get 0 1296; CHECK-NEXT: local.get 1 1297; CHECK-NEXT: v128.store 0 1298; CHECK-NEXT: # fallthrough-return 1299 store <4 x float> %v, <4 x float>* %p, align 16 1300 ret void 1301} 1302 1303; 32 is greater than the default alignment so it is ignored. 1304define void @store_v4f32_a32(<4 x float> *%p, <4 x float> %v) { 1305; CHECK-LABEL: store_v4f32_a32: 1306; CHECK: .functype store_v4f32_a32 (i32, v128) -> () 1307; CHECK-NEXT: # %bb.0: 1308; CHECK-NEXT: local.get 0 1309; CHECK-NEXT: local.get 1 1310; CHECK-NEXT: v128.store 0 1311; CHECK-NEXT: # fallthrough-return 1312 store <4 x float> %v, <4 x float>* %p, align 32 1313 ret void 1314} 1315 1316; ============================================================================== 1317; 2 x double 1318; ============================================================================== 1319 1320define <2 x double> @load_v2f64_a1(<2 x double> *%p) { 1321; CHECK-LABEL: load_v2f64_a1: 1322; CHECK: .functype load_v2f64_a1 (i32) -> (v128) 1323; CHECK-NEXT: # %bb.0: 1324; CHECK-NEXT: local.get 0 1325; CHECK-NEXT: v128.load 0:p2align=0 1326; CHECK-NEXT: # fallthrough-return 1327 %v = load <2 x double>, <2 x double>* %p, align 1 1328 ret <2 x double> %v 1329} 1330 1331define <2 x double> @load_v2f64_a4(<2 x double> *%p) { 1332; CHECK-LABEL: load_v2f64_a4: 1333; CHECK: .functype load_v2f64_a4 (i32) -> (v128) 1334; CHECK-NEXT: # %bb.0: 1335; CHECK-NEXT: local.get 0 1336; CHECK-NEXT: v128.load 0:p2align=2 1337; CHECK-NEXT: # fallthrough-return 1338 %v = load <2 x double>, <2 x double>* %p, align 4 1339 ret <2 x double> %v 1340} 1341 1342; 2 is the default alignment for v128 so no attribute is needed. 1343define <2 x double> @load_v2f64_a16(<2 x double> *%p) { 1344; CHECK-LABEL: load_v2f64_a16: 1345; CHECK: .functype load_v2f64_a16 (i32) -> (v128) 1346; CHECK-NEXT: # %bb.0: 1347; CHECK-NEXT: local.get 0 1348; CHECK-NEXT: v128.load 0 1349; CHECK-NEXT: # fallthrough-return 1350 %v = load <2 x double>, <2 x double>* %p, align 16 1351 ret <2 x double> %v 1352} 1353 1354; 32 is greater than the default alignment so it is ignored. 1355define <2 x double> @load_v2f64_a32(<2 x double> *%p) { 1356; CHECK-LABEL: load_v2f64_a32: 1357; CHECK: .functype load_v2f64_a32 (i32) -> (v128) 1358; CHECK-NEXT: # %bb.0: 1359; CHECK-NEXT: local.get 0 1360; CHECK-NEXT: v128.load 0 1361; CHECK-NEXT: # fallthrough-return 1362 %v = load <2 x double>, <2 x double>* %p, align 32 1363 ret <2 x double> %v 1364} 1365 1366define void @store_v2f64_a1(<2 x double> *%p, <2 x double> %v) { 1367; CHECK-LABEL: store_v2f64_a1: 1368; CHECK: .functype store_v2f64_a1 (i32, v128) -> () 1369; CHECK-NEXT: # %bb.0: 1370; CHECK-NEXT: local.get 0 1371; CHECK-NEXT: local.get 1 1372; CHECK-NEXT: v128.store 0:p2align=0 1373; CHECK-NEXT: # fallthrough-return 1374 store <2 x double> %v, <2 x double>* %p, align 1 1375 ret void 1376} 1377 1378define void @store_v2f64_a4(<2 x double> *%p, <2 x double> %v) { 1379; CHECK-LABEL: store_v2f64_a4: 1380; CHECK: .functype store_v2f64_a4 (i32, v128) -> () 1381; CHECK-NEXT: # %bb.0: 1382; CHECK-NEXT: local.get 0 1383; CHECK-NEXT: local.get 1 1384; CHECK-NEXT: v128.store 0:p2align=2 1385; CHECK-NEXT: # fallthrough-return 1386 store <2 x double> %v, <2 x double>* %p, align 4 1387 ret void 1388} 1389 1390; 16 is the default alignment for v128 so no attribute is needed. 1391define void @store_v2f64_a16(<2 x double> *%p, <2 x double> %v) { 1392; CHECK-LABEL: store_v2f64_a16: 1393; CHECK: .functype store_v2f64_a16 (i32, v128) -> () 1394; CHECK-NEXT: # %bb.0: 1395; CHECK-NEXT: local.get 0 1396; CHECK-NEXT: local.get 1 1397; CHECK-NEXT: v128.store 0 1398; CHECK-NEXT: # fallthrough-return 1399 store <2 x double> %v, <2 x double>* %p, align 16 1400 ret void 1401} 1402 1403; 32 is greater than the default alignment so it is ignored. 1404define void @store_v2f64_a32(<2 x double> *%p, <2 x double> %v) { 1405; CHECK-LABEL: store_v2f64_a32: 1406; CHECK: .functype store_v2f64_a32 (i32, v128) -> () 1407; CHECK-NEXT: # %bb.0: 1408; CHECK-NEXT: local.get 0 1409; CHECK-NEXT: local.get 1 1410; CHECK-NEXT: v128.store 0 1411; CHECK-NEXT: # fallthrough-return 1412 store <2 x double> %v, <2 x double>* %p, align 32 1413 ret void 1414} 1415