X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=examples%2FFibonacci%2Ffibonacci.cpp;h=8cbf7d159fc5d2791ee52128e36179aad1b18ee4;hb=1b0dc64919e947bb4f4677b138c734e33061f7c4;hp=776378dc1fa1852ce034dcf450be6abe07edb245;hpb=e784fa40c5808bfb88480f0ab3746ed378a939df;p=oota-llvm.git diff --git a/examples/Fibonacci/fibonacci.cpp b/examples/Fibonacci/fibonacci.cpp index 776378dc1fa..8cbf7d159fc 100644 --- a/examples/Fibonacci/fibonacci.cpp +++ b/examples/Fibonacci/fibonacci.cpp @@ -1,188 +1,137 @@ -//===--- fibonacci.cpp - An example use of the JIT ----------------------===// -// +//===--- examples/Fibonacci/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 file 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 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+ . +// The goal of this snippet is to create in the memory the LLVM module +// consisting of one function as follow: // -// (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); +// } // -// 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' +// Once we have this, we compile the module via JIT, then execute the `fib' // function and return result to a driver, i.e. to a "host program". // +//===----------------------------------------------------------------------===// -#include - -#include -#include -#include -#include -#include -#include -#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/Analysis/Verifier.h" #include "llvm/ExecutionEngine/GenericValue.h" +#include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +static Function *CreateFibFunction(Module *M, LLVMContext &Context) { + // Create the fib function and insert it into module M. This function is said + // to return an int and take an int parameter. + Function *FibF = + cast(M->getOrInsertFunction("fib", Type::getInt32Ty(Context), + Type::getInt32Ty(Context), + (Type *)0)); -using namespace llvm; + // Add a basic block to the function. + BasicBlock *BB = BasicBlock::Create(Context, "EntryBlock", FibF); -int main(int argc, char**argv) { + // Get pointers to the constants. + Value *One = ConstantInt::get(Type::getInt32Ty(Context), 1); + Value *Two = ConstantInt::get(Type::getInt32Ty(Context), 2); - int n = argc > 1 ? atol(argv[1]) : 44; + // Get pointer to the integer argument of the add1 function... + Argument *ArgX = FibF->arg_begin(); // Get the arg. + ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. - // Create some module to put our function into it. - Module *M = new Module("test"); + // Create the true_block. + BasicBlock *RetBB = BasicBlock::Create(Context, "return", FibF); + // Create an exit block. + BasicBlock* RecurseBB = BasicBlock::Create(Context, "recurse", FibF); + // Create the "if (arg <= 2) goto exitbb" + Value *CondInst = new ICmpInst(*BB, ICmpInst::ICMP_SLE, ArgX, Two, "cond"); + BranchInst::Create(RetBB, RecurseBB, CondInst, BB); - // 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 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); - } + // Create: ret int 1 + ReturnInst::Create(Context, One, RetBB); - // Now we going to create JIT - ExistingModuleProvider* MP = new ExistingModuleProvider(M); - ExecutionEngine* EE = ExecutionEngine::create( MP, false ); + // create fib(x-1) + Value *Sub = BinaryOperator::CreateSub(ArgX, One, "arg", RecurseBB); + CallInst *CallFibX1 = CallInst::Create(FibF, Sub, "fibx1", RecurseBB); + CallFibX1->setTailCall(); - // Call the `foo' function with argument n: - std::vector args(1); - args[0].IntVal = n; + // create fib(x-2) + Sub = BinaryOperator::CreateSub(ArgX, Two, "arg", RecurseBB); + CallInst *CallFibX2 = CallInst::Create(FibF, Sub, "fibx2", RecurseBB); + CallFibX2->setTailCall(); - std::clog << "verifying... "; - if (verifyModule(*M)) { - std::cerr << argv[0] - << ": assembly parsed, but does not verify as correct!\n"; + // fib(x-1)+fib(x-2) + Value *Sum = BinaryOperator::CreateAdd(CallFibX1, CallFibX2, + "addresult", RecurseBB); + + // Create the return instruction and add it to the basic block + ReturnInst::Create(Context, Sum, RecurseBB); + + return FibF; +} + + +int main(int argc, char **argv) { + int n = argc > 1 ? atol(argv[1]) : 24; + + InitializeNativeTarget(); + LLVMContext Context; + + // Create some module to put our function into it. + OwningPtr M(new Module("test", Context)); + + // We are about to create the "fib" function: + Function *FibF = CreateFibFunction(M.get(), Context); + + // Now we going to create JIT + std::string errStr; + ExecutionEngine *EE = + EngineBuilder(M.get()) + .setErrorStr(&errStr) + .setEngineKind(EngineKind::JIT) + .create(); + + if (!EE) { + errs() << argv[0] << ": Failed to construct ExecutionEngine: " << errStr + << "\n"; return 1; } - else - std::clog << "OK\n"; + errs() << "verifying... "; + if (verifyModule(*M)) { + errs() << argv[0] << ": Error constructing function!\n"; + return 1; + } - std::clog << "We just constructed this LLVM module:\n\n---------\n" << *M; - std::clog << "---------\nstarting fibonacci(" - << n << ") with JIT...\n" << std::flush; + errs() << "OK\n"; + errs() << "We just constructed this LLVM module:\n\n---------\n" << *M; + errs() << "---------\nstarting fibonacci(" << n << ") with JIT...\n"; - GenericValue gv = EE->runFunction(FibF, args); + // Call the Fibonacci function with argument n: + std::vector Args(1); + Args[0].IntVal = APInt(32, n); + GenericValue GV = EE->runFunction(FibF, Args); - // import result of execution: - std::cout << "Result: " << gv.IntVal << std:: endl; + // import result of execution + outs() << "Result: " << GV.IntVal << "\n"; return 0; }