[LLVMdev] JIT API example (fibonacci)

Chris Lattner sabre at nondot.org
Tue Aug 17 19:52:42 PDT 2004


On Tue, 17 Aug 2004, Reid Spencer wrote:

> On second thought, the makefiles don't (easily) allow this do they? You can
> only build one program per directory. Were you suggesting that you wanted me to
> move the entire directories under a "small examples" directory?

You're right.  The simples way to do this would be to have:
  projects/
           SmallExamples/
                         ModuleMaker/
                         HowToUseTheJIT/
                         FibBuilder/

etc.  Each subsubdir would have a makefile and a .cpp file.

-Chris

> Chris Lattner wrote:
>
> > On Tue, 17 Aug 2004, Reid Spencer wrote:
> >
> >
> >>That's pretty cute actually. Do you want this "brilliant" :) example in the cvs
> >>repository? I'd be happy to put it in.
> >
> >
> > Here's an idea: how about we take the ModuleMaker, Valery's previous
> > example, and this one and put them all in one "small examples" project?
> >
> > -Chris
> >
> >
> >>Valery A.Khamenya wrote:
> >>
> >>
> >>>Hi LLVMers,
> >>>
> >>>  the example attached I have used to prove that JIT and some visible
> >>>  optimizations are really invoked.
> >>>
> >>>  Proved OK. I got 30% speed-up in comparison to gcc 3.3.3
> >>>  on my Athlon XP 1500.
> >>>
> >>>  Nice.
> >>>
> >>>  P.S. guys, no fears, I don't plan to flood the cvs repository
> >>>  with my "brilliant" examples ;)
> >>>
> >>>---
> >>>Valery A.Khamenya
> >>>
> >>>
> >>>
> >>>
> >>>------------------------------------------------------------------------
> >>>
> >>>//===--- fibonacci.cpp - An example use of the JIT ----------------------===//
> >>>//
> >>>//                     The LLVM Compiler Infrastructure
> >>>//
> >>>// This file was developed by Valery A. Khamenya and is distributed under the
> >>>// University of Illinois Open Source License. See LICENSE.TXT for details.
> >>>//
> >>>//===----------------------------------------------------------------------===//
> >>>//
> >>>// This small program provides an example of how to build quickly a small
> >>>// module with function Fibonacci and execute it with the JIT.
> >>>//
> >>>// This simple example shows as well 30% speed up with LLVM 1.3
> >>>// in comparison to gcc 3.3.3 at AMD Athlon XP 1500+ .
> >>>//
> >>>// (Modified from HowToUseJIT.cpp and Stacker/lib/compiler/StackerCompiler.cpp)
> >>>//
> >>>//===------------------------------------------------------------------------===
> >>>// Goal:
> >>>//  The goal of this snippet is to create in the memory
> >>>//  the LLVM module consisting of one function as follow:
> >>>//
> >>>// int fib(int x) {
> >>>//   if(x<=2) return 1;
> >>>//   return fib(x-1)+fib(x-2);
> >>>// }
> >>>//
> >>>// then compile the module via JIT, then execute the `fib'
> >>>// function and return result to a driver, i.e. to a "host program".
> >>>//
> >>>
> >>>#include <iostream>
> >>>
> >>>#include <llvm/Module.h>
> >>>#include <llvm/DerivedTypes.h>
> >>>#include <llvm/Constants.h>
> >>>#include <llvm/Instructions.h>
> >>>#include <llvm/ModuleProvider.h>
> >>>#include <llvm/Analysis/Verifier.h>
> >>>#include "llvm/ExecutionEngine/ExecutionEngine.h"
> >>>#include "llvm/ExecutionEngine/GenericValue.h"
> >>>
> >>>
> >>>using namespace llvm;
> >>>
> >>>int main(int argc, char**argv) {
> >>>
> >>>  int n = argc > 1 ? atol(argv[1]) : 44;
> >>>
> >>>  // Create some module to put our function into it.
> >>>  Module *M = new Module("test");
> >>>
> >>>
> >>>  // We are about to create the "fib" function:
> >>>  Function *FibF;
> >>>
> >>>  {
> >>>    // first create type for the single argument of fib function:
> >>>    // the type is 'int ()'
> >>>    std::vector<const Type*> ArgT(1);
> >>>    ArgT[0] = Type::IntTy;
> >>>
> >>>    // now create full type of the "fib" function:
> >>>    FunctionType *FibT = FunctionType::get(Type::IntTy, // type of result
> >>>					   ArgT,
> >>>					   /*not vararg*/false);
> >>>
> >>>    // Now create the fib function entry and
> >>>    // insert this entry into module M
> >>>    // (By passing a module as the last parameter to the Function constructor,
> >>>    // it automatically gets appended to the Module.)
> >>>    FibF = new Function(FibT,
> >>>			Function::ExternalLinkage, // maybe too much
> >>>			"fib", M);
> >>>
> >>>    // Add a basic block to the function... (again, it automatically inserts
> >>>    // because of the last argument.)
> >>>    BasicBlock *BB = new BasicBlock("EntryBlock of fib function", FibF);
> >>>
> >>>    // Get pointers to the constants ...
> >>>    Value *One = ConstantSInt::get(Type::IntTy, 1);
> >>>    Value *Two = ConstantSInt::get(Type::IntTy, 2);
> >>>
> >>>    // Get pointers to the integer argument of the add1 function...
> >>>    assert(FibF->abegin() != FibF->aend()); // Make sure there's an arg
> >>>
> >>>    Argument &ArgX = FibF->afront();  // Get the arg
> >>>    ArgX.setName("AnArg");            // Give it a nice symbolic name for fun.
> >>>
> >>>    SetCondInst* CondInst
> >>>      = new SetCondInst( Instruction::SetLE,
> >>>			 &ArgX, Two );
> >>>
> >>>    BB->getInstList().push_back(CondInst);
> >>>
> >>>    // Create the true_block
> >>>    BasicBlock* true_bb = new BasicBlock("arg<=2");
> >>>
> >>>
> >>>    // Create the return instruction and add it
> >>>    // to the basic block for true case:
> >>>    true_bb->getInstList().push_back(new ReturnInst(One));
> >>>
> >>>    // Create an exit block
> >>>    BasicBlock* exit_bb = new BasicBlock("arg>2");
> >>>
> >>>    {
> >>>
> >>>      // create fib(x-1)
> >>>      CallInst* CallFibX1;
> >>>      {
> >>>	// Create the sub instruction... does not insert...
> >>>	Instruction *Sub
> >>>	  = BinaryOperator::create(Instruction::Sub, &ArgX, One,
> >>>						"arg");
> >>>
> >>>	exit_bb->getInstList().push_back(Sub);
> >>>
> >>>	CallFibX1 = new CallInst(FibF, Sub, "fib(x-1)");
> >>>	exit_bb->getInstList().push_back(CallFibX1);
> >>>
> >>>      }
> >>>
> >>>      // create fib(x-2)
> >>>      CallInst* CallFibX2;
> >>>      {
> >>>	// Create the sub instruction... does not insert...
> >>>	Instruction * Sub
> >>>	  = BinaryOperator::create(Instruction::Sub, &ArgX, Two,
> >>>						"arg");
> >>>
> >>>	exit_bb->getInstList().push_back(Sub);
> >>>	CallFibX2 = new CallInst(FibF, Sub, "fib(x-2)");
> >>>	exit_bb->getInstList().push_back(CallFibX2);
> >>>
> >>>      }
> >>>
> >>>      // Create the add instruction... does not insert...
> >>>      Instruction *Add =
> >>>	BinaryOperator::create(Instruction::Add,
> >>>			       CallFibX1, CallFibX2, "addresult");
> >>>
> >>>      // explicitly insert it into the basic block...
> >>>      exit_bb->getInstList().push_back(Add);
> >>>
> >>>      // Create the return instruction and add it to the basic block
> >>>      exit_bb->getInstList().push_back(new ReturnInst(Add));
> >>>    }
> >>>
> >>>    // Create a branch on the SetCond
> >>>    BranchInst* br_inst =
> >>>      new BranchInst( true_bb, exit_bb, CondInst );
> >>>
> >>>    BB->getInstList().push_back( br_inst );
> >>>    FibF->getBasicBlockList().push_back(true_bb);
> >>>    FibF->getBasicBlockList().push_back(exit_bb);
> >>>  }
> >>>
> >>>  // Now we going to create JIT
> >>>  ExistingModuleProvider* MP = new ExistingModuleProvider(M);
> >>>  ExecutionEngine* EE = ExecutionEngine::create( MP, false );
> >>>
> >>>  // Call the `foo' function with argument n:
> >>>  std::vector<GenericValue> args(1);
> >>>  args[0].IntVal = n;
> >>>
> >>>
> >>>  std::clog << "verifying... ";
> >>>  if (verifyModule(*M)) {
> >>>    std::cerr << argv[0]
> >>>	      << ": assembly parsed, but does not verify as correct!\n";
> >>>    return 1;
> >>>  }
> >>>  else
> >>>    std::clog << "OK\n";
> >>>
> >>>
> >>>  std::clog << "We just constructed this LLVM module:\n\n---------\n" << *M;
> >>>  std::clog << "---------\nstarting fibonacci("
> >>>	    << n << ") with JIT...\n" << std::flush;
> >>>
> >>>  GenericValue gv = EE->runFunction(FibF, args);
> >>>
> >>>  // import result of execution:
> >>>  std::cout << "Result: " << gv.IntVal << std:: endl;
> >>>
> >>>  return 0;
> >>>}
> >>>
> >>>
> >>>------------------------------------------------------------------------
> >>>
> >>>_______________________________________________
> >>>LLVM Developers mailing list
> >>>LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> >>>http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev
> >>
> >>_______________________________________________
> >>LLVM Developers mailing list
> >>LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> >>http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev
> >>
> >
> >
> > -Chris
> >
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev
>

-Chris

-- 
http://llvm.org/
http://nondot.org/sabre/




More information about the llvm-dev mailing list