[llvm] [llvm][LICM] Limit multi-use BOAssociation to FP and Vector (PR #149829)
Theodoros Theodoridis via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 14 02:41:56 PDT 2025
https://github.com/thetheodor updated https://github.com/llvm/llvm-project/pull/149829
>From 3090a5799670e26a26b0bf77ceaa6fa5585f2a23 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] [LICM] Limit association of BinOps with multiple uses to FP
and Vec types.
Reassociation and hoisting of binary ops with multiple uses can lead to
increased instruction count (and higher register pressure in some
targets). This patch limits reassociation of binary ops with multiple
usersto FP and Vec types.
---
llvm/lib/Transforms/Scalar/LICM.cpp | 2 +-
llvm/test/CodeGen/PowerPC/p10-spill-crlt.ll | 16 +-
llvm/test/CodeGen/PowerPC/swaps-le-1.ll | 40 ++--
llvm/test/Transforms/LICM/hoist-binop.ll | 186 ++++++++----------
llvm/test/Transforms/LICM/sink-foldable.ll | 2 +-
.../LICM/update-scev-after-hoist.ll | 4 +-
6 files changed, 116 insertions(+), 134 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 1ef4fcc5fac47..4c035a2464c84 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -2867,7 +2867,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(BO0->getType()->isIntegerTy() ? 2 : 3))
return false;
Value *LV = BO0->getOperand(0);
diff --git a/llvm/test/CodeGen/PowerPC/p10-spill-crlt.ll b/llvm/test/CodeGen/PowerPC/p10-spill-crlt.ll
index c733a01950603..4b032781c3764 100644
--- a/llvm/test/CodeGen/PowerPC/p10-spill-crlt.ll
+++ b/llvm/test/CodeGen/PowerPC/p10-spill-crlt.ll
@@ -30,16 +30,14 @@ define dso_local void @P10_Spill_CR_LT() local_unnamed_addr {
; CHECK-NEXT: mflr r0
; CHECK-NEXT: std r0, 16(r1)
; CHECK-NEXT: stw r12, 8(r1)
-; CHECK-NEXT: stdu r1, -64(r1)
-; CHECK-NEXT: .cfi_def_cfa_offset 64
+; CHECK-NEXT: stdu r1, -48(r1)
+; CHECK-NEXT: .cfi_def_cfa_offset 48
; CHECK-NEXT: .cfi_offset lr, 16
-; CHECK-NEXT: .cfi_offset r29, -24
; CHECK-NEXT: .cfi_offset r30, -16
; CHECK-NEXT: .cfi_offset cr2, 8
; CHECK-NEXT: .cfi_offset cr3, 8
; CHECK-NEXT: .cfi_offset cr4, 8
-; CHECK-NEXT: std r29, 40(r1) # 8-byte Folded Spill
-; CHECK-NEXT: std r30, 48(r1) # 8-byte Folded Spill
+; CHECK-NEXT: std r30, 32(r1) # 8-byte Folded Spill
; CHECK-NEXT: bl call_2 at notoc
; CHECK-NEXT: bc 12, 4*cr5+lt, .LBB0_13
; CHECK-NEXT: # %bb.1: # %bb
@@ -67,11 +65,10 @@ define dso_local void @P10_Spill_CR_LT() local_unnamed_addr {
; CHECK-NEXT: bc 12, 4*cr3+eq, .LBB0_11
; CHECK-NEXT: # %bb.6: # %bb32
; CHECK-NEXT: #
+; CHECK-NEXT: rlwinm r30, r30, 0, 24, 22
; CHECK-NEXT: andi. r3, r30, 2
-; CHECK-NEXT: rlwinm r29, r30, 0, 24, 22
; CHECK-NEXT: mcrf cr2, cr0
; CHECK-NEXT: bl call_4 at notoc
-; CHECK-NEXT: mr r30, r29
; CHECK-NEXT: beq+ cr2, .LBB0_3
; CHECK-NEXT: # %bb.7: # %bb37
; CHECK-NEXT: .LBB0_8: # %bb22
@@ -92,13 +89,11 @@ define dso_local void @P10_Spill_CR_LT() local_unnamed_addr {
; CHECK-BE-NEXT: stdu r1, -144(r1)
; CHECK-BE-NEXT: .cfi_def_cfa_offset 144
; CHECK-BE-NEXT: .cfi_offset lr, 16
-; CHECK-BE-NEXT: .cfi_offset r28, -32
; CHECK-BE-NEXT: .cfi_offset r29, -24
; CHECK-BE-NEXT: .cfi_offset r30, -16
; CHECK-BE-NEXT: .cfi_offset cr2, 8
; CHECK-BE-NEXT: .cfi_offset cr2, 8
; CHECK-BE-NEXT: .cfi_offset cr2, 8
-; CHECK-BE-NEXT: std r28, 112(r1) # 8-byte Folded Spill
; CHECK-BE-NEXT: std r29, 120(r1) # 8-byte Folded Spill
; CHECK-BE-NEXT: std r30, 128(r1) # 8-byte Folded Spill
; CHECK-BE-NEXT: bl call_2
@@ -131,12 +126,11 @@ define dso_local void @P10_Spill_CR_LT() local_unnamed_addr {
; CHECK-BE-NEXT: bc 12, 4*cr3+eq, .LBB0_11
; CHECK-BE-NEXT: # %bb.6: # %bb32
; CHECK-BE-NEXT: #
+; CHECK-BE-NEXT: rlwinm r29, r29, 0, 24, 22
; CHECK-BE-NEXT: andi. r3, r29, 2
-; CHECK-BE-NEXT: rlwinm r28, r29, 0, 24, 22
; CHECK-BE-NEXT: mcrf cr2, cr0
; CHECK-BE-NEXT: bl call_4
; CHECK-BE-NEXT: nop
-; CHECK-BE-NEXT: mr r29, r28
; CHECK-BE-NEXT: beq+ cr2, .LBB0_3
; CHECK-BE-NEXT: # %bb.7: # %bb37
; CHECK-BE-NEXT: .LBB0_8: # %bb22
diff --git a/llvm/test/CodeGen/PowerPC/swaps-le-1.ll b/llvm/test/CodeGen/PowerPC/swaps-le-1.ll
index f3e34101efa29..5d5445f9f473a 100644
--- a/llvm/test/CodeGen/PowerPC/swaps-le-1.ll
+++ b/llvm/test/CodeGen/PowerPC/swaps-le-1.ll
@@ -187,34 +187,34 @@ define void @foo() {
; CHECK-P9-NEXT: .p2align 4
; CHECK-P9-NEXT: .LBB0_1: # %vector.body
; CHECK-P9-NEXT: #
-; CHECK-P9-NEXT: lxv 2, -32(6)
-; CHECK-P9-NEXT: lxv 3, -32(5)
-; CHECK-P9-NEXT: lxv 4, -16(5)
-; CHECK-P9-NEXT: vadduwm 2, 3, 2
+; CHECK-P9-NEXT: lxv 2, -32(3)
; CHECK-P9-NEXT: lxv 3, -32(4)
+; CHECK-P9-NEXT: lxv 4, -16(4)
+; CHECK-P9-NEXT: vadduwm 2, 3, 2
+; CHECK-P9-NEXT: lxv 3, -32(5)
; CHECK-P9-NEXT: vmuluwm 2, 2, 3
-; CHECK-P9-NEXT: lxv 3, -16(6)
-; CHECK-P9-NEXT: vadduwm 3, 4, 3
-; CHECK-P9-NEXT: lxv 4, 0(5)
-; CHECK-P9-NEXT: stxv 2, -32(3)
-; CHECK-P9-NEXT: lxv 2, -16(4)
-; CHECK-P9-NEXT: vmuluwm 2, 3, 2
-; CHECK-P9-NEXT: lxv 3, 0(6)
+; CHECK-P9-NEXT: lxv 3, -16(3)
; CHECK-P9-NEXT: vadduwm 3, 4, 3
-; CHECK-P9-NEXT: lxv 4, 16(5)
-; CHECK-P9-NEXT: addi 5, 5, 64
-; CHECK-P9-NEXT: stxv 2, -16(3)
-; CHECK-P9-NEXT: lxv 2, 0(4)
+; CHECK-P9-NEXT: lxv 4, 0(4)
+; CHECK-P9-NEXT: stxv 2, -32(6)
+; CHECK-P9-NEXT: lxv 2, -16(5)
; CHECK-P9-NEXT: vmuluwm 2, 3, 2
-; CHECK-P9-NEXT: lxv 3, 16(6)
-; CHECK-P9-NEXT: addi 6, 6, 64
+; CHECK-P9-NEXT: lxv 3, 0(3)
; CHECK-P9-NEXT: vadduwm 3, 4, 3
-; CHECK-P9-NEXT: stxv 2, 0(3)
-; CHECK-P9-NEXT: lxv 2, 16(4)
+; CHECK-P9-NEXT: lxv 4, 16(4)
; CHECK-P9-NEXT: addi 4, 4, 64
+; CHECK-P9-NEXT: stxv 2, -16(6)
+; CHECK-P9-NEXT: lxv 2, 0(5)
; CHECK-P9-NEXT: vmuluwm 2, 3, 2
-; CHECK-P9-NEXT: stxv 2, 16(3)
+; CHECK-P9-NEXT: lxv 3, 16(3)
; CHECK-P9-NEXT: addi 3, 3, 64
+; CHECK-P9-NEXT: vadduwm 3, 4, 3
+; CHECK-P9-NEXT: stxv 2, 0(6)
+; CHECK-P9-NEXT: lxv 2, 16(5)
+; CHECK-P9-NEXT: addi 5, 5, 64
+; CHECK-P9-NEXT: vmuluwm 2, 3, 2
+; CHECK-P9-NEXT: stxv 2, 16(6)
+; CHECK-P9-NEXT: addi 6, 6, 64
; CHECK-P9-NEXT: bdnz .LBB0_1
; CHECK-P9-NEXT: # %bb.2: # %for.end
; CHECK-P9-NEXT: blr
diff --git a/llvm/test/Transforms/LICM/hoist-binop.ll b/llvm/test/Transforms/LICM/hoist-binop.ll
index 1b1347776fb9e..724f45979f6ba 100644
--- a/llvm/test/Transforms/LICM/hoist-binop.ll
+++ b/llvm/test/Transforms/LICM/hoist-binop.ll
@@ -22,6 +22,31 @@ loop:
br label %loop
}
+; Don't hoist ADD if the op has more than one use.
+define void @add_two_uses(i64 %c1, i64 %c2) {
+; CHECK-LABEL: @add_two_uses(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]]
+; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
+; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[STEP_ADD]], [[C2:%.*]]
+; CHECK-NEXT: call void @use(i64 [[INDEX_NEXT]])
+; CHECK-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
+ call void @use(i64 %index.next)
+ br label %loop
+}
+
; Hoist MUL and remove old op if unused.
define void @mul_one_use(i64 %c1, i64 %c2) {
; CHECK-LABEL: @mul_one_use(
@@ -51,8 +76,6 @@ define void @add_nuw(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -62,7 +85,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nuw i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = add nuw i64 %step.add, %c2
br label %loop
}
@@ -76,8 +98,6 @@ define void @add_nuw_comm(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[C1]], [[INDEX]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -87,7 +107,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nuw i64 %c1, %index
- call void @use(i64 %step.add)
%index.next = add nuw i64 %step.add, %c2
br label %loop
}
@@ -101,8 +120,6 @@ define void @add_nuw_comm2(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -112,7 +129,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nuw i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = add nuw i64 %c2, %step.add
br label %loop
}
@@ -126,8 +142,6 @@ define void @add_nuw_comm3(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[C1]], [[INDEX]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -137,7 +151,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nuw i64 %c1, %index
- call void @use(i64 %step.add)
%index.next = add nuw i64 %c2, %step.add
br label %loop
}
@@ -152,8 +165,6 @@ define void @add_nuw_twobinops(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw i64 [[C1]], [[INDEX]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -163,135 +174,134 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nuw i64 %c1, %index
- call void @use(i64 %step.add)
%c2.plus.2 = add nuw i64 %c2, 2
%index.next = add nuw i64 %step.add, %c2.plus.2
br label %loop
}
; Hoist MUL and drop NUW even if both ops have it.
-define void @mul_nuw(i64 %c1, i64 %c2) {
+define void @mul_nuw(<2 x i64> %c1, <2 x i64> %c2) {
; CHECK-LABEL: @mul_nuw(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
+; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
-; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[INDEX]], [[C1]]
+; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])
+; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
entry:
br label %loop
loop:
- %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
- %step.add = mul nuw i64 %index, %c1
- call void @use(i64 %step.add)
- %index.next = mul nuw i64 %step.add, %c2
+ %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]
+ %step.add = mul nuw <2 x i64> %index, %c1
+ call void @use(<2 x i64> %step.add)
+ %index.next = mul nuw <2 x i64> %step.add, %c2
br label %loop
}
; Hoist MUL and drop NUW even if both ops have it.
; Version where operands are commuted.
-define void @mul_nuw_comm(i64 %c1, i64 %c2) {
+define void @mul_nuw_comm(<2 x i64> %c1, <2 x i64> %c2) {
; CHECK-LABEL: @mul_nuw_comm(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
+; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[C1]], [[INDEX]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
-; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]]
+; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])
+; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
entry:
br label %loop
loop:
- %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
- %step.add = mul nuw i64 %c1, %index
- call void @use(i64 %step.add)
- %index.next = mul nuw i64 %step.add, %c2
+ %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]
+ %step.add = mul nuw <2 x i64> %c1, %index
+ call void @use(<2 x i64> %step.add)
+ %index.next = mul nuw <2 x i64> %step.add, %c2
br label %loop
}
; Hoist MUL and drop NUW even if both ops have it.
; Another version where operands are commuted.
-define void @mul_nuw_comm2(i64 %c1, i64 %c2) {
+define void @mul_nuw_comm2(<2 x i64> %c1, <2 x i64> %c2) {
; CHECK-LABEL: @mul_nuw_comm2(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
+; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
-; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[INDEX]], [[C1]]
+; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])
+; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
entry:
br label %loop
loop:
- %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
- %step.add = mul nuw i64 %index, %c1
- call void @use(i64 %step.add)
- %index.next = mul nuw i64 %c2, %step.add
+ %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]
+ %step.add = mul nuw <2 x i64> %index, %c1
+ call void @use(<2 x i64> %step.add)
+ %index.next = mul nuw <2 x i64> %c2, %step.add
br label %loop
}
; Hoist MUL and drop NUW even if both ops have it.
; Another version where operands are commuted.
-define void @mul_nuw_comm3(i64 %c1, i64 %c2) {
+define void @mul_nuw_comm3(<2 x i64> %c1, <2 x i64> %c2) {
; CHECK-LABEL: @mul_nuw_comm3(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
+; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[C1]], [[INDEX]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
-; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]]
+; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])
+; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
entry:
br label %loop
loop:
- %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
- %step.add = mul nuw i64 %c1, %index
- call void @use(i64 %step.add)
- %index.next = mul nuw i64 %c2, %step.add
+ %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]
+ %step.add = mul nuw <2 x i64> %c1, %index
+ call void @use(<2 x i64> %step.add)
+ %index.next = mul nuw <2 x i64> %c2, %step.add
br label %loop
}
; Hoist MUL and drop NUW even if both ops have it.
; A version where the LHS and RHS of the outer BinOp are BinOps.
-define void @mul_nuw_twobinops(i64 %c1, i64 %c2) {
+define void @mul_nuw_twobinops(<2 x i64> %c1, <2 x i64> %c2) {
; CHECK-LABEL: @mul_nuw_twobinops(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[C2_PLUS_2:%.*]] = add nuw i64 [[C2:%.*]], 2
-; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2_PLUS_2]]
+; CHECK-NEXT: [[C2_PLUS_2:%.*]] = add nuw <2 x i64> [[C2:%.*]], splat (i64 2)
+; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2_PLUS_2]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw i64 [[C1]], [[INDEX]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
-; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]]
+; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])
+; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
entry:
br label %loop
loop:
- %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
- %step.add = mul nuw i64 %c1, %index
- call void @use(i64 %step.add)
- %c2.plus.2 = add nuw i64 %c2, 2
- %index.next = mul nuw i64 %step.add, %c2.plus.2
+ %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]
+ %step.add = mul nuw <2 x i64> %c1, %index
+ call void @use(<2 x i64> %step.add)
+ %c2.plus.2 = add nuw <2 x i64> %c2, <i64 2, i64 2>
+ %index.next = mul nuw <2 x i64> %step.add, %c2.plus.2
br label %loop
}
@@ -303,8 +313,6 @@ define void @add_no_nuw(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -314,7 +322,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = add nuw i64 %step.add, %c2
br label %loop
}
@@ -327,8 +334,6 @@ define void @add_no_nsw(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -338,7 +343,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = add nsw i64 %step.add, %c2
br label %loop
}
@@ -351,8 +355,6 @@ define void @add_no_nsw_2(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nsw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -362,7 +364,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nsw i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = add nsw i64 %step.add, %c2
br label %loop
}
@@ -375,8 +376,6 @@ define void @add_nuw_nsw(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw nsw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw nsw i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -386,7 +385,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nuw nsw i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = add nuw nsw i64 %step.add, %c2
br label %loop
}
@@ -398,8 +396,6 @@ define void @add_both_nsw_first_nuw(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nuw nsw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -409,7 +405,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nuw nsw i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = add nsw i64 %step.add, %c2
br label %loop
}
@@ -421,8 +416,6 @@ define void @add_both_nsw_second_nuw(i64 %c1, i64 %c2) {
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = add nsw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -432,33 +425,32 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add nsw i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = add nuw nsw i64 %step.add, %c2
br label %loop
}
;
; Hoist MUL and drop NSW even if both ops have it.
-define void @mul_no_nsw_2(i64 %c1, i64 %c2) {
+define void @mul_no_nsw_2(<2 x i64> %c1, <2 x i64> %c2) {
; CHECK-LABEL: @mul_no_nsw_2(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]
+; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
-; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
-; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nsw i64 [[INDEX]], [[C1]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
-; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul i64 [[INDEX]], [[INVARIANT_OP]]
+; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nsw <2 x i64> [[INDEX]], [[C1]]
+; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])
+; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]
; CHECK-NEXT: br label [[LOOP]]
;
entry:
br label %loop
loop:
- %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
- %step.add = mul nsw i64 %index, %c1
- call void @use(i64 %step.add)
- %index.next = mul nsw i64 %step.add, %c2
+ %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]
+ %step.add = mul nsw <2 x i64> %index, %c1
+ call void @use(<2 x i64> %step.add)
+ %index.next = mul nsw <2 x i64> %step.add, %c2
br label %loop
}
@@ -470,7 +462,6 @@ define void @diff_ops(i64 %c1, i64 %c2) {
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT]] = mul i64 [[STEP_ADD]], [[C2:%.*]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -480,7 +471,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = add i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = mul i64 %step.add, %c2
br label %loop
}
@@ -493,7 +483,6 @@ define void @noassoc_ops(i64 %c1, i64 %c2) {
; CHECK: loop:
; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[STEP_ADD:%.*]] = sub i64 [[INDEX]], [[C1:%.*]]
-; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])
; CHECK-NEXT: [[INDEX_NEXT]] = sub i64 [[STEP_ADD]], [[C2:%.*]]
; CHECK-NEXT: br label [[LOOP]]
;
@@ -503,7 +492,6 @@ entry:
loop:
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
%step.add = sub i64 %index, %c1
- call void @use(i64 %step.add)
%index.next = sub i64 %step.add, %c2
br label %loop
}
diff --git a/llvm/test/Transforms/LICM/sink-foldable.ll b/llvm/test/Transforms/LICM/sink-foldable.ll
index d1cf3de5301b2..59dea58a6adee 100644
--- a/llvm/test/Transforms/LICM/sink-foldable.ll
+++ b/llvm/test/Transforms/LICM/sink-foldable.ll
@@ -97,7 +97,7 @@ define ptr @test2(i32 %j, ptr readonly %P, ptr readnone %Q) {
; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds ptr, ptr [[ADD_PTR]], i64 [[IDX2_EXT]]
; CHECK-NEXT: [[L1:%.*]] = load ptr, ptr [[ARRAYIDX2]], align 8
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt ptr [[L1]], [[Q]]
-; CHECK-NEXT: [[ADD_REASS]] = add i32 [[I_ADDR]], 2
+; CHECK-NEXT: [[ADD_REASS]] = add nsw i32 [[ADD_I]], 1
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOPEXIT2:%.*]], label [[FOR_COND]]
; CHECK: loopexit0:
; CHECK-NEXT: [[P0:%.*]] = phi ptr [ null, [[FOR_COND]] ]
diff --git a/llvm/test/Transforms/LICM/update-scev-after-hoist.ll b/llvm/test/Transforms/LICM/update-scev-after-hoist.ll
index e303d04ce3191..8f9045350813a 100644
--- a/llvm/test/Transforms/LICM/update-scev-after-hoist.ll
+++ b/llvm/test/Transforms/LICM/update-scev-after-hoist.ll
@@ -4,7 +4,7 @@
define i16 @main() {
; SCEV-EXPR-LABEL: 'main'
; SCEV-EXPR-NEXT: Classifying expressions for: @main
-; SCEV-EXPR-NEXT: %mul = phi i16 [ 1, %entry ], [ %mul.n.3.reass, %loop ]
+; SCEV-EXPR-NEXT: %mul = phi i16 [ 1, %entry ], [ %mul.n.3, %loop ]
; SCEV-EXPR-NEXT: --> %mul U: [0,-15) S: [-32768,32753) Exits: 4096 LoopDispositions: { %loop: Variant }
; SCEV-EXPR-NEXT: %div = phi i16 [ 32767, %entry ], [ %div.n.3, %loop ]
; SCEV-EXPR-NEXT: --> %div U: [-2048,-32768) S: [-2048,-32768) Exits: 7 LoopDispositions: { %loop: Variant }
@@ -16,7 +16,7 @@ define i16 @main() {
; SCEV-EXPR-NEXT: --> %div.n.1 U: [-8192,8192) S: [-8192,8192) Exits: 1 LoopDispositions: { %loop: Variant }
; SCEV-EXPR-NEXT: %div.n.2 = sdiv i16 %div.n.1, 2
; SCEV-EXPR-NEXT: --> %div.n.2 U: [-4096,4096) S: [-4096,4096) Exits: 0 LoopDispositions: { %loop: Variant }
-; SCEV-EXPR-NEXT: %mul.n.3.reass = mul i16 %mul, 16
+; SCEV-EXPR-NEXT: %mul.n.3 = mul i16 %mul.n.reass.reass, 2
; SCEV-EXPR-NEXT: --> (16 * %mul) U: [0,-15) S: [-32768,32753) Exits: 0 LoopDispositions: { %loop: Variant }
; SCEV-EXPR-NEXT: %div.n.3 = sdiv i16 %div.n.2, 2
; SCEV-EXPR-NEXT: --> %div.n.3 U: [-2048,2048) S: [-2048,2048) Exits: 0 LoopDispositions: { %loop: Variant }
More information about the llvm-commits
mailing list