From 53416bafffd98e399e8f99a19c64f68fe7e82d0f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 28 Sep 2023 13:51:06 -0700 Subject: [PATCH 1/5] [LICM][WIP] Make an integer version of hoistFPAssociation. This is a naive copy/paste of the FP code. We could do more integration to share code. Posting for discussion. --- llvm/lib/Transforms/Scalar/LICM.cpp | 74 ++ .../Transforms/LICM/expr-reassociate-int.ll | 1078 +++++++++++++++++ 2 files changed, 1152 insertions(+) create mode 100644 llvm/test/Transforms/LICM/expr-reassociate-int.ll diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index f3e40a5cb809b..3e534aa20568e 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -110,6 +110,9 @@ STATISTIC(NumAddSubHoisted, "Number of add/subtract expressions reassociated " "and hoisted out of the loop"); STATISTIC(NumFPAssociationsHoisted, "Number of invariant FP expressions " "reassociated and hoisted out of the loop"); +STATISTIC(NumIntAssociationsHoisted, + "Number of invariant int expressions " + "reassociated and hoisted out of the loop"); /// Memory promotion is enabled by default. static cl::opt @@ -135,6 +138,12 @@ static cl::opt FPAssociationUpperLimit( "Set upper limit for the number of transformations performed " "during a single round of hoisting the reassociated expressions.")); +cl::opt IntAssociationUpperLimit( + "licm-max-num-int-reassociations", cl::init(5U), cl::Hidden, + cl::desc( + "Set upper limit for the number of transformations performed " + "during a single round of hoisting the reassociated expressions.")); + // 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 @@ -2727,6 +2736,65 @@ static bool hoistFPAssociation(Instruction &I, Loop &L, return true; } +static bool hoistIntAssociation(Instruction &I, Loop &L, + ICFLoopSafetyInfo &SafetyInfo, + MemorySSAUpdater &MSSAU, AssumptionCache *AC, + DominatorTree *DT) { + using namespace PatternMatch; + Value *VariantOp = nullptr, *InvariantOp = nullptr; + + if (!match(&I, m_Mul(m_Value(VariantOp), m_Value(InvariantOp)))) + return false; + if (L.isLoopInvariant(VariantOp)) + std::swap(VariantOp, InvariantOp); + if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp)) + return false; + Value *Factor = InvariantOp; + + // First, we need to make sure we should do the transformation. + SmallVector Changes; + SmallVector Worklist; + if (BinaryOperator *VariantBinOp = dyn_cast(VariantOp)) + Worklist.push_back(VariantBinOp); + while (!Worklist.empty()) { + BinaryOperator *BO = Worklist.pop_back_val(); + if (!BO->hasOneUse()) + return false; + BinaryOperator *Op0, *Op1; + if (match(BO, m_Add(m_BinOp(Op0), m_BinOp(Op1)))) { + Worklist.push_back(Op0); + Worklist.push_back(Op1); + continue; + } + if (BO->getOpcode() != Instruction::Mul || L.isLoopInvariant(BO)) + return false; + Use &U0 = BO->getOperandUse(0); + Use &U1 = BO->getOperandUse(1); + if (L.isLoopInvariant(U0)) + Changes.push_back(&U0); + else if (L.isLoopInvariant(U1)) + Changes.push_back(&U1); + else + return false; + if (Changes.size() > IntAssociationUpperLimit) + return false; + } + if (Changes.empty()) + return false; + + // We know we should do it so let's do the transformation. + auto *Preheader = L.getLoopPreheader(); + assert(Preheader && "Loop is not in simplify form?"); + IRBuilder<> Builder(Preheader->getTerminator()); + for (auto *U : Changes) { + assert(L.isLoopInvariant(U->get())); + U->set(Builder.CreateMul(U->get(), Factor, "factor.op.mul")); + } + I.replaceAllUsesWith(VariantOp); + eraseInstruction(I, SafetyInfo, MSSAU); + return true; +} + static bool hoistArithmetics(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, AssumptionCache *AC, @@ -2760,6 +2828,12 @@ static bool hoistArithmetics(Instruction &I, Loop &L, return true; } + if (hoistIntAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) { + ++NumHoisted; + ++NumIntAssociationsHoisted; + return true; + } + return false; } diff --git a/llvm/test/Transforms/LICM/expr-reassociate-int.ll b/llvm/test/Transforms/LICM/expr-reassociate-int.ll new file mode 100644 index 0000000000000..556bcfa4dbfd0 --- /dev/null +++ b/llvm/test/Transforms/LICM/expr-reassociate-int.ll @@ -0,0 +1,1078 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 +; RUN: opt -passes='reassociate' -S < %s | FileCheck %s --check-prefix=REASSOCIATE_ONLY +; RUN: opt -passes='licm' -S < %s | FileCheck %s --check-prefix=LICM_ONLY +; RUN: opt -passes='licm' -licm-max-num-int-reassociations=1 -S < %s | FileCheck %s --check-prefix=LICM_ONLY_CONSTRAINED +; RUN: opt -passes='reassociate,loop-mssa(licm)' -S < %s | FileCheck %s --check-prefix=LICM_AFTER_REASSOCIATE +; RUN: opt -passes='reassociate,loop-mssa(licm)' -licm-max-num-int-reassociations=1 -S < %s | FileCheck %s --check-prefix=LICM_AFTER_REASSOCIATE_CONSTRAINED + +; +; A simple loop, should not get modified: +; +; int j; +; const uint64_t d1d = d1 * delta; +; +; for (j = 0; j <= i; j++) +; cells[j] = d1d * cells[j + 1]; +; + +define void @innermost_loop_1d(i32 %i, i64 %d1, i64 %delta, ptr %cells) { +; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_1d +; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; REASSOCIATE_ONLY-NEXT: entry: +; REASSOCIATE_ONLY-NEXT: [[FMUL_D1:%.*]] = mul i64 [[DELTA]], [[D1]] +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] +; REASSOCIATE_ONLY: for.cond: +; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; REASSOCIATE_ONLY: for.body: +; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; REASSOCIATE_ONLY-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] +; REASSOCIATE_ONLY: for.end: +; REASSOCIATE_ONLY-NEXT: ret void +; +; LICM_ONLY-LABEL: define void @innermost_loop_1d +; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY-NEXT: entry: +; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY: for.cond: +; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY: for.body: +; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: br label [[FOR_COND]] +; LICM_ONLY: for.end: +; LICM_ONLY-NEXT: ret void +; +; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_1d +; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY_CONSTRAINED-NEXT: entry: +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY_CONSTRAINED: for.cond: +; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY_CONSTRAINED: for.body: +; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_ONLY_CONSTRAINED: for.end: +; LICM_ONLY_CONSTRAINED-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_1d +; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE-NEXT: entry: +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_D1:%.*]] = mul i64 [[DELTA]], [[D1]] +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE: for.cond: +; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE: for.body: +; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE: for.end: +; LICM_AFTER_REASSOCIATE-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_1d +; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = mul i64 [[DELTA]], [[D1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; +entry: + %fmul.d1 = mul i64 %d1, %delta + br label %for.cond + +for.cond: + %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] + %cmp.not = icmp sgt i32 %j, %i + br i1 %cmp.not, label %for.end, label %for.body + +for.body: + %add.j.1 = add nuw nsw i32 %j, 1 + %idxprom.j.1 = zext i32 %add.j.1 to i64 + %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 + %cell.1 = load i64, ptr %arrayidx.j.1, align 8 + %fmul.1 = mul i64 %fmul.d1, %cell.1 + %idxprom.j = zext i32 %j to i64 + %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j + store i64 %fmul.1, ptr %arrayidx.j, align 8 + br label %for.cond + +for.end: + ret void +} + +; +; A simple loop: +; +; int j; +; +; for (j = 0; j <= i; j++) +; cells[j] = d1 * cells[j + 1] * delta; +; +; ...should be transformed by the LICM pass into this: +; +; int j; +; const uint64_t d1d = d1 * delta; +; +; for (j = 0; j <= i; j++) +; cells[j] = d1d * cells[j + 1]; +; + +define void @innermost_loop_1d_shouldhoist(i32 %i, i64 %d1, i64 %delta, ptr %cells) { +; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_1d_shouldhoist +; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; REASSOCIATE_ONLY-NEXT: entry: +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] +; REASSOCIATE_ONLY: for.cond: +; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; REASSOCIATE_ONLY: for.body: +; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[DELTA]], [[D1]] +; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_1]], [[CELL_1]] +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; REASSOCIATE_ONLY-NEXT: store i64 [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] +; REASSOCIATE_ONLY: for.end: +; REASSOCIATE_ONLY-NEXT: ret void +; +; LICM_ONLY-LABEL: define void @innermost_loop_1d_shouldhoist +; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY-NEXT: entry: +; LICM_ONLY-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY: for.cond: +; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY: for.body: +; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FACTOR_OP_MUL]], [[CELL_1]] +; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: br label [[FOR_COND]] +; LICM_ONLY: for.end: +; LICM_ONLY-NEXT: ret void +; +; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_1d_shouldhoist +; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY_CONSTRAINED-NEXT: entry: +; LICM_ONLY_CONSTRAINED-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY_CONSTRAINED: for.cond: +; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY_CONSTRAINED: for.body: +; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FACTOR_OP_MUL]], [[CELL_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_ONLY_CONSTRAINED: for.end: +; LICM_ONLY_CONSTRAINED-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_1d_shouldhoist +; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE-NEXT: entry: +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[DELTA]], [[D1]] +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE: for.cond: +; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE: for.body: +; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_1]], [[CELL_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE: for.end: +; LICM_AFTER_REASSOCIATE-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_1d_shouldhoist +; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[DELTA]], [[D1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_1]], [[CELL_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; +entry: + br label %for.cond + +for.cond: + %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] + %cmp.not = icmp sgt i32 %j, %i + br i1 %cmp.not, label %for.end, label %for.body + +for.body: + %add.j.1 = add nuw nsw i32 %j, 1 + %idxprom.j.1 = zext i32 %add.j.1 to i64 + %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 + %cell.1 = load i64, ptr %arrayidx.j.1, align 8 + %fmul.1 = mul i64 %d1, %cell.1 + %fmul.2 = mul i64 %fmul.1, %delta + %idxprom.j = zext i32 %j to i64 + %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j + store i64 %fmul.2, ptr %arrayidx.j, align 8 + br label %for.cond + +for.end: + ret void +} + +; +; The following loop will be modified by the 'Reassociate expressions' pass, +; +; int j; +; const uint64_t d1d = d1 * delta; +; const uint64_t d2d = d2 * delta; +; +; for (j = 0; j <= i; j++) +; cells[j] = d1d * cells[j + 1] + d2d * cells[j]; +; +; ...into this: +; +; int j; +; +; for (j = 0; j <= i; j++) +; cells[j] = (d1 * cells[j + 1] + d2 * cells[j]) * delta; +; +; We expect the LICM pass to undo this transformation. +; + +define void @innermost_loop_2d(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { +; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d +; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; REASSOCIATE_ONLY-NEXT: entry: +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] +; REASSOCIATE_ONLY: for.cond: +; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; REASSOCIATE_ONLY: for.body: +; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] +; REASSOCIATE_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] +; REASSOCIATE_ONLY: for.end: +; REASSOCIATE_ONLY-NEXT: ret void +; +; LICM_ONLY-LABEL: define void @innermost_loop_2d +; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY-NEXT: entry: +; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY-NEXT: [[FMUL_D2:%.*]] = mul i64 [[D2]], [[DELTA]] +; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY: for.cond: +; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY: for.body: +; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_D2]], [[CELL_2]] +; LICM_ONLY-NEXT: [[FADD_1:%.*]] = add i64 [[FMUL_1]], [[FMUL_2]] +; LICM_ONLY-NEXT: store i64 [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: br label [[FOR_COND]] +; LICM_ONLY: for.end: +; LICM_ONLY-NEXT: ret void +; +; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d +; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY_CONSTRAINED-NEXT: entry: +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D2:%.*]] = mul i64 [[D2]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY_CONSTRAINED: for.cond: +; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY_CONSTRAINED: for.body: +; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_D2]], [[CELL_2]] +; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_1:%.*]] = add i64 [[FMUL_1]], [[FMUL_2]] +; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_ONLY_CONSTRAINED: for.end: +; LICM_ONLY_CONSTRAINED-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d +; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE-NEXT: entry: +; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]] +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE: for.cond: +; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE: for.body: +; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]] +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE: for.end: +; LICM_AFTER_REASSOCIATE-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d +; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; +entry: + %fmul.d1 = mul i64 %d1, %delta + %fmul.d2 = mul i64 %d2, %delta + br label %for.cond + +for.cond: + %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] + %cmp.not = icmp sgt i32 %j, %i + br i1 %cmp.not, label %for.end, label %for.body + +for.body: + %add.j.1 = add nuw nsw i32 %j, 1 + %idxprom.j.1 = zext i32 %add.j.1 to i64 + %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 + %cell.1 = load i64, ptr %arrayidx.j.1, align 8 + %fmul.1 = mul i64 %fmul.d1, %cell.1 + %idxprom.j = zext i32 %j to i64 + %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j + %cell.2 = load i64, ptr %arrayidx.j, align 8 + %fmul.2 = mul i64 %fmul.d2, %cell.2 + %fadd.1 = add i64 %fmul.1, %fmul.2 + store i64 %fadd.1, ptr %arrayidx.j, align 8 + br label %for.cond + +for.end: + ret void +} + +; +; The following loop will be modified by the 'Reassociate expressions' pass, +; +; int j; +; const uint64_t d1d = d1 * delta; +; const uint64_t d2d = d2 * delta; +; const uint64_t d3d = d3 * delta; +; +; for (j = 0; j <= i; j++) +; cells[j] = d1d * cells[j + 1] + d2d * cells[j] + d3d * cells[j + 2]; +; +; ...into this: +; +; int j; +; +; for (j = 0; j <= i; j++) +; cells[j] = (d1 * cells[j + 1] + d2 * cells[j] + d3 * cells[j + 2]) * delta; +; +; We expect the LICM pass to undo this transformation. +; + + +define void @innermost_loop_3d(i32 %i, i64 %d1, i64 %d2, i64 %d3, i64 %delta, ptr %cells) { +; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_3d +; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; REASSOCIATE_ONLY-NEXT: entry: +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] +; REASSOCIATE_ONLY: for.cond: +; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; REASSOCIATE_ONLY: for.body: +; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; REASSOCIATE_ONLY-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; REASSOCIATE_ONLY-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_3:%.*]] = mul i64 [[CELL_3]], [[D3]] +; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; REASSOCIATE_ONLY-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[FMUL_3]] +; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD1]], [[DELTA]] +; REASSOCIATE_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] +; REASSOCIATE_ONLY: for.end: +; REASSOCIATE_ONLY-NEXT: ret void +; +; LICM_ONLY-LABEL: define void @innermost_loop_3d +; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY-NEXT: entry: +; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY-NEXT: [[FMUL_D2:%.*]] = mul i64 [[D2]], [[DELTA]] +; LICM_ONLY-NEXT: [[FMUL_D3:%.*]] = mul i64 [[D3]], [[DELTA]] +; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY: for.cond: +; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY: for.body: +; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_D2]], [[CELL_2]] +; LICM_ONLY-NEXT: [[FADD_1:%.*]] = add i64 [[FMUL_1]], [[FMUL_2]] +; LICM_ONLY-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 +; LICM_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; LICM_ONLY-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_ONLY-NEXT: [[FMUL_3:%.*]] = mul i64 [[FMUL_D3]], [[CELL_3]] +; LICM_ONLY-NEXT: [[FADD_2:%.*]] = add i64 [[FADD_1]], [[FMUL_3]] +; LICM_ONLY-NEXT: store i64 [[FADD_2]], ptr [[ARRAYIDX_J_2]], align 8 +; LICM_ONLY-NEXT: br label [[FOR_COND]] +; LICM_ONLY: for.end: +; LICM_ONLY-NEXT: ret void +; +; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_3d +; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY_CONSTRAINED-NEXT: entry: +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D2:%.*]] = mul i64 [[D2]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D3:%.*]] = mul i64 [[D3]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY_CONSTRAINED: for.cond: +; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY_CONSTRAINED: for.body: +; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_D2]], [[CELL_2]] +; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_1:%.*]] = add i64 [[FMUL_1]], [[FMUL_2]] +; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_3:%.*]] = mul i64 [[FMUL_D3]], [[CELL_3]] +; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_2:%.*]] = add i64 [[FADD_1]], [[FMUL_3]] +; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[FADD_2]], ptr [[ARRAYIDX_J_2]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_ONLY_CONSTRAINED: for.end: +; LICM_ONLY_CONSTRAINED-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_3d +; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE-NEXT: entry: +; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D3]], [[DELTA]] +; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL2:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL3:%.*]] = mul i64 [[D2]], [[DELTA]] +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE: for.cond: +; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE: for.body: +; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL2]] +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL3]] +; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_3:%.*]] = mul i64 [[CELL_3]], [[FACTOR_OP_MUL]] +; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[FMUL_3]] +; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[REASS_ADD1]], ptr [[ARRAYIDX_J_2]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE: for.end: +; LICM_AFTER_REASSOCIATE-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_3d +; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_3:%.*]] = mul i64 [[CELL_3]], [[D3]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[FMUL_3]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD1]], [[DELTA]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; +entry: + %fmul.d1 = mul i64 %d1, %delta + %fmul.d2 = mul i64 %d2, %delta + %fmul.d3 = mul i64 %d3, %delta + br label %for.cond + +for.cond: + %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] + %cmp.not = icmp sgt i32 %j, %i + br i1 %cmp.not, label %for.end, label %for.body + +for.body: + %add.j.1 = add nuw nsw i32 %j, 1 + %idxprom.j.1 = zext i32 %add.j.1 to i64 + %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 + %cell.1 = load i64, ptr %arrayidx.j.1, align 8 + %fmul.1 = mul i64 %fmul.d1, %cell.1 + %idxprom.j = zext i32 %j to i64 + %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j + %cell.2 = load i64, ptr %arrayidx.j, align 8 + %fmul.2 = mul i64 %fmul.d2, %cell.2 + %fadd.1 = add i64 %fmul.1, %fmul.2 + %add.j.2 = add nuw nsw i32 %j, 2 + %idxprom.j.2 = zext i32 %add.j.2 to i64 + %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2 + %cell.3 = load i64, ptr %arrayidx.j.2, align 8 + %fmul.3 = mul i64 %fmul.d3, %cell.3 + %fadd.2 = add i64 %fadd.1, %fmul.3 + store i64 %fadd.2, ptr %arrayidx.j.2, align 8 + br label %for.cond + +for.end: + ret void +} + +; +; The following loop should be modified by the LICM pass, +; +; int j; +; +; for (j = 0; j <= i; j++) +; cells[j] = (d1 * cells[j + 1] + d2 * cells[j]) * delta; +; +; ...into this: +; +; int j; +; const uint64_t d1d = d1 * delta; +; const uint64_t d2d = d2 * delta; +; +; for (j = 0; j <= i; j++) +; cells[j] = d1d * cells[j + 1] + d2d * cells[j]; +; + +define void @innermost_loop_2d_reassociated(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { +; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d_reassociated +; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; REASSOCIATE_ONLY-NEXT: entry: +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] +; REASSOCIATE_ONLY: for.cond: +; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; REASSOCIATE_ONLY: for.body: +; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] +; REASSOCIATE_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] +; REASSOCIATE_ONLY: for.end: +; REASSOCIATE_ONLY-NEXT: ret void +; +; LICM_ONLY-LABEL: define void @innermost_loop_2d_reassociated +; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY-NEXT: entry: +; LICM_ONLY-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_ONLY-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]] +; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY: for.cond: +; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY: for.body: +; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]] +; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]] +; LICM_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_ONLY-NEXT: store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: br label [[FOR_COND]] +; LICM_ONLY: for.end: +; LICM_ONLY-NEXT: ret void +; +; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d_reassociated +; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY_CONSTRAINED-NEXT: entry: +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY_CONSTRAINED: for.cond: +; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY_CONSTRAINED: for.body: +; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_ONLY_CONSTRAINED: for.end: +; LICM_ONLY_CONSTRAINED-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d_reassociated +; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE-NEXT: entry: +; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] +; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]] +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE: for.cond: +; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE: for.body: +; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]] +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE: for.end: +; LICM_AFTER_REASSOCIATE-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d_reassociated +; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; +entry: + br label %for.cond + +for.cond: + %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] + %cmp.not = icmp sgt i32 %j, %i + br i1 %cmp.not, label %for.end, label %for.body + +for.body: + %add.j.1 = add nuw nsw i32 %j, 1 + %idxprom.j.1 = zext i32 %add.j.1 to i64 + %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 + %cell.1 = load i64, ptr %arrayidx.j.1, align 8 + %fmul.1 = mul i64 %cell.1, %d1 + %idxprom.j = zext i32 %j to i64 + %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j + %cell.2 = load i64, ptr %arrayidx.j, align 8 + %fmul.2 = mul i64 %cell.2, %d2 + %reass.add = add i64 %fmul.2, %fmul.1 + %reass.mul = mul i64 %reass.add, %delta + store i64 %reass.mul, ptr %arrayidx.j, align 8 + br label %for.cond + +for.end: + ret void +} + +; +; The following loop will not be modified by the LICM pass: +; +; int j; +; +; for (j = 0; j <= i; j++) +; cells[j] = (d1 * cells[j + 1] + d2 * cells[j] + +; cells[j] * cells[j + 1]) * delta; +; +; This case differs as one of the multiplications involves no invariants. +; + +define void @innermost_loop_3d_fast_reassociated_different(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { +; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_3d_fast_reassociated_different +; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; REASSOCIATE_ONLY-NEXT: entry: +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] +; REASSOCIATE_ONLY: for.cond: +; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; REASSOCIATE_ONLY: for.body: +; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_3:%.*]] = zext i32 [[ADD_J_1]] to i64 +; REASSOCIATE_ONLY-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; REASSOCIATE_ONLY-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] +; REASSOCIATE_ONLY-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] +; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[FMUL_1]] +; REASSOCIATE_ONLY-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[FMUL_2]] +; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] +; REASSOCIATE_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] +; REASSOCIATE_ONLY: for.end: +; REASSOCIATE_ONLY-NEXT: ret void +; +; LICM_ONLY-LABEL: define void @innermost_loop_3d_fast_reassociated_different +; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY-NEXT: entry: +; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY: for.cond: +; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY: for.body: +; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_ONLY-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] +; LICM_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_ONLY-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] +; LICM_ONLY-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[REASS_ADD]] +; LICM_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] +; LICM_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY-NEXT: br label [[FOR_COND]] +; LICM_ONLY: for.end: +; LICM_ONLY-NEXT: ret void +; +; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_3d_fast_reassociated_different +; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_ONLY_CONSTRAINED-NEXT: entry: +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_ONLY_CONSTRAINED: for.cond: +; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_ONLY_CONSTRAINED: for.body: +; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] +; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] +; LICM_ONLY_CONSTRAINED-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] +; LICM_ONLY_CONSTRAINED-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[REASS_ADD]] +; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] +; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_ONLY_CONSTRAINED: for.end: +; LICM_ONLY_CONSTRAINED-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_3d_fast_reassociated_different +; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE-NEXT: entry: +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE: for.cond: +; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE: for.body: +; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] +; LICM_AFTER_REASSOCIATE-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] +; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[FMUL_1]] +; LICM_AFTER_REASSOCIATE-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[FMUL_2]] +; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] +; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE: for.end: +; LICM_AFTER_REASSOCIATE-NEXT: ret void +; +; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_3d_fast_reassociated_different +; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[FMUL_1]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[FMUL_2]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] +; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: +; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; +entry: + br label %for.cond + +for.cond: + %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] + %cmp.not = icmp sgt i32 %j, %i + br i1 %cmp.not, label %for.end, label %for.body + +for.body: + %add.j.1 = add nuw nsw i32 %j, 1 + %idxprom.j.1 = zext i32 %add.j.1 to i64 + %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 + %cell.1 = load i64, ptr %arrayidx.j.1, align 8 + %add.j.2 = add nuw nsw i32 %j, 2 + %idxprom.j.2 = zext i32 %add.j.1 to i64 + %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2 + %cell.2 = load i64, ptr %arrayidx.j.2, align 8 + %add.j.3 = add nuw nsw i32 %j, 3 + %idxprom.j.3 = zext i32 %add.j.1 to i64 + %arrayidx.j.3 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.3 + %cell.3 = load i64, ptr %arrayidx.j.2, align 8 + %idxprom.j = zext i32 %j to i64 + %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j + %cell.4 = load i64, ptr %arrayidx.j, align 8 + %fmul.1 = mul i64 %cell.1, %d1 + %fmul.2 = mul i64 %cell.4, %d2 + %reass.add = add i64 %fmul.2, %fmul.1 + %extra.mul = mul i64 %cell.3, %cell.2 + %extra.add = add i64 %extra.mul, %reass.add + %reass.mul = mul i64 %extra.add, %delta + store i64 %reass.mul, ptr %arrayidx.j, align 8 + br label %for.cond + +for.end: + ret void +} From e4fa2d19512d5b7964615120fe67e89a1602b5df Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 2 Feb 2024 13:39:04 -0800 Subject: [PATCH 2/5] fixup! Simplify test. --- .../Transforms/LICM/expr-reassociate-int.ll | 1086 +++-------------- 1 file changed, 186 insertions(+), 900 deletions(-) diff --git a/llvm/test/Transforms/LICM/expr-reassociate-int.ll b/llvm/test/Transforms/LICM/expr-reassociate-int.ll index 556bcfa4dbfd0..63548974fb318 100644 --- a/llvm/test/Transforms/LICM/expr-reassociate-int.ll +++ b/llvm/test/Transforms/LICM/expr-reassociate-int.ll @@ -1,154 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 -; RUN: opt -passes='reassociate' -S < %s | FileCheck %s --check-prefix=REASSOCIATE_ONLY -; RUN: opt -passes='licm' -S < %s | FileCheck %s --check-prefix=LICM_ONLY -; RUN: opt -passes='licm' -licm-max-num-int-reassociations=1 -S < %s | FileCheck %s --check-prefix=LICM_ONLY_CONSTRAINED -; RUN: opt -passes='reassociate,loop-mssa(licm)' -S < %s | FileCheck %s --check-prefix=LICM_AFTER_REASSOCIATE -; RUN: opt -passes='reassociate,loop-mssa(licm)' -licm-max-num-int-reassociations=1 -S < %s | FileCheck %s --check-prefix=LICM_AFTER_REASSOCIATE_CONSTRAINED - -; -; A simple loop, should not get modified: -; -; int j; -; const uint64_t d1d = d1 * delta; -; -; for (j = 0; j <= i; j++) -; cells[j] = d1d * cells[j + 1]; -; - -define void @innermost_loop_1d(i32 %i, i64 %d1, i64 %delta, ptr %cells) { -; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_1d -; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; REASSOCIATE_ONLY-NEXT: entry: -; REASSOCIATE_ONLY-NEXT: [[FMUL_D1:%.*]] = mul i64 [[DELTA]], [[D1]] -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] -; REASSOCIATE_ONLY: for.cond: -; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; REASSOCIATE_ONLY: for.body: -; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; REASSOCIATE_ONLY-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] -; REASSOCIATE_ONLY: for.end: -; REASSOCIATE_ONLY-NEXT: ret void -; -; LICM_ONLY-LABEL: define void @innermost_loop_1d -; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY-NEXT: entry: -; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY: for.cond: -; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY: for.body: -; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: br label [[FOR_COND]] -; LICM_ONLY: for.end: -; LICM_ONLY-NEXT: ret void -; -; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_1d -; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY_CONSTRAINED-NEXT: entry: -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY_CONSTRAINED: for.cond: -; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY_CONSTRAINED: for.body: -; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_ONLY_CONSTRAINED: for.end: -; LICM_ONLY_CONSTRAINED-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_1d -; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE-NEXT: entry: -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_D1:%.*]] = mul i64 [[DELTA]], [[D1]] -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE: for.cond: -; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE: for.body: -; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE: for.end: -; LICM_AFTER_REASSOCIATE-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_1d -; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = mul i64 [[DELTA]], [[D1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void -; -entry: - %fmul.d1 = mul i64 %d1, %delta - br label %for.cond - -for.cond: - %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] - %cmp.not = icmp sgt i32 %j, %i - br i1 %cmp.not, label %for.end, label %for.body - -for.body: - %add.j.1 = add nuw nsw i32 %j, 1 - %idxprom.j.1 = zext i32 %add.j.1 to i64 - %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 - %cell.1 = load i64, ptr %arrayidx.j.1, align 8 - %fmul.1 = mul i64 %fmul.d1, %cell.1 - %idxprom.j = zext i32 %j to i64 - %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j - store i64 %fmul.1, ptr %arrayidx.j, align 8 - br label %for.cond - -for.end: - ret void -} +; RUN: opt -passes='loop-mssa(licm)' -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CONSTRAINED +; RUN: opt -passes='loop-mssa(licm)' -licm-max-num-int-reassociations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,CONSTRAINED ; ; A simple loop: @@ -168,115 +20,27 @@ for.end: ; define void @innermost_loop_1d_shouldhoist(i32 %i, i64 %d1, i64 %delta, ptr %cells) { -; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_1d_shouldhoist -; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; REASSOCIATE_ONLY-NEXT: entry: -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] -; REASSOCIATE_ONLY: for.cond: -; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; REASSOCIATE_ONLY: for.body: -; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[DELTA]], [[D1]] -; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_1]], [[CELL_1]] -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; REASSOCIATE_ONLY-NEXT: store i64 [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] -; REASSOCIATE_ONLY: for.end: -; REASSOCIATE_ONLY-NEXT: ret void -; -; LICM_ONLY-LABEL: define void @innermost_loop_1d_shouldhoist -; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY-NEXT: entry: -; LICM_ONLY-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY: for.cond: -; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY: for.body: -; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FACTOR_OP_MUL]], [[CELL_1]] -; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: br label [[FOR_COND]] -; LICM_ONLY: for.end: -; LICM_ONLY-NEXT: ret void -; -; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_1d_shouldhoist -; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY_CONSTRAINED-NEXT: entry: -; LICM_ONLY_CONSTRAINED-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY_CONSTRAINED: for.cond: -; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY_CONSTRAINED: for.body: -; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FACTOR_OP_MUL]], [[CELL_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[FMUL_1]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_ONLY_CONSTRAINED: for.end: -; LICM_ONLY_CONSTRAINED-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_1d_shouldhoist -; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE-NEXT: entry: -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[DELTA]], [[D1]] -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE: for.cond: -; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE: for.body: -; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_1]], [[CELL_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE: for.end: -; LICM_AFTER_REASSOCIATE-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_1d_shouldhoist -; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[DELTA]], [[D1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_1]], [[CELL_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[FMUL_2]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; CHECK-LABEL: define void @innermost_loop_1d_shouldhoist +; CHECK-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[MUL_1:%.*]] = mul i64 [[DELTA]], [[D1]] +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; CHECK-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; CHECK: for.body: +; CHECK-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; CHECK-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; CHECK-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; CHECK-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; CHECK-NEXT: [[MUL_2:%.*]] = mul i64 [[MUL_1]], [[CELL_1]] +; CHECK-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; CHECK-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; CHECK-NEXT: store i64 [[MUL_2]], ptr [[ARRAYIDX_J]], align 8 +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: for.end: +; CHECK-NEXT: ret void ; entry: br label %for.cond @@ -291,11 +55,11 @@ for.body: %idxprom.j.1 = zext i32 %add.j.1 to i64 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 - %fmul.1 = mul i64 %d1, %cell.1 - %fmul.2 = mul i64 %fmul.1, %delta + %mul.1 = mul i64 %delta, %d1 + %mul.2 = mul i64 %mul.1, %cell.1 %idxprom.j = zext i32 %j to i64 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j - store i64 %fmul.2, ptr %arrayidx.j, align 8 + store i64 %mul.2, ptr %arrayidx.j, align 8 br label %for.cond for.end: @@ -323,137 +87,58 @@ for.end: ; define void @innermost_loop_2d(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { -; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d -; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; REASSOCIATE_ONLY-NEXT: entry: -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] -; REASSOCIATE_ONLY: for.cond: -; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; REASSOCIATE_ONLY: for.body: -; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] -; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] -; REASSOCIATE_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] -; REASSOCIATE_ONLY: for.end: -; REASSOCIATE_ONLY-NEXT: ret void -; -; LICM_ONLY-LABEL: define void @innermost_loop_2d -; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY-NEXT: entry: -; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY-NEXT: [[FMUL_D2:%.*]] = mul i64 [[D2]], [[DELTA]] -; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY: for.cond: -; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY: for.body: -; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_D2]], [[CELL_2]] -; LICM_ONLY-NEXT: [[FADD_1:%.*]] = add i64 [[FMUL_1]], [[FMUL_2]] -; LICM_ONLY-NEXT: store i64 [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: br label [[FOR_COND]] -; LICM_ONLY: for.end: -; LICM_ONLY-NEXT: ret void -; -; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d -; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY_CONSTRAINED-NEXT: entry: -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D2:%.*]] = mul i64 [[D2]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY_CONSTRAINED: for.cond: -; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY_CONSTRAINED: for.body: -; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_D2]], [[CELL_2]] -; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_1:%.*]] = add i64 [[FMUL_1]], [[FMUL_2]] -; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[FADD_1]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_ONLY_CONSTRAINED: for.end: -; LICM_ONLY_CONSTRAINED-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d -; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE-NEXT: entry: -; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]] -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE: for.cond: -; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE: for.body: -; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]] -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE: for.end: -; LICM_AFTER_REASSOCIATE-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d -; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; NOT_CONSTRAINED-LABEL: define void @innermost_loop_2d +; NOT_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; NOT_CONSTRAINED-NEXT: entry: +; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] +; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]] +; NOT_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; NOT_CONSTRAINED: for.cond: +; NOT_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; NOT_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; NOT_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; NOT_CONSTRAINED: for.body: +; NOT_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; NOT_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; NOT_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; NOT_CONSTRAINED-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]] +; NOT_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; NOT_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; NOT_CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]] +; NOT_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]] +; NOT_CONSTRAINED-NEXT: store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 +; NOT_CONSTRAINED-NEXT: br label [[FOR_COND]] +; NOT_CONSTRAINED: for.end: +; NOT_CONSTRAINED-NEXT: ret void +; +; CONSTRAINED-LABEL: define void @innermost_loop_2d +; CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; CONSTRAINED-NEXT: entry: +; CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; CONSTRAINED: for.cond: +; CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; CONSTRAINED: for.body: +; CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; CONSTRAINED-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]] +; CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] +; CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; CONSTRAINED-NEXT: br label [[FOR_COND]] +; CONSTRAINED: for.end: +; CONSTRAINED-NEXT: ret void ; entry: - %fmul.d1 = mul i64 %d1, %delta - %fmul.d2 = mul i64 %d2, %delta br label %for.cond for.cond: @@ -466,13 +151,14 @@ for.body: %idxprom.j.1 = zext i32 %add.j.1 to i64 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 - %fmul.1 = mul i64 %fmul.d1, %cell.1 + %mul.1 = mul i64 %cell.1, %d1 %idxprom.j = zext i32 %j to i64 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j %cell.2 = load i64, ptr %arrayidx.j, align 8 - %fmul.2 = mul i64 %fmul.d2, %cell.2 - %fadd.1 = add i64 %fmul.1, %fmul.2 - store i64 %fadd.1, ptr %arrayidx.j, align 8 + %mul.2 = mul i64 %cell.2, %d2 + %reass.add = add i64 %mul.2, %mul.1 + %reass.mul = mul i64 %reass.add, %delta + store i64 %reass.mul, ptr %arrayidx.j, align 8 br label %for.cond for.end: @@ -502,171 +188,71 @@ for.end: define void @innermost_loop_3d(i32 %i, i64 %d1, i64 %d2, i64 %d3, i64 %delta, ptr %cells) { -; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_3d -; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; REASSOCIATE_ONLY-NEXT: entry: -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] -; REASSOCIATE_ONLY: for.cond: -; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; REASSOCIATE_ONLY: for.body: -; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] -; REASSOCIATE_ONLY-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; REASSOCIATE_ONLY-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_3:%.*]] = mul i64 [[CELL_3]], [[D3]] -; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; REASSOCIATE_ONLY-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[FMUL_3]] -; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD1]], [[DELTA]] -; REASSOCIATE_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] -; REASSOCIATE_ONLY: for.end: -; REASSOCIATE_ONLY-NEXT: ret void -; -; LICM_ONLY-LABEL: define void @innermost_loop_3d -; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY-NEXT: entry: -; LICM_ONLY-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY-NEXT: [[FMUL_D2:%.*]] = mul i64 [[D2]], [[DELTA]] -; LICM_ONLY-NEXT: [[FMUL_D3:%.*]] = mul i64 [[D3]], [[DELTA]] -; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY: for.cond: -; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY: for.body: -; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_D2]], [[CELL_2]] -; LICM_ONLY-NEXT: [[FADD_1:%.*]] = add i64 [[FMUL_1]], [[FMUL_2]] -; LICM_ONLY-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 -; LICM_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; LICM_ONLY-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_ONLY-NEXT: [[FMUL_3:%.*]] = mul i64 [[FMUL_D3]], [[CELL_3]] -; LICM_ONLY-NEXT: [[FADD_2:%.*]] = add i64 [[FADD_1]], [[FMUL_3]] -; LICM_ONLY-NEXT: store i64 [[FADD_2]], ptr [[ARRAYIDX_J_2]], align 8 -; LICM_ONLY-NEXT: br label [[FOR_COND]] -; LICM_ONLY: for.end: -; LICM_ONLY-NEXT: ret void -; -; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_3d -; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY_CONSTRAINED-NEXT: entry: -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D1:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D2:%.*]] = mul i64 [[D2]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_D3:%.*]] = mul i64 [[D3]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY_CONSTRAINED: for.cond: -; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY_CONSTRAINED: for.body: -; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[FMUL_D1]], [[CELL_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[FMUL_D2]], [[CELL_2]] -; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_1:%.*]] = add i64 [[FMUL_1]], [[FMUL_2]] -; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_3:%.*]] = mul i64 [[FMUL_D3]], [[CELL_3]] -; LICM_ONLY_CONSTRAINED-NEXT: [[FADD_2:%.*]] = add i64 [[FADD_1]], [[FMUL_3]] -; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[FADD_2]], ptr [[ARRAYIDX_J_2]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_ONLY_CONSTRAINED: for.end: -; LICM_ONLY_CONSTRAINED-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_3d -; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE-NEXT: entry: -; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D3]], [[DELTA]] -; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL2:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL3:%.*]] = mul i64 [[D2]], [[DELTA]] -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE: for.cond: -; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE: for.body: -; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL2]] -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL3]] -; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_3:%.*]] = mul i64 [[CELL_3]], [[FACTOR_OP_MUL]] -; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[FMUL_3]] -; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[REASS_ADD1]], ptr [[ARRAYIDX_J_2]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE: for.end: -; LICM_AFTER_REASSOCIATE-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_3d -; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_3:%.*]] = mul i64 [[CELL_3]], [[D3]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[FMUL_3]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD1]], [[DELTA]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +; NOT_CONSTRAINED-LABEL: define void @innermost_loop_3d +; NOT_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; NOT_CONSTRAINED-NEXT: entry: +; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D3]], [[DELTA]] +; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D1]], [[DELTA]] +; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL2:%.*]] = mul i64 [[D2]], [[DELTA]] +; NOT_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; NOT_CONSTRAINED: for.cond: +; NOT_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; NOT_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; NOT_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; NOT_CONSTRAINED: for.body: +; NOT_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; NOT_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; NOT_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; NOT_CONSTRAINED-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL1]] +; NOT_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; NOT_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; NOT_CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL2]] +; NOT_CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 +; NOT_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 +; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; NOT_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; NOT_CONSTRAINED-NEXT: [[MUL_3:%.*]] = mul i64 [[CELL_3]], [[FACTOR_OP_MUL]] +; NOT_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]] +; NOT_CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[MUL_3]] +; NOT_CONSTRAINED-NEXT: store i64 [[REASS_ADD1]], ptr [[ARRAYIDX_J_2]], align 8 +; NOT_CONSTRAINED-NEXT: br label [[FOR_COND]] +; NOT_CONSTRAINED: for.end: +; NOT_CONSTRAINED-NEXT: ret void +; +; CONSTRAINED-LABEL: define void @innermost_loop_3d +; CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; CONSTRAINED-NEXT: entry: +; CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] +; CONSTRAINED: for.cond: +; CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; CONSTRAINED: for.body: +; CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; CONSTRAINED-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] +; CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 +; CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 +; CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; CONSTRAINED-NEXT: [[MUL_3:%.*]] = mul i64 [[CELL_3]], [[D3]] +; CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]] +; CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[MUL_3]] +; CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD1]], [[DELTA]] +; CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 +; CONSTRAINED-NEXT: br label [[FOR_COND]] +; CONSTRAINED: for.end: +; CONSTRAINED-NEXT: ret void ; entry: - %fmul.d1 = mul i64 %d1, %delta - %fmul.d2 = mul i64 %d2, %delta - %fmul.d3 = mul i64 %d3, %delta br label %for.cond for.cond: @@ -679,192 +265,20 @@ for.body: %idxprom.j.1 = zext i32 %add.j.1 to i64 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 - %fmul.1 = mul i64 %fmul.d1, %cell.1 + %mul.1 = mul i64 %cell.1, %d1 %idxprom.j = zext i32 %j to i64 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j %cell.2 = load i64, ptr %arrayidx.j, align 8 - %fmul.2 = mul i64 %fmul.d2, %cell.2 - %fadd.1 = add i64 %fmul.1, %fmul.2 + %mul.2 = mul i64 %cell.2, %d2 %add.j.2 = add nuw nsw i32 %j, 2 %idxprom.j.2 = zext i32 %add.j.2 to i64 %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2 %cell.3 = load i64, ptr %arrayidx.j.2, align 8 - %fmul.3 = mul i64 %fmul.d3, %cell.3 - %fadd.2 = add i64 %fadd.1, %fmul.3 - store i64 %fadd.2, ptr %arrayidx.j.2, align 8 - br label %for.cond - -for.end: - ret void -} - -; -; The following loop should be modified by the LICM pass, -; -; int j; -; -; for (j = 0; j <= i; j++) -; cells[j] = (d1 * cells[j + 1] + d2 * cells[j]) * delta; -; -; ...into this: -; -; int j; -; const uint64_t d1d = d1 * delta; -; const uint64_t d2d = d2 * delta; -; -; for (j = 0; j <= i; j++) -; cells[j] = d1d * cells[j + 1] + d2d * cells[j]; -; - -define void @innermost_loop_2d_reassociated(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { -; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_2d_reassociated -; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; REASSOCIATE_ONLY-NEXT: entry: -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] -; REASSOCIATE_ONLY: for.cond: -; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; REASSOCIATE_ONLY: for.body: -; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] -; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] -; REASSOCIATE_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] -; REASSOCIATE_ONLY: for.end: -; REASSOCIATE_ONLY-NEXT: ret void -; -; LICM_ONLY-LABEL: define void @innermost_loop_2d_reassociated -; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY-NEXT: entry: -; LICM_ONLY-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_ONLY-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]] -; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY: for.cond: -; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY: for.body: -; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]] -; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]] -; LICM_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_ONLY-NEXT: store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: br label [[FOR_COND]] -; LICM_ONLY: for.end: -; LICM_ONLY-NEXT: ret void -; -; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_2d_reassociated -; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY_CONSTRAINED-NEXT: entry: -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY_CONSTRAINED: for.cond: -; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY_CONSTRAINED: for.body: -; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] -; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_ONLY_CONSTRAINED: for.end: -; LICM_ONLY_CONSTRAINED-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_2d_reassociated -; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE-NEXT: entry: -; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] -; LICM_AFTER_REASSOCIATE-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]] -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE: for.cond: -; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE: for.body: -; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]] -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE: for.end: -; LICM_AFTER_REASSOCIATE-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_2d_reassociated -; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void -; -entry: - br label %for.cond - -for.cond: - %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] - %cmp.not = icmp sgt i32 %j, %i - br i1 %cmp.not, label %for.end, label %for.body - -for.body: - %add.j.1 = add nuw nsw i32 %j, 1 - %idxprom.j.1 = zext i32 %add.j.1 to i64 - %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 - %cell.1 = load i64, ptr %arrayidx.j.1, align 8 - %fmul.1 = mul i64 %cell.1, %d1 - %idxprom.j = zext i32 %j to i64 - %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j - %cell.2 = load i64, ptr %arrayidx.j, align 8 - %fmul.2 = mul i64 %cell.2, %d2 - %reass.add = add i64 %fmul.2, %fmul.1 - %reass.mul = mul i64 %reass.add, %delta - store i64 %reass.mul, ptr %arrayidx.j, align 8 + %mul.3 = mul i64 %cell.3, %d3 + %reass.add = add i64 %mul.2, %mul.1 + %reass.add1 = add i64 %reass.add, %mul.3 + %reass.mul = mul i64 %reass.add1, %delta + store i64 %reass.mul, ptr %arrayidx.j.2, align 8 br label %for.cond for.end: @@ -883,162 +297,37 @@ for.end: ; This case differs as one of the multiplications involves no invariants. ; -define void @innermost_loop_3d_fast_reassociated_different(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { -; REASSOCIATE_ONLY-LABEL: define void @innermost_loop_3d_fast_reassociated_different -; REASSOCIATE_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; REASSOCIATE_ONLY-NEXT: entry: -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND:%.*]] -; REASSOCIATE_ONLY: for.cond: -; REASSOCIATE_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; REASSOCIATE_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; REASSOCIATE_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; REASSOCIATE_ONLY: for.body: -; REASSOCIATE_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; REASSOCIATE_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; REASSOCIATE_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J_3:%.*]] = zext i32 [[ADD_J_1]] to i64 -; REASSOCIATE_ONLY-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; REASSOCIATE_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; REASSOCIATE_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; REASSOCIATE_ONLY-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; REASSOCIATE_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] -; REASSOCIATE_ONLY-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] -; REASSOCIATE_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[FMUL_1]] -; REASSOCIATE_ONLY-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[FMUL_2]] -; REASSOCIATE_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] -; REASSOCIATE_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; REASSOCIATE_ONLY-NEXT: br label [[FOR_COND]] -; REASSOCIATE_ONLY: for.end: -; REASSOCIATE_ONLY-NEXT: ret void -; -; LICM_ONLY-LABEL: define void @innermost_loop_3d_fast_reassociated_different -; LICM_ONLY-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY-NEXT: entry: -; LICM_ONLY-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY: for.cond: -; LICM_ONLY-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY: for.body: -; LICM_ONLY-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; LICM_ONLY-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_ONLY-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_ONLY-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; LICM_ONLY-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] -; LICM_ONLY-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_ONLY-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] -; LICM_ONLY-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[REASS_ADD]] -; LICM_ONLY-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] -; LICM_ONLY-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY-NEXT: br label [[FOR_COND]] -; LICM_ONLY: for.end: -; LICM_ONLY-NEXT: ret void -; -; LICM_ONLY_CONSTRAINED-LABEL: define void @innermost_loop_3d_fast_reassociated_different -; LICM_ONLY_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_ONLY_CONSTRAINED-NEXT: entry: -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_ONLY_CONSTRAINED: for.cond: -; LICM_ONLY_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_ONLY_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_ONLY_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_ONLY_CONSTRAINED: for.body: -; LICM_ONLY_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_ONLY_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_ONLY_CONSTRAINED-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] -; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[FMUL_2]], [[FMUL_1]] -; LICM_ONLY_CONSTRAINED-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] -; LICM_ONLY_CONSTRAINED-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[REASS_ADD]] -; LICM_ONLY_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] -; LICM_ONLY_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; LICM_ONLY_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_ONLY_CONSTRAINED: for.end: -; LICM_ONLY_CONSTRAINED-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE-LABEL: define void @innermost_loop_3d_fast_reassociated_different -; LICM_AFTER_REASSOCIATE-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE-NEXT: entry: -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE: for.cond: -; LICM_AFTER_REASSOCIATE-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE: for.body: -; LICM_AFTER_REASSOCIATE-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] -; LICM_AFTER_REASSOCIATE-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] -; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[FMUL_1]] -; LICM_AFTER_REASSOCIATE-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[FMUL_2]] -; LICM_AFTER_REASSOCIATE-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] -; LICM_AFTER_REASSOCIATE-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE: for.end: -; LICM_AFTER_REASSOCIATE-NEXT: ret void -; -; LICM_AFTER_REASSOCIATE_CONSTRAINED-LABEL: define void @innermost_loop_3d_fast_reassociated_different -; LICM_AFTER_REASSOCIATE_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: entry: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.cond: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.body: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[FMUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[FMUL_1]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[FMUL_2]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: br label [[FOR_COND]] -; LICM_AFTER_REASSOCIATE_CONSTRAINED: for.end: -; LICM_AFTER_REASSOCIATE_CONSTRAINED-NEXT: ret void +define void @innermost_loop_3d_reassociated_different(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { +; CHECK-LABEL: define void @innermost_loop_3d_reassociated_different +; CHECK-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] +; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] +; CHECK-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] +; CHECK: for.body: +; CHECK-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 +; CHECK-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 +; CHECK-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] +; CHECK-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 +; CHECK-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 +; CHECK-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] +; CHECK-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; CHECK-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 +; CHECK-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 +; CHECK-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] +; CHECK-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 +; CHECK-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] +; CHECK-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] +; CHECK-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] +; CHECK-NEXT: [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[MUL_1]] +; CHECK-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[MUL_2]] +; CHECK-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] +; CHECK-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: for.end: +; CHECK-NEXT: ret void ; entry: br label %for.cond @@ -1053,22 +342,19 @@ for.body: %idxprom.j.1 = zext i32 %add.j.1 to i64 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 - %add.j.2 = add nuw nsw i32 %j, 2 %idxprom.j.2 = zext i32 %add.j.1 to i64 %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2 %cell.2 = load i64, ptr %arrayidx.j.2, align 8 - %add.j.3 = add nuw nsw i32 %j, 3 %idxprom.j.3 = zext i32 %add.j.1 to i64 - %arrayidx.j.3 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.3 %cell.3 = load i64, ptr %arrayidx.j.2, align 8 %idxprom.j = zext i32 %j to i64 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j %cell.4 = load i64, ptr %arrayidx.j, align 8 - %fmul.1 = mul i64 %cell.1, %d1 - %fmul.2 = mul i64 %cell.4, %d2 - %reass.add = add i64 %fmul.2, %fmul.1 + %mul.1 = mul i64 %cell.1, %d1 + %mul.2 = mul i64 %cell.4, %d2 %extra.mul = mul i64 %cell.3, %cell.2 - %extra.add = add i64 %extra.mul, %reass.add + %reass.add = add i64 %extra.mul, %mul.1 + %extra.add = add i64 %reass.add, %mul.2 %reass.mul = mul i64 %extra.add, %delta store i64 %reass.mul, ptr %arrayidx.j, align 8 br label %for.cond From 3880028a66736f7ed1a89440055278a6fff6ab99 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 10 Feb 2024 23:54:07 -0800 Subject: [PATCH 3/5] fixup! Merge int and FP implementations. --- llvm/lib/Transforms/Scalar/LICM.cpp | 120 +++++++++------------------- 1 file changed, 39 insertions(+), 81 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index 3e534aa20568e..63c5c62e9442d 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -2670,21 +2670,31 @@ static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, return false; } +static BinaryOperator *isReassociableOp(BinaryOperator *BO, unsigned Opcode1, + unsigned Opcode2) { + if (BO->getOpcode() == Opcode1 || BO->getOpcode() == Opcode2) + if (!isa(BO) || + (BO->hasAllowReassoc() && BO->hasNoSignedZeros())) + return BO; + return nullptr; +} + /// Try to reassociate expressions like ((A1 * B1) + (A2 * B2) + ...) * C where /// A1, A2, ... and C are loop invariants into expressions like /// ((A1 * C * B1) + (A2 * C * B2) + ...) and hoist the (A1 * C), (A2 * C), ... /// invariant expressions. This functions returns true only if any hoisting has /// actually occured. -static bool hoistFPAssociation(Instruction &I, Loop &L, - ICFLoopSafetyInfo &SafetyInfo, - MemorySSAUpdater &MSSAU, AssumptionCache *AC, - DominatorTree *DT) { +static bool hoistMulAddAssociation(Instruction &I, Loop &L, + ICFLoopSafetyInfo &SafetyInfo, + MemorySSAUpdater &MSSAU, AssumptionCache *AC, + DominatorTree *DT) { using namespace PatternMatch; - Value *VariantOp = nullptr, *InvariantOp = nullptr; - if (!match(&I, m_FMul(m_Value(VariantOp), m_Value(InvariantOp))) || - !I.hasAllowReassoc() || !I.hasNoSignedZeros()) + if (auto *BO = dyn_cast(&I); + !BO || !isReassociableOp(BO, Instruction::Mul, Instruction::FMul)) return false; + Value *VariantOp = I.getOperand(0); + Value *InvariantOp = I.getOperand(1); if (L.isLoopInvariant(VariantOp)) std::swap(VariantOp, InvariantOp); if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp)) @@ -2698,15 +2708,17 @@ static bool hoistFPAssociation(Instruction &I, Loop &L, Worklist.push_back(VariantBinOp); while (!Worklist.empty()) { BinaryOperator *BO = Worklist.pop_back_val(); - if (!BO->hasOneUse() || !BO->hasAllowReassoc() || !BO->hasNoSignedZeros()) + if (!BO->hasOneUse()) return false; - BinaryOperator *Op0, *Op1; - if (match(BO, m_FAdd(m_BinOp(Op0), m_BinOp(Op1)))) { - Worklist.push_back(Op0); - Worklist.push_back(Op1); + if (isReassociableOp(BO, Instruction::Add, Instruction::FAdd) && + isa(BO->getOperand(0)) && + isa(BO->getOperand(1))) { + Worklist.push_back(cast(BO->getOperand(0))); + Worklist.push_back(cast(BO->getOperand(1))); continue; } - if (BO->getOpcode() != Instruction::FMul || L.isLoopInvariant(BO)) + if (!isReassociableOp(BO, Instruction::Mul, Instruction::FMul) || + L.isLoopInvariant(BO)) return false; Use &U0 = BO->getOperandUse(0); Use &U1 = BO->getOperandUse(1); @@ -2716,7 +2728,10 @@ static bool hoistFPAssociation(Instruction &I, Loop &L, Changes.push_back(&U1); else return false; - if (Changes.size() > FPAssociationUpperLimit) + unsigned Limit = I.getType()->isIntOrIntVectorTy() + ? IntAssociationUpperLimit + : FPAssociationUpperLimit; + if (Changes.size() > Limit) return false; } if (Changes.empty()) @@ -2729,66 +2744,12 @@ static bool hoistFPAssociation(Instruction &I, Loop &L, for (auto *U : Changes) { assert(L.isLoopInvariant(U->get())); Instruction *Ins = cast(U->getUser()); - U->set(Builder.CreateFMulFMF(U->get(), Factor, Ins, "factor.op.fmul")); - } - I.replaceAllUsesWith(VariantOp); - eraseInstruction(I, SafetyInfo, MSSAU); - return true; -} - -static bool hoistIntAssociation(Instruction &I, Loop &L, - ICFLoopSafetyInfo &SafetyInfo, - MemorySSAUpdater &MSSAU, AssumptionCache *AC, - DominatorTree *DT) { - using namespace PatternMatch; - Value *VariantOp = nullptr, *InvariantOp = nullptr; - - if (!match(&I, m_Mul(m_Value(VariantOp), m_Value(InvariantOp)))) - return false; - if (L.isLoopInvariant(VariantOp)) - std::swap(VariantOp, InvariantOp); - if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp)) - return false; - Value *Factor = InvariantOp; - - // First, we need to make sure we should do the transformation. - SmallVector Changes; - SmallVector Worklist; - if (BinaryOperator *VariantBinOp = dyn_cast(VariantOp)) - Worklist.push_back(VariantBinOp); - while (!Worklist.empty()) { - BinaryOperator *BO = Worklist.pop_back_val(); - if (!BO->hasOneUse()) - return false; - BinaryOperator *Op0, *Op1; - if (match(BO, m_Add(m_BinOp(Op0), m_BinOp(Op1)))) { - Worklist.push_back(Op0); - Worklist.push_back(Op1); - continue; - } - if (BO->getOpcode() != Instruction::Mul || L.isLoopInvariant(BO)) - return false; - Use &U0 = BO->getOperandUse(0); - Use &U1 = BO->getOperandUse(1); - if (L.isLoopInvariant(U0)) - Changes.push_back(&U0); - else if (L.isLoopInvariant(U1)) - Changes.push_back(&U1); + Value *Mul; + if (I.getType()->isIntOrIntVectorTy()) + Mul = Builder.CreateMul(U->get(), Factor, "factor.op.mul"); else - return false; - if (Changes.size() > IntAssociationUpperLimit) - return false; - } - if (Changes.empty()) - return false; - - // We know we should do it so let's do the transformation. - auto *Preheader = L.getLoopPreheader(); - assert(Preheader && "Loop is not in simplify form?"); - IRBuilder<> Builder(Preheader->getTerminator()); - for (auto *U : Changes) { - assert(L.isLoopInvariant(U->get())); - U->set(Builder.CreateMul(U->get(), Factor, "factor.op.mul")); + Mul = Builder.CreateFMulFMF(U->get(), Factor, Ins, "factor.op.fmul"); + U->set(Mul); } I.replaceAllUsesWith(VariantOp); eraseInstruction(I, SafetyInfo, MSSAU); @@ -2822,15 +2783,12 @@ static bool hoistArithmetics(Instruction &I, Loop &L, return true; } - if (hoistFPAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) { - ++NumHoisted; - ++NumFPAssociationsHoisted; - return true; - } - - if (hoistIntAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) { + if (hoistMulAddAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) { ++NumHoisted; - ++NumIntAssociationsHoisted; + if (I.getType()->isIntOrIntVectorTy()) + ++NumIntAssociationsHoisted; + else + ++NumFPAssociationsHoisted; return true; } From 0ccdfc467f2df0155443c7999a0f47791e5331e9 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 12 Feb 2024 09:40:20 -0800 Subject: [PATCH 4/5] fixup! Make Int and FP opcodes for isReassociableOp explicit. Use BinaryOperator::getOperand. --- llvm/lib/Transforms/Scalar/LICM.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index 63c5c62e9442d..8d308a5e70e13 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -2670,12 +2670,13 @@ static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, return false; } -static BinaryOperator *isReassociableOp(BinaryOperator *BO, unsigned Opcode1, - unsigned Opcode2) { - if (BO->getOpcode() == Opcode1 || BO->getOpcode() == Opcode2) - if (!isa(BO) || - (BO->hasAllowReassoc() && BO->hasNoSignedZeros())) - return BO; +static BinaryOperator *isReassociableOp(BinaryOperator *BO, unsigned IntOpcode, + unsigned FPOpcode) { + if (BO->getOpcode() == IntOpcode) + return BO; + if (BO->getOpcode() == FPOpcode && BO->hasAllowReassoc() && + BO->hasNoSignedZeros()) + return BO; return nullptr; } @@ -2690,11 +2691,11 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L, DominatorTree *DT) { using namespace PatternMatch; - if (auto *BO = dyn_cast(&I); - !BO || !isReassociableOp(BO, Instruction::Mul, Instruction::FMul)) + auto *BO = dyn_cast(&I); + if (!BO || !isReassociableOp(BO, Instruction::Mul, Instruction::FMul)) return false; - Value *VariantOp = I.getOperand(0); - Value *InvariantOp = I.getOperand(1); + Value *VariantOp = BO->getOperand(0); + Value *InvariantOp = BO->getOperand(1); if (L.isLoopInvariant(VariantOp)) std::swap(VariantOp, InvariantOp); if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp)) From 0c789c040b52f8b9afcb544ed9fa6a0567ad1ecb Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 12 Feb 2024 14:24:55 -0800 Subject: [PATCH 5/5] fixup! Remove unnecessary dyn_cast. Make isReassociableOp return bool. --- llvm/lib/Transforms/Scalar/LICM.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index 8d308a5e70e13..67295f1c76147 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -2670,14 +2670,14 @@ static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, return false; } -static BinaryOperator *isReassociableOp(BinaryOperator *BO, unsigned IntOpcode, - unsigned FPOpcode) { - if (BO->getOpcode() == IntOpcode) - return BO; - if (BO->getOpcode() == FPOpcode && BO->hasAllowReassoc() && - BO->hasNoSignedZeros()) - return BO; - return nullptr; +static bool isReassociableOp(Instruction *I, unsigned IntOpcode, + unsigned FPOpcode) { + if (I->getOpcode() == IntOpcode) + return true; + if (I->getOpcode() == FPOpcode && I->hasAllowReassoc() && + I->hasNoSignedZeros()) + return true; + return false; } /// Try to reassociate expressions like ((A1 * B1) + (A2 * B2) + ...) * C where @@ -2691,11 +2691,10 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L, DominatorTree *DT) { using namespace PatternMatch; - auto *BO = dyn_cast(&I); - if (!BO || !isReassociableOp(BO, Instruction::Mul, Instruction::FMul)) + if (!isReassociableOp(&I, Instruction::Mul, Instruction::FMul)) return false; - Value *VariantOp = BO->getOperand(0); - Value *InvariantOp = BO->getOperand(1); + Value *VariantOp = I.getOperand(0); + Value *InvariantOp = I.getOperand(1); if (L.isLoopInvariant(VariantOp)) std::swap(VariantOp, InvariantOp); if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp))