Cleanup runtime support. Inline via IR builder.
Change-Id: Ia2d1a5c7273d71e3267ce4631cc5a56ad7f3af7a
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index 87fd724..b5ff67c 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -98,6 +98,7 @@
}
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const {
+ AU.addRequired<llvm::LoopInfo>();
AU.addRequiredID(llvm::LoopSimplifyID);
AU.addPreserved<llvm::DominatorTree>();
@@ -108,15 +109,28 @@
}
virtual bool runOnLoop(llvm::Loop *loop, llvm::LPPassManager &lpm) {
+ llvm::LoopInfo* loop_info = &getAnalysis<llvm::LoopInfo>();
+
CHECK_EQ(loop->getNumBackEdges(), 1U) << "Loop must be simplified!";
llvm::BasicBlock* bb = loop->getLoopLatch();
CHECK_NE(bb, static_cast<void*>(NULL)) << "A single loop latch must exist.";
- irb_->SetInsertPoint(bb->getTerminator());
+ llvm::BasicBlock* tb = bb->splitBasicBlock(bb->getTerminator(), "suspend_exit");
+ // Remove unconditional branch which is added by splitBasicBlock.
+ bb->getTerminator()->eraseFromParent();
- using art::compiler_llvm::runtime_support::TestSuspend;
- llvm::Value* runtime_func = irb_->GetRuntime(TestSuspend);
- irb_->CreateCall(runtime_func, irb_->getJNull());
+ irb_->SetInsertPoint(bb);
+ irb_->Runtime().EmitTestSuspend();
+ irb_->CreateBr(tb);
+
+ loop->addBasicBlockToLoop(tb, loop_info->getBase());
+ // EmitTestSuspend() creates some basic blocks. We should add them to using
+ // addBasicBlockToLoop(...) as above.
+ for (llvm::succ_iterator succ_iter = llvm::succ_begin(bb), succ_end = llvm::succ_end(bb);
+ succ_iter != succ_end;
+ succ_iter++) {
+ loop->addBasicBlockToLoop(*succ_iter, loop_info->getBase());
+ }
return true;
}
@@ -177,8 +191,6 @@
break;
}
- runtime_support_->OptimizeRuntimeSupport();
-
irb_->SetRuntimeSupport(runtime_support_.get());
}
@@ -342,8 +354,10 @@
// Add optimization pass
llvm::PassManagerBuilder pm_builder;
+ // TODO: Use inliner after we can do IPO.
+ pm_builder.Inliner = NULL;
//pm_builder.Inliner = llvm::createFunctionInliningPass();
- pm_builder.Inliner = llvm::createAlwaysInlinerPass();
+ //pm_builder.Inliner = llvm::createAlwaysInlinerPass();
//pm_builder.Inliner = llvm::createPartialInliningPass();
pm_builder.OptLevel = 3;
pm_builder.DisableSimplifyLibCalls = 1;
diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc
index 77c1bf5..dd16ef7 100644
--- a/src/compiler_llvm/gbc_expander.cc
+++ b/src/compiler_llvm/gbc_expander.cc
@@ -106,6 +106,8 @@
//----------------------------------------------------------------------------
void Expand_TestSuspend(llvm::CallInst& call_inst);
+ void Expand_MarkGCCard(llvm::CallInst& call_inst);
+
llvm::Value* Expand_GetException();
llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
@@ -515,6 +517,20 @@
return;
}
+void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
+ llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
+ llvm::BasicBlock* begin_bb =
+ llvm::BasicBlock::Create(context_, "mark_gc_card", parent_func);
+
+ irb_.SetInsertPoint(begin_bb);
+ irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
+
+ llvm::BasicBlock* end_bb = irb_.GetInsertBlock();
+
+ SplitAndInsertBasicBlocksAfter(call_inst, begin_bb, end_bb);
+ return;
+}
+
llvm::Value* GBCExpanderPass::Expand_GetException() {
// Get thread-local exception field address
llvm::Value* exception_object_addr =
@@ -974,7 +990,8 @@
return NULL;
}
case IntrinsicHelper::MarkGCCard: {
- return ExpandToRuntime(runtime_support::MarkGCCard, call_inst);
+ Expand_MarkGCCard(call_inst);
+ return NULL;
}
//==- Exception --------------------------------------------------------==//
case IntrinsicHelper::ThrowException: {
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 4dc3954..ca8888c 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -2190,9 +2190,7 @@
void MethodCompiler::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
// Using runtime support, let the target can override by InlineAssembly.
- llvm::Function* runtime_func = irb_.GetRuntime(MarkGCCard);
-
- irb_.CreateCall2(runtime_func, value, target_addr);
+ irb_.Runtime().EmitMarkGCCard(value, target_addr);
}
void
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index 7ef8917..6be113d 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -21,7 +21,6 @@
#include "monitor.h"
#include "object.h"
#include "thread.h"
-#include "utils_llvm.h"
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
@@ -55,27 +54,12 @@
#undef GET_RUNTIME_SUPPORT_FUNC_DECL
}
-void RuntimeSupportBuilder::MakeFunctionInline(llvm::Function* func) {
- func->setLinkage(GlobalValue::LinkOnceODRLinkage);
- func->addFnAttr(Attribute::AlwaysInline);
-}
-
-void RuntimeSupportBuilder::OverrideRuntimeSupportFunction(RuntimeId id, llvm::Function* function) {
- // TODO: Check function prototype.
- if (id >= 0 && id < MAX_ID) {
- runtime_support_func_decls_[id] = function;
- target_runtime_support_func_[id] = true;
- } else {
- LOG(ERROR) << "Unknown runtime function id: " << id;
- }
-}
-
/* Thread */
llvm::Value* RuntimeSupportBuilder::EmitGetCurrentThread() {
Function* func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
- llvm::CallInst* call_inst = irb_.CreateCall(func);
+ CallInst* call_inst = irb_.CreateCall(func);
call_inst->setOnlyReadsMemory();
irb_.SetTBAA(call_inst, kTBAAConstJObject);
return call_inst;
@@ -83,13 +67,13 @@
llvm::Value* RuntimeSupportBuilder::EmitLoadFromThreadOffset(int64_t offset, llvm::Type* type,
TBAASpecialType s_ty) {
- llvm::Value* thread = EmitGetCurrentThread();
+ Value* thread = EmitGetCurrentThread();
return irb_.LoadFromObjectOffset(thread, offset, type, s_ty);
}
void RuntimeSupportBuilder::EmitStoreToThreadOffset(int64_t offset, llvm::Value* value,
TBAASpecialType s_ty) {
- llvm::Value* thread = EmitGetCurrentThread();
+ Value* thread = EmitGetCurrentThread();
irb_.StoreToObjectOffset(thread, offset, value, s_ty);
}
@@ -156,7 +140,7 @@
irb_.getJObjectTy(),
kTBAAJRuntime);
// If exception not null
- return irb_.CreateICmpNE(exception, irb_.getJNull());
+ return irb_.CreateIsNotNull(exception);
}
void RuntimeSupportBuilder::EmitTestSuspend() {
@@ -166,7 +150,7 @@
kTBAARuntimeInfo);
Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getJInt(0));
- llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
+ Function* parent_func = irb_.GetInsertBlock()->getParent();
BasicBlock* basic_block_suspend = BasicBlock::Create(context_, "suspend", parent_func);
BasicBlock* basic_block_cont = BasicBlock::Create(context_, "suspend_cont", parent_func);
irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
@@ -189,24 +173,24 @@
}
void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) {
- llvm::Value* lock_id =
+ Value* lock_id =
EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
irb_.getJIntTy(),
kTBAARuntimeInfo);
- llvm::Value* monitor =
+ Value* monitor =
irb_.LoadFromObjectOffset(object,
Object::MonitorOffset().Int32Value(),
irb_.getJIntTy(),
kTBAARuntimeInfo);
- llvm::Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
- llvm::Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
- llvm::Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+ Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
+ Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+ Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
// Is thin lock, held by us and not recursively acquired
- llvm::Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor);
+ Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor);
- llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
+ Function* parent_func = irb_.GetInsertBlock()->getParent();
BasicBlock* bb_fast = BasicBlock::Create(context_, "unlock_fast", parent_func);
BasicBlock* bb_slow = BasicBlock::Create(context_, "unlock_slow", parent_func);
BasicBlock* bb_cont = BasicBlock::Create(context_, "unlock_cont", parent_func);
@@ -229,59 +213,27 @@
}
-void RuntimeSupportBuilder::OptimizeRuntimeSupport() {
- // TODO: Remove this after we remove suspend loop pass.
- if (!target_runtime_support_func_[runtime_support::TestSuspend]) {
- Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
- Function* func = Function::Create(slow_func->getFunctionType(),
- GlobalValue::LinkOnceODRLinkage,
- "art_test_suspend_fast",
- &module_);
- MakeFunctionInline(func);
- BasicBlock* basic_block = BasicBlock::Create(context_, "entry", func);
- irb_.SetInsertPoint(basic_block);
+void RuntimeSupportBuilder::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
+ Function* parent_func = irb_.GetInsertBlock()->getParent();
+ BasicBlock* bb_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", parent_func);
+ BasicBlock* bb_cont = BasicBlock::Create(context_, "mark_gc_card_cont", parent_func);
- EmitTestSuspend();
+ llvm::Value* not_null = irb_.CreateIsNotNull(value);
+ irb_.CreateCondBr(not_null, bb_mark_gc_card, bb_cont);
- irb_.CreateRetVoid();
+ irb_.SetInsertPoint(bb_mark_gc_card);
+ Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
+ irb_.getInt8Ty()->getPointerTo(),
+ kTBAAConstJObject);
+ Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
+ Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(GC_CARD_SHIFT));
+ Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
+ irb_.CreateStore(irb_.getInt8(GC_CARD_DIRTY), card_table_entry, kTBAARuntimeInfo);
+ irb_.CreateBr(bb_cont);
- OverrideRuntimeSupportFunction(runtime_support::TestSuspend, func);
-
- VERIFY_LLVM_FUNCTION(*func);
- }
-
- if (!target_runtime_support_func_[MarkGCCard]) {
- Function* func = GetRuntimeSupportFunction(MarkGCCard);
- MakeFunctionInline(func);
- BasicBlock* basic_block = BasicBlock::Create(context_, "entry", func);
- irb_.SetInsertPoint(basic_block);
- Function::arg_iterator arg_iter = func->arg_begin();
- Value* value = arg_iter++;
- Value* target_addr = arg_iter++;
-
- llvm::Value* is_value_null = irb_.CreateICmpEQ(value, irb_.getJNull());
-
- llvm::BasicBlock* block_value_is_null = BasicBlock::Create(context_, "value_is_null", func);
- llvm::BasicBlock* block_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", func);
-
- irb_.CreateCondBr(is_value_null, block_value_is_null, block_mark_gc_card);
-
- irb_.SetInsertPoint(block_value_is_null);
- irb_.CreateRetVoid();
-
- irb_.SetInsertPoint(block_mark_gc_card);
- Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
- irb_.getInt8Ty()->getPointerTo(),
- kTBAAConstJObject);
- Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
- Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(GC_CARD_SHIFT));
- Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
- irb_.CreateStore(irb_.getInt8(GC_CARD_DIRTY), card_table_entry, kTBAARuntimeInfo);
- irb_.CreateRetVoid();
-
- VERIFY_LLVM_FUNCTION(*func);
- }
+ irb_.SetInsertPoint(bb_cont);
}
+
} // namespace compiler_llvm
} // namespace art
diff --git a/src/compiler_llvm/runtime_support_builder.h b/src/compiler_llvm/runtime_support_builder.h
index 8fd0d17..05b9e53 100644
--- a/src/compiler_llvm/runtime_support_builder.h
+++ b/src/compiler_llvm/runtime_support_builder.h
@@ -64,6 +64,9 @@
virtual void EmitLockObject(llvm::Value* object);
virtual void EmitUnlockObject(llvm::Value* object);
+ /* MarkGCCard */
+ virtual void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
+
llvm::Function* GetRuntimeSupportFunction(runtime_support::RuntimeId id) {
if (id >= 0 && id < runtime_support::MAX_ID) {
return runtime_support_func_decls_[id];
@@ -73,19 +76,9 @@
}
}
- void OptimizeRuntimeSupport();
-
virtual ~RuntimeSupportBuilder() {}
protected:
- // Mark a function as inline function.
- // You should implement the function, if mark as inline.
- void MakeFunctionInline(llvm::Function* function);
-
- void OverrideRuntimeSupportFunction(runtime_support::RuntimeId id, llvm::Function* function);
-
-
- protected:
llvm::LLVMContext& context_;
llvm::Module& module_;
IRBuilder& irb_;