how to code a loop in llvm assembly

Hi,

I've read over the "LLVM Language Reference Manual"
a few times, and writing some ll code, but i'm stuck at
a very basic point. How to decrement a counter variable ?

int %count(int %n) {
EntryBlock:
  %cond = seteq int %n, 0
  br bool %cond, label %Exit, label %Next
Next:
; how to decrement n ?
  %new_n = sub int %n, 1
  br label %EntryBlock
Exit:
  ret int 0
}

I guess I could malloc a variable and use store/load. Is that the right way ?

Also the above code is invalid:
Entry block to function must not have predecessors!
label %EntryBlock
Broken module found, compilation aborted!

thanks for any hints,

Simon.

Simon Burton <simon@arrowtheory.com> writes:

Hi,

I've read over the "LLVM Language Reference Manual"
a few times, and writing some ll code, but i'm stuck at
a very basic point. How to decrement a counter variable ?

int %count(int %n) {
EntryBlock:
  %cond = seteq int %n, 0
  br bool %cond, label %Exit, label %Next
Next:
; how to decrement n ?
  %new_n = sub int %n, 1
  br label %EntryBlock
Exit:
  ret int 0
}

I guess I could malloc a variable and use store/load. Is that the right way ?

Also the above code is invalid:
Entry block to function must not have predecessors!
label %EntryBlock
Broken module found, compilation aborted!

You need a phi node.

A good way to learn how to write LLVM assembler is to use the online
demo available at http://llvm.org/demo/ You feed a C/C++/Stacker
program and you get the equivalent LLVM code. In this case, something
like this C code is necessary:

int foo(int n, int x) {
  while(n > x) --n;
  return n;
}

The extra stuff is for circumventing the optimizer. If you write

int foo(int n) {
  while(n) --n;
  return 0;
}

the optimizer will reduce it to a ret int 0, which teach us nothing.

An option for disabing optimizations would be very helpful for
learners.

BTW, Simon, is there a reason for writing LLVM assembler and not
generating LLVM code directly? The later is simpler and relieves you
from some nasty burdens. It doesn't require you to generate SSA
conformant code, for instance. Relating to your present problem, it is
"natural" to code a loop without resorting to phi nodes.

Oscar Fuentes <oscarfv@telefonica.net> writes:

[snip]

BTW, Simon, is there a reason for writing LLVM assembler and not
generating LLVM code directly? The later is simpler and relieves you
from some nasty burdens. It doesn't require you to generate SSA
conformant code, for instance. Relating to your present problem, it is
"natural" to code a loop without resorting to phi nodes.

Clarification: it is incorrect to say that generating LLVM code by
instantiating LLVM instructions doesn't require to follow SSA
rules. The truth is that the API is designed in such a way that you
follow SSA rules without knowing about them, except for things like
entries/exits of basic blocks (at least, I have not found any other
issues with SSA so far).

Hi Simon,

I've read over the "LLVM Language Reference Manual" a few times, and
writing some ll code, but i'm stuck at a very basic point. How to
decrement a counter variable ?

As Oscar pointed out, you need a phi-node. I read some of the published
papers on LLVM before the Language Reference Manual and found them to be
of use. You may also find Wikipedia's explanation of SSA useful,
especially the key paragraph

    Static single-assignment form - Wikipedia

    "Note: the phi functions are not actually implemented; instead,
    they're just markers for the compiler to place the value of all the
    variables grouped together by the phi function, in the same location
    in memory (or same register)."

Cheers,

Ralph.

Simon Burton <simon@arrowtheory.com> writes:
> I've read over the "LLVM Language Reference Manual"
> a few times, and writing some ll code, but i'm stuck at
> a very basic point. How to decrement a counter variable ?

[snip]

> I guess I could malloc a variable and use store/load. Is that the right way ?

[snip]

You need a phi node.

As others have pointed out, because LLVM is in SSA form, you will need
to use a phi node. To see how it would be written, try using the demo
script as Oscar suggested, or you can do what you suggested (I would use
alloca instead of malloc, though I think either should work) and then
run it through "opt -mem2reg" to convert it to the phi-node form.

FYI, in case you're wondering about the validity of this approach,
generating alloca instructions and relying on -mem2reg is what the C/C++
front ends do. It is a little more straight forward to code than
manually worrying about the PHI nodes. Either approach will work, take
your pick :slight_smile:

Reid.

Using an alloca'd variable with loads and stores would work well too. To date this
is how every llvm language front end works. You would want to avoid malloc for
such a purpose generally. mem2reg is nice enough to take your local load
and stores and promote them to registers with PHINodes :slight_smile:

FYI, in case you're wondering about the validity of this approach,
generating alloca instructions and relying on -mem2reg is what the C/C++
front ends do. It is a little more straight forward to code than
manually worrying about the PHI nodes.

Yeah I wouldn't want to worry about calculating dominance frontiers in my
code generator unless I had to :slight_smile:

Patrick Meredith wrote:

Using an alloca'd variable with loads and stores would work well too. To date this
is how every llvm language front end works.

nope :-). PyPy produces SSA code diretly when using the LLVM backend, which is not surprising, since PyPy uses SSA internally.

You would want to avoid malloc for
such a purpose generally. mem2reg is nice enough to take your local load
and stores and promote them to registers with PHINodes :slight_smile:

Cheers,

Carl Friedrich Bolz

BTW, Simon, is there a reason for writing LLVM assembler and not
generating LLVM code directly?

You mean write C++ code that calls the LLVM library ?
I have a mild C++ allergy that I don't wish to aggravate.

The later is simpler and relieves you
from some nasty burdens.

Yes, i'm finding it quite hairy!

:slight_smile:

Simon.

I also suffer from the same C++ allergy notably shoot in foot with dynamic grammers and overloading… creates gasey code feeling…especially in the backend… :)cheers!

I also suffer from the same C++ allergy notably shoot in foot with dynamic grammers and overloading.. creates gasey code feeling..especially in the backend.. :)cheers!

I have no idea what this is supposed to mean: "creates gasey code feeling..especially in the backend.."

However, if there is serious interest, many people would like an easy to use C wrapper around the LLVM API's.

libjit, for all its flaws, seems to have a pretty reasonable C api, one that would be trivial to implement with LLVM: http://www.southern-storm.com.au/doc/libjit/libjit_toc.html

If someone wanted to write a libjit-compatible C interface, or something completely different, but similar in spirit, it would be a very cool and useful project, and would fit in naturally with the rest of the LLVM libraries.

This is a way that those with "C++ Allergies" could band together and help each other out :slight_smile:

-Chris

Simon Burton <simon@arrowtheory.com> wrote: On Sat, 15 Apr 2006 07:47:00 +0200
Oscar Fuentes wrote:

BTW, Simon, is there a reason for writing LLVM assembler and not
generating LLVM code directly?

You mean write C++ code that calls the LLVM library ?
I have a mild C++ allergy that I don't wish to aggravate.

The later is simpler and relieves you
from some nasty burdens.

Yes, i'm finding it quite hairy!

:slight_smile:

Simon.

-Chris

Hi,

Chris Lattner wrote:

if there is serious interest, many people would like an easy to use C
wrapper around the LLVM API's.

...

This is a way that those with "C++ Allergies" could band together and
help each other out :slight_smile:

I'm hoping the PyPy effort will see the start of a C interface to LLVM
that can be filled out as others need more bits. I'm another one that's
+1 for a C interface. :slight_smile:

Cheers,

Ralph.