Permalink
Browse files

Add ability to elide guards based on the type of a local

  • Loading branch information...
1 parent e66dfd8 commit 5308a44d658cb3e6bdac4205f7913ec83fcc6fff @evanphx evanphx committed Aug 26, 2011
Showing with 184 additions and 56 deletions.
  1. +24 −16 vm/llvm/inline.cpp
  2. +9 −0 vm/llvm/inline.hpp
  3. +8 −13 vm/llvm/inline_primitive.cpp
  4. +19 −2 vm/llvm/jit.hpp
  5. +11 −8 vm/llvm/jit_operations.hpp
  6. +23 −5 vm/llvm/jit_visit.hpp
  7. +43 −7 vm/llvm/types.cpp
  8. +47 −5 vm/llvm/types.hpp
View
@@ -14,6 +14,18 @@
#include "ffi_util.hpp"
namespace rubinius {
+
+ void Inliner::check_class(llvm::Value* recv, Class* klass, llvm::BasicBlock* bb) {
+ if(!bb) bb = failure();
+
+ guarded_type_ = ops_.check_class(recv, klass, bb);
+ guarded_type_.inherit_source(ops_.state(), recv);
+ }
+
+ void Inliner::check_recv(Class* klass, llvm::BasicBlock* bb) {
+ check_class(recv(), klass, bb);
+ }
+
bool Inliner::consider() {
Class* klass = cache_->dominating_class();
if(!klass) {
@@ -265,11 +277,7 @@ namespace rubinius {
VMMethod* vmm = cm->backend_method();
- Value* self = recv();
-
- if(klass) {
- ops_.check_class(self, klass, failure());
- }
+ if(klass) check_recv(klass);
Value* val = 0;
/////
@@ -298,7 +306,7 @@ namespace rubinius {
val = ops_.constant(Fixnum::from(-1));
break;
case InstructionSequence::insn_push_self:
- val = self;
+ val = recv();
break;
default:
assert(0 && "Trivial detection is broken!");
@@ -330,10 +338,11 @@ namespace rubinius {
context_.enter_inline();
ops_.state()->add_accessor_inlined();
+ check_recv(klass);
+
Value* val = arg(0);
- Value* self = recv();
- ops_.check_reference_class(self, klass->class_id(), failure());
+ Value* self = recv();
// Figure out if we should use the table ivar lookup or
// the slot ivar lookup.
@@ -459,8 +468,8 @@ namespace rubinius {
void Inliner::inline_generic_method(Class* klass, Module* defined_in,
CompiledMethod* cm, VMMethod* vmm) {
context_.enter_inline();
- Value* self = recv();
- int class_id = ops_.check_class(self, klass, failure());
+
+ check_recv(klass);
JITMethodInfo info(context_, cm, vmm);
info.set_parent_info(ops_.info());
@@ -469,7 +478,8 @@ namespace rubinius {
info.called_args = count_;
info.root = ops_.root_method_info();
info.set_inline_block(inline_block_);
- info.self_class_id = class_id;
+
+ info.self_type = guarded_type_;
info.set_self_class(klass);
@@ -496,7 +506,7 @@ namespace rubinius {
if(vmm->call_count >= 0) vmm->call_count /= 2;
- BasicBlock* entry = work.setup_inline(self, blk, args);
+ BasicBlock* entry = work.setup_inline(recv(), blk, args);
if(!work.generate_body()) {
rubinius::bug("LLVM failed to compile a function");
@@ -529,7 +539,7 @@ namespace rubinius {
info.set_creator_info(creator_info_);
info.set_inline_block(inline_block_);
info.set_block_info(block_info_);
- info.self_class_id = ops_.info().self_class_id;
+ info.self_type = ops_.info().self_type;
jit::RuntimeData* rd = new jit::RuntimeData(ib->method(), nil<Symbol>(), nil<Module>());
context_.add_runtime_data(rd);
@@ -614,9 +624,7 @@ namespace rubinius {
}
bool Inliner::inline_ffi(Class* klass, NativeFunction* nf) {
- Value* self = recv();
-
- ops_.check_class(self, klass, failure());
+ check_recv(klass);
///
View
@@ -32,6 +32,8 @@ namespace rubinius {
bool fail_to_send_;
+ type::KnownType guarded_type_;
+
public:
Inliner(jit::Context& ctx,
@@ -132,6 +134,10 @@ namespace rubinius {
fail_to_send_ = true;
}
+ type::KnownType guarded_type() {
+ return guarded_type_;
+ }
+
bool consider();
void inline_block(JITInlineBlock* ib, Value* self);
@@ -153,6 +159,9 @@ namespace rubinius {
int detect_jit_intrinsic(Class* klass, CompiledMethod* cm);
void inline_intrinsic(Class* klass, CompiledMethod* cm, int which);
+
+ void check_class(llvm::Value* recv, Class* klass, llvm::BasicBlock* bb=0);
+ void check_recv(Class* klass, llvm::BasicBlock* bb=0);
};
}
@@ -419,8 +419,7 @@ namespace rubinius {
i.use_send_for_failure();
- Value* self = i.recv();
- ops.check_class(self, klass, i.failure());
+ i.check_recv(klass);
Value* arg = i.arg(0);
@@ -462,7 +461,7 @@ namespace rubinius {
rhs->addIncoming(unboxed_rhs, unbox_block);
rhs->addIncoming(fix_rhs, convert_block);
- Value* fself = ops.b().CreateBitCast(self, ops.state()->ptr_type("Float"),
+ Value* fself = ops.b().CreateBitCast(i.recv(), ops.state()->ptr_type("Float"),
"self_float");
Value* lhs = ops.b().CreateLoad(
@@ -514,8 +513,7 @@ namespace rubinius {
i.use_send_for_failure();
- Value* self = i.recv();
- ops.check_class(self, klass, i.failure());
+ i.check_recv(klass);
// Support compare against Floats and Fixnums inline
BasicBlock* do_compare = ops.new_block("float_compare");
@@ -551,7 +549,7 @@ namespace rubinius {
rhs->addIncoming(unboxed_rhs, unboxed_block);
rhs->addIncoming(converted_rhs, converted_block);
- Value* fself = ops.b().CreateBitCast(self, ops.state()->ptr_type("Float"),
+ Value* fself = ops.b().CreateBitCast(i.recv(), ops.state()->ptr_type("Float"),
"self_float");
Value* lhs = ops.b().CreateLoad(
ops.b().CreateConstGEP2_32(fself, 0, 1, "self.value_pos"), "fself");
@@ -590,11 +588,9 @@ namespace rubinius {
log("object_equal");
i.context().enter_inline();
- Value* self = i.recv();
-
- ops.check_class(self, klass, i.failure());
+ i.check_recv(klass);
- Value* cmp = ops.create_equal(self, i.arg(0), "idenity_equal");
+ Value* cmp = ops.create_equal(i.recv(), i.arg(0), "idenity_equal");
Value* imm_value = SelectInst::Create(cmp, ops.constant(Qtrue),
ops.constant(Qfalse), "select_bool", ops.current_block());
@@ -734,8 +730,7 @@ namespace rubinius {
context_.enter_inline();
- Value* self = recv();
- ops_.check_class(self, klass, failure());
+ check_recv(klass);
std::vector<Value*> call_args;
@@ -749,7 +744,7 @@ namespace rubinius {
}
sig << "Object";
- call_args.push_back(self);
+ call_args.push_back(recv());
for(int i = 0; i < stub_res.arg_count(); i++) {
sig << "Object";
View
@@ -128,6 +128,8 @@ namespace rubinius {
}
};
+ typedef std::map<int, LocalInfo> LocalMap;
+
class JITMethodInfo {
jit::Context& context_;
llvm::Function* function_;
@@ -157,7 +159,7 @@ namespace rubinius {
llvm::PHINode* return_phi_;
TypedRoot<Class*> self_class_;
- std::map<int, LocalInfo> local_info_;
+ LocalMap local_info_;
public:
VMMethod* vmm;
@@ -170,7 +172,7 @@ namespace rubinius {
JITStackArgs* stack_args;
JITMethodInfo* root;
- int self_class_id;
+ type::KnownType self_type;
public:
JITMethodInfo(jit::Context& ctx, CompiledMethod* cm, VMMethod* v,
@@ -417,6 +419,8 @@ namespace rubinius {
bool landing_pad;
int exception_type;
+ LocalMap local_info_;
+
public:
JITBasicBlock()
: block(0)
@@ -434,6 +438,19 @@ namespace rubinius {
if(prologue) return prologue;
return block;
}
+
+ void add_local(int which, type::KnownType kt) {
+ LocalInfo li(which);
+ li.set_known_type(kt);
+
+ local_info_[which] = li;
+ }
+
+ LocalInfo* get_local(int which) {
+ LocalMap::iterator i = local_info_.find(which);
+ if(i == local_info_.end()) return 0;
+ return &i->second;
+ }
};
typedef std::map<int, JITBasicBlock> BlockMap;
View
@@ -317,7 +317,7 @@ namespace rubinius {
failure->moveAfter(cont);
}
- int check_class(Value* obj, Class* klass, BasicBlock* failure) {
+ type::KnownType check_class(Value* obj, Class* klass, BasicBlock* failure) {
object_type type = (object_type)klass->instance_type()->to_native();
switch(type) {
@@ -327,37 +327,40 @@ namespace rubinius {
if(kt.symbol_p()) {
context().info("eliding guard: detected symbol");
+ return kt;
} else {
verify_guard(check_is_symbol(obj), failure);
}
} else {
verify_guard(check_is_symbol(obj), failure);
}
- return -1;
+
+ return type::KnownType::symbol();
case rubinius::Fixnum::type:
{
if(ls_->type_optz()) {
type::KnownType kt = type::KnownType::extract(ls_, obj);
if(kt.static_fixnum_p()) {
context().info("eliding guard: detected static fixnum");
+ return kt;
} else {
verify_guard(check_is_fixnum(obj), failure);
}
} else {
verify_guard(check_is_fixnum(obj), failure);
}
}
- return -1;
+ return type::KnownType::fixnum();
case NilType:
verify_guard(check_is_immediate(obj, Qnil), failure);
- return -1;
+ return type::KnownType::nil();
case TrueType:
verify_guard(check_is_immediate(obj, Qtrue), failure);
- return -1;
+ return type::KnownType::true_();
case FalseType:
verify_guard(check_is_immediate(obj, Qfalse), failure);
- return -1;
+ return type::KnownType::false_();
default:
{
type::KnownType kt = type::KnownType::extract(ls_, obj);
@@ -369,11 +372,11 @@ namespace rubinius {
<< " (" << klass->class_id() << ")\n";
}
- return klass->class_id();
+ return kt;
}
check_reference_class(obj, klass->class_id(), failure);
- return klass->class_id();
+ return type::KnownType::instance(klass->class_id());
}
}
}
View
@@ -1190,6 +1190,14 @@ namespace rubinius {
Value* pos = b().CreateGEP(vars_, idx2, idx2+3, "local_pos");
+ if(LocalInfo* bli = current_jbb_->get_local(which)) {
+ type::KnownType kt = bli->known_type();
+ kt.set_local_source(which);
+
+ stack_push(b().CreateLoad(pos, "local"), kt);
+ return;
+ }
+
LocalInfo* li = info().get_local(which);
/*
@@ -1202,9 +1210,15 @@ namespace rubinius {
*/
if(!info().use_full_scope() && li->static_type_argument_p()) {
- stack_push(b().CreateLoad(pos, "local"), li->known_type());
+ type::KnownType kt = li->known_type();
+ kt.set_local_source(which);
+
+ stack_push(b().CreateLoad(pos, "local"), kt);
} else {
- stack_push(b().CreateLoad(pos, "local"));
+ type::KnownType kt;
+ kt.set_local_source(which);
+
+ stack_push(b().CreateLoad(pos, "local"), kt);
}
}
@@ -1288,9 +1302,7 @@ namespace rubinius {
void visit_push_self() {
Instruction* val = get_self();
- if(info().self_class_id >= 0) {
- type::KnownType::instance(info().self_class_id).associate(ls_, val);
- }
+ info().self_type.associate(ls_, val);
stack_push(val);
}
@@ -1488,6 +1500,12 @@ namespace rubinius {
}
stack_push(inl.result());
+ type::KnownType kt = inl.guarded_type();
+
+ if(kt.local_source_p() && kt.known_p()) {
+ current_jbb_->add_local(kt.local_id(), kt);
+ }
+
b().CreateBr(cont);
set_block(cont);
Oops, something went wrong.

0 comments on commit 5308a44

Please sign in to comment.