# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s --- | @g = external hidden unnamed_addr global i32, align 4 define void @not_necessarily_equiv_loads() { ret void } define void @invariant_loads() { ret void } define void @both_have_to_be_invariant_1() { ret void } define void @both_have_to_be_invariant_2() { ret void } define void @both_have_to_have_same_size() { ret void } ... --- name: not_necessarily_equiv_loads tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: ; %load1 || %load2 == %load1 is not necessarily true, even though they ; both load from the same address. Whatever is in that address may be ; changed by another instruction which appears between them. ; ; Check that we don't remove the G_OR. ; CHECK-LABEL: name: not_necessarily_equiv_loads ; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g ; CHECK-NEXT: %load1:_(s32) = G_LOAD %ptr(p0) :: (load (s32) from @g) ; CHECK-NEXT: %load2:_(s32) = G_LOAD %ptr(p0) :: (load (s32) from @g) ; CHECK-NEXT: %or:_(s32) = G_OR %load2, %load1 ; CHECK-NEXT: G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) ; CHECK-NEXT: RET_ReallyLR %ptr:_(p0) = G_GLOBAL_VALUE @g %load1:_(s32) = G_LOAD %ptr(p0) :: (load (s32) from @g) %load2:_(s32) = G_LOAD %ptr(p0) :: (load (s32) from @g) %or:_(s32) = G_OR %load2, %load1 G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) RET_ReallyLR ... --- name: invariant_loads tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: ; %load1 || %load2 == %load1 is fine here, because the loads are invariant. ; CHECK-LABEL: name: invariant_loads ; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g ; CHECK-NEXT: %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) ; CHECK-NEXT: G_STORE %load2(s32), %ptr(p0) :: (store (s32) into @g) ; CHECK-NEXT: RET_ReallyLR %ptr:_(p0) = G_GLOBAL_VALUE @g %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) %or:_(s32) = G_OR %load2, %load1 G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) RET_ReallyLR ... --- name: both_have_to_be_invariant_1 tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: ; We shouldn't combine here, because the loads both have to be invariant. ; CHECK-LABEL: name: both_have_to_be_invariant_1 ; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g ; CHECK-NEXT: %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) ; CHECK-NEXT: %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable load (s32) from @g) ; CHECK-NEXT: %or:_(s32) = G_OR %load2, %load1 ; CHECK-NEXT: G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) ; CHECK-NEXT: RET_ReallyLR %ptr:_(p0) = G_GLOBAL_VALUE @g %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable load (s32) from @g) %or:_(s32) = G_OR %load2, %load1 G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) RET_ReallyLR ... --- name: both_have_to_be_invariant_2 tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: ; We shouldn't combine here, because the loads both have to be invariant. ; CHECK-LABEL: name: both_have_to_be_invariant_2 ; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g ; CHECK-NEXT: %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable load (s32) from @g) ; CHECK-NEXT: %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) ; CHECK-NEXT: %or:_(s32) = G_OR %load2, %load1 ; CHECK-NEXT: G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) ; CHECK-NEXT: RET_ReallyLR %ptr:_(p0) = G_GLOBAL_VALUE @g %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable load (s32) from @g) %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g) %or:_(s32) = G_OR %load2, %load1 G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) RET_ReallyLR ... --- name: both_have_to_have_same_size tracksRegLiveness: true machineFunctionInfo: {} body: | bb.0: ; We shouldn't combine here, because the loads both have to have the same size. ; CHECK-LABEL: name: both_have_to_have_same_size ; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g ; CHECK-NEXT: %load1:_(s32) = G_ZEXTLOAD %ptr(p0) :: (dereferenceable invariant load (s8) from @g) ; CHECK-NEXT: %load2:_(s32) = G_ZEXTLOAD %ptr(p0) :: (dereferenceable invariant load (s16) from @g) ; CHECK-NEXT: %or:_(s32) = G_OR %load2, %load1 ; CHECK-NEXT: G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) ; CHECK-NEXT: RET_ReallyLR %ptr:_(p0) = G_GLOBAL_VALUE @g %load1:_(s32) = G_ZEXTLOAD %ptr(p0) :: (dereferenceable invariant load (s8) from @g) %load2:_(s32) = G_ZEXTLOAD %ptr(p0) :: (dereferenceable invariant load (s16) from @g) %or:_(s32) = G_OR %load2, %load1 G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g) RET_ReallyLR ...