issue #60 add optimized versions of table access with integer keys

pull/81/head
Dibyendu Majumdar 9 years ago
parent ff1bffb415
commit 62e892e6aa

@ -323,8 +323,9 @@ struct LuaLLVMTypes {
llvm::MDNode *tbaa_RaviArray_lenT;
llvm::MDNode *tbaa_TString_hash;
llvm::MDNode *tbaa_Table_lsizenode;
llvm::MDNode *tbaa_Table_array;
llvm::MDNode *tbaa_Table_node;
llvm::MDNode *tbaa_Table_sizearray;
llvm::MDNode *tbaa_Table_array;
};
class RAVI_API RaviJITStateImpl;
@ -757,6 +758,10 @@ public:
llvm::Value *emit_table_get_value(RaviFunctionDef *def, llvm::Value *node, llvm::Value *index);
llvm::Value *emit_table_get_arraysize(RaviFunctionDef *def, llvm::Value *table);
llvm::Value *emit_table_get_array(RaviFunctionDef *def, llvm::Value *table);
llvm::Instruction *emit_load_reg_s(RaviFunctionDef *def, llvm::Value *rb);
// emit code to load pointer to int array
@ -960,11 +965,15 @@ public:
void emit_SETTABLE(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_SETTABLE_I(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_GETTABLE(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_GETTABLE_S(RaviFunctionDef *def, int A, int B, int C, int pc,
TString *key);
void emit_GETTABLE_I(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_SELF(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_GETUPVAL(RaviFunctionDef *def, int A, int B, int pc);

@ -350,6 +350,23 @@ llvm::Value *RaviCodeGenerator::emit_table_get_value(RaviFunctionDef *def, llvm:
return emit_gep(def, "nodeval", node, index, 0);
}
llvm::Value *RaviCodeGenerator::emit_table_get_arraysize(RaviFunctionDef *def, llvm::Value *table) {
// Obtain the lsizenode of the hash table
llvm::Value *sizearray_ptr = emit_gep(def, "sizearray", table, 0, 5);
llvm::Instruction *sizearray = def->builder->CreateLoad(sizearray_ptr);
sizearray->setMetadata(llvm::LLVMContext::MD_tbaa,
def->types->tbaa_Table_sizearray);
return sizearray;
}
llvm::Value *RaviCodeGenerator::emit_table_get_array(RaviFunctionDef *def, llvm::Value *table) {
// Get access to the node array
llvm::Value *array_ptr = emit_gep(def, "array", table, 0, 6);
llvm::Instruction *arry = def->builder->CreateLoad(array_ptr);
arry->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_array);
return arry;
}
llvm::Instruction *RaviCodeGenerator::emit_load_reg_s(RaviFunctionDef *def,
llvm::Value *rb) {
llvm::Value *rb_s = def->builder->CreateBitCast(rb, def->types->ppTStringT);

@ -57,8 +57,26 @@ void RaviCodeGenerator::emit_LEN(RaviFunctionDef *def, int A, int B, int pc) {
}
// R(A)[RK(B)] := RK(C)
void RaviCodeGenerator::emit_SETTABLE(RaviFunctionDef *def, int A, int B, int C,
// This is a more optimized version that calls
// luaH_setint() instead of luaV_settable().
// This relies on two things:
// a) we know we have a table
// b) we know the key is an integer
void RaviCodeGenerator::emit_SETTABLE_I(RaviFunctionDef *def, int A, int B, int C,
int pc) {
emit_debug_trace(def, OP_RAVI_SETTABLE_I, pc);
emit_load_base(def);
llvm::Value *ra = emit_gep_register(def, A);
llvm::Value *rb = emit_gep_register_or_constant(def, B);
llvm::Value *rc = emit_gep_register_or_constant(def, C);
llvm::Instruction *t = emit_load_reg_h(def, ra);
llvm::Instruction *key = emit_load_reg_i(def, rb);
CreateCall3(def->builder, def->luaH_setintF, t, key, rc);
}
// R(A)[RK(B)] := RK(C)
void RaviCodeGenerator::emit_SETTABLE(RaviFunctionDef *def, int A, int B, int C,
int pc) {
// Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
bool traced = emit_debug_trace(def, OP_SETTABLE, pc);
// Below may invoke metamethod so we set savedpc
@ -86,6 +104,59 @@ void RaviCodeGenerator::emit_GETTABLE(RaviFunctionDef *def, int A, int B, int C,
CreateCall4(def->builder, def->luaV_gettableF, def->L, rb, rc, ra);
}
// R(A) := R(B)[RK(C)]
// This is a more optimized version that attempts to do an inline
// array get first and only if that fails it fals back on calling
// luaH_getint(). This relies on two things:
// a) we know we have a table
// b) we know the key is an integer
void RaviCodeGenerator::emit_GETTABLE_I(RaviFunctionDef *def, int A, int B, int C,
int pc) {
emit_debug_trace(def, OP_RAVI_GETTABLE_I, pc);
emit_load_base(def);
llvm::Value *ra = emit_gep_register(def, A);
llvm::Value *rb = emit_gep_register(def, B);
llvm::Value *rc = emit_gep_register_or_constant(def, C);
llvm::Instruction *key = emit_load_reg_i(def, rc);
llvm::Instruction *t = emit_load_reg_h(def, rb);
llvm::Value *data = emit_table_get_array(def, t);
llvm::Value *len = emit_table_get_arraysize(def, t);
llvm::Value *key_minus_1 =
def->builder->CreateSub(key, def->types->kluaInteger[1]);
llvm::Value *ukey =
def->builder->CreateTrunc(key_minus_1, def->types->C_intT);
llvm::Value *cmp = def->builder->CreateICmpULT(ukey, len);
llvm::BasicBlock *then_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.in.range", def->f);
llvm::BasicBlock *else_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.not.in.range");
llvm::BasicBlock *end_block =
llvm::BasicBlock::Create(def->jitState->context(), "if.end");
def->builder->CreateCondBr(cmp, then_block, else_block);
def->builder->SetInsertPoint(then_block);
// Key is in range so array access possible
llvm::Value *value1 = def->builder->CreateGEP(data, ukey);
def->builder->CreateBr(end_block);
// Out of range so fall back to luaH_getint()
def->f->getBasicBlockList().push_back(else_block);
def->builder->SetInsertPoint(else_block);
llvm::Value *value2 =
CreateCall2(def->builder, def->luaH_getintF, t, key);
def->builder->CreateBr(end_block);
// Merge results from the two branches above
def->f->getBasicBlockList().push_back(end_block);
def->builder->SetInsertPoint(end_block);
llvm::PHINode *phi = def->builder->CreatePHI(def->types->pTValueT, 2);
phi->addIncoming(value1, then_block);
phi->addIncoming(value2, else_block);
emit_assign(def, ra, phi);
}
// R(A) := R(B)[RK(C)]
// Emit inline code for accessing a table element using a string key
// We try to access the element using the hash part but if the
// key is not in the main position then we fall back on luaH_getstr().
@ -104,8 +175,8 @@ void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B,
// A number of macros are involved above do the
// the generated code is somewhat more complex
// we don't need to refresh base here as the lua_State is not being touched
emit_debug_trace(def, OP_RAVI_GETTABLE_S, pc);
emit_load_base(def);
llvm::Value *ra = emit_gep_register(def, A);
llvm::Value *rb = emit_gep_register(def, B);

@ -1207,6 +1207,7 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) {
tbaa_RaviArray_typeT =
mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_charT, 44);
tbaa_Table_lsizenode = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_charT, 7);
tbaa_Table_sizearray = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 8);
tbaa_Table_array = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 12);
tbaa_Table_node = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 16);
}

Loading…
Cancel
Save