/* * Iterative Fibonacci demonstration using LLVM JIT. * * The main driver function, at the end of this file, is derived from code by * Valery A. Khamenya; the header from the the original file follows. * * All other content (C)2007 Cliff L. Biffle, released into the public domain. */ //===--- 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. //===----------------------------------------------------------------------===// #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/JIT.h" #include "llvm/ExecutionEngine/Interpreter.h" #include "llvm/ExecutionEngine/GenericValue.h" #include using namespace llvm; static uint64_t usecs() { struct timeval tv; gettimeofday(&tv, NULL); return ((uint64_t)tv.tv_sec * 1000000) + tv.tv_usec; } static Function *CreateIterativeFibFunction(Module *M) { Function *FibF = M->getOrInsertFunction("ifib", Type::IntTy, Type::IntTy, (Type *)0); Value *one = ConstantInt::get(Type::IntTy, 1); Value *uint_one = ConstantInt::get(Type::UIntTy, 1); Value *two = ConstantInt::get(Type::IntTy, 2); Value *uint_zero = ConstantInt::getNullValue(Type::UIntTy); Value *int_undef = UndefValue::get(Type::IntTy); Argument *argX = FibF->arg_begin(); argX->setName("x"); BasicBlock *entry = new BasicBlock("entry", FibF); BasicBlock *body = new BasicBlock("body", FibF); BasicBlock *tail = new BasicBlock("tail", FibF); BasicBlock *end = new BasicBlock("end", FibF); // Entry block SetCondInst *nontrivial = new SetCondInst(Instruction::SetGT, argX, two, "nontrivial", entry); BranchInst *entry_term = new BranchInst(body, end, nontrivial, entry); // Loop tail Argument *fwdref_a = new Argument(Type::IntTy); Argument *fwdref_b = new Argument(Type::IntTy); BinaryOperator *sum = BinaryOperator::create(Instruction::Add, fwdref_a, fwdref_b, "sum", tail); Argument *fwdref_indvar = new Argument(Type::UIntTy); BinaryOperator *indvar_next = BinaryOperator::create(Instruction::Add, fwdref_indvar, uint_one, "indvar.next", tail); BranchInst *tail_term = new BranchInst(body, tail); // Main loop body PHINode *indvar = new PHINode(Type::UIntTy, "indvar", body); indvar->reserveOperandSpace(2); indvar->addIncoming(indvar_next, tail); indvar->addIncoming(uint_zero, entry); PHINode *c0 = new PHINode(Type::IntTy, "c0", body); c0->reserveOperandSpace(2); c0->addIncoming(sum, tail); c0->addIncoming(int_undef, entry); PHINode *b = new PHINode(Type::IntTy, "b", body); b->reserveOperandSpace(2); b->addIncoming(fwdref_a, tail); b->addIncoming(one, entry); PHINode *a = new PHINode(Type::IntTy, "a", body); a->reserveOperandSpace(2); a->addIncoming(sum, tail); a->addIncoming(one, entry); // This section is a little odd, but very similar to the code from // the C frontend. Truly handwritten code would handle the loop // variable differently. CastInst *int_indvar = new CastInst(indvar, Type::IntTy, "indvar", body); BinaryOperator *ctr = BinaryOperator::create(Instruction::Sub, argX, int_indvar, "ctr", body); SetCondInst *more = new SetCondInst(Instruction::SetGT, ctr, two, "more", body); BranchInst *body_term = new BranchInst(tail, end, more, body); // End block PHINode *retval = new PHINode(Type::IntTy, "retval", end); retval->reserveOperandSpace(2); retval->addIncoming(one, entry); retval->addIncoming(c0, body); ReturnInst *end_term = new ReturnInst(retval, end); // Resolve forward refs fwdref_a->replaceAllUsesWith(a); delete fwdref_a; fwdref_b->replaceAllUsesWith(b); delete fwdref_b; fwdref_indvar->replaceAllUsesWith(indvar); delete fwdref_indvar; return FibF; } int main(int argc, char **argv) { int n = argc > 1 ? atol(argv[1]) : 24; // Create some module to put our function into it. Module *M = new Module("test"); // We are about to create the "fib" function: Function *FibF = CreateIterativeFibFunction(M); // Now we going to create JIT ExistingModuleProvider *MP = new ExistingModuleProvider(M); ExecutionEngine *EE = ExecutionEngine::create(MP, false); std::cerr << "verifying... "; if (verifyModule(*M)) { std::cerr << argv[0] << ": Error constructing function!\n"; return 1; } /* std::cerr << "OK\n"; std::cerr << "We just constructed this LLVM module:\n\n---------\n" << *M; std::cerr << "---------\nstarting fibonacci(" << n << ") with JIT...\n"; */ // Call the Fibonacci function with argument n: std::vector Args(1); Args[0].IntVal = n; int (*func)(int) = (int(*)(int))EE->getPointerToFunction(FibF); uint64_t start = usecs(); for(int i = 0; i < 1000; i++) { //GenericValue GV = EE->runFunction(FibF, Args); // int r = GV.IntVal; int r = func(n); // import result of execution } uint64_t end = usecs(); std::cout << "Time: " << (end - start) << " us\n"; return 0; }