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 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)')
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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),
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user