| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py |
| # RUN: llc -mtriple aarch64-apple-darwin -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s |
| |
| --- | |
| @g = external hidden global i32 |
| |
| %opaque = type opaque |
| @unsized = external hidden global %opaque |
| @thread_local = thread_local global i32 0 |
| |
| define void @one_ptr_add() { ret void } |
| define void @add_to_offset() { ret void } |
| define void @two_ptr_adds_same_offset() { ret void } |
| define void @two_ptr_adds_different_offset() { ret void } |
| define void @ptr_add_chain() { ret void } |
| |
| define void @dont_fold_negative_offset() { ret void } |
| define void @dont_min_offset_less_than_curr_offset() { ret void } |
| define void @dont_fold_max_offset() { ret void } |
| define void @dont_fold_offset_larger_than_type_alloc() { ret void } |
| define void @dont_fold_unsized_type() { ret void } |
| define void @dont_fold_thread_local() { ret void } |
| ... |
| --- |
| name: one_ptr_add |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| liveins: $x0 |
| |
| ; We should fold the offset 1 into the G_GLOBAL_VALUE. |
| |
| ; CHECK-LABEL: name: one_ptr_add |
| ; CHECK: liveins: $x0 |
| ; CHECK: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @g + 1 |
| ; CHECK: $x0 = COPY [[GV]](p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @g |
| %offset:_(s64) = G_CONSTANT i64 1 |
| %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| $x0 = COPY %ptr_add |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: add_to_offset |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| liveins: $x0 |
| |
| ; We should fold the offset 1 into the G_GLOBAL_VALUE, resulting in a |
| ; final offset of 4. |
| |
| ; CHECK-LABEL: name: add_to_offset |
| ; CHECK: liveins: $x0 |
| ; CHECK: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @g + 4 |
| ; CHECK: $x0 = COPY [[GV]](p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @g + 3 |
| %offset:_(s64) = G_CONSTANT i64 1 |
| %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| $x0 = COPY %ptr_add |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: two_ptr_adds_same_offset |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| |
| ; We're allowed to have more than one G_PTR_ADD use. We should fold 1 into |
| ; the G_GLOBAL_VALUE's offset. |
| |
| ; CHECK-LABEL: name: two_ptr_adds_same_offset |
| ; CHECK: liveins: $x0, $x1 |
| ; CHECK: %val1:_(s64) = COPY $x0 |
| ; CHECK: %val2:_(s64) = COPY $x1 |
| ; CHECK: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @g + 1 |
| ; CHECK: G_STORE %val1(s64), [[GV]](p0) :: (store (s64)) |
| ; CHECK: G_STORE %val2(s64), [[GV]](p0) :: (store (s64)) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %val1:_(s64) = COPY $x0 |
| %val2:_(s64) = COPY $x1 |
| %global:_(p0) = G_GLOBAL_VALUE @g |
| %offset:_(s64) = G_CONSTANT i64 1 |
| %ptr_add1:_(p0) = G_PTR_ADD %global, %offset(s64) |
| %ptr_add2:_(p0) = G_PTR_ADD %global, %offset(s64) |
| G_STORE %val1:_(s64), %ptr_add1 :: (store (s64)) |
| G_STORE %val2:_(s64), %ptr_add2 :: (store (s64)) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: two_ptr_adds_different_offset |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| liveins: $x0, $x1 |
| ; The lowest offset G_PTR_ADD (2) should be folded into the G_GLOBAL_VALUE. |
| ; |
| ; The other G_PTR_ADD should have its offset decremented by 2. |
| |
| ; CHECK-LABEL: name: two_ptr_adds_different_offset |
| ; CHECK: liveins: $x0, $x1 |
| ; CHECK: %val1:_(s64) = COPY $x0 |
| ; CHECK: %val2:_(s64) = COPY $x1 |
| ; CHECK: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @g + 2 |
| ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 8 |
| ; CHECK: %ptr_add2:_(p0) = G_PTR_ADD [[GV]], [[C]](s64) |
| ; CHECK: G_STORE %val1(s64), [[GV]](p0) :: (store (s64)) |
| ; CHECK: G_STORE %val2(s64), %ptr_add2(p0) :: (store (s64)) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %val1:_(s64) = COPY $x0 |
| %val2:_(s64) = COPY $x1 |
| %global:_(p0) = G_GLOBAL_VALUE @g |
| %offset1:_(s64) = G_CONSTANT i64 2 |
| %offset2:_(s64) = G_CONSTANT i64 10 |
| %ptr_add1:_(p0) = G_PTR_ADD %global, %offset1(s64) |
| %ptr_add2:_(p0) = G_PTR_ADD %global, %offset2(s64) |
| G_STORE %val1:_(s64), %ptr_add1 :: (store (s64)) |
| G_STORE %val2:_(s64), %ptr_add2 :: (store (s64)) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: ptr_add_chain |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| liveins: $x0 |
| ; We should be able to fold all of the G_PTR_ADDs, except for the last one |
| ; into the G_GLOBAL_VALUE. |
| ; |
| ; (TypeAllocSize = 4, so the offset on the G_GLOBAL_VALUE can't go above |
| ; that.) |
| |
| ; CHECK-LABEL: name: ptr_add_chain |
| ; CHECK: liveins: $x0 |
| ; CHECK: [[GV:%[0-9]+]]:_(p0) = G_GLOBAL_VALUE @g + 1 |
| ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 |
| ; CHECK: %dont_fold_me:_(p0) = G_PTR_ADD [[GV]], [[C]](s64) |
| ; CHECK: $x0 = COPY %dont_fold_me(p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @g |
| %offset:_(s64) = G_CONSTANT i64 1 |
| %ptr_add1:_(p0) = G_PTR_ADD %global, %offset(s64) |
| %ptr_add2:_(p0) = G_PTR_ADD %ptr_add1, %offset(s64) |
| %ptr_add3:_(p0) = G_PTR_ADD %ptr_add2, %offset(s64) |
| %ptr_add4:_(p0) = G_PTR_ADD %ptr_add3, %offset(s64) |
| %dont_fold_me:_(p0) = G_PTR_ADD %ptr_add4, %offset(s64) |
| $x0 = COPY %dont_fold_me |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_fold_negative_offset |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| liveins: $x0 |
| |
| ; Do not add negative offsets to G_GLOBAL_VALUE. |
| |
| ; CHECK-LABEL: name: dont_fold_negative_offset |
| ; CHECK: liveins: $x0 |
| ; CHECK: %global:_(p0) = G_GLOBAL_VALUE @g |
| ; CHECK: %offset:_(s64) = G_CONSTANT i64 -1 |
| ; CHECK: %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| ; CHECK: $x0 = COPY %ptr_add(p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @g |
| %offset:_(s64) = G_CONSTANT i64 -1 |
| %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| $x0 = COPY %ptr_add |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_min_offset_less_than_curr_offset |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| liveins: $x0 |
| |
| ; Do not create smaller offsets. Ensures combine termination. |
| |
| ; CHECK-LABEL: name: dont_min_offset_less_than_curr_offset |
| ; CHECK: liveins: $x0 |
| ; CHECK: %global:_(p0) = G_GLOBAL_VALUE @g + 3 |
| ; CHECK: %offset:_(s64) = G_CONSTANT i64 -1 |
| ; CHECK: %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| ; CHECK: $x0 = COPY %ptr_add(p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @g + 3 |
| %offset:_(s64) = G_CONSTANT i64 -1 |
| %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| $x0 = COPY %ptr_add |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_fold_max_offset |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| liveins: $x0 |
| |
| ; 1 << 21 is the largest offset expressible in all object formats. |
| ; Don't fold it. |
| |
| ; CHECK-LABEL: name: dont_fold_max_offset |
| ; CHECK: liveins: $x0 |
| ; CHECK: %global:_(p0) = G_GLOBAL_VALUE @g |
| ; CHECK: %offset:_(s64) = G_CONSTANT i64 4292870144 |
| ; CHECK: %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| ; CHECK: $x0 = COPY %ptr_add(p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @g |
| %offset:_(s64) = G_CONSTANT i64 4292870144 ; 1 << 21 |
| %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| $x0 = COPY %ptr_add |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_fold_offset_larger_than_type_alloc |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| |
| ; Type alloc size = 4, offset = 16. Don't fold. |
| |
| ; CHECK-LABEL: name: dont_fold_offset_larger_than_type_alloc |
| ; CHECK: %global:_(p0) = G_GLOBAL_VALUE @g |
| ; CHECK: %offset:_(s64) = G_CONSTANT i64 16 |
| ; CHECK: %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| ; CHECK: $x0 = COPY %ptr_add(p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @g |
| %offset:_(s64) = G_CONSTANT i64 16 |
| %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| $x0 = COPY %ptr_add(p0) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_fold_unsized_type |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| ; Check that we don't touch unsized globals. |
| |
| ; CHECK-LABEL: name: dont_fold_unsized_type |
| ; CHECK: %global:_(p0) = G_GLOBAL_VALUE @unsized |
| ; CHECK: %offset:_(s64) = G_CONSTANT i64 16 |
| ; CHECK: %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| ; CHECK: $x0 = COPY %ptr_add(p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @unsized |
| %offset:_(s64) = G_CONSTANT i64 16 |
| %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| $x0 = COPY %ptr_add(p0) |
| RET_ReallyLR implicit $x0 |
| |
| ... |
| --- |
| name: dont_fold_thread_local |
| alignment: 4 |
| tracksRegLiveness: true |
| machineFunctionInfo: {} |
| body: | |
| bb.0: |
| ; Check that we don't touch thread-local globals. |
| |
| ; CHECK-LABEL: name: dont_fold_thread_local |
| ; CHECK: %global:_(p0) = G_GLOBAL_VALUE @thread_local |
| ; CHECK: %offset:_(s64) = G_CONSTANT i64 16 |
| ; CHECK: %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| ; CHECK: $x0 = COPY %ptr_add(p0) |
| ; CHECK: RET_ReallyLR implicit $x0 |
| %global:_(p0) = G_GLOBAL_VALUE @thread_local |
| %offset:_(s64) = G_CONSTANT i64 16 |
| %ptr_add:_(p0) = G_PTR_ADD %global, %offset(s64) |
| $x0 = COPY %ptr_add(p0) |
| RET_ReallyLR implicit $x0 |