[CodeGenPrepare] Fix counting uses when folding addresses into memory instructions
authorMomchil Velikov <momchil.velikov@arm.com>
Thu, 30 Mar 2023 12:31:45 +0000 (13:31 +0100)
committerMomchil Velikov <momchil.velikov@arm.com>
Thu, 30 Mar 2023 13:18:14 +0000 (14:18 +0100)
The counter of the number of instructions seen in `FindAllMemoryUses`
is reset after returning from a recursive invocation of
`FindAllMemoryUses` to the value it had before the call. In effect,
depending on the shape of the uses graph, the function may scan up to
`2^N-1` instructions where `N` is the scan limit
(`MaxMemoryUsesToScan`).  This does not look intuitive or intended.

This patch changes the counting to just count the scanned
instructions, independent of the shape of the references.

Reviewed By: mkazantsev

Differential Revision: https://reviews.llvm.org/D143893

Change-Id: I99f5de55e84843cf2fbea287d6ae4312fa196240

llvm/lib/CodeGen/CodeGenPrepare.cpp
llvm/test/CodeGen/Generic/addr-use-count.ll

index ddbba80..db3aa72 100644 (file)
@@ -4972,7 +4972,7 @@ static bool FindAllMemoryUses(
     Instruction *I, SmallVectorImpl<std::pair<Value *, Type *>> &MemoryUses,
     SmallPtrSetImpl<Instruction *> &ConsideredInsts, const TargetLowering &TLI,
     const TargetRegisterInfo &TRI, bool OptSize, ProfileSummaryInfo *PSI,
-    BlockFrequencyInfo *BFI, int SeenInsts = 0) {
+    BlockFrequencyInfo *BFI, int &SeenInsts) {
   // If we already considered this instruction, we're done.
   if (!ConsideredInsts.insert(I).second)
     return false;
@@ -5043,6 +5043,17 @@ static bool FindAllMemoryUses(
   return false;
 }
 
+static bool FindAllMemoryUses(
+    Instruction *I, SmallVectorImpl<std::pair<Value *, Type *>> &MemoryUses,
+    const TargetLowering &TLI, const TargetRegisterInfo &TRI, bool OptSize,
+    ProfileSummaryInfo *PSI, BlockFrequencyInfo *BFI) {
+  int SeenInsts = 0;
+  SmallPtrSet<Instruction *, 16> ConsideredInsts;
+  return FindAllMemoryUses(I, MemoryUses, ConsideredInsts, TLI, TRI, OptSize,
+                           PSI, BFI, SeenInsts);
+}
+
+
 /// Return true if Val is already known to be live at the use site that we're
 /// folding it into. If so, there is no cost to include it in the addressing
 /// mode. KnownLive1 and KnownLive2 are two values that we know are live at the
@@ -5125,9 +5136,7 @@ bool AddressingModeMatcher::isProfitableToFoldIntoAddressingMode(
   // for another (at worst.)  In this context, folding an addressing mode into
   // the use is just a particularly nice way of sinking it.
   SmallVector<std::pair<Value *, Type *>, 16> MemoryUses;
-  SmallPtrSet<Instruction *, 16> ConsideredInsts;
-  if (FindAllMemoryUses(I, MemoryUses, ConsideredInsts, TLI, TRI, OptSize, PSI,
-                        BFI))
+  if (FindAllMemoryUses(I, MemoryUses, TLI, TRI, OptSize, PSI, BFI))
     return false; // Has a non-memory, non-foldable use!
 
   // Now that we know that all uses of this instruction are part of a chain of
index a3b110b..825d432 100644 (file)
@@ -2,7 +2,7 @@
 ; RUN: opt -S -codegenprepare < %s | FileCheck %s
 ; REQUIRES: aarch64-registered-target
 
-; Test that `%addr` is sunk, even though the number of memory uses to scan exceeds the limit.
+; Test that `%addr` is not sunk, since the number of memory uses to scan exceeds the limit.
 
 target triple = "aarch64-linux"
 
@@ -11,28 +11,30 @@ declare void @g(...)
 define void @f(ptr %p) {
 ; CHECK-LABEL: @f(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[SUNKADDR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 4
-; CHECK-NEXT:    [[T0:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T1:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T2:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T3:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T4:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T5:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T6:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T7:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T8:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T9:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T10:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T11:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T12:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T13:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T14:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T15:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T16:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T17:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[T18:%.*]] = load i32, ptr [[SUNKADDR]], align 4
-; CHECK-NEXT:    [[SUNKADDR1:%.*]] = getelementptr i8, ptr [[P]], i64 8
-; CHECK-NEXT:    [[T19:%.*]] = load i32, ptr [[SUNKADDR1]], align 4
+; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 4
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[T0:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T1:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T2:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T3:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T4:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T5:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T6:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T7:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T8:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T9:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T10:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T11:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T12:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T13:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T14:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T15:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T16:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T17:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[T18:%.*]] = load i32, ptr [[ADDR]], align 4
+; CHECK-NEXT:    [[ADDR_1:%.*]] = getelementptr i8, ptr [[ADDR]], i32 4
+; CHECK-NEXT:    [[T19:%.*]] = load i32, ptr [[ADDR_1]], align 4
 ; CHECK-NEXT:    call void @g(i32 [[T0]], i32 [[T1]], i32 [[T2]], i32 [[T3]], i32 [[T4]], i32 [[T5]], i32 [[T6]], i32 [[T7]], i32 [[T8]], i32 [[T9]], i32 [[T10]], i32 [[T11]], i32 [[T12]], i32 [[T13]], i32 [[T14]], i32 [[T15]], i32 [[T16]], i32 [[T17]], i32 [[T18]], i32 [[T19]])
 ; CHECK-NEXT:    ret void
 ;