[LSR] Don't consider users of constant outside loop
authorNikita Popov <npopov@redhat.com>
Wed, 12 Jul 2023 10:35:01 +0000 (12:35 +0200)
committerNikita Popov <npopov@redhat.com>
Thu, 13 Jul 2023 10:22:38 +0000 (12:22 +0200)
In CollectLoopInvariantFixupsAndFormulae(), LSR looks at users
outside the loop. E.g. if we have an addrec based on %base, and
%base is also used outside the loop, then we have to keep it in a
register anyway, which may make it more profitable to use
%base + %idx style addressing.

This reasoning doesn't hold up when the base is a constant, because
the constant can be rematerialized. The lsr-memcpy.ll test regressed
when enabling opaque pointers, because inttoptr (i64 6442450944 to ptr)
now also has a use outside the loop (previously it didn't due to a
pointer type difference), and that extra "use" results in worse use
of addressing modes in the loop. However, the use outside the loop
actually gets rematerialized, so the alleged register saving does
not occur.

The same reasoning also applies to other types of constants, such
as global variable references.

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

llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
llvm/test/Transforms/LoopStrengthReduce/AArch64/lsr-memcpy.ll

index 905f84efcae58e1c7f05bd8c1a4f97b5a6c55f82..be7784faeea22863e6e9b345119d9a6ff19f4ca9 100644 (file)
@@ -3507,8 +3507,8 @@ LSRInstance::CollectLoopInvariantFixupsAndFormulae() {
       if (const Instruction *Inst = dyn_cast<Instruction>(V)) {
         // Look for instructions defined outside the loop.
         if (L->contains(Inst)) continue;
-      } else if (isa<UndefValue>(V))
-        // Undef doesn't have a live range, so it doesn't matter.
+      } else if (isa<Constant>(V))
+        // Constants can be re-materialized.
         continue;
       for (const Use &U : V->uses()) {
         const Instruction *UserInst = dyn_cast<Instruction>(U.getUser());
index 8092d598f85fbe0aa5db8df78203249fdfa2c1e3..2521f3e84475a272ca604d53aa9528c5a9c34c10 100644 (file)
@@ -7,21 +7,18 @@
 ; <rdar://problem/12702735> [ARM64][coalescer] need better register
 ; coalescing for simple unit tests.
 
-; FIXME: This regressed after enabling opaque pointers.
 define i32 @test_inttoptr() nounwind {
 ; CHECK-LABEL: test_inttoptr:
 ; CHECK:       // %bb.0: // %entry
 ; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
-; CHECK-NEXT:    mov x8, #0 // =0x0
-; CHECK-NEXT:    mov w9, #1288 // =0x508
-; CHECK-NEXT:    mov x10, #4294967296 // =0x100000000
-; CHECK-NEXT:    mov x11, #6442450944 // =0x180000000
+; CHECK-NEXT:    mov w8, #1288 // =0x508
+; CHECK-NEXT:    mov x9, #4294967296 // =0x100000000
+; CHECK-NEXT:    mov x10, #6442450944 // =0x180000000
 ; CHECK-NEXT:  .LBB0_1: // %while.body
 ; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
-; CHECK-NEXT:    ldr x12, [x8, x10]
-; CHECK-NEXT:    str x12, [x8, x11]
-; CHECK-NEXT:    add x8, x8, #8
-; CHECK-NEXT:    subs x9, x9, #8
+; CHECK-NEXT:    ldr x11, [x9], #8
+; CHECK-NEXT:    str x11, [x10], #8
+; CHECK-NEXT:    subs x8, x8, #8
 ; CHECK-NEXT:    b.pl .LBB0_1
 ; CHECK-NEXT:  // %bb.2: // %while.end
 ; CHECK-NEXT:    mov x8, #6442450944 // =0x180000000
@@ -55,18 +52,16 @@ while.end:                                        ; preds = %while.body
 define ptr @test_globals() nounwind {
 ; CHECK-LABEL: test_globals:
 ; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    mov x8, #0 // =0x0
-; CHECK-NEXT:    mov w9, #1288 // =0x508
-; CHECK-NEXT:    adrp x10, g2
-; CHECK-NEXT:    add x10, x10, :lo12:g2
-; CHECK-NEXT:    adrp x11, g1
-; CHECK-NEXT:    add x11, x11, :lo12:g1
+; CHECK-NEXT:    mov w8, #1288 // =0x508
+; CHECK-NEXT:    adrp x9, g2
+; CHECK-NEXT:    add x9, x9, :lo12:g2
+; CHECK-NEXT:    adrp x10, g1
+; CHECK-NEXT:    add x10, x10, :lo12:g1
 ; CHECK-NEXT:  .LBB1_1: // %while.body
 ; CHECK-NEXT:    // =>This Inner Loop Header: Depth=1
-; CHECK-NEXT:    ldr x12, [x10, x8]
-; CHECK-NEXT:    str x12, [x11, x8]
-; CHECK-NEXT:    add x8, x8, #8
-; CHECK-NEXT:    subs x9, x9, #8
+; CHECK-NEXT:    ldr x11, [x9], #8
+; CHECK-NEXT:    str x11, [x10], #8
+; CHECK-NEXT:    subs x8, x8, #8
 ; CHECK-NEXT:    b.pl .LBB1_1
 ; CHECK-NEXT:  // %bb.2: // %while.end
 ; CHECK-NEXT:    adrp x0, g1