summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2013-03-19 17:39:29 +0100
committerSebastien Hertz <shertz@google.com>2013-03-19 18:24:51 +0100
commitf11afa079d5899b9ff74d2cad507cfa8c7324690 (patch)
treeaf4dc69d36edc6e0b372408d718068541bc0d18b /src/compiler
parent2af52e76dc76b41969b6147d7bd6925d0f61e932 (diff)
downloadandroid_art-f11afa079d5899b9ff74d2cad507cfa8c7324690.tar.gz
android_art-f11afa079d5899b9ff74d2cad507cfa8c7324690.tar.bz2
android_art-f11afa079d5899b9ff74d2cad507cfa8c7324690.zip
Make shadow frame addresses unique.
This CL makes each virtual register's shadow frame address unique in the LLVM function. Every shadow frame address (gep instructions) are placed right after allocas to dominate all their uses. This reduces the number of emitted gep instructions and the memory footprint. This may also "help" optimization passes to simplify the detection of addresses in load/store operations where some transformations may be simplified. Change-Id: I8fe155108db1736c533289962c983caea8c2b63f
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/llvm/gbc_expander.cc35
1 files changed, 28 insertions, 7 deletions
diff --git a/src/compiler/llvm/gbc_expander.cc b/src/compiler/llvm/gbc_expander.cc
index 9b71694a09..70c54ea839 100644
--- a/src/compiler/llvm/gbc_expander.cc
+++ b/src/compiler/llvm/gbc_expander.cc
@@ -79,6 +79,9 @@ class GBCExpanderPass : public llvm::FunctionPass {
landing_pad_phi_mapping_;
llvm::BasicBlock* basic_block_unwind_;
+ // Maps each vreg to its shadow frame address.
+ std::vector<llvm::Value*> shadow_frame_vreg_addresses_;
+
bool changed_;
private:
@@ -375,6 +378,7 @@ bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
func_ = &func;
changed_ = false; // Assume unchanged
+ shadow_frame_vreg_addresses_.resize(dex_compilation_unit_->GetCodeItem()->registers_size_, NULL);
basic_blocks_.resize(dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
basic_block_landing_pads_.resize(dex_compilation_unit_->GetCodeItem()->tries_size_, NULL);
basic_block_unwind_ = NULL;
@@ -1304,15 +1308,32 @@ void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
llvm::Value* value) {
- DCHECK(shadow_frame_ != NULL);
+ unsigned vreg_idx = LV2UInt(entry_idx);
+ DCHECK_LT(vreg_idx, dex_compilation_unit_->GetCodeItem()->registers_size_);
- llvm::Value* gep_index[] = {
- irb_.getInt32(0), // No pointer displacement
- irb_.getInt32(1), // VRegs
- entry_idx // Pointer field
- };
+ llvm::Value* vreg_addr = shadow_frame_vreg_addresses_[vreg_idx];
+ if (UNLIKELY(vreg_addr == NULL)) {
+ DCHECK(shadow_frame_ != NULL);
+
+ llvm::Value* gep_index[] = {
+ irb_.getInt32(0), // No pointer displacement
+ irb_.getInt32(1), // VRegs
+ entry_idx // Pointer field
+ };
- llvm::Value* vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+ // A shadow frame address must dominate every use in the function so we
+ // place it in the entry block right after the allocas.
+ llvm::BasicBlock::iterator first_non_alloca = func_->getEntryBlock().begin();
+ while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
+ ++first_non_alloca;
+ }
+
+ llvm::IRBuilderBase::InsertPoint ip = irb_.saveIP();
+ irb_.SetInsertPoint(static_cast<llvm::Instruction*>(first_non_alloca));
+ vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+ shadow_frame_vreg_addresses_[vreg_idx] = vreg_addr;
+ irb_.restoreIP(ip);
+ }
irb_.CreateStore(value,
irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),