[llvm] LICM: hoist BO assoc for and, or, xor (PR #111146)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 4 05:55:15 PDT 2024


https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/111146

Trivially lift the Opcode limitation on hoistBOAssociation to also hoist and, or, and xor.

Alive2 proofs: https://alive2.llvm.org/ce/z/rVNP2X

>From b2dcc0c1961abd069614c39af033f65dbb570163 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Fri, 4 Oct 2024 11:43:30 +0100
Subject: [PATCH] LICM: hoist BO assoc for and, or, xor

Trivially lift the Opcode limitation on hoistBOAssociation to also hoist
and, or, and xor.

Alive2 proofs: https://alive2.llvm.org/ce/z/rVNP2X
---
 llvm/lib/Transforms/Scalar/LICM.cpp      | 11 -----
 llvm/test/Transforms/LICM/hoist-binop.ll | 63 ++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index d73b550741fb39..50f7637b07f6f6 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -2820,18 +2820,7 @@ static bool hoistBOAssociation(Instruction &I, Loop &L,
   if (!BO || !BO->isAssociative())
     return false;
 
-  // TODO: Only hoist ADDs, MULs, FADDs, and FMULs for now.
   Instruction::BinaryOps Opcode = BO->getOpcode();
-  switch (Opcode) {
-  case Instruction::Add:
-  case Instruction::Mul:
-  case Instruction::FAdd:
-  case Instruction::FMul:
-    break;
-  default:
-    return false;
-  }
-
   bool LVInRHS = L.isLoopInvariant(BO->getOperand(0));
   auto *BO0 = dyn_cast<BinaryOperator>(BO->getOperand(LVInRHS));
   if (!BO0 || BO0->getOpcode() != Opcode || !BO0->isAssociative() ||
diff --git a/llvm/test/Transforms/LICM/hoist-binop.ll b/llvm/test/Transforms/LICM/hoist-binop.ll
index 74e2b7a2caf4a5..ea7d96c07d5ff2 100644
--- a/llvm/test/Transforms/LICM/hoist-binop.ll
+++ b/llvm/test/Transforms/LICM/hoist-binop.ll
@@ -681,6 +681,69 @@ loop:
   br label %loop
 }
 
+; Trivially hoist and.
+define void @and(i64 %c1, i64 %c2) {
+; CHECK-LABEL: @and(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INVARIANT_OP:%.*]] = and i64 [[C1:%.*]], [[C2:%.*]]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[INDEX_NEXT_REASS]] = and i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT:    br label [[LOOP]]
+;
+entry:
+  br label %loop
+
+loop:
+  %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
+  %step.add = and i64 %index, %c1
+  %index.next = and i64 %step.add, %c2
+  br label %loop
+}
+
+; Trivially hoist or.
+define void @or(i64 %c1, i64 %c2) {
+; CHECK-LABEL: @or(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INVARIANT_OP:%.*]] = or i64 [[C1:%.*]], [[C2:%.*]]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[INDEX_NEXT_REASS]] = or i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT:    br label [[LOOP]]
+;
+entry:
+  br label %loop
+
+loop:
+  %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
+  %step.add = or i64 %index, %c1
+  %index.next = or i64 %c2, %step.add
+  br label %loop
+}
+
+; Trivially hoist xor.
+define void @xor(i64 %c1, i64 %c2) {
+; CHECK-LABEL: @xor(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[INVARIANT_OP:%.*]] = xor i64 [[C1:%.*]], [[C2:%.*]]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[INDEX_NEXT_REASS]] = xor i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT:    br label [[LOOP]]
+;
+entry:
+  br label %loop
+
+loop:
+  %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
+  %step.add = xor i64 %c1, %index
+  %index.next = xor i64 %step.add, %c2
+  br label %loop
+}
+
 ; Don't hoist if the intermediate op has more than two uses. This is an
 ; heuristic that can be adjusted if warranted. Currently we are being
 ; conservative to minimise potential impact in code size.



More information about the llvm-commits mailing list