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:
@@ -110,8 +110,6 @@ def gen_instruction_data_impl(fmt):
|
||||
|
||||
- `pub fn opcode(&self) -> Opcode`
|
||||
- `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_mut(&mut self, &pool) -> &mut [Value]`
|
||||
- `pub fn take_value_list(&mut self) -> Option<ValueList>`
|
||||
@@ -147,42 +145,6 @@ def gen_instruction_data_impl(fmt):
|
||||
'InstructionData::{} {{ ref mut ty, .. }} => ty,'
|
||||
.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.')
|
||||
with fmt.indented(
|
||||
'pub fn typevar_operand(&self, pool: &ValueListPool) -> '
|
||||
@@ -529,8 +491,6 @@ def gen_format_constructor(iform, fmt):
|
||||
'let data = InstructionData::{} {{'.format(iform.name), '};'):
|
||||
fmt.line('opcode: opcode,')
|
||||
fmt.line('ty: types::VOID,')
|
||||
if iform.multiple_results:
|
||||
fmt.line('second_result: None.into(),')
|
||||
gen_member_inits(iform, fmt)
|
||||
|
||||
fmt.line('self.build(data, ctrl_typevar)')
|
||||
|
||||
@@ -118,13 +118,6 @@ impl<'f> InstBuilderBase<'f> for ReplaceBuilder<'f> {
|
||||
// Construct new ones.
|
||||
self.dfg.make_inst_results(self.inst, ctrl_typevar);
|
||||
} 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
|
||||
// going to call that, so set it manually.
|
||||
*self.dfg[self.inst].first_type_mut() = self.dfg
|
||||
|
||||
@@ -457,12 +457,6 @@ impl DataFlowGraph {
|
||||
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();
|
||||
|
||||
// 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
|
||||
/// alternate instruction for computing the primary result 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);
|
||||
if !self.insts[inst].first_type().is_void() {
|
||||
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`.
|
||||
@@ -524,32 +523,21 @@ impl DataFlowGraph {
|
||||
/// created automatically. The `res` value must be a secondary instruction result detached from
|
||||
/// somewhere else.
|
||||
pub fn attach_secondary_result(&mut self, last_res: Value, res: Value) {
|
||||
let (res_inst, res_num) = match last_res.expand() {
|
||||
ExpandedValue::Direct(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)
|
||||
}
|
||||
let res_inst = match last_res.expand() {
|
||||
ExpandedValue::Direct(inst) => inst,
|
||||
ExpandedValue::Table(idx) => {
|
||||
if let ValueData::Inst {
|
||||
num,
|
||||
inst,
|
||||
ref mut next,
|
||||
..
|
||||
} = self.extended_values[idx] {
|
||||
if let ValueData::Inst { inst, ref mut next, .. } = self.extended_values[idx] {
|
||||
assert!(next.is_none(), "last_res is not the last result");
|
||||
*next = res.into();
|
||||
assert!(num < u16::MAX, "Too many arguments to EBB");
|
||||
(inst, num + 1)
|
||||
inst
|
||||
} else {
|
||||
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.
|
||||
if let ExpandedValue::Table(idx) = res.expand() {
|
||||
@@ -559,7 +547,7 @@ impl DataFlowGraph {
|
||||
ref mut next,
|
||||
..
|
||||
} = self.extended_values[idx] {
|
||||
*num = res_num;
|
||||
*num = res_num as u16;
|
||||
*inst = res_inst;
|
||||
*next = None.into();
|
||||
return;
|
||||
|
||||
@@ -17,7 +17,6 @@ use ir::types;
|
||||
use ir::DataFlowGraph;
|
||||
|
||||
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
|
||||
@@ -126,7 +125,6 @@ pub enum InstructionData {
|
||||
UnarySplit {
|
||||
opcode: Opcode,
|
||||
ty: Type,
|
||||
second_result: PackedOption<Value>,
|
||||
arg: Value,
|
||||
},
|
||||
Binary {
|
||||
@@ -143,7 +141,6 @@ pub enum InstructionData {
|
||||
BinaryOverflow {
|
||||
opcode: Opcode,
|
||||
ty: Type,
|
||||
second_result: PackedOption<Value>,
|
||||
args: [Value; 2],
|
||||
},
|
||||
Ternary {
|
||||
@@ -154,7 +151,6 @@ pub enum InstructionData {
|
||||
MultiAry {
|
||||
opcode: Opcode,
|
||||
ty: Type,
|
||||
second_result: PackedOption<Value>,
|
||||
args: ValueList,
|
||||
},
|
||||
InsertLane {
|
||||
@@ -216,14 +212,12 @@ pub enum InstructionData {
|
||||
Call {
|
||||
opcode: Opcode,
|
||||
ty: Type,
|
||||
second_result: PackedOption<Value>,
|
||||
func_ref: FuncRef,
|
||||
args: ValueList,
|
||||
},
|
||||
IndirectCall {
|
||||
opcode: Opcode,
|
||||
ty: Type,
|
||||
second_result: PackedOption<Value>,
|
||||
sig_ref: SigRef,
|
||||
args: ValueList,
|
||||
},
|
||||
|
||||
@@ -1442,7 +1442,6 @@ impl<'a> Parser<'a> {
|
||||
InstructionData::UnarySplit {
|
||||
opcode: opcode,
|
||||
ty: VOID,
|
||||
second_result: None.into(),
|
||||
arg: self.match_value("expected SSA value operand")?,
|
||||
}
|
||||
}
|
||||
@@ -1474,7 +1473,6 @@ impl<'a> Parser<'a> {
|
||||
InstructionData::BinaryOverflow {
|
||||
opcode: opcode,
|
||||
ty: VOID,
|
||||
second_result: None.into(),
|
||||
args: [lhs, rhs],
|
||||
}
|
||||
}
|
||||
@@ -1497,7 +1495,6 @@ impl<'a> Parser<'a> {
|
||||
InstructionData::MultiAry {
|
||||
opcode: opcode,
|
||||
ty: VOID,
|
||||
second_result: None.into(),
|
||||
args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
|
||||
}
|
||||
}
|
||||
@@ -1610,7 +1607,6 @@ impl<'a> Parser<'a> {
|
||||
InstructionData::Call {
|
||||
opcode: opcode,
|
||||
ty: VOID,
|
||||
second_result: None.into(),
|
||||
func_ref: func_ref,
|
||||
args: args.into_value_list(&[], &mut ctx.function.dfg.value_lists),
|
||||
}
|
||||
@@ -1626,7 +1622,6 @@ impl<'a> Parser<'a> {
|
||||
InstructionData::IndirectCall {
|
||||
opcode: opcode,
|
||||
ty: VOID,
|
||||
second_result: None.into(),
|
||||
sig_ref: sig_ref,
|
||||
args: args.into_value_list(&[callee], &mut ctx.function.dfg.value_lists),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user