Index: include/polly/CodeGen/BlockGenerators.h =================================================================== --- include/polly/CodeGen/BlockGenerators.h +++ include/polly/CodeGen/BlockGenerators.h @@ -136,31 +136,89 @@ /// @brief Maps to resolve scalar dependences for PHI operands and scalars. /// - /// Usage example: - /// - /// x1 = ... // x1 will be inserted in the ScalarMap and PhiOpMap. - /// for (i=0...N) { - /// x2 = phi(x1, add) // x2 will be inserted in the ScalarMap, x1 and - /// // add are mapped in the PHIOpMap. - /// add = x2 + A[i]; // add will be inserted in the ScalarMap and - /// // the PhiOpMap. - /// } - /// print(x1) // x1 is mapped in the ScalarMap. - /// print(x2) // x2 is mapped in the ScalarMap. - /// print(add) // add is mapped in the ScalarMap. - /// + /// When translating code that contains scalar dependences as they result from + /// inter-block scalar dependences (including the use of data carrying + /// PHI nodes), we do not directly regenerate in-register SSA code, but + /// instead allocate some stack memory through which these scalar values are + /// passed. Only a later pass of -mem2reg will then (re)introduce in-register + /// computations. + /// + /// To keep track of the memory location(s) used to store the data computed by + /// a given SSA instruction, we use the maps 'ScalarMap' and 'PHIOpMap'. Each + /// maps a given scalar value to a junk of stack allocated memory. + /// + /// 'ScalarMap' is used for normal scalar dependences that go from a scalar + /// definition to its use. Such dependences are lowered by directly writing + /// the value an instruction computes into the corresponding chunk of memory + /// and reading it back from this chunk of memory right before every use of + /// this original scalar value. The memory locations in 'ScalarMap' end with + /// '.s2a'. + /// + /// 'PHIOpMap' is used to model PHI nodes. For each PHI nodes we introduce, + /// besides the memory in 'ScalarMap', a second chunk of memory into which we + /// write at the end of each basic block preceeding the PHI instruction the + /// value passed through this basic block. At the place where the PHI node is + /// executed, we replace the PHI node with a load from the corresponding + /// memory location in the 'PHIOpMap' table. The memory locations in + /// 'PHIOpMap' end with '.phiops'. + /// + /// An access to/from memory that belongs to a PHI node is in the ScopInfo + /// always modeled with the name of the PHI node. However, in reality PHI + /// nodes can introduce reads/writes to two different memory locations, the + /// normal '.s2a' locations and the special '.phiops' locations. We do not + /// track this difference in the polyhedral description, but only through + /// the content of the two maps 'ScalarMap' and 'PHIOpMap'. + /// + /// Example: + /// + /// Input C Code + /// ============ + /// + /// x1 = ... + /// for (i=0...N) { + /// x2 = phi(x1, add) + /// add = x2 + 42; + /// } + /// print(x1) + /// print(x2) + /// print(add) + /// + /// + /// Unmodified IR IR After expansion + /// ============= ================== + /// + /// x1 = ... x1 = ... + /// x1.s2a = s1 + /// x2.phiops = s1 + /// | | + /// | <--<--<--<--< | <--<--<--<--< + /// | / \ | / \ + /// V V \ V V \ + /// x2 = phi (x1, add) | x2 = x2.phiops | + /// | x2.s2a = x2 | + /// | | + /// add = x2 + 42 | add = x2 + 42 | + /// | add.s2a = add | + /// | x2.phiops = add | + /// | \ / | \ / + /// | \ / | \ / + /// | >-->-->-->--> | >-->-->-->--> + /// V V + /// x1 = x1.s2a + /// ... = x1 ... = x1 + /// x2 = x2.s2a + /// ... = x2 ... = x2 + /// add = add.s2a + /// ... = add ... = add + /// + /// ScalarMap = { x1 -> x1.s2a, x2 -> x2.s2a, add -> add.s2a } + /// PHIOpMap = { x2 -> x2.phiops } ///{ - - /// The PHIOpMap is used to get the alloca to communicate a value to a PHI - /// node, hence when the operand of a PHI is demoted the corresponding write - /// access will use the PHIOpMap to look for the correct alloca. PHI nodes - /// will then read that location in order to get the correct/current operand - /// value. + /// + /// @brief Memory locations used for the special PHI node modeling. ScalarAllocaMapTy &PHIOpMap; - /// The ScalarMap is used in __all__ other cases, thus always when a scalar - /// variable is read/written and the write is not because the scalar is a PHI - /// operand. + /// @brief Memory locations used to model scalar dependences. ScalarAllocaMapTy &ScalarMap; ///}