|  | ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | 
|  | ; RUN: llc < %s -verify-machineinstrs -mattr=+simd128 | FileCheck %s | 
|  |  | 
|  | ; Test SIMD v128.load{32,64}_zero instructions | 
|  |  | 
|  | target triple = "wasm32-unknown-unknown" | 
|  |  | 
|  | ;===---------------------------------------------------------------------------- | 
|  | ; v128.load32_zero | 
|  | ;===---------------------------------------------------------------------------- | 
|  |  | 
|  | define <4 x i32> @load_zero_i32_no_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i32_no_offset: | 
|  | ; CHECK:         .functype load_zero_i32_no_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    v128.load32_zero 0 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %x = load i32, ptr %p | 
|  | %v = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0 | 
|  | ret <4 x i32> %v | 
|  | } | 
|  |  | 
|  | define <4 x i32> @load_zero_i32_with_folded_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i32_with_folded_offset: | 
|  | ; CHECK:         .functype load_zero_i32_with_folded_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    v128.load32_zero 24 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %q = ptrtoint ptr %p to i32 | 
|  | %r = add nuw i32 %q, 24 | 
|  | %s = inttoptr i32 %r to ptr | 
|  | %x = load i32, ptr %s | 
|  | %t = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0 | 
|  | ret <4 x i32> %t | 
|  | } | 
|  |  | 
|  | define <4 x i32> @load_zero_i32_with_folded_gep_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i32_with_folded_gep_offset: | 
|  | ; CHECK:         .functype load_zero_i32_with_folded_gep_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    v128.load32_zero 24 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %s = getelementptr inbounds i32, ptr %p, i32 6 | 
|  | %x = load i32, ptr %s | 
|  | %t = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0 | 
|  | ret <4 x i32> %t | 
|  | } | 
|  |  | 
|  | define <4 x i32> @load_zero_i32_with_unfolded_gep_negative_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i32_with_unfolded_gep_negative_offset: | 
|  | ; CHECK:         .functype load_zero_i32_with_unfolded_gep_negative_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    i32.const -24 | 
|  | ; CHECK-NEXT:    i32.add | 
|  | ; CHECK-NEXT:    v128.load32_zero 0 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %s = getelementptr inbounds i32, ptr %p, i32 -6 | 
|  | %x = load i32, ptr %s | 
|  | %t = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0 | 
|  | ret <4 x i32> %t | 
|  | } | 
|  |  | 
|  | define <4 x i32> @load_zero_i32_with_unfolded_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i32_with_unfolded_offset: | 
|  | ; CHECK:         .functype load_zero_i32_with_unfolded_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    i32.const 24 | 
|  | ; CHECK-NEXT:    i32.add | 
|  | ; CHECK-NEXT:    v128.load32_zero 0 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %q = ptrtoint ptr %p to i32 | 
|  | %r = add nsw i32 %q, 24 | 
|  | %s = inttoptr i32 %r to ptr | 
|  | %x = load i32, ptr %s | 
|  | %t = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0 | 
|  | ret <4 x i32> %t | 
|  | } | 
|  |  | 
|  | define <4 x i32> @load_zero_i32_with_unfolded_gep_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i32_with_unfolded_gep_offset: | 
|  | ; CHECK:         .functype load_zero_i32_with_unfolded_gep_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    i32.const 24 | 
|  | ; CHECK-NEXT:    i32.add | 
|  | ; CHECK-NEXT:    v128.load32_zero 0 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %s = getelementptr i32, ptr %p, i32 6 | 
|  | %x = load i32, ptr %s | 
|  | %t = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0 | 
|  | ret <4 x i32> %t | 
|  | } | 
|  |  | 
|  | define <4 x i32> @load_zero_i32_from_numeric_address() { | 
|  | ; CHECK-LABEL: load_zero_i32_from_numeric_address: | 
|  | ; CHECK:         .functype load_zero_i32_from_numeric_address () -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    i32.const 0 | 
|  | ; CHECK-NEXT:    v128.load32_zero 42 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %s = inttoptr i32 42 to ptr | 
|  | %x = load i32, ptr %s | 
|  | %t = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0 | 
|  | ret <4 x i32> %t | 
|  | } | 
|  |  | 
|  | @gv_i32 = global i32 0 | 
|  | define <4 x i32> @load_zero_i32_from_global_address() { | 
|  | ; CHECK-LABEL: load_zero_i32_from_global_address: | 
|  | ; CHECK:         .functype load_zero_i32_from_global_address () -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    i32.const 0 | 
|  | ; CHECK-NEXT:    v128.load32_zero gv_i32 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %x = load i32, ptr @gv_i32 | 
|  | %t = insertelement <4 x i32> zeroinitializer, i32 %x, i32 0 | 
|  | ret <4 x i32> %t | 
|  | } | 
|  |  | 
|  | ;===---------------------------------------------------------------------------- | 
|  | ; v128.load64_zero | 
|  | ;===---------------------------------------------------------------------------- | 
|  |  | 
|  | define <2 x i64> @load_zero_i64_no_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i64_no_offset: | 
|  | ; CHECK:         .functype load_zero_i64_no_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    v128.load64_zero 0 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %x = load i64, ptr %p | 
|  | %v = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0 | 
|  | ret <2 x i64> %v | 
|  | } | 
|  |  | 
|  | define <2 x i64> @load_zero_i64_with_folded_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i64_with_folded_offset: | 
|  | ; CHECK:         .functype load_zero_i64_with_folded_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    v128.load64_zero 24 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %q = ptrtoint ptr %p to i32 | 
|  | %r = add nuw i32 %q, 24 | 
|  | %s = inttoptr i32 %r to ptr | 
|  | %x = load i64, ptr %s | 
|  | %t = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0 | 
|  | ret <2 x i64> %t | 
|  | } | 
|  |  | 
|  | define <2 x i64> @load_zero_i64_with_folded_gep_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i64_with_folded_gep_offset: | 
|  | ; CHECK:         .functype load_zero_i64_with_folded_gep_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    v128.load64_zero 48 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %s = getelementptr inbounds i64, ptr %p, i64 6 | 
|  | %x = load i64, ptr %s | 
|  | %t = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0 | 
|  | ret <2 x i64> %t | 
|  | } | 
|  |  | 
|  | define <2 x i64> @load_zero_i64_with_unfolded_gep_negative_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i64_with_unfolded_gep_negative_offset: | 
|  | ; CHECK:         .functype load_zero_i64_with_unfolded_gep_negative_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    i32.const -48 | 
|  | ; CHECK-NEXT:    i32.add | 
|  | ; CHECK-NEXT:    v128.load64_zero 0 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %s = getelementptr inbounds i64, ptr %p, i64 -6 | 
|  | %x = load i64, ptr %s | 
|  | %t = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0 | 
|  | ret <2 x i64> %t | 
|  | } | 
|  |  | 
|  | define <2 x i64> @load_zero_i64_with_unfolded_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i64_with_unfolded_offset: | 
|  | ; CHECK:         .functype load_zero_i64_with_unfolded_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    i32.const 24 | 
|  | ; CHECK-NEXT:    i32.add | 
|  | ; CHECK-NEXT:    v128.load64_zero 0 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %q = ptrtoint ptr %p to i32 | 
|  | %r = add nsw i32 %q, 24 | 
|  | %s = inttoptr i32 %r to ptr | 
|  | %x = load i64, ptr %s | 
|  | %t = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0 | 
|  | ret <2 x i64> %t | 
|  | } | 
|  |  | 
|  | define <2 x i64> @load_zero_i64_with_unfolded_gep_offset(ptr %p) { | 
|  | ; CHECK-LABEL: load_zero_i64_with_unfolded_gep_offset: | 
|  | ; CHECK:         .functype load_zero_i64_with_unfolded_gep_offset (i32) -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    local.get 0 | 
|  | ; CHECK-NEXT:    i32.const 48 | 
|  | ; CHECK-NEXT:    i32.add | 
|  | ; CHECK-NEXT:    v128.load64_zero 0 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %s = getelementptr i64, ptr %p, i64 6 | 
|  | %x = load i64, ptr %s | 
|  | %t = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0 | 
|  | ret <2 x i64> %t | 
|  | } | 
|  |  | 
|  | define <2 x i64> @load_zero_i64_from_numeric_address() { | 
|  | ; CHECK-LABEL: load_zero_i64_from_numeric_address: | 
|  | ; CHECK:         .functype load_zero_i64_from_numeric_address () -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    i32.const 0 | 
|  | ; CHECK-NEXT:    v128.load64_zero 42 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %s = inttoptr i32 42 to ptr | 
|  | %x = load i64, ptr %s | 
|  | %t = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0 | 
|  | ret <2 x i64> %t | 
|  | } | 
|  |  | 
|  | @gv_i64 = global i64 0 | 
|  | define <2 x i64> @load_zero_i64_from_global_address() { | 
|  | ; CHECK-LABEL: load_zero_i64_from_global_address: | 
|  | ; CHECK:         .functype load_zero_i64_from_global_address () -> (v128) | 
|  | ; CHECK-NEXT:  # %bb.0: | 
|  | ; CHECK-NEXT:    i32.const 0 | 
|  | ; CHECK-NEXT:    v128.load64_zero gv_i64 | 
|  | ; CHECK-NEXT:    # fallthrough-return | 
|  | %x = load i64, ptr @gv_i64 | 
|  | %t = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0 | 
|  | ret <2 x i64> %t | 
|  | } |