IR output from CodegenGcd define i32 @gcd(i32 %x, i32 %y) { entry: %tmp = icmp eq i32 %x, %y br i1 %tmp, label %return, label %cond_false return: ; preds = %entry ret i32 %x cond_false: ; preds = %entry %tmp2 = icmp ult i32 %x, %y br i1 %tmp2, label %cond_true, label %cond_false1 cond_true:
| 112 | // LLVM IR module which contains one function to return the GCD of two numbers |
| 113 | // } |
| 114 | llvm::Module* CodegenGcd(llvm::LLVMContext* context) { |
| 115 | llvm::Module* mod = new llvm::Module("gcd", *context); |
| 116 | llvm::Constant* c = mod->getOrInsertFunction("gcd", |
| 117 | llvm::IntegerType::get(*context, 32), llvm::IntegerType::get(*context, 32), |
| 118 | llvm::IntegerType::get(*context, 32)); |
| 119 | llvm::Function* gcd = llvm::cast<llvm::Function>(c); |
| 120 | llvm::Function::arg_iterator args = gcd->arg_begin(); |
| 121 | llvm::Value* x = &*args; |
| 122 | ++args; |
| 123 | x->setName("x"); |
| 124 | llvm::Value* y = &*args; |
| 125 | ++args; |
| 126 | y->setName("y"); |
| 127 | llvm::BasicBlock* entry = llvm::BasicBlock::Create(*context, "entry", gcd); |
| 128 | llvm::BasicBlock* ret = llvm::BasicBlock::Create(*context, "return", gcd); |
| 129 | llvm::BasicBlock* cond_false = llvm::BasicBlock::Create(*context, "cond_false", gcd); |
| 130 | llvm::BasicBlock* cond_true = llvm::BasicBlock::Create(*context, "cond_true", gcd); |
| 131 | llvm::BasicBlock* cond_false_2 = llvm::BasicBlock::Create(*context, "cond_false", gcd); |
| 132 | llvm::IRBuilder<> builder(entry); |
| 133 | llvm::Value* xEqualsY = builder.CreateICmpEQ(x, y, "tmp"); |
| 134 | builder.CreateCondBr(xEqualsY, ret, cond_false); builder.SetInsertPoint(ret); |
| 135 | builder.CreateRet(x); |
| 136 | builder.SetInsertPoint(cond_false); |
| 137 | llvm::Value* xLessThanY = builder.CreateICmpULT(x, y, "tmp"); |
| 138 | builder.CreateCondBr(xLessThanY, cond_true, cond_false_2); |
| 139 | builder.SetInsertPoint(cond_true); |
| 140 | llvm::Value* yMinusX = builder.CreateSub(y, x, "tmp"); |
| 141 | llvm::Value* args1[2] = {x, yMinusX}; |
| 142 | llvm::Value* recur_1 = builder.CreateCall(gcd, args1, "tmp"); |
| 143 | builder.CreateRet(recur_1); |
| 144 | builder.SetInsertPoint(cond_false_2); |
| 145 | llvm::Value* xMinusY = builder.CreateSub(x, y, "tmp"); |
| 146 | llvm::Value* args2[2] = {xMinusY, y}; |
| 147 | llvm::Value* recur_2 = builder.CreateCall(gcd, args2, "tmp"); |
| 148 | builder.CreateRet(recur_2); |
| 149 | return mod; |
| 150 | } |
| 151 | |
| 152 | TEST_F(InstructionCounterTest, TestMemInstrCount) { |
| 153 | llvm::Module* GcdModule = CodegenGcd(&context_); |
no test coverage detected