| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py |
| # RUN: llc -debugify-and-strip-all-safe -mtriple aarch64 -O0 -run-pass=aarch64-prelegalizer-combiner --aarch64prelegalizercombinerhelper-only-enable-rule="load_or_combine" -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=LITTLE |
| # RUN: llc -debugify-and-strip-all-safe -mtriple arm64eb -O0 -run-pass=aarch64-prelegalizer-combiner --aarch64prelegalizercombinerhelper-only-enable-rule="load_or_combine" -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=BIG |
| |
| # REQUIRES: asserts |
| |
| # Test that we can combine patterns like |
| # |
| # s8* x = ... |
| # s32 y = (x[0] | (x[1] << 8)) | ((x[2] << 16) | (x[3] << 24)) |
| # |
| # Into either a load, or a load with a bswap. |
| |
| ... |
| --- |
| name: s8_loads_to_s32_little_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s8* x = ... |
| ; s32 y = (x[0] | (x[1] << 8)) | ((x[2] << 16) | (x[3] << 24)) |
| ; |
| ; -> Little endian: Load from x[0] |
| ; -> Big endian: Load from x[0] + BSWAP |
| |
| ; LITTLE-LABEL: name: s8_loads_to_s32_little_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %full_load:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 1) |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: s8_loads_to_s32_little_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 1) |
| ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s32) = G_CONSTANT i32 1 |
| %cst_2:_(s32) = G_CONSTANT i32 2 |
| %cst_3:_(s32) = G_CONSTANT i32 3 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| |
| %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| |
| %byte1:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| %byte3:_(s32) = nuw G_SHL %elt3, %cst_24(s32) |
| |
| ; Note the shape of the tree: |
| ; |
| ; byte byte byte byte |
| ; \ / \ / |
| ; OR OR |
| ; \ / |
| ; \ / |
| ; OR |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %byte2, %byte3 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: s8_loads_to_s32_big_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s8* x = ... |
| ; s32 y = (x[0] << 24 | (x[1] << 16)) | ((x[2] << 8) | x[3])) |
| ; |
| ; -> Little endian: Load from x[0] + BSWAP |
| ; -> Big endian: Load from x[0] |
| |
| ; LITTLE-LABEL: name: s8_loads_to_s32_big_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 1) |
| ; LITTLE: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: s8_loads_to_s32_big_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %full_load:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 1) |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s32) = G_CONSTANT i32 1 |
| %cst_2:_(s32) = G_CONSTANT i32 2 |
| %cst_3:_(s32) = G_CONSTANT i32 3 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| |
| %elt0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| |
| %byte0:_(s32) = nuw G_SHL %elt0, %cst_24(s32) |
| %byte1:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| %byte2:_(s32) = nuw G_SHL %elt2, %cst_8(s32) |
| %byte3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %byte2, %byte3 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: different_or_pattern |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; Slightly different OR tree. |
| ; |
| ; s8* x = ... |
| ; s32 y = (((x[0] | (x[1] << 8)) | (x[2] << 16)) | (x[3] << 24)) |
| ; |
| ; -> Little endian: Load from x[0] |
| ; -> Big endian: Load from x[0] + BSWAP |
| |
| ; LITTLE-LABEL: name: different_or_pattern |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %full_load:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 1) |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: different_or_pattern |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 1) |
| ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s32) = G_CONSTANT i32 1 |
| %cst_2:_(s32) = G_CONSTANT i32 2 |
| %cst_3:_(s32) = G_CONSTANT i32 3 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| |
| %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| |
| %byte1:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| %byte3:_(s32) = nuw G_SHL %elt3, %cst_24(s32) |
| |
| ; Note the shape of the tree: |
| ; |
| ; byte byte |
| ; \ / |
| ; OR_1 byte |
| ; \ / |
| ; OR_2 |
| ; \ |
| ; ... |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %or1, %byte2 |
| %full_load:_(s32) = G_OR %or2, %byte3 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: s16_loads_to_s32_little_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s16* x = ... |
| ; s32 y = x[0] | (x[1] << 16) |
| ; |
| ; -> Little endian: Load from x[0] |
| ; -> Big endian: Load from x[0] + BSWAP |
| |
| ; LITTLE-LABEL: name: s16_loads_to_s32_little_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %full_load:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 2) |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: s16_loads_to_s32_little_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 2) |
| ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: s16_loads_to_s32_big_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s16 *x = ... |
| ; s32 y = x[1] | (x[0] << 16) |
| ; |
| ; -> Little endian: Load from x[0] + BSWAP |
| ; -> Big endian: Load from x[0] |
| |
| ; LITTLE-LABEL: name: s16_loads_to_s32_big_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 2) |
| ; LITTLE: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: s16_loads_to_s32_big_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %full_load:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 2) |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %elt0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt0, %cst_16(s32) |
| %low_half:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: s16_loads_to_s64_little_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s16 *x = ... |
| ; s32 y = (x[0] | (x[1] << 16)) | ((x[2] << 32) | (x[3] << 48)) |
| ; |
| ; -> Little endian: Load from x[0] |
| ; -> Big endian: Load from x[0] + BSWAP |
| |
| ; LITTLE-LABEL: name: s16_loads_to_s64_little_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %full_load:_(s64) = G_LOAD %ptr(p0) :: (load 8, align 2) |
| ; LITTLE: $x1 = COPY %full_load(s64) |
| ; LITTLE: RET_ReallyLR implicit $x1 |
| ; BIG-LABEL: name: s16_loads_to_s64_little_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD %ptr(p0) :: (load 8, align 2) |
| ; BIG: %full_load:_(s64) = G_BSWAP [[LOAD]] |
| ; BIG: $x1 = COPY %full_load(s64) |
| ; BIG: RET_ReallyLR implicit $x1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_2:_(s64) = G_CONSTANT i64 2 |
| %cst_3:_(s64) = G_CONSTANT i64 3 |
| |
| %cst_16:_(s64) = G_CONSTANT i64 16 |
| %cst_32:_(s64) = G_CONSTANT i64 32 |
| %cst_48:_(s64) = G_CONSTANT i64 48 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) |
| |
| %byte0_byte1:_(s64) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| |
| %elt1:_(s64) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %elt2:_(s64) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 2) |
| %elt3:_(s64) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 2) |
| |
| %byte2_byte3:_(s64) = nuw G_SHL %elt1, %cst_16(s64) |
| %byte4_byte5:_(s64) = nuw G_SHL %elt2, %cst_32(s64) |
| %byte6_byte7:_(s64) = nuw G_SHL %elt3, %cst_48(s64) |
| |
| %or1:_(s64) = G_OR %byte0_byte1, %byte2_byte3 |
| %or2:_(s64) = G_OR %byte4_byte5, %byte6_byte7 |
| %full_load:_(s64) = G_OR %or1, %or2 |
| |
| $x1 = COPY %full_load(s64) |
| RET_ReallyLR implicit $x1 |
| |
| ... |
| --- |
| name: s16_loads_to_s64_big_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s16 *x = ... |
| ; s64 y = (x[3] | (x[2] << 16)) | ((x[1] << 32) | (x[0] << 48)) |
| ; |
| ; -> Little endian: Load from x[0] + BSWAP |
| ; -> Big endian: Load from x[0] |
| |
| ; LITTLE-LABEL: name: s16_loads_to_s64_big_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: [[LOAD:%[0-9]+]]:_(s64) = G_LOAD %ptr(p0) :: (load 8, align 2) |
| ; LITTLE: %full_load:_(s64) = G_BSWAP [[LOAD]] |
| ; LITTLE: $x1 = COPY %full_load(s64) |
| ; LITTLE: RET_ReallyLR implicit $x1 |
| ; BIG-LABEL: name: s16_loads_to_s64_big_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %full_load:_(s64) = G_LOAD %ptr(p0) :: (load 8, align 2) |
| ; BIG: $x1 = COPY %full_load(s64) |
| ; BIG: RET_ReallyLR implicit $x1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_2:_(s64) = G_CONSTANT i64 2 |
| %cst_3:_(s64) = G_CONSTANT i64 3 |
| |
| %cst_16:_(s64) = G_CONSTANT i64 16 |
| %cst_32:_(s64) = G_CONSTANT i64 32 |
| %cst_48:_(s64) = G_CONSTANT i64 48 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s64) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) |
| |
| %elt0:_(s64) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %elt1:_(s64) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %elt2:_(s64) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 2) |
| |
| %byte0_byte1:_(s64) = nuw G_SHL %elt0, %cst_48(s64) |
| %byte2_byte3:_(s64) = nuw G_SHL %elt1, %cst_32(s64) |
| %byte4_byte5:_(s64) = nuw G_SHL %elt2, %cst_16(s64) |
| %byte6_byte7:_(s64) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 2) |
| |
| %or1:_(s64) = G_OR %byte0_byte1, %byte2_byte3 |
| %or2:_(s64) = G_OR %byte4_byte5, %byte6_byte7 |
| %full_load:_(s64) = G_OR %or1, %or2 |
| |
| $x1 = COPY %full_load(s64) |
| RET_ReallyLR implicit $x1 |
| |
| |
| ... |
| --- |
| name: nonzero_start_idx_positive_little_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s8* x = ... |
| ; s32 y = (x[1] | (x[2] << 8)) | ((x[3] << 16) | (x[4] << 24)) |
| ; |
| ; -> Little endian: Load from x[1] |
| ; -> Big endian: Load from x[1] + BSWAP |
| |
| ; LITTLE-LABEL: name: nonzero_start_idx_positive_little_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; LITTLE: %ptr:_(p0) = COPY $x0 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; LITTLE: %full_load:_(s32) = G_LOAD %ptr_elt_1(p0) :: (load 4, align 1) |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: nonzero_start_idx_positive_little_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; BIG: %ptr:_(p0) = COPY $x0 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; BIG: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr_elt_1(p0) :: (load 4, align 1) |
| ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s32) = G_CONSTANT i32 1 |
| %cst_2:_(s32) = G_CONSTANT i32 2 |
| %cst_3:_(s32) = G_CONSTANT i32 3 |
| %cst_4:_(s32) = G_CONSTANT i32 4 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x0 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| %ptr_elt_4:_(p0) = G_PTR_ADD %ptr, %cst_4(s32) |
| |
| %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| %elt4:_(s32) = G_ZEXTLOAD %ptr_elt_4(p0) :: (load 1) |
| |
| %byte0:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %byte1:_(s32) = nuw G_SHL %elt2, %cst_8(s32) |
| %byte2:_(s32) = nuw G_SHL %elt3, %cst_16(s32) |
| %byte3:_(s32) = nuw G_SHL %elt4, %cst_24(s32) |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %byte2, %byte3 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: nonzero_start_idx_positive_big_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s8* x = ... |
| ; s32 y = (x[4] | (x[3] << 8)) | ((x[2] << 16) | (x[1] << 24)) |
| ; |
| ; -> Little endian: Load from x[1] + BSWAP |
| ; -> Big endian: Load from x[1] |
| |
| ; LITTLE-LABEL: name: nonzero_start_idx_positive_big_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; LITTLE: %ptr:_(p0) = COPY $x0 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; LITTLE: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr_elt_1(p0) :: (load 4, align 1) |
| ; LITTLE: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: nonzero_start_idx_positive_big_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; BIG: %ptr:_(p0) = COPY $x0 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; BIG: %full_load:_(s32) = G_LOAD %ptr_elt_1(p0) :: (load 4, align 1) |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s32) = G_CONSTANT i32 1 |
| %cst_2:_(s32) = G_CONSTANT i32 2 |
| %cst_3:_(s32) = G_CONSTANT i32 3 |
| %cst_4:_(s32) = G_CONSTANT i32 4 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x0 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| %ptr_elt_4:_(p0) = G_PTR_ADD %ptr, %cst_4(s32) |
| |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| |
| %byte0:_(s32) = G_ZEXTLOAD %ptr_elt_4(p0) :: (load 1) |
| %byte1:_(s32) = nuw G_SHL %elt3, %cst_8(s32) |
| %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| %byte3:_(s32) = nuw G_SHL %elt1, %cst_24(s32) |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %byte2, %byte3 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: nonzero_start_idx_negative_little_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s8* x = ... |
| ; s32 y = (x[-3] | (x[-2] << 8)) | ((x[-1] << 16) | (x[0] << 24)) |
| ; |
| ; -> Little endian: Load from x[-3] |
| ; -> Big endian: Load from x[-3] + BSWAP |
| |
| ; LITTLE-LABEL: name: nonzero_start_idx_negative_little_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_neg_3:_(s32) = G_CONSTANT i32 -3 |
| ; LITTLE: %ptr:_(p0) = COPY $x0 |
| ; LITTLE: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) |
| ; LITTLE: %full_load:_(s32) = G_LOAD %ptr_elt_neg_3(p0) :: (load 4, align 1) |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: nonzero_start_idx_negative_little_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_neg_3:_(s32) = G_CONSTANT i32 -3 |
| ; BIG: %ptr:_(p0) = COPY $x0 |
| ; BIG: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) |
| ; BIG: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr_elt_neg_3(p0) :: (load 4, align 1) |
| ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_neg_1:_(s32) = G_CONSTANT i32 -1 |
| %cst_neg_2:_(s32) = G_CONSTANT i32 -2 |
| %cst_neg_3:_(s32) = G_CONSTANT i32 -3 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x0 |
| %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) |
| %ptr_elt_neg_2:_(p0) = G_PTR_ADD %ptr, %cst_neg_2(s32) |
| %ptr_elt_neg_1:_(p0) = G_PTR_ADD %ptr, %cst_neg_1(s32) |
| |
| %elt_neg_2:_(s32) = G_ZEXTLOAD %ptr_elt_neg_2(p0) :: (load 1) |
| %elt_neg_1:_(s32) = G_ZEXTLOAD %ptr_elt_neg_1(p0) :: (load 1) |
| %elt_0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| |
| %byte0:_(s32) = G_ZEXTLOAD %ptr_elt_neg_3(p0) :: (load 1) |
| %byte1:_(s32) = nuw G_SHL %elt_neg_2, %cst_8(s32) |
| %byte2:_(s32) = nuw G_SHL %elt_neg_1, %cst_16(s32) |
| %byte3:_(s32) = nuw G_SHL %elt_0, %cst_24(s32) |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %byte2, %byte3 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: nonzero_start_idx_negative_big_endian_pat |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; s8* x = ... |
| ; s32 y = (x[0] | (x[-1] << 8)) | ((x[-2] << 16) | (x[-3] << 24)) |
| ; |
| ; -> Little endian: Load from x[-3] + BSWAP |
| ; -> Big endian: Load from x[-3] |
| |
| ; LITTLE-LABEL: name: nonzero_start_idx_negative_big_endian_pat |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_neg_3:_(s32) = G_CONSTANT i32 -3 |
| ; LITTLE: %ptr:_(p0) = COPY $x0 |
| ; LITTLE: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) |
| ; LITTLE: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr_elt_neg_3(p0) :: (load 4, align 1) |
| ; LITTLE: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: nonzero_start_idx_negative_big_endian_pat |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_neg_3:_(s32) = G_CONSTANT i32 -3 |
| ; BIG: %ptr:_(p0) = COPY $x0 |
| ; BIG: %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) |
| ; BIG: %full_load:_(s32) = G_LOAD %ptr_elt_neg_3(p0) :: (load 4, align 1) |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_neg_1:_(s32) = G_CONSTANT i32 -1 |
| %cst_neg_2:_(s32) = G_CONSTANT i32 -2 |
| %cst_neg_3:_(s32) = G_CONSTANT i32 -3 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x0 |
| %ptr_elt_neg_3:_(p0) = G_PTR_ADD %ptr, %cst_neg_3(s32) |
| %ptr_elt_neg_2:_(p0) = G_PTR_ADD %ptr, %cst_neg_2(s32) |
| %ptr_elt_neg_1:_(p0) = G_PTR_ADD %ptr, %cst_neg_1(s32) |
| |
| %elt_neg_3:_(s32) = G_ZEXTLOAD %ptr_elt_neg_3(p0) :: (load 1) |
| %elt_neg_2:_(s32) = G_ZEXTLOAD %ptr_elt_neg_2(p0) :: (load 1) |
| %elt_neg_1:_(s32) = G_ZEXTLOAD %ptr_elt_neg_1(p0) :: (load 1) |
| %elt_0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| |
| %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| %byte1:_(s32) = nuw G_SHL %elt_neg_1, %cst_8(s32) |
| %byte2:_(s32) = nuw G_SHL %elt_neg_2, %cst_16(s32) |
| %byte3:_(s32) = nuw G_SHL %elt_neg_3, %cst_24(s32) |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %byte2, %byte3 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_volatile |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; Combine should only happen with unordered loads. |
| |
| ; LITTLE-LABEL: name: dont_combine_volatile |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (volatile load 2) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_volatile |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (volatile load 2) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (volatile load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_wrong_memop_size |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; Combine should only happen when the loads load the same size. |
| |
| ; LITTLE-LABEL: name: dont_wrong_memop_size |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %wrong_size_load:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %wrong_size_load, %cst_16(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_wrong_memop_size |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %wrong_size_load:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %wrong_size_load, %cst_16(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %wrong_size_load:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %high_half:_(s32) = nuw G_SHL %wrong_size_load, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_wrong_offset |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; This is not equivalent to a 32-bit load with/without a BSWAP: |
| ; |
| ; s16 *x = ... |
| ; s32 y = x[0] | (x[1] << 24) |
| |
| ; LITTLE-LABEL: name: dont_combine_wrong_offset |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_24:_(s32) = G_CONSTANT i32 24 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_24(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_wrong_offset |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_24:_(s32) = G_CONSTANT i32 24 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_24(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_24(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_wrong_offset_2 |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; This does not correspond to a 32-bit load with/without a BSWAP: |
| ; |
| ; s16 *x = ... |
| ; s32 y = x[0] | (x[1] << 8) |
| |
| ; LITTLE-LABEL: name: dont_combine_wrong_offset_2 |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_8:_(s32) = G_CONSTANT i32 8 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_wrong_offset_2 |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_8:_(s32) = G_CONSTANT i32 8 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_missing_load |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; This is missing x[2], so we shouldn't combine: |
| ; |
| ; s16 *x = ... |
| ; s64 y = (x[0] | (x[1] << 16)) | (x[3] << 48) |
| |
| ; LITTLE-LABEL: name: dont_combine_missing_load |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_3:_(s64) = G_CONSTANT i64 3 |
| ; LITTLE: %cst_16:_(s64) = G_CONSTANT i64 16 |
| ; LITTLE: %cst_48:_(s64) = G_CONSTANT i64 48 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) |
| ; LITTLE: %byte0_byte1:_(s64) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %elt1:_(s64) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; LITTLE: %elt3:_(s64) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 2) |
| ; LITTLE: %byte2_byte3:_(s64) = nuw G_SHL %elt1, %cst_16(s64) |
| ; LITTLE: %byte6_byte7:_(s64) = nuw G_SHL %elt3, %cst_48(s64) |
| ; LITTLE: %or1:_(s64) = G_OR %byte0_byte1, %byte2_byte3 |
| ; LITTLE: %full_load:_(s64) = G_OR %or1, %byte6_byte7 |
| ; LITTLE: $x1 = COPY %full_load(s64) |
| ; LITTLE: RET_ReallyLR implicit $x1 |
| ; BIG-LABEL: name: dont_combine_missing_load |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_3:_(s64) = G_CONSTANT i64 3 |
| ; BIG: %cst_16:_(s64) = G_CONSTANT i64 16 |
| ; BIG: %cst_48:_(s64) = G_CONSTANT i64 48 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) |
| ; BIG: %byte0_byte1:_(s64) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %elt1:_(s64) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; BIG: %elt3:_(s64) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 2) |
| ; BIG: %byte2_byte3:_(s64) = nuw G_SHL %elt1, %cst_16(s64) |
| ; BIG: %byte6_byte7:_(s64) = nuw G_SHL %elt3, %cst_48(s64) |
| ; BIG: %or1:_(s64) = G_OR %byte0_byte1, %byte2_byte3 |
| ; BIG: %full_load:_(s64) = G_OR %or1, %byte6_byte7 |
| ; BIG: $x1 = COPY %full_load(s64) |
| ; BIG: RET_ReallyLR implicit $x1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_3:_(s64) = G_CONSTANT i64 3 |
| |
| %cst_16:_(s64) = G_CONSTANT i64 16 |
| %cst_48:_(s64) = G_CONSTANT i64 48 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s64) |
| |
| %byte0_byte1:_(s64) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| |
| %elt1:_(s64) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %elt3:_(s64) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 2) |
| |
| %byte2_byte3:_(s64) = nuw G_SHL %elt1, %cst_16(s64) |
| %byte6_byte7:_(s64) = nuw G_SHL %elt3, %cst_48(s64) |
| |
| %or1:_(s64) = G_OR %byte0_byte1, %byte2_byte3 |
| %full_load:_(s64) = G_OR %or1, %byte6_byte7 |
| |
| $x1 = COPY %full_load(s64) |
| RET_ReallyLR implicit $x1 |
| |
| ... |
| --- |
| name: dont_combine_different_addr_spaces |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; When the loads are from different address spaces, don't combine. |
| |
| ; LITTLE-LABEL: name: dont_combine_different_addr_spaces |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2, addrspace 1) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_different_addr_spaces |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2, addrspace 1) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2, addrspace 0) |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2, addrspace 1) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_duplicate_idx |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; If two of the G_PTR_ADDs have the same index, then don't combine. |
| ; |
| ; sN *x = ... |
| ; sM y = (x[i] << A) | (x[i] << B) ... |
| |
| ; LITTLE-LABEL: name: dont_combine_duplicate_idx |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; LITTLE: %reused_idx:_(s32) = G_CONSTANT i32 2 |
| ; LITTLE: %cst_8:_(s32) = G_CONSTANT i32 8 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %cst_24:_(s32) = G_CONSTANT i32 24 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; LITTLE: %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) |
| ; LITTLE: %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) |
| ; LITTLE: %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| ; LITTLE: %elt2:_(s32) = G_ZEXTLOAD %uses_idx_2(p0) :: (load 1) |
| ; LITTLE: %elt3:_(s32) = G_ZEXTLOAD %also_uses_idx_2(p0) :: (load 1) |
| ; LITTLE: %byte1:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| ; LITTLE: %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| ; LITTLE: %byte3:_(s32) = nuw G_SHL %elt3, %cst_24(s32) |
| ; LITTLE: %or1:_(s32) = G_OR %byte0, %byte1 |
| ; LITTLE: %or2:_(s32) = G_OR %byte2, %byte3 |
| ; LITTLE: %full_load:_(s32) = G_OR %or1, %or2 |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_duplicate_idx |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; BIG: %reused_idx:_(s32) = G_CONSTANT i32 2 |
| ; BIG: %cst_8:_(s32) = G_CONSTANT i32 8 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %cst_24:_(s32) = G_CONSTANT i32 24 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; BIG: %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) |
| ; BIG: %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) |
| ; BIG: %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| ; BIG: %elt2:_(s32) = G_ZEXTLOAD %uses_idx_2(p0) :: (load 1) |
| ; BIG: %elt3:_(s32) = G_ZEXTLOAD %also_uses_idx_2(p0) :: (load 1) |
| ; BIG: %byte1:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| ; BIG: %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| ; BIG: %byte3:_(s32) = nuw G_SHL %elt3, %cst_24(s32) |
| ; BIG: %or1:_(s32) = G_OR %byte0, %byte1 |
| ; BIG: %or2:_(s32) = G_OR %byte2, %byte3 |
| ; BIG: %full_load:_(s32) = G_OR %or1, %or2 |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s32) = G_CONSTANT i32 1 |
| %reused_idx:_(s32) = G_CONSTANT i32 2 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| %uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) |
| %also_uses_idx_2:_(p0) = G_PTR_ADD %ptr, %reused_idx(s32) |
| |
| %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %elt2:_(s32) = G_ZEXTLOAD %uses_idx_2(p0) :: (load 1) |
| %elt3:_(s32) = G_ZEXTLOAD %also_uses_idx_2(p0) :: (load 1) |
| |
| %byte1:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| %byte3:_(s32) = nuw G_SHL %elt3, %cst_24(s32) |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %byte2, %byte3 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| ... |
| --- |
| name: dont_combine_duplicate_offset |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; If two of the G_SHLs have the same constant, then we should not combine. |
| ; |
| ; sN *x = ... |
| ; sM y = (x[i] << A) | (x[i+1] << A) ... |
| |
| ; LITTLE-LABEL: name: dont_combine_duplicate_offset |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; LITTLE: %cst_2:_(s32) = G_CONSTANT i32 2 |
| ; LITTLE: %cst_3:_(s32) = G_CONSTANT i32 3 |
| ; LITTLE: %cst_8:_(s32) = G_CONSTANT i32 8 |
| ; LITTLE: %duplicate_shl_cst:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; LITTLE: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| ; LITTLE: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| ; LITTLE: %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| ; LITTLE: %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| ; LITTLE: %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| ; LITTLE: %byte1:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| ; LITTLE: %duplicate_shl_1:_(s32) = nuw G_SHL %elt2, %duplicate_shl_cst(s32) |
| ; LITTLE: %duplicate_shl_2:_(s32) = nuw G_SHL %elt3, %duplicate_shl_cst(s32) |
| ; LITTLE: %or1:_(s32) = G_OR %byte0, %byte1 |
| ; LITTLE: %or2:_(s32) = G_OR %duplicate_shl_1, %duplicate_shl_2 |
| ; LITTLE: %full_load:_(s32) = G_OR %or1, %or2 |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_duplicate_offset |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; BIG: %cst_2:_(s32) = G_CONSTANT i32 2 |
| ; BIG: %cst_3:_(s32) = G_CONSTANT i32 3 |
| ; BIG: %cst_8:_(s32) = G_CONSTANT i32 8 |
| ; BIG: %duplicate_shl_cst:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; BIG: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| ; BIG: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| ; BIG: %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| ; BIG: %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| ; BIG: %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| ; BIG: %byte1:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| ; BIG: %duplicate_shl_1:_(s32) = nuw G_SHL %elt2, %duplicate_shl_cst(s32) |
| ; BIG: %duplicate_shl_2:_(s32) = nuw G_SHL %elt3, %duplicate_shl_cst(s32) |
| ; BIG: %or1:_(s32) = G_OR %byte0, %byte1 |
| ; BIG: %or2:_(s32) = G_OR %duplicate_shl_1, %duplicate_shl_2 |
| ; BIG: %full_load:_(s32) = G_OR %or1, %or2 |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s32) = G_CONSTANT i32 1 |
| %cst_2:_(s32) = G_CONSTANT i32 2 |
| %cst_3:_(s32) = G_CONSTANT i32 3 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %duplicate_shl_cst:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| |
| %byte0:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| |
| %byte1:_(s32) = nuw G_SHL %elt1, %cst_8(s32) |
| %duplicate_shl_1:_(s32) = nuw G_SHL %elt2, %duplicate_shl_cst(s32) |
| %duplicate_shl_2:_(s32) = nuw G_SHL %elt3, %duplicate_shl_cst(s32) |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %duplicate_shl_1, %duplicate_shl_2 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_lowest_index_not_zero_offset |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; In this case, the lowest index load (e.g. x[0]) does not end up at byte |
| ; offset 0. We shouldn't combine. |
| ; |
| ; s8 *x = ... |
| ; s32 y = (x[0] << 8) | (x[1]) | (x[2] << 16) ... |
| |
| ; LITTLE-LABEL: name: dont_combine_lowest_index_not_zero_offset |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; LITTLE: %cst_2:_(s32) = G_CONSTANT i32 2 |
| ; LITTLE: %cst_3:_(s32) = G_CONSTANT i32 3 |
| ; LITTLE: %cst_8:_(s32) = G_CONSTANT i32 8 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %cst_24:_(s32) = G_CONSTANT i32 24 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; LITTLE: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| ; LITTLE: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| ; LITTLE: %lowest_idx_load:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| ; LITTLE: %byte0:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| ; LITTLE: %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| ; LITTLE: %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| ; LITTLE: %byte1:_(s32) = nuw G_SHL %lowest_idx_load, %cst_8(s32) |
| ; LITTLE: %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| ; LITTLE: %byte3:_(s32) = nuw G_SHL %elt3, %cst_24(s32) |
| ; LITTLE: %or1:_(s32) = G_OR %byte0, %byte1 |
| ; LITTLE: %or2:_(s32) = G_OR %byte2, %byte3 |
| ; LITTLE: %full_load:_(s32) = G_OR %or1, %or2 |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_lowest_index_not_zero_offset |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s32) = G_CONSTANT i32 1 |
| ; BIG: %cst_2:_(s32) = G_CONSTANT i32 2 |
| ; BIG: %cst_3:_(s32) = G_CONSTANT i32 3 |
| ; BIG: %cst_8:_(s32) = G_CONSTANT i32 8 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %cst_24:_(s32) = G_CONSTANT i32 24 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| ; BIG: %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| ; BIG: %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| ; BIG: %lowest_idx_load:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| ; BIG: %byte0:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| ; BIG: %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| ; BIG: %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| ; BIG: %byte1:_(s32) = nuw G_SHL %lowest_idx_load, %cst_8(s32) |
| ; BIG: %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| ; BIG: %byte3:_(s32) = nuw G_SHL %elt3, %cst_24(s32) |
| ; BIG: %or1:_(s32) = G_OR %byte0, %byte1 |
| ; BIG: %or2:_(s32) = G_OR %byte2, %byte3 |
| ; BIG: %full_load:_(s32) = G_OR %or1, %or2 |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s32) = G_CONSTANT i32 1 |
| %cst_2:_(s32) = G_CONSTANT i32 2 |
| %cst_3:_(s32) = G_CONSTANT i32 3 |
| |
| %cst_8:_(s32) = G_CONSTANT i32 8 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| %cst_24:_(s32) = G_CONSTANT i32 24 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s32) |
| %ptr_elt_2:_(p0) = G_PTR_ADD %ptr, %cst_2(s32) |
| %ptr_elt_3:_(p0) = G_PTR_ADD %ptr, %cst_3(s32) |
| |
| ; This load is index 0 |
| %lowest_idx_load:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 1) |
| %byte0:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 1) |
| %elt2:_(s32) = G_ZEXTLOAD %ptr_elt_2(p0) :: (load 1) |
| %elt3:_(s32) = G_ZEXTLOAD %ptr_elt_3(p0) :: (load 1) |
| |
| ; ... But it ends up being shifted, so we shouldn't combine. |
| %byte1:_(s32) = nuw G_SHL %lowest_idx_load, %cst_8(s32) |
| %byte2:_(s32) = nuw G_SHL %elt2, %cst_16(s32) |
| %byte3:_(s32) = nuw G_SHL %elt3, %cst_24(s32) |
| |
| %or1:_(s32) = G_OR %byte0, %byte1 |
| %or2:_(s32) = G_OR %byte2, %byte3 |
| %full_load:_(s32) = G_OR %or1, %or2 |
| |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_more_than_one_use_load |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; If any load is used more than once, don't combine. We want to remove the |
| ; entire tree. |
| |
| ; LITTLE-LABEL: name: dont_combine_more_than_one_use_load |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: %extra_use:_(s32) = G_AND %full_load, %low_half |
| ; LITTLE: $w1 = COPY %extra_use(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_more_than_one_use_load |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: %extra_use:_(s32) = G_AND %full_load, %low_half |
| ; BIG: $w1 = COPY %extra_use(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| %extra_use:_(s32) = G_AND %full_load, %low_half |
| $w1 = COPY %extra_use(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_more_than_one_use_shl |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; If anything feeding into any of the ors is used more than once, don't |
| ; combine. |
| |
| ; LITTLE-LABEL: name: dont_combine_more_than_one_use_shl |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: %extra_use:_(s32) = G_AND %full_load, %high_half |
| ; LITTLE: $w1 = COPY %extra_use(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_more_than_one_use_shl |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: %extra_use:_(s32) = G_AND %full_load, %high_half |
| ; BIG: $w1 = COPY %extra_use(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| %extra_use:_(s32) = G_AND %full_load, %high_half |
| $w1 = COPY %extra_use(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_store_between_same_mbb |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| ; If there is a store between any of the loads, then do not combine. |
| |
| ; LITTLE-LABEL: name: dont_combine_store_between_same_mbb |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: %other_ptr:_(p0) = COPY $x1 |
| ; LITTLE: %some_val:_(s32) = G_CONSTANT i32 12 |
| ; LITTLE: G_STORE %some_val(s32), %other_ptr(p0) :: (store 2) |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_store_between_same_mbb |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: %other_ptr:_(p0) = COPY $x1 |
| ; BIG: %some_val:_(s32) = G_CONSTANT i32 12 |
| ; BIG: G_STORE %some_val(s32), %other_ptr(p0) :: (store 2) |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| |
| ; Memory could be modified here, so don't combine! |
| %other_ptr:_(p0) = COPY $x1 |
| %some_val:_(s32) = G_CONSTANT i32 12 |
| G_STORE %some_val, %other_ptr :: (store 2) |
| |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: dont_combine_store_between_different_mbb |
| tracksRegLiveness: true |
| body: | |
| ; There is a store between the two loads, hidden away in a different MBB. |
| ; We should not combine here. |
| |
| ; LITTLE-LABEL: name: dont_combine_store_between_different_mbb |
| ; LITTLE: bb.0: |
| ; LITTLE: successors: %bb.1(0x80000000) |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: bb.1: |
| ; LITTLE: successors: %bb.2(0x80000000) |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %other_ptr:_(p0) = COPY $x1 |
| ; LITTLE: %some_val:_(s32) = G_CONSTANT i32 12 |
| ; LITTLE: G_STORE %some_val(s32), %other_ptr(p0) :: (store 2) |
| ; LITTLE: bb.2: |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: dont_combine_store_between_different_mbb |
| ; BIG: bb.0: |
| ; BIG: successors: %bb.1(0x80000000) |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: bb.1: |
| ; BIG: successors: %bb.2(0x80000000) |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %other_ptr:_(p0) = COPY $x1 |
| ; BIG: %some_val:_(s32) = G_CONSTANT i32 12 |
| ; BIG: G_STORE %some_val(s32), %other_ptr(p0) :: (store 2) |
| ; BIG: bb.2: |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| |
| bb.0: |
| successors: %bb.1(0x80000000) |
| liveins: $x0, $x1 |
| ; If there is a store between any of the loads, then do not combine. |
| |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| |
| bb.1: |
| liveins: $x0, $x1 |
| successors: %bb.2(0x80000000) |
| ; Memory could be modified here, so don't combine! |
| %other_ptr:_(p0) = COPY $x1 |
| %some_val:_(s32) = G_CONSTANT i32 12 |
| G_STORE %some_val, %other_ptr :: (store 2) |
| |
| bb.2: |
| liveins: $x0, $x1 |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: different_mbb |
| tracksRegLiveness: true |
| body: | |
| ; It should be possible to combine here, but it's not supported right now. |
| |
| ; LITTLE-LABEL: name: different_mbb |
| ; LITTLE: bb.0: |
| ; LITTLE: successors: %bb.1(0x80000000) |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; LITTLE: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; LITTLE: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; LITTLE: bb.1: |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; LITTLE: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; LITTLE: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: different_mbb |
| ; BIG: bb.0: |
| ; BIG: successors: %bb.1(0x80000000) |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %cst_1:_(s64) = G_CONSTANT i64 1 |
| ; BIG: %cst_16:_(s32) = G_CONSTANT i32 16 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| ; BIG: %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| ; BIG: bb.1: |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| ; BIG: %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| ; BIG: %full_load:_(s32) = G_OR %low_half, %high_half |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| |
| bb.0: |
| successors: %bb.1(0x80000000) |
| liveins: $x0, $x1 |
| |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| |
| bb.1: |
| liveins: $x0, $x1 |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |
| |
| ... |
| --- |
| name: load_first |
| tracksRegLiveness: true |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| ; Test for a bug fix for predecessor-checking code. |
| |
| ; LITTLE-LABEL: name: load_first |
| ; LITTLE: liveins: $x0, $x1 |
| ; LITTLE: %ptr:_(p0) = COPY $x1 |
| ; LITTLE: %full_load:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 2) |
| ; LITTLE: $w1 = COPY %full_load(s32) |
| ; LITTLE: RET_ReallyLR implicit $w1 |
| ; BIG-LABEL: name: load_first |
| ; BIG: liveins: $x0, $x1 |
| ; BIG: %ptr:_(p0) = COPY $x1 |
| ; BIG: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD %ptr(p0) :: (load 4, align 2) |
| ; BIG: %full_load:_(s32) = G_BSWAP [[LOAD]] |
| ; BIG: $w1 = COPY %full_load(s32) |
| ; BIG: RET_ReallyLR implicit $w1 |
| %low_half:_(s32) = G_ZEXTLOAD %ptr(p0) :: (load 2) |
| %cst_1:_(s64) = G_CONSTANT i64 1 |
| %cst_16:_(s32) = G_CONSTANT i32 16 |
| |
| %ptr:_(p0) = COPY $x1 |
| %ptr_elt_1:_(p0) = G_PTR_ADD %ptr, %cst_1(s64) |
| |
| %elt1:_(s32) = G_ZEXTLOAD %ptr_elt_1(p0) :: (load 2) |
| %high_half:_(s32) = nuw G_SHL %elt1, %cst_16(s32) |
| |
| %full_load:_(s32) = G_OR %low_half, %high_half |
| $w1 = COPY %full_load(s32) |
| RET_ReallyLR implicit $w1 |