[LLVMdev] JIT API example (fibonacci)

Chris Lattner sabre at nondot.org
Tue Aug 17 15:32:32 PDT 2004


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

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




More information about the llvm-dev mailing list