提交 e4dccf46 编写于 作者: S Shreedhar Hardikar

Implement InlineFunction to force inline at call site

上级 71170942
......@@ -30,6 +30,7 @@
#include "codegen/utils/macros.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
......@@ -43,6 +44,7 @@
#include "llvm/IR/Type.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Value.h"
#include "llvm/Transforms/Utils/Cloning.h"
namespace gpcodegen {
......@@ -479,6 +481,24 @@ class CodegenUtils {
void CreateFallback(llvm::Function* regular_function,
llvm::Function* generated_function);
/*
* @brief Force inline an LLVM function at the call site. Note that this only
* does one level of inlining.
*
* @param LLVM call Instruction where the called function should be inlined
* @return false if it is not possible to inline. true otherwise.
*/
bool InlineFunction(llvm::CallInst* call_inst) {
// Check that the call instruction belongs to a BasicBlock which is part of
// a valid function
if (!(call_inst && call_inst->getParent()
&& call_inst->getParent()->getParent())){
return false;
}
llvm::InlineFunctionInfo info;
return llvm::InlineFunction(llvm::CallSite(call_inst), info);
}
private:
// Give ClangCompiler access to 'context_' add allow it to add compiled C++
// sources to 'auxiliary_modules_'.
......
......@@ -41,6 +41,7 @@
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
......@@ -2736,9 +2737,9 @@ TEST_F(CodegenUtilsTest, CppClassObjectTest) {
EXPECT_EQ(-12.75, (*accumulate_test_fn_compiled)(-22.75));
}
// Test GetOrGetOrRegisterExternalFunction to return the right llvm::Function if
// Test GetOrRegisterExternalFunction to return the right llvm::Function if
// previously registered or else register it anew
TEST_F(CodegenUtilsTest, GetOrGetOrRegisterExternalFunctionTest) {
TEST_F(CodegenUtilsTest, GetOrRegisterExternalFunctionTest) {
// Test previous unregistered function
EXPECT_EQ(nullptr, codegen_utils_->module()->getFunction("floor"));
llvm::Function* floor_func = codegen_utils_->GetOrRegisterExternalFunction(
......@@ -2762,6 +2763,56 @@ TEST_F(CodegenUtilsTest, GetOrGetOrRegisterExternalFunctionTest) {
EXPECT_EQ(expected_fprintf_func, fprintf_func);
}
// Utility method to compute the number of calls in an llvm::Function*
int GetLLVMFunctionCallCount(llvm::Function* F) {
return std::count_if(llvm::inst_begin(F), llvm::inst_end(F),
[] (llvm::Instruction& i)-> bool {
return (llvm::dyn_cast<llvm::CallInst>(&i));
});
}
// Test InlineFunction
TEST_F(CodegenUtilsTest, InlineFunctionTest) {
auto irb = codegen_utils_->ir_builder();
typedef int (*AddConstToIntFn) (int);
// Create a simple adds 1 to a number and returns the new value
llvm::Function* add_one_fn = codegen_utils_->CreateFunction<AddConstToIntFn>("add_one");
irb->SetInsertPoint(codegen_utils_->CreateBasicBlock("main", add_one_fn));
irb->CreateRet(irb->CreateAdd(ArgumentByPosition(add_one_fn, 0),
codegen_utils_->GetConstant(1)));
// Create another simple function add_two which calls add_one twice
llvm::Function* add_two_fn = codegen_utils_->CreateFunction<AddConstToIntFn>("add_two");
irb->SetInsertPoint(codegen_utils_->CreateBasicBlock("main", add_two_fn));
llvm::CallInst* first_call = irb->CreateCall(add_one_fn, {ArgumentByPosition(add_two_fn, 0)});
llvm::CallInst* second_call = irb->CreateCall(add_one_fn, {first_call});
irb->CreateRet(second_call);
EXPECT_EQ(GetLLVMFunctionCallCount(add_two_fn), 2);
EXPECT_TRUE(codegen_utils_->InlineFunction(first_call));
EXPECT_EQ(GetLLVMFunctionCallCount(add_two_fn), 1);
EXPECT_FALSE(codegen_utils_->InlineFunction(first_call));
EXPECT_TRUE(codegen_utils_->InlineFunction(second_call));
EXPECT_EQ(GetLLVMFunctionCallCount(add_two_fn), 0);
// Compiled module
EXPECT_TRUE(codegen_utils_->PrepareForExecution(
CodegenUtils::OptimizationLevel::kNone, false));
AddConstToIntFn compiled_add_two_fn =
codegen_utils_->GetFunctionPointer<AddConstToIntFn>("add_two");
// Test normal functionality, even after inlining
EXPECT_TRUE(nullptr != compiled_add_two_fn);
EXPECT_EQ(compiled_add_two_fn(5), 7);
EXPECT_EQ(compiled_add_two_fn(-5), -3);
}
#ifdef GPCODEGEN_DEBUG
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册