Use value lists for call arguments.
Add a new kind of instruction format that keeps all of its value arguments in a value list. These value lists are all allocated out of the dfg.value_lists memory pool. Instruction formats with the value_list property set store *all* of their value arguments in a single value list. There is no distinction between fixed arguments and variable arguments. Change the Call instruction format to use the value list representation for its arguments. This change is only the beginning. The intent is to eliminate the boxed_storage instruction formats completely. Value lists use less memory, and when the transition is complete, InstructionData will have a trivial Drop implementation.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
use ir::{types, instructions};
|
||||
use ir::{InstructionData, DataFlowGraph, Cursor};
|
||||
use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, VariableArgs, SigRef, FuncRef};
|
||||
use ir::{Opcode, Type, Inst, Value, Ebb, JumpTable, VariableArgs, SigRef, FuncRef, ValueList};
|
||||
use ir::immediates::{Imm64, Uimm8, Ieee32, Ieee64, ImmVector};
|
||||
use ir::condcodes::{IntCC, FloatCC};
|
||||
|
||||
@@ -21,6 +21,7 @@ pub trait InstBuilderBase<'f>: Sized {
|
||||
/// Get an immutable reference to the data flow graph that will hold the constructed
|
||||
/// instructions.
|
||||
fn data_flow_graph(&self) -> &DataFlowGraph;
|
||||
fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph;
|
||||
|
||||
/// Insert a simple instruction and return a reference to it.
|
||||
///
|
||||
@@ -76,6 +77,10 @@ impl<'c, 'fc, 'fd> InstBuilderBase<'fd> for InsertBuilder<'c, 'fc, 'fd> {
|
||||
self.dfg
|
||||
}
|
||||
|
||||
fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph {
|
||||
self.dfg
|
||||
}
|
||||
|
||||
fn simple_instruction(self, data: InstructionData) -> (Inst, &'fd mut DataFlowGraph) {
|
||||
let inst = self.dfg.make_inst(data);
|
||||
self.pos.insert_inst(inst);
|
||||
@@ -129,6 +134,10 @@ impl<'f> InstBuilderBase<'f> for ReplaceBuilder<'f> {
|
||||
self.dfg
|
||||
}
|
||||
|
||||
fn data_flow_graph_mut(&mut self) -> &mut DataFlowGraph {
|
||||
self.dfg
|
||||
}
|
||||
|
||||
fn simple_instruction(self, data: InstructionData) -> (Inst, &'f mut DataFlowGraph) {
|
||||
// The replacement instruction cannot generate multiple results, so verify that the old
|
||||
// instruction's secondary results have been detached.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Data flow graph tracking Instructions, Values, and EBBs.
|
||||
|
||||
use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef};
|
||||
use ir::{Ebb, Inst, Value, Type, SigRef, Signature, FuncRef, ValueListPool};
|
||||
use ir::entities::ExpandedValue;
|
||||
use ir::instructions::{Opcode, InstructionData, CallInfo};
|
||||
use ir::extfunc::ExtFuncData;
|
||||
@@ -24,7 +24,10 @@ pub struct DataFlowGraph {
|
||||
/// Data about all of the instructions in the function, including opcodes and operands.
|
||||
/// The instructions in this map are not in program order. That is tracked by `Layout`, along
|
||||
/// with the EBB containing each instruction.
|
||||
insts: EntityMap<Inst, InstructionData>,
|
||||
pub insts: EntityMap<Inst, InstructionData>,
|
||||
|
||||
/// Memory pool of value lists referenced by instructions in `insts`.
|
||||
pub value_lists: ValueListPool,
|
||||
|
||||
/// Extended basic blocks in the function and their arguments.
|
||||
/// This map is not in program order. That is handled by `Layout`, and so is the sequence of
|
||||
@@ -56,6 +59,7 @@ impl DataFlowGraph {
|
||||
pub fn new() -> DataFlowGraph {
|
||||
DataFlowGraph {
|
||||
insts: EntityMap::new(),
|
||||
value_lists: ValueListPool::new(),
|
||||
ebbs: EntityMap::new(),
|
||||
extended_values: Vec::new(),
|
||||
signatures: EntityMap::new(),
|
||||
@@ -429,7 +433,7 @@ impl DataFlowGraph {
|
||||
/// Get the call signature of a direct or indirect call instruction.
|
||||
/// Returns `None` if `inst` is not a call instruction.
|
||||
pub fn call_signature(&self, inst: Inst) -> Option<SigRef> {
|
||||
match self.insts[inst].analyze_call() {
|
||||
match self.insts[inst].analyze_call(&self.value_lists) {
|
||||
CallInfo::NotACall => None,
|
||||
CallInfo::Direct(f, _) => Some(self.ext_funcs[f].signature),
|
||||
CallInfo::Indirect(s, _) => Some(s),
|
||||
|
||||
@@ -16,8 +16,17 @@ use ir::condcodes::*;
|
||||
use ir::types;
|
||||
use ir::DataFlowGraph;
|
||||
|
||||
use ref_slice::*;
|
||||
use entity_list;
|
||||
use packed_option::PackedOption;
|
||||
use ref_slice::{ref_slice, ref_slice_mut};
|
||||
|
||||
/// Some instructions use an external list of argument values because there is not enough space in
|
||||
/// the 16-byte `InstructionData` struct. These value lists are stored in a memory pool in
|
||||
/// `dfg.value_lists`.
|
||||
pub type ValueList = entity_list::EntityList<Value>;
|
||||
|
||||
/// Memory pool for holding value lists. See `ValueList`.
|
||||
pub type ValueListPool = entity_list::ListPool<Value>;
|
||||
|
||||
// Include code generated by `lib/cretonne/meta/gen_instr.py`. This file contains:
|
||||
//
|
||||
@@ -204,7 +213,8 @@ pub enum InstructionData {
|
||||
opcode: Opcode,
|
||||
ty: Type,
|
||||
second_result: PackedOption<Value>,
|
||||
data: Box<CallData>,
|
||||
func_ref: FuncRef,
|
||||
args: ValueList,
|
||||
},
|
||||
IndirectCall {
|
||||
opcode: Opcode,
|
||||
@@ -244,6 +254,13 @@ impl VariableArgs {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
/// Convert this to a value list in `pool`.
|
||||
pub fn into_value_list(self, pool: &mut ValueListPool) -> ValueList {
|
||||
let mut vlist = ValueList::default();
|
||||
vlist.extend(self.0, pool);
|
||||
vlist
|
||||
}
|
||||
}
|
||||
|
||||
// Coerce `VariableArgs` into a `&[Value]` slice.
|
||||
@@ -364,16 +381,6 @@ impl Display for BranchData {
|
||||
}
|
||||
}
|
||||
|
||||
/// Payload of a call instruction.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CallData {
|
||||
/// Callee function.
|
||||
pub func_ref: FuncRef,
|
||||
|
||||
/// Dynamically sized array containing call argument values.
|
||||
pub varargs: VariableArgs,
|
||||
}
|
||||
|
||||
/// Payload of an indirect call instruction.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IndirectCallData {
|
||||
@@ -434,10 +441,10 @@ impl ReturnRegData {
|
||||
impl InstructionData {
|
||||
/// Execute a closure once for each argument to this instruction.
|
||||
/// See also the `arguments()` method.
|
||||
pub fn each_arg<F>(&self, mut func: F)
|
||||
pub fn each_arg<F>(&self, pool: &ValueListPool, mut func: F)
|
||||
where F: FnMut(Value)
|
||||
{
|
||||
for part in &self.arguments() {
|
||||
for part in &self.arguments(pool) {
|
||||
for &arg in part.iter() {
|
||||
func(arg);
|
||||
}
|
||||
@@ -446,10 +453,10 @@ impl InstructionData {
|
||||
|
||||
/// Execute a closure with a mutable reference to each argument to this instruction.
|
||||
/// See also the `arguments_mut()` method.
|
||||
pub fn each_arg_mut<F>(&mut self, mut func: F)
|
||||
pub fn each_arg_mut<F>(&mut self, pool: &mut ValueListPool, mut func: F)
|
||||
where F: FnMut(&mut Value)
|
||||
{
|
||||
for part in &mut self.arguments_mut() {
|
||||
for part in &mut self.arguments_mut(pool) {
|
||||
for arg in part.iter_mut() {
|
||||
func(arg);
|
||||
}
|
||||
@@ -476,10 +483,10 @@ impl InstructionData {
|
||||
/// Return information about a call instruction.
|
||||
///
|
||||
/// Any instruction that can call another function reveals its call signature here.
|
||||
pub fn analyze_call<'a>(&'a self) -> CallInfo<'a> {
|
||||
pub fn analyze_call<'a>(&'a self, pool: &'a ValueListPool) -> CallInfo<'a> {
|
||||
match self {
|
||||
&InstructionData::Call { ref data, .. } => {
|
||||
CallInfo::Direct(data.func_ref, &data.varargs)
|
||||
&InstructionData::Call { func_ref, ref args, .. } => {
|
||||
CallInfo::Direct(func_ref, &args.as_slice(pool))
|
||||
}
|
||||
&InstructionData::IndirectCall { ref data, .. } => {
|
||||
CallInfo::Indirect(data.sig_ref, &data.varargs)
|
||||
|
||||
@@ -20,7 +20,7 @@ pub use ir::funcname::FunctionName;
|
||||
pub use ir::extfunc::{Signature, ArgumentType, ArgumentExtension, ExtFuncData};
|
||||
pub use ir::types::Type;
|
||||
pub use ir::entities::{Ebb, Inst, Value, StackSlot, JumpTable, FuncRef, SigRef};
|
||||
pub use ir::instructions::{Opcode, InstructionData, VariableArgs};
|
||||
pub use ir::instructions::{Opcode, InstructionData, VariableArgs, ValueList, ValueListPool};
|
||||
pub use ir::stackslot::StackSlotData;
|
||||
pub use ir::jumptable::JumpTableData;
|
||||
pub use ir::valueloc::{ValueLoc, ArgumentLoc};
|
||||
|
||||
Reference in New Issue
Block a user