[llvm] [llvm][LICM] Add flag to control re-association (PR #149829)

Theodoros Theodoridis via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 23 07:30:14 PDT 2025


https://github.com/thetheodor updated https://github.com/llvm/llvm-project/pull/149829

>From 583f17ec2e20f8d01b23163365a7b6dae58ffc39 Mon Sep 17 00:00:00 2001
From: Theodoros Theodoridis <ttheodoridis at nvidia.com>
Date: Wed, 4 Jun 2025 14:34:40 +0000
Subject: [PATCH 1/2] [llvm][LICM] Flag to control re-association

Add a command line flag that controls the amount of binary op
re-association based on the number of uses.
---
 llvm/lib/Transforms/Scalar/LICM.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 68094c354cf46..35d2dc0a0e641 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -146,6 +146,11 @@ static cl::opt<unsigned> IntAssociationUpperLimit(
         "Set upper limit for the number of transformations performed "
         "during a single round of hoisting the reassociated expressions."));
 
+static cl::opt<unsigned> BOAssociationUserLimit(
+    "licm-hoist-bo-association-user-limit", cl::init(2), cl::Hidden,
+    cl::desc("Limit the number of users of the variant operand when "
+             "reassociating a binary operator for hoisting."));
+
 // Experimental option to allow imprecision in LICM in pathological cases, in
 // exchange for faster compile. This is to be removed if MemorySSA starts to
 // address the same issue. LICM calls MemorySSAWalker's
@@ -2850,7 +2855,7 @@ static bool hoistBOAssociation(Instruction &I, Loop &L,
   bool LVInRHS = L.isLoopInvariant(BO->getOperand(0));
   auto *BO0 = dyn_cast<BinaryOperator>(BO->getOperand(LVInRHS));
   if (!BO0 || BO0->getOpcode() != Opcode || !BO0->isAssociative() ||
-      BO0->hasNUsesOrMore(3))
+      BO0->hasNUsesOrMore(BOAssociationUserLimit + 1))
     return false;
 
   Value *LV = BO0->getOperand(0);

>From 4147222d1a6096be627cc865cd38ad076436f0b2 Mon Sep 17 00:00:00 2001
From: Theodoros Theodoridis <ttheodoridis at nvidia.com>
Date: Wed, 23 Jul 2025 14:25:24 +0000
Subject: [PATCH 2/2] Add test for licm-hoist-bo-association-user-limit

---
 .../Transforms/LICM/hoist-binop-user-limit.ll | 90 +++++++++++++++++++
 1 file changed, 90 insertions(+)
 create mode 100644 llvm/test/Transforms/LICM/hoist-binop-user-limit.ll

diff --git a/llvm/test/Transforms/LICM/hoist-binop-user-limit.ll b/llvm/test/Transforms/LICM/hoist-binop-user-limit.ll
new file mode 100644
index 0000000000000..dc413fd5fbfa1
--- /dev/null
+++ b/llvm/test/Transforms/LICM/hoist-binop-user-limit.ll
@@ -0,0 +1,90 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=licm -licm-hoist-bo-association-user-limit=0 < %s | FileCheck %s --check-prefix=LIMIT0
+; RUN: opt -S -passes=licm -licm-hoist-bo-association-user-limit=1 < %s | FileCheck %s --check-prefix=LIMIT1
+; RUN: opt -S -passes=licm -licm-hoist-bo-association-user-limit=2 < %s | FileCheck %s --check-prefix=LIMIT2
+
+; Hoisted if the limit is at least 1.
+define void @single_use(i64 %c1, i64 %c2) {
+; LIMIT0-LABEL: @single_use(
+; LIMIT0-NEXT:  entry:
+; LIMIT0-NEXT:    br label [[LOOP:%.*]]
+; LIMIT0:       loop:
+; LIMIT0-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
+; LIMIT0-NEXT:    [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]]
+; LIMIT0-NEXT:    [[INDEX_NEXT]] = add i64 [[STEP_ADD]], [[C2:%.*]]
+; LIMIT0-NEXT:    br label [[LOOP]]
+;
+; LIMIT1-LABEL: @single_use(
+; LIMIT1-NEXT:  entry:
+; LIMIT1-NEXT:    [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]
+; LIMIT1-NEXT:    br label [[LOOP:%.*]]
+; LIMIT1:       loop:
+; LIMIT1-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; LIMIT1-NEXT:    [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]
+; LIMIT1-NEXT:    br label [[LOOP]]
+;
+; LIMIT2-LABEL: @single_use(
+; LIMIT2-NEXT:  entry:
+; LIMIT2-NEXT:    [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]
+; LIMIT2-NEXT:    br label [[LOOP:%.*]]
+; LIMIT2:       loop:
+; LIMIT2-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; LIMIT2-NEXT:    [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]
+; LIMIT2-NEXT:    br label [[LOOP]]
+;
+entry:
+  br label %loop
+
+loop:
+  %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
+  %step.add = add i64 %index, %c1
+  %index.next = add i64 %step.add, %c2
+  br label %loop
+}
+
+; Hoisted if the limit is at least 2.
+define void @two_uses(i64 %c1, i64 %c2) {
+; LIMIT0-LABEL: @two_uses(
+; LIMIT0-NEXT:  entry:
+; LIMIT0-NEXT:    br label [[LOOP:%.*]]
+; LIMIT0:       loop:
+; LIMIT0-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
+; LIMIT0-NEXT:    [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]]
+; LIMIT0-NEXT:    call void @use(i64 [[STEP_ADD]])
+; LIMIT0-NEXT:    [[INDEX_NEXT]] = add i64 [[STEP_ADD]], [[C2:%.*]]
+; LIMIT0-NEXT:    br label [[LOOP]]
+;
+; LIMIT1-LABEL: @two_uses(
+; LIMIT1-NEXT:  entry:
+; LIMIT1-NEXT:    br label [[LOOP:%.*]]
+; LIMIT1:       loop:
+; LIMIT1-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; LIMIT1-NEXT:    [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]]
+; LIMIT1-NEXT:    call void @use(i64 [[STEP_ADD]])
+; LIMIT1-NEXT:    [[INDEX_NEXT_REASS]] = add i64 [[STEP_ADD]], [[C2:%.*]]
+; LIMIT1-NEXT:    br label [[LOOP]]
+;
+; LIMIT2-LABEL: @two_uses(
+; LIMIT2-NEXT:  entry:
+; LIMIT2-NEXT:    [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]
+; LIMIT2-NEXT:    br label [[LOOP:%.*]]
+; LIMIT2:       loop:
+; LIMIT2-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; LIMIT2-NEXT:    [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1]]
+; LIMIT2-NEXT:    call void @use(i64 [[STEP_ADD]])
+; LIMIT2-NEXT:    [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]
+; LIMIT2-NEXT:    br label [[LOOP]]
+;
+entry:
+  br label %loop
+
+loop:
+  %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
+  %step.add = add i64 %index, %c1
+  call void @use(i64 %step.add)
+  %index.next = add i64 %step.add, %c2
+  br label %loop
+}
+
+
+declare void @use()



More information about the llvm-commits mailing list