Hi, I'm incrementing my toy compiler to account for variable mutations around if/else blocks. Reading the Kaleidoscope tutorial, I've learnt that I can substitute the PHI node creation by allocas and retrieving the value later, if needed. The Kaleidoscope example seems to account for one value only, the result of: Value *ThenV = Then->Codegen(); (...) Value *ElseV = Else->Codegen(); (...) PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); But both Then and Else are expressions, so the Value returned is in the form of a single variable. ExprAST *Then = ParseExpression(); (...) ExprAST *Else = ParseExpression(); In my toy language, I accept any number of statements inside a block. Ignoring nested if statements, should I keep track of *each* variable mutation inside the block, or is there some LLVM magic (as I'm getting used to)? A simple C example would be: int a, b, c, d; (...) if (a > 10) { b = c = d = 10 * a; } else { b = c = d = 10 / a; } As I'm always using alloca, the mem2reg pass seems to do the trick, but I'm not sure it would in all cases. The tutorial states that it works on all scalar values (I have no structs or arrays), so I believe I'm safe. Am I? cheers, --renato
On Thu, Oct 1, 2009 at 4:35 PM, Renato Golin <rengolin at systemcall.org> wrote:> Hi, > > I'm incrementing my toy compiler to account for variable mutations > around if/else blocks. > > Reading the Kaleidoscope tutorial, I've learnt that I can substitute > the PHI node creation by allocas and retrieving the value later, if > needed. The Kaleidoscope example seems to account for one value only, > the result of: > > Value *ThenV = Then->Codegen(); > (...) > Value *ElseV = Else->Codegen(); > (...) > PN->addIncoming(ThenV, ThenBB); > PN->addIncoming(ElseV, ElseBB); > > But both Then and Else are expressions, so the Value returned is in > the form of a single variable. > > ExprAST *Then = ParseExpression(); > (...) > ExprAST *Else = ParseExpression(); > > In my toy language, I accept any number of statements inside a block. > > Ignoring nested if statements, should I keep track of *each* variable > mutation inside the block, or is there some LLVM magic (as I'm getting > used to)? > > A simple C example would be: > > int a, b, c, d; > (...) > if (a > 10) { > b = c = d = 10 * a; > } else { > b = c = d = 10 / a; > } > > As I'm always using alloca, the mem2reg pass seems to do the trick, > but I'm not sure it would in all cases. The tutorial states that it > works on all scalar values (I have no structs or arrays), so I believe > I'm safe. > > Am I?I hope so, because I've been doing the same thing. My local variables are always bound to alloca's, and my test makefile just calls "opt -std-compile-opts" after my compiler runs; so far it's been giving me pretty good code as a result.
2009/10/1 Kenneth Uildriks <kennethuil at gmail.com>:> I hope so, because I've been doing the same thing. My local variables > are always bound to alloca's, and my test makefile just calls "opt > -std-compile-opts" after my compiler runs; so far it's been giving me > pretty good code as a result.Same here, but I'm not compiling any really complex code, so I thought it was just beginner's luck. Looks like it's another score for the "LLVM magic"! ;) It might create problems for a potential debugger, but I'm not planning to create one too soon. cheers, --renato
On Thu, Oct 1, 2009 at 2:35 PM, Renato Golin <rengolin at systemcall.org> wrote:> As I'm always using alloca, the mem2reg pass seems to do the trick, > but I'm not sure it would in all cases. The tutorial states that it > works on all scalar values (I have no structs or arrays), so I believe > I'm safe. > > Am I?Yes, you're safe; if the alloca is a scalar and you don't do anything other than load and store to the alloca, mem2reg will eliminate the alloca regardless of the control flow. It's a fundamental property of the algorithm to convert to SSA form; there's a comment in the source code pointing to the paper in question if you're interested in the theory. -Eli