Remove the second_result field from instructions.

Now that result values are stored in value lists in the DFG, these
head-of-list pointers are no longer needed.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-12 09:08:29 -07:00
parent 69180a2f84
commit 8b840e0a9a
5 changed files with 13 additions and 83 deletions

View File

@@ -110,8 +110,6 @@ def gen_instruction_data_impl(fmt):
- `pub fn opcode(&self) -> Opcode` - `pub fn opcode(&self) -> Opcode`
- `pub fn first_type(&self) -> Type` - `pub fn first_type(&self) -> Type`
- `pub fn second_result(&self) -> Option<Value>`
- `pub fn second_result_mut(&mut self) -> Option<&mut PackedOption<Value>>`
- `pub fn arguments(&self, &pool) -> &[Value]` - `pub fn arguments(&self, &pool) -> &[Value]`
- `pub fn arguments_mut(&mut self, &pool) -> &mut [Value]` - `pub fn arguments_mut(&mut self, &pool) -> &mut [Value]`
- `pub fn take_value_list(&mut self) -> Option<ValueList>` - `pub fn take_value_list(&mut self) -> Option<ValueList>`
@@ -147,42 +145,6 @@ def gen_instruction_data_impl(fmt):
'InstructionData::{} {{ ref mut ty, .. }} => ty,' 'InstructionData::{} {{ ref mut ty, .. }} => ty,'
.format(f.name)) .format(f.name))
# Generate shared and mutable accessors for `second_result` which only
# applies to instruction formats that can produce multiple results.
# Everything else returns `None`.
fmt.doc_comment('Second result value, if any.')
with fmt.indented(
'pub fn second_result(&self) -> Option<Value> {', '}'):
with fmt.indented('match *self {', '}'):
for f in InstructionFormat.all_formats:
if f.multiple_results:
fmt.line(
'InstructionData::' + f.name +
' { second_result, .. }' +
' => second_result.into(),')
else:
# Single or no results.
fmt.line(
'InstructionData::{} {{ .. }} => None,'
.format(f.name))
fmt.doc_comment('Mutable reference to second result value, if any.')
with fmt.indented(
"pub fn second_result_mut(&mut self)" +
" -> Option<&mut PackedOption<Value>> {", '}'):
with fmt.indented('match *self {', '}'):
for f in InstructionFormat.all_formats:
if f.multiple_results:
fmt.line(
'InstructionData::' + f.name +
' { ref mut second_result, .. }' +
' => Some(second_result),')
else:
# Single or no results.
fmt.line(
'InstructionData::{} {{ .. }} => None,'
.format(f.name))
fmt.doc_comment('Get the controlling type variable operand.') fmt.doc_comment('Get the controlling type variable operand.')
with fmt.indented( with fmt.indented(
'pub fn typevar_operand(&self, pool: &ValueListPool) -> ' 'pub fn typevar_operand(&self, pool: &ValueListPool) -> '
@@ -529,8 +491,6 @@ def gen_format_constructor(iform, fmt):
'let data = InstructionData::{} {{'.format(iform.name), '};'): 'let data = InstructionData::{} {{'.format(iform.name), '};'):
fmt.line('opcode: opcode,') fmt.line('opcode: opcode,')
fmt.line('ty: types::VOID,') fmt.line('ty: types::VOID,')
if iform.multiple_results:
fmt.line('second_result: None.into(),')
gen_member_inits(iform, fmt) gen_member_inits(iform, fmt)
fmt.line('self.build(data, ctrl_typevar)') fmt.line('self.build(data, ctrl_typevar)')

View File

@@ -118,13 +118,6 @@ impl<'f> InstBuilderBase<'f> for ReplaceBuilder<'f> {
// Construct new ones. // Construct new ones.
self.dfg.make_inst_results(self.inst, ctrl_typevar); self.dfg.make_inst_results(self.inst, ctrl_typevar);
} else { } else {
// Reattach the old secondary values.
let old_second_value = self.dfg.inst_results(self.inst).get(1).cloned();
if let Some(val_ref) = self.dfg[self.inst].second_result_mut() {
// Don't check types here. Leave that to the verifier.
*val_ref = old_second_value.into();
}
// Normally, make_inst_results() would also set the first result type, but we're not // Normally, make_inst_results() would also set the first result type, but we're not
// going to call that, so set it manually. // going to call that, so set it manually.
*self.dfg[self.inst].first_type_mut() = self.dfg *self.dfg[self.inst].first_type_mut() = self.dfg

View File

@@ -457,12 +457,6 @@ impl DataFlowGraph {
first_type = Some(constraints.result_type(res_idx, ctrl_typevar)); first_type = Some(constraints.result_type(res_idx, ctrl_typevar));
} }
// Update the second_result pointer in `inst`.
if head.is_some() {
*self.insts[inst]
.second_result_mut()
.expect("instruction format doesn't allow multiple results") = head.into();
}
*self.insts[inst].first_type_mut() = first_type.unwrap_or_default(); *self.insts[inst].first_type_mut() = first_type.unwrap_or_default();
// Include the first result in the results vector. // Include the first result in the results vector.
@@ -497,11 +491,16 @@ impl DataFlowGraph {
/// Use this method to detach secondary values before using `replace(inst)` to provide an /// Use this method to detach secondary values before using `replace(inst)` to provide an
/// alternate instruction for computing the primary result value. /// alternate instruction for computing the primary result value.
pub fn detach_secondary_results(&mut self, inst: Inst) -> Option<Value> { pub fn detach_secondary_results(&mut self, inst: Inst) -> Option<Value> {
if !self.has_results(inst) {
return None;
}
let second = self.results[inst].get(1, &mut self.value_lists);
self.results[inst].clear(&mut self.value_lists); self.results[inst].clear(&mut self.value_lists);
if !self.insts[inst].first_type().is_void() { if !self.insts[inst].first_type().is_void() {
self.results[inst].push(Value::new_direct(inst), &mut self.value_lists); self.results[inst].push(Value::new_direct(inst), &mut self.value_lists);
} }
self[inst].second_result_mut().and_then(|r| r.take()) second
} }
/// Get the next secondary result after `value`. /// Get the next secondary result after `value`.
@@ -524,32 +523,21 @@ impl DataFlowGraph {
/// created automatically. The `res` value must be a secondary instruction result detached from /// created automatically. The `res` value must be a secondary instruction result detached from
/// somewhere else. /// somewhere else.
pub fn attach_secondary_result(&mut self, last_res: Value, res: Value) { pub fn attach_secondary_result(&mut self, last_res: Value, res: Value) {
let (res_inst, res_num) = match last_res.expand() { let res_inst = match last_res.expand() {
ExpandedValue::Direct(inst) => { ExpandedValue::Direct(inst) => inst,
// We're adding the second value to `inst`.
let next = self[inst].second_result_mut().expect("bad inst format");
assert!(next.is_none(), "last_res is not the last result");
*next = res.into();
(inst, 1)
}
ExpandedValue::Table(idx) => { ExpandedValue::Table(idx) => {
if let ValueData::Inst { if let ValueData::Inst { inst, ref mut next, .. } = self.extended_values[idx] {
num,
inst,
ref mut next,
..
} = self.extended_values[idx] {
assert!(next.is_none(), "last_res is not the last result"); assert!(next.is_none(), "last_res is not the last result");
*next = res.into(); *next = res.into();
assert!(num < u16::MAX, "Too many arguments to EBB"); inst
(inst, num + 1)
} else { } else {
panic!("last_res is not an instruction result"); panic!("last_res is not an instruction result");
} }
} }
}; };
self.results[res_inst].push(res, &mut self.value_lists); let res_num = self.results[res_inst].push(res, &mut self.value_lists);
assert!(res_num <= u16::MAX as usize, "Too many result values");
// Now update `res` itself. // Now update `res` itself.
if let ExpandedValue::Table(idx) = res.expand() { if let ExpandedValue::Table(idx) = res.expand() {
@@ -559,7 +547,7 @@ impl DataFlowGraph {
ref mut next, ref mut next,
.. ..
} = self.extended_values[idx] { } = self.extended_values[idx] {
*num = res_num; *num = res_num as u16;
*inst = res_inst; *inst = res_inst;
*next = None.into(); *next = None.into();
return; return;

View File

@@ -17,7 +17,6 @@ use ir::types;
use ir::DataFlowGraph; use ir::DataFlowGraph;
use entity_list; use entity_list;
use packed_option::PackedOption;
use ref_slice::{ref_slice, ref_slice_mut}; use ref_slice::{ref_slice, ref_slice_mut};
/// Some instructions use an external list of argument values because there is not enough space in /// Some instructions use an external list of argument values because there is not enough space in
@@ -126,7 +125,6 @@ pub enum InstructionData {
UnarySplit { UnarySplit {
opcode: Opcode, opcode: Opcode,
ty: Type, ty: Type,
second_result: PackedOption<Value>,
arg: Value, arg: Value,
}, },
Binary { Binary {
@@ -143,7 +141,6 @@ pub enum InstructionData {
BinaryOverflow { BinaryOverflow {
opcode: Opcode, opcode: Opcode,
ty: Type, ty: Type,
second_result: PackedOption<Value>,
args: [Value; 2], args: [Value; 2],
}, },
Ternary { Ternary {
@@ -154,7 +151,6 @@ pub enum InstructionData {
MultiAry { MultiAry {
opcode: Opcode, opcode: Opcode,
ty: Type, ty: Type,
second_result: PackedOption<Value>,
args: ValueList, args: ValueList,
}, },
InsertLane { InsertLane {
@@ -216,14 +212,12 @@ pub enum InstructionData {
Call { Call {
opcode: Opcode, opcode: Opcode,
ty: Type, ty: Type,
second_result: PackedOption<Value>,
func_ref: FuncRef, func_ref: FuncRef,
args: ValueList, args: ValueList,
}, },
IndirectCall { IndirectCall {
opcode: Opcode, opcode: Opcode,
ty: Type, ty: Type,
second_result: PackedOption<Value>,
sig_ref: SigRef, sig_ref: SigRef,
args: ValueList, args: ValueList,
}, },

View File

@@ -1442,7 +1442,6 @@ impl<'a> Parser<'a> {
InstructionData::UnarySplit { InstructionData::UnarySplit {
opcode: opcode, opcode: opcode,
ty: VOID, ty: VOID,
second_result: None.into(),
arg: self.match_value("expected SSA value operand")?, arg: self.match_value("expected SSA value operand")?,
} }
} }
@@ -1474,7 +1473,6 @@ impl<'a> Parser<'a> {
InstructionData::BinaryOverflow { InstructionData::BinaryOverflow {
opcode: opcode, opcode: opcode,
ty: VOID, ty: VOID,
second_result: None.into(),
args: [lhs, rhs], args: [lhs, rhs],
} }
} }
@@ -1497,7 +1495,6 @@ impl<'a> Parser<'a> {
InstructionData::MultiAry { InstructionData::MultiAry {
opcode: opcode, opcode: opcode,
ty: VOID, ty: VOID,
second_result: None.into(),
args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists), args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
} }
} }
@@ -1610,7 +1607,6 @@ impl<'a> Parser<'a> {
InstructionData::Call { InstructionData::Call {
opcode: opcode, opcode: opcode,
ty: VOID, ty: VOID,
second_result: None.into(),
func_ref: func_ref, func_ref: func_ref,
args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists), args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
} }
@@ -1626,7 +1622,6 @@ impl<'a> Parser<'a> {
InstructionData::IndirectCall { InstructionData::IndirectCall {
opcode: opcode, opcode: opcode,
ty: VOID, ty: VOID,
second_result: None.into(),
sig_ref: sig_ref, sig_ref: sig_ref,
args: args.into_value_list(&[callee], &mut ctx.function.dfg.value_lists), args: args.into_value_list(&[callee], &mut ctx.function.dfg.value_lists),
} }