[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