Index: polly/trunk/lib/Analysis/ScopBuilder.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopBuilder.cpp +++ polly/trunk/lib/Analysis/ScopBuilder.cpp @@ -691,23 +691,31 @@ /// Generate a name for a statement. /// -/// @param S The parent SCoP. -/// @param BB The basic block the statement will represent. -/// @param Count The index of the created statement in @p BB. -static std::string makeStmtName(Scop *S, BasicBlock *BB, int Count) { - std::string Suffix = ""; - if (Count != 0) - Suffix += std::to_string(Count); - return getIslCompatibleName("Stmt", BB, S->getNextStmtIdx(), Suffix, - UseInstructionNames); +/// @param BB The basic block the statement will represent. +/// @param BBIdx The index of the @p BB relative to other BBs/regions. +/// @param Count The index of the created statement in @p BB. +/// @param IsMain Whether this is the main of all statement for @p BB. If true, +/// no suffix will be added. +static std::string makeStmtName(BasicBlock *BB, long BBIdx, int Count, + bool IsMain) { + std::string Suffix; + if (!IsMain) { + if (UseInstructionNames) + Suffix = '_'; + if (Count < 26) + Suffix += 'a' + Count; + else + Suffix += std::to_string(Count); + } + return getIslCompatibleName("Stmt", BB, BBIdx, Suffix, UseInstructionNames); } /// Generate a name for a statement that represents a non-affine subregion. /// -/// @param S The parent SCoP. -/// @param R The region the statement will represent. -static std::string makeStmtName(Scop *S, Region *R) { - return getIslCompatibleName("Stmt", R->getNameStr(), S->getNextStmtIdx(), "", +/// @param R The region the statement will represent. +/// @param RIdx The index of the @p R relative to other BBs/regions. +static std::string makeStmtName(Region *R, long RIdx) { + return getIslCompatibleName("Stmt", R->getNameStr(), RIdx, "", UseInstructionNames); } @@ -715,20 +723,21 @@ Loop *SurroundingLoop = LI.getLoopFor(BB); int Count = 0; + long BBIdx = scop->getNextStmtIdx(); std::vector Instructions; for (Instruction &Inst : *BB) { if (shouldModelInst(&Inst, SurroundingLoop)) Instructions.push_back(&Inst); if (Inst.getMetadata("polly_split_after") || (SplitOnStore && isa(Inst))) { - std::string Name = makeStmtName(scop.get(), BB, Count); + std::string Name = makeStmtName(BB, BBIdx, Count, Count == 0); scop->addScopStmt(BB, Name, SurroundingLoop, Instructions); Count++; Instructions.clear(); } } - std::string Name = makeStmtName(scop.get(), BB, Count); + std::string Name = makeStmtName(BB, BBIdx, Count, Count == 0); scop->addScopStmt(BB, Name, SurroundingLoop, Instructions); } @@ -853,11 +862,21 @@ // shouldModelInst() repeatedly. SmallVector ModeledInsts; EquivalenceClasses UnionFind; + Instruction *MainInst = nullptr; for (Instruction &Inst : *BB) { if (!shouldModelInst(&Inst, L)) continue; ModeledInsts.push_back(&Inst); UnionFind.insert(&Inst); + + // When a BB is split into multiple statements, the main statement is the + // one containing the 'main' instruction. We select the first instruction + // that is unlikely to be removed (because it has side-effects) as the main + // one. It is used to ensure that at least one statement from the bb has the + // same name as with -polly-stmt-granularity=bb. + if (!MainInst && (isa(Inst) || + (isa(Inst) && !isa(Inst)))) + MainInst = &Inst; } // 'nullptr' represents the last statement for a basic block. It contains no @@ -896,10 +915,20 @@ // Finally build the statements. int Count = 0; + long BBIdx = scop->getNextStmtIdx(); for (auto &Instructions : reverse(LeaderToInstList)) { std::vector &InstList = Instructions.second; + + // If there is no main instruction, make the first statement the main. + bool IsMain; + if (MainInst) + IsMain = std::find(InstList.begin(), InstList.end(), MainInst) != + InstList.end(); + else + IsMain = (Count == 0); + std::reverse(InstList.begin(), InstList.end()); - std::string Name = makeStmtName(scop.get(), BB, Count); + std::string Name = makeStmtName(BB, BBIdx, Count, IsMain); scop->addScopStmt(BB, Name, L, std::move(InstList)); Count += 1; } @@ -913,7 +942,8 @@ for (Instruction &Inst : *SR.getEntry()) if (shouldModelInst(&Inst, SurroundingLoop)) Instructions.push_back(&Inst); - std::string Name = makeStmtName(scop.get(), &SR); + long RIdx = scop->getNextStmtIdx(); + std::string Name = makeStmtName(&SR, RIdx); scop->addScopStmt(&SR, Name, SurroundingLoop, Instructions); return; } Index: polly/trunk/test/ScopInfo/granularity_same_name.ll =================================================================== --- polly/trunk/test/ScopInfo/granularity_same_name.ll +++ polly/trunk/test/ScopInfo/granularity_same_name.ll @@ -0,0 +1,49 @@ +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=0 -polly-scops -analyze < %s | FileCheck %s -match-full-lines -check-prefix=IDX +; RUN: opt %loadPolly -polly-stmt-granularity=bb -polly-use-llvm-names=1 -polly-scops -analyze < %s | FileCheck %s -match-full-lines -check-prefix=BB +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=0 -polly-scops -analyze < %s | FileCheck %s -match-full-lines -check-prefix=IDX +; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-use-llvm-names=1 -polly-scops -analyze < %s | FileCheck %s -match-full-lines -check-prefix=BB +; +; Check that the statement has the same name, regardless of how the +; basic block is split into multiple statements. +; Note that %unrelatedA and %unrelatedB can be put into separate +; statements, but are removed because those have no side-effects. +; +; for (int j = 0; j < n; j += 1) { +; body: +; double unrelatedA = 21.0 + 21.0; +; A[0] = 0.0; +; double unrelatedB = 21.0 + 21.0; +; } +; +define void @func(i32 %n, double* noalias nonnull %A) { +entry: + br label %for + +for: + %j = phi i32 [0, %entry], [%j.inc, %inc] + %j.cmp = icmp slt i32 %j, %n + br i1 %j.cmp, label %body, label %exit + + body: + %unrelatedA = fadd double 21.0, 21.0 + store double 0.0, double* %A + %unrelatedB = fadd double 21.0, 21.0 + br label %inc + +inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + +exit: + br label %return + +return: + ret void +} + + +; IDX: Statements { +; IDX-NEXT: Stmt1 + +; BB: Statements { +; BB-NEXT: Stmt_body Index: polly/trunk/test/ScopInfo/granularity_scalar-indep.ll =================================================================== --- polly/trunk/test/ScopInfo/granularity_scalar-indep.ll +++ polly/trunk/test/ScopInfo/granularity_scalar-indep.ll @@ -54,13 +54,13 @@ ; CHECK-NEXT: %valA = load double, double* %A ; CHECK-NEXT: store double %valA, double* %A ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_body1 +; CHECK-NEXT: Stmt_body_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: [n] -> { Stmt_body1[i0] : 0 <= i0 < n }; +; CHECK-NEXT: [n] -> { Stmt_body_b[i0] : 0 <= i0 < n }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: [n] -> { Stmt_body1[i0] -> [i0, 1] }; +; CHECK-NEXT: [n] -> { Stmt_body_b[i0] -> [i0, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: [n] -> { Stmt_body1[i0] -> MemRef_B[0] }; +; CHECK-NEXT: [n] -> { Stmt_body_b[i0] -> MemRef_B[0] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: %valB = fadd double 2.100000e+01, 2.100000e+01 ; CHECK-NEXT: store double %valB, double* %B Index: polly/trunk/test/ScopInfo/granularity_scalar-indep_epilogue.ll =================================================================== --- polly/trunk/test/ScopInfo/granularity_scalar-indep_epilogue.ll +++ polly/trunk/test/ScopInfo/granularity_scalar-indep_epilogue.ll @@ -56,13 +56,13 @@ ; CHECK-NEXT: %valA = load double, double* %A ; CHECK-NEXT: store double %valA, double* %A ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_bodyA1 +; CHECK-NEXT: Stmt_bodyA_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: [n] -> { Stmt_bodyA1[i0] : 0 <= i0 < n }; +; CHECK-NEXT: [n] -> { Stmt_bodyA_b[i0] : 0 <= i0 < n }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: [n] -> { Stmt_bodyA1[i0] -> [i0, 1] }; +; CHECK-NEXT: [n] -> { Stmt_bodyA_b[i0] -> [i0, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] -; CHECK-NEXT: [n] -> { Stmt_bodyA1[i0] -> MemRef_phi__phi[] }; +; CHECK-NEXT: [n] -> { Stmt_bodyA_b[i0] -> MemRef_phi__phi[] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: } ; CHECK-NEXT: } Index: polly/trunk/test/ScopInfo/stmt_split_exit_of_region_stmt.ll =================================================================== --- polly/trunk/test/ScopInfo/stmt_split_exit_of_region_stmt.ll +++ polly/trunk/test/ScopInfo/stmt_split_exit_of_region_stmt.ll @@ -21,19 +21,19 @@ ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Stmt_Stmt_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] : 0 <= i0 <= 1023 }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 2] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> [i0, 2] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_B[i0] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 ; CHECK-NEXT: } ; CHECK-NEXT: } ; -; Function Attrs: noinline nounwind uwtable +; Function Attrs: noinline nounwind uwtable define void @func(i32* %A, i32* %B, double* %C) { entry: br label %for.cond Index: polly/trunk/test/ScopInfo/stmt_split_no_dependence.ll =================================================================== --- polly/trunk/test/ScopInfo/stmt_split_no_dependence.ll +++ polly/trunk/test/ScopInfo/stmt_split_no_dependence.ll @@ -19,13 +19,13 @@ ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Stmt_Stmt_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] : 0 <= i0 <= 1023 }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> [i0, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_B[i0] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 ; CHECK-NEXT: } Index: polly/trunk/test/ScopInfo/stmt_split_on_store.ll =================================================================== --- polly/trunk/test/ScopInfo/stmt_split_on_store.ll +++ polly/trunk/test/ScopInfo/stmt_split_on_store.ll @@ -19,13 +19,13 @@ ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4 ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Stmt_Stmt_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] : 0 <= i0 <= 1023 }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> [i0, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_B[i0] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 ; CHECK-NEXT: } Index: polly/trunk/test/ScopInfo/stmt_split_on_synthesizable.ll =================================================================== --- polly/trunk/test/ScopInfo/stmt_split_on_synthesizable.ll +++ polly/trunk/test/ScopInfo/stmt_split_on_synthesizable.ll @@ -11,13 +11,13 @@ ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4 ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Stmt_Stmt_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] : 0 <= i0 <= 1023 }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> [i0, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_B[i0] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 ; CHECK-NEXT: } Index: polly/trunk/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll =================================================================== --- polly/trunk/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll +++ polly/trunk/test/ScopInfo/stmt_split_phi_in_beginning_bb.ll @@ -11,13 +11,13 @@ ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %phi, i32* %arrayidx, align 4, !polly_split_after !0 ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Stmt_Stmt_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] : 0 <= i0 <= 1023 }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> [i0, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_B[i0] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 ; CHECK-NEXT: } Index: polly/trunk/test/ScopInfo/stmt_split_phi_in_stmt.ll =================================================================== --- polly/trunk/test/ScopInfo/stmt_split_phi_in_stmt.ll +++ polly/trunk/test/ScopInfo/stmt_split_phi_in_stmt.ll @@ -11,15 +11,15 @@ ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Stmt_Stmt_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] : 0 <= i0 <= 1023 }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> [i0, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[i0] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_B[i0] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_phi__phi[] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_phi__phi[] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: %d = fadd double 2.100000e+01, 2.100000e+01 ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 Index: polly/trunk/test/ScopInfo/stmt_split_scalar_dependence.ll =================================================================== --- polly/trunk/test/ScopInfo/stmt_split_scalar_dependence.ll +++ polly/trunk/test/ScopInfo/stmt_split_scalar_dependence.ll @@ -14,15 +14,15 @@ ; CHECK-NEXT: %a = fadd double 2.100000e+01, 2.100000e+01 ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Stmt_Stmt_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: { Stmt_Stmt1[i0] : 0 <= i0 <= 1023 }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] : 0 <= i0 <= 1023 }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: { Stmt_Stmt1[i0] -> [i0, 1] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> [i0, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_B[0] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_B[0] }; ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1] -; CHECK-NEXT: { Stmt_Stmt1[i0] -> MemRef_a[] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0] -> MemRef_a[] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store double %a, double* %B ; CHECK-NEXT: } Index: polly/trunk/test/ScopInfo/stmt_split_within_loop.ll =================================================================== --- polly/trunk/test/ScopInfo/stmt_split_within_loop.ll +++ polly/trunk/test/ScopInfo/stmt_split_within_loop.ll @@ -11,13 +11,13 @@ ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx, align 4, !polly_split_after !0 ; CHECK-NEXT: } -; CHECK-NEXT: Stmt_Stmt1 +; CHECK-NEXT: Stmt_Stmt_b ; CHECK-NEXT: Domain := -; CHECK-NEXT: { Stmt_Stmt1[i0, i1] : 0 <= i0 <= 1023 and 0 <= i1 <= 512 }; +; CHECK-NEXT: { Stmt_Stmt_b[i0, i1] : 0 <= i0 <= 1023 and 0 <= i1 <= 512 }; ; CHECK-NEXT: Schedule := -; CHECK-NEXT: { Stmt_Stmt1[i0, i1] -> [i0, i1, 1] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0, i1] -> [i0, i1, 1] }; ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] -; CHECK-NEXT: { Stmt_Stmt1[i0, i1] -> MemRef_B[i0] }; +; CHECK-NEXT: { Stmt_Stmt_b[i0, i1] -> MemRef_B[i0] }; ; CHECK-NEXT: Instructions { ; CHECK-NEXT: store i32 %i.0, i32* %arrayidx2, align 4 ; CHECK-NEXT: %cond = icmp slt i32 %j, 512