[llvm] cd4ed08 - [GlobalISel] Don't combine instructions which are fed by memory instructions using different size
Jessica Paquette via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 4 15:01:05 PST 2022
Author: Róbert Ágoston
Date: 2022-02-04T15:00:47-08:00
New Revision: cd4ed08b5aa1d7a3437e9c80dc68092b24da821d
URL: https://github.com/llvm/llvm-project/commit/cd4ed08b5aa1d7a3437e9c80dc68092b24da821d
DIFF: https://github.com/llvm/llvm-project/commit/cd4ed08b5aa1d7a3437e9c80dc68092b24da821d.diff
LOG: [GlobalISel] Don't combine instructions which are fed by memory instructions using different size
Memory instructions like extending loads from the same address are not equal if
their size is not equal.
This fixes https://github.com/llvm/llvm-project/issues/53524.
Differential Revision: https://reviews.llvm.org/D118805
Added:
Modified:
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 20677dcb0cd7a..e9bec116cc87a 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2368,6 +2368,19 @@ bool CombinerHelper::matchEqualDefs(const MachineOperand &MOP1,
if (I1->mayLoadOrStore() && !I1->isDereferenceableInvariantLoad(nullptr))
return false;
+ // If both instructions are loads or stores, they are equal only if both
+ // are dereferenceable invariant loads with the same number of bits.
+ if (I1->mayLoadOrStore() && I2->mayLoadOrStore()) {
+ GLoadStore *LS1 = dyn_cast<GLoadStore>(I1);
+ GLoadStore *LS2 = dyn_cast<GLoadStore>(I2);
+ if (!LS1 || !LS2)
+ return false;
+
+ if (!I2->isDereferenceableInvariantLoad(nullptr) ||
+ (LS1->getMemSizeInBits() != LS2->getMemSizeInBits()))
+ return false;
+ }
+
// Check for physical registers on the instructions first to avoid cases
// like this:
//
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir
index b8187de6157bb..76cfad48e16fe 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-not-really-equiv-insts.mir
@@ -5,7 +5,10 @@
@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() { 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
@@ -22,11 +25,11 @@ body: |
; CHECK-LABEL: name: not_necessarily_equiv_loads
; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g
- ; CHECK: %load1:_(s32) = G_LOAD %ptr(p0) :: (load (s32) from @g)
- ; CHECK: %load2:_(s32) = G_LOAD %ptr(p0) :: (load (s32) from @g)
- ; CHECK: %or:_(s32) = G_OR %load2, %load1
- ; CHECK: G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g)
- ; CHECK: RET_ReallyLR
+ ; 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)
@@ -46,9 +49,9 @@ body: |
; CHECK-LABEL: name: invariant_loads
; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g
- ; CHECK: %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g)
- ; CHECK: G_STORE %load2(s32), %ptr(p0) :: (store (s32) into @g)
- ; CHECK: RET_ReallyLR
+ ; 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)
@@ -58,7 +61,7 @@ body: |
...
---
-name: both_have_to_be_invariant
+name: both_have_to_be_invariant_1
tracksRegLiveness: true
machineFunctionInfo: {}
body: |
@@ -66,13 +69,13 @@ body: |
; We shouldn't combine here, because the loads both have to be invariant.
- ; CHECK-LABEL: name: both_have_to_be_invariant
+ ; CHECK-LABEL: name: both_have_to_be_invariant_1
; CHECK: %ptr:_(p0) = G_GLOBAL_VALUE @g
- ; CHECK: %load1:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable invariant load (s32) from @g)
- ; CHECK: %load2:_(s32) = G_LOAD %ptr(p0) :: (dereferenceable load (s32) from @g)
- ; CHECK: %or:_(s32) = G_OR %load2, %load1
- ; CHECK: G_STORE %or(s32), %ptr(p0) :: (store (s32) into @g)
- ; CHECK: RET_ReallyLR
+ ; 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)
@@ -80,3 +83,49 @@ body: |
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
+...
More information about the llvm-commits
mailing list