Convert legalizer::split and generated legalization code to FuncCursor.
This commit is contained in:
@@ -152,7 +152,7 @@ def unwrap_inst(iref, node, fmt):
|
|||||||
# type: (str, Def, Formatter) -> bool
|
# type: (str, Def, Formatter) -> bool
|
||||||
"""
|
"""
|
||||||
Given a `Def` node, emit code that extracts all the instruction fields from
|
Given a `Def` node, emit code that extracts all the instruction fields from
|
||||||
`dfg[iref]`.
|
`pos.func.dfg[iref]`.
|
||||||
|
|
||||||
Create local variables named after the `Var` instances in `node`.
|
Create local variables named after the `Var` instances in `node`.
|
||||||
|
|
||||||
@@ -181,7 +181,8 @@ def unwrap_inst(iref, node, fmt):
|
|||||||
elif iform.has_value_list or nvops > 1:
|
elif iform.has_value_list or nvops > 1:
|
||||||
fmt.line('ref args,')
|
fmt.line('ref args,')
|
||||||
fmt.line('..')
|
fmt.line('..')
|
||||||
fmt.outdented_line('} = dfg[inst] {')
|
fmt.outdented_line('} = pos.func.dfg[inst] {')
|
||||||
|
fmt.line('let dfg = &pos.func.dfg;')
|
||||||
if iform.has_value_list:
|
if iform.has_value_list:
|
||||||
fmt.line('let args = args.as_slice(&dfg.value_lists);')
|
fmt.line('let args = args.as_slice(&dfg.value_lists);')
|
||||||
elif nvops == 1:
|
elif nvops == 1:
|
||||||
@@ -205,7 +206,7 @@ def unwrap_inst(iref, node, fmt):
|
|||||||
for opnum in expr.inst.value_opnums:
|
for opnum in expr.inst.value_opnums:
|
||||||
v = expr.args[opnum]
|
v = expr.args[opnum]
|
||||||
if isinstance(v, Var) and v.has_free_typevar():
|
if isinstance(v, Var) and v.has_free_typevar():
|
||||||
fmt.line('let typeof_{0} = dfg.value_type({0});'.format(v))
|
fmt.format('let typeof_{0} = pos.func.dfg.value_type({0});', v)
|
||||||
|
|
||||||
# If the node has results, detach the values.
|
# If the node has results, detach the values.
|
||||||
# Place the values in locals.
|
# Place the values in locals.
|
||||||
@@ -223,13 +224,13 @@ def unwrap_inst(iref, node, fmt):
|
|||||||
for d in node.defs:
|
for d in node.defs:
|
||||||
fmt.line('let {};'.format(d))
|
fmt.line('let {};'.format(d))
|
||||||
with fmt.indented('{', '}'):
|
with fmt.indented('{', '}'):
|
||||||
fmt.line('let r = dfg.inst_results(inst);')
|
fmt.line('let r = pos.func.dfg.inst_results(inst);')
|
||||||
for i in range(len(node.defs)):
|
for i in range(len(node.defs)):
|
||||||
fmt.line('{} = r[{}];'.format(node.defs[i], i))
|
fmt.line('{} = r[{}];'.format(node.defs[i], i))
|
||||||
for d in node.defs:
|
for d in node.defs:
|
||||||
if d.has_free_typevar():
|
if d.has_free_typevar():
|
||||||
fmt.line(
|
fmt.line(
|
||||||
'let typeof_{0} = dfg.value_type({0});'
|
'let typeof_{0} = pos.func.dfg.value_type({0});'
|
||||||
.format(d))
|
.format(d))
|
||||||
|
|
||||||
return replace_inst
|
return replace_inst
|
||||||
@@ -265,8 +266,9 @@ def emit_dst_inst(node, fmt):
|
|||||||
# special functions in the `legalizer::split` module. These functions
|
# special functions in the `legalizer::split` module. These functions
|
||||||
# will eliminate concat-split patterns.
|
# will eliminate concat-split patterns.
|
||||||
fmt.line('let curpos = pos.position();')
|
fmt.line('let curpos = pos.position();')
|
||||||
|
fmt.line('let srcloc = pos.srcloc();')
|
||||||
fmt.format(
|
fmt.format(
|
||||||
'let {} = split::{}(dfg, pos.layout, cfg, curpos, {});',
|
'let {} = split::{}(pos.func, cfg, curpos, srcloc, {});',
|
||||||
wrap_tup(node.defs),
|
wrap_tup(node.defs),
|
||||||
node.expr.inst.snake_name(),
|
node.expr.inst.snake_name(),
|
||||||
node.expr.args[0])
|
node.expr.args[0])
|
||||||
@@ -274,7 +276,7 @@ def emit_dst_inst(node, fmt):
|
|||||||
if len(node.defs) == 0:
|
if len(node.defs) == 0:
|
||||||
# This node doesn't define any values, so just insert the new
|
# This node doesn't define any values, so just insert the new
|
||||||
# instruction.
|
# instruction.
|
||||||
builder = 'dfg.ins(pos)'
|
builder = 'pos.ins()'
|
||||||
else:
|
else:
|
||||||
src_def0 = node.defs[0].src_def
|
src_def0 = node.defs[0].src_def
|
||||||
if src_def0 and node.defs == src_def0.defs:
|
if src_def0 and node.defs == src_def0.defs:
|
||||||
@@ -282,12 +284,12 @@ def emit_dst_inst(node, fmt):
|
|||||||
# the source pattern. Unwrapping would have left the results
|
# the source pattern. Unwrapping would have left the results
|
||||||
# intact.
|
# intact.
|
||||||
# Replace the whole instruction.
|
# Replace the whole instruction.
|
||||||
builder = 'let {} = dfg.replace(inst)'.format(
|
builder = 'let {} = pos.func.dfg.replace(inst)'.format(
|
||||||
wrap_tup(node.defs))
|
wrap_tup(node.defs))
|
||||||
replaced_inst = 'inst'
|
replaced_inst = 'inst'
|
||||||
else:
|
else:
|
||||||
# Insert a new instruction.
|
# Insert a new instruction.
|
||||||
builder = 'let {} = dfg.ins(pos)'.format(wrap_tup(node.defs))
|
builder = 'let {} = pos.ins()'.format(wrap_tup(node.defs))
|
||||||
# We may want to reuse some of the detached output values.
|
# We may want to reuse some of the detached output values.
|
||||||
if len(node.defs) == 1 and node.defs[0].is_output():
|
if len(node.defs) == 1 and node.defs[0].is_output():
|
||||||
# Reuse the single source result value.
|
# Reuse the single source result value.
|
||||||
@@ -335,7 +337,7 @@ def gen_xform(xform, fmt, type_sets):
|
|||||||
# If we're going to delete `inst`, we need to detach its results first
|
# If we're going to delete `inst`, we need to detach its results first
|
||||||
# so they can be reattached during pattern expansion.
|
# so they can be reattached during pattern expansion.
|
||||||
if not replace_inst:
|
if not replace_inst:
|
||||||
fmt.line('dfg.clear_results(inst);')
|
fmt.line('pos.func.dfg.clear_results(inst);')
|
||||||
|
|
||||||
# Emit the destination pattern.
|
# Emit the destination pattern.
|
||||||
for dst in xform.dst.rtl:
|
for dst in xform.dst.rtl:
|
||||||
@@ -357,8 +359,10 @@ def gen_xform_group(xgrp, fmt, type_sets):
|
|||||||
'func: &mut ir::Function, '
|
'func: &mut ir::Function, '
|
||||||
'cfg: &mut ::flowgraph::ControlFlowGraph) -> '
|
'cfg: &mut ::flowgraph::ControlFlowGraph) -> '
|
||||||
'bool {{'.format(xgrp.name), '}'):
|
'bool {{'.format(xgrp.name), '}'):
|
||||||
fmt.line('use ir::{InstBuilder, CursorBase};')
|
fmt.line('use ir::{InstBuilder};')
|
||||||
fmt.line('let srcloc = func.srclocs[inst];')
|
fmt.line('use cursor::{Cursor, FuncCursor};')
|
||||||
|
fmt.line('let pos = &mut FuncCursor::new(func).at_inst(inst);')
|
||||||
|
fmt.line('pos.use_srcloc(inst);')
|
||||||
|
|
||||||
# Group the xforms by opcode so we can generate a big switch.
|
# Group the xforms by opcode so we can generate a big switch.
|
||||||
# Preserve ordering.
|
# Preserve ordering.
|
||||||
@@ -368,16 +372,10 @@ def gen_xform_group(xgrp, fmt, type_sets):
|
|||||||
xforms[inst.camel_name].append(xform)
|
xforms[inst.camel_name].append(xform)
|
||||||
|
|
||||||
with fmt.indented('{', '}'):
|
with fmt.indented('{', '}'):
|
||||||
with fmt.indented('match func.dfg[inst].opcode() {', '}'):
|
with fmt.indented('match pos.func.dfg[inst].opcode() {', '}'):
|
||||||
for camel_name in sorted(xforms.keys()):
|
for camel_name in sorted(xforms.keys()):
|
||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'ir::Opcode::{} => {{'.format(camel_name), '}'):
|
'ir::Opcode::{} => {{'.format(camel_name), '}'):
|
||||||
fmt.line(
|
|
||||||
'let pos = &mut ir::Cursor::new'
|
|
||||||
'(&mut func.layout, &mut func.srclocs)'
|
|
||||||
'.with_srcloc(srcloc)'
|
|
||||||
'.at_inst(inst);')
|
|
||||||
fmt.line('let dfg = &mut func.dfg;')
|
|
||||||
for xform in xforms[camel_name]:
|
for xform in xforms[camel_name]:
|
||||||
gen_xform(xform, fmt, type_sets)
|
gen_xform(xform, fmt, type_sets)
|
||||||
|
|
||||||
@@ -387,7 +385,7 @@ def gen_xform_group(xgrp, fmt, type_sets):
|
|||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'ir::Opcode::{} => {{'
|
'ir::Opcode::{} => {{'
|
||||||
.format(inst.camel_name), '}'):
|
.format(inst.camel_name), '}'):
|
||||||
fmt.format('{}(inst, func, cfg);', funcname)
|
fmt.format('{}(inst, pos.func, cfg);', funcname)
|
||||||
fmt.line('return true;')
|
fmt.line('return true;')
|
||||||
|
|
||||||
# We'll assume there are uncovered opcodes.
|
# We'll assume there are uncovered opcodes.
|
||||||
@@ -395,7 +393,7 @@ def gen_xform_group(xgrp, fmt, type_sets):
|
|||||||
|
|
||||||
# If we fall through, nothing was expanded. Call the chain if any.
|
# If we fall through, nothing was expanded. Call the chain if any.
|
||||||
if xgrp.chain:
|
if xgrp.chain:
|
||||||
fmt.format('{}(inst, func, cfg)', xgrp.chain.rust_name())
|
fmt.format('{}(inst, pos.func, cfg)', xgrp.chain.rust_name())
|
||||||
else:
|
else:
|
||||||
fmt.line('false')
|
fmt.line('false')
|
||||||
|
|
||||||
|
|||||||
@@ -325,13 +325,15 @@ fn convert_to_abi<PutArg>(
|
|||||||
match legalize_abi_value(ty, &arg_type) {
|
match legalize_abi_value(ty, &arg_type) {
|
||||||
ValueConversion::IntSplit => {
|
ValueConversion::IntSplit => {
|
||||||
let curpos = pos.position();
|
let curpos = pos.position();
|
||||||
let (lo, hi) = isplit(&mut pos.func.dfg, &mut pos.func.layout, cfg, curpos, value);
|
let srcloc = pos.srcloc();
|
||||||
|
let (lo, hi) = isplit(&mut pos.func, cfg, curpos, srcloc, value);
|
||||||
convert_to_abi(pos, cfg, lo, put_arg);
|
convert_to_abi(pos, cfg, lo, put_arg);
|
||||||
convert_to_abi(pos, cfg, hi, put_arg);
|
convert_to_abi(pos, cfg, hi, put_arg);
|
||||||
}
|
}
|
||||||
ValueConversion::VectorSplit => {
|
ValueConversion::VectorSplit => {
|
||||||
let curpos = pos.position();
|
let curpos = pos.position();
|
||||||
let (lo, hi) = vsplit(&mut pos.func.dfg, &mut pos.func.layout, cfg, curpos, value);
|
let srcloc = pos.srcloc();
|
||||||
|
let (lo, hi) = vsplit(&mut pos.func, cfg, curpos, srcloc, value);
|
||||||
convert_to_abi(pos, cfg, lo, put_arg);
|
convert_to_abi(pos, cfg, lo, put_arg);
|
||||||
convert_to_abi(pos, cfg, hi, put_arg);
|
convert_to_abi(pos, cfg, hi, put_arg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
//! It is possible to have circular dependencies of EBB arguments that are never used by any real
|
//! It is possible to have circular dependencies of EBB arguments that are never used by any real
|
||||||
//! instructions. These loops will remain in the program.
|
//! instructions. These loops will remain in the program.
|
||||||
|
|
||||||
use cursor::{Cursor, CursorPosition};
|
use cursor::{Cursor, CursorPosition, FuncCursor};
|
||||||
use flowgraph::ControlFlowGraph;
|
use flowgraph::ControlFlowGraph;
|
||||||
use ir::{self, Ebb, Inst, Value, Type, Opcode, ValueDef, InstructionData, InstBuilder};
|
use ir::{self, Ebb, Inst, Value, Type, Opcode, ValueDef, InstructionData, InstBuilder};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
@@ -72,25 +72,25 @@ use std::iter;
|
|||||||
/// Split `value` into two values using the `isplit` semantics. Do this by reusing existing values
|
/// Split `value` into two values using the `isplit` semantics. Do this by reusing existing values
|
||||||
/// if possible.
|
/// if possible.
|
||||||
pub fn isplit(
|
pub fn isplit(
|
||||||
dfg: &mut ir::DataFlowGraph,
|
func: &mut ir::Function,
|
||||||
layout: &mut ir::Layout,
|
|
||||||
cfg: &ControlFlowGraph,
|
cfg: &ControlFlowGraph,
|
||||||
pos: CursorPosition,
|
pos: CursorPosition,
|
||||||
|
srcloc: ir::SourceLoc,
|
||||||
value: Value,
|
value: Value,
|
||||||
) -> (Value, Value) {
|
) -> (Value, Value) {
|
||||||
split_any(dfg, layout, cfg, pos, value, Opcode::Iconcat)
|
split_any(func, cfg, pos, srcloc, value, Opcode::Iconcat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Split `value` into halves using the `vsplit` semantics. Do this by reusing existing values if
|
/// Split `value` into halves using the `vsplit` semantics. Do this by reusing existing values if
|
||||||
/// possible.
|
/// possible.
|
||||||
pub fn vsplit(
|
pub fn vsplit(
|
||||||
dfg: &mut ir::DataFlowGraph,
|
func: &mut ir::Function,
|
||||||
layout: &mut ir::Layout,
|
|
||||||
cfg: &ControlFlowGraph,
|
cfg: &ControlFlowGraph,
|
||||||
pos: CursorPosition,
|
pos: CursorPosition,
|
||||||
|
srcloc: ir::SourceLoc,
|
||||||
value: Value,
|
value: Value,
|
||||||
) -> (Value, Value) {
|
) -> (Value, Value) {
|
||||||
split_any(dfg, layout, cfg, pos, value, Opcode::Vconcat)
|
split_any(func, cfg, pos, srcloc, value, Opcode::Vconcat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// After splitting an EBB argument, we need to go back and fix up all of the predecessor
|
/// After splitting an EBB argument, we need to go back and fix up all of the predecessor
|
||||||
@@ -112,54 +112,53 @@ struct Repair {
|
|||||||
|
|
||||||
/// Generic version of `isplit` and `vsplit` controlled by the `concat` opcode.
|
/// Generic version of `isplit` and `vsplit` controlled by the `concat` opcode.
|
||||||
fn split_any(
|
fn split_any(
|
||||||
dfg: &mut ir::DataFlowGraph,
|
func: &mut ir::Function,
|
||||||
layout: &mut ir::Layout,
|
|
||||||
cfg: &ControlFlowGraph,
|
cfg: &ControlFlowGraph,
|
||||||
pos: CursorPosition,
|
pos: CursorPosition,
|
||||||
|
srcloc: ir::SourceLoc,
|
||||||
value: Value,
|
value: Value,
|
||||||
concat: Opcode,
|
concat: Opcode,
|
||||||
) -> (Value, Value) {
|
) -> (Value, Value) {
|
||||||
let mut repairs = Vec::new();
|
let mut repairs = Vec::new();
|
||||||
let mut pos = ir::Cursor::new(layout, None).at_position(pos);
|
let pos = &mut FuncCursor::new(func).at_position(pos).with_srcloc(srcloc);
|
||||||
let result = split_value(dfg, &mut pos, value, concat, &mut repairs);
|
let result = split_value(pos, value, concat, &mut repairs);
|
||||||
|
|
||||||
// We have split the value requested, and now we may need to fix some EBB predecessors.
|
// We have split the value requested, and now we may need to fix some EBB predecessors.
|
||||||
while let Some(repair) = repairs.pop() {
|
while let Some(repair) = repairs.pop() {
|
||||||
for &(_, inst) in cfg.get_predecessors(repair.ebb) {
|
for &(_, inst) in cfg.get_predecessors(repair.ebb) {
|
||||||
let branch_opc = dfg[inst].opcode();
|
let branch_opc = pos.func.dfg[inst].opcode();
|
||||||
assert!(
|
assert!(
|
||||||
branch_opc.is_branch(),
|
branch_opc.is_branch(),
|
||||||
"Predecessor not a branch: {}",
|
"Predecessor not a branch: {}",
|
||||||
dfg.display_inst(inst, None)
|
pos.func.dfg.display_inst(inst, None)
|
||||||
);
|
);
|
||||||
let fixed_args = branch_opc.constraints().fixed_value_arguments();
|
let fixed_args = branch_opc.constraints().fixed_value_arguments();
|
||||||
let mut args = dfg[inst].take_value_list().expect(
|
let mut args = pos.func.dfg[inst].take_value_list().expect(
|
||||||
"Branches must have value lists.",
|
"Branches must have value lists.",
|
||||||
);
|
);
|
||||||
let num_args = args.len(&dfg.value_lists);
|
let num_args = args.len(&pos.func.dfg.value_lists);
|
||||||
// Get the old value passed to the EBB argument we're repairing.
|
// Get the old value passed to the EBB argument we're repairing.
|
||||||
let old_arg = args.get(fixed_args + repair.num, &dfg.value_lists).expect(
|
let old_arg = args.get(fixed_args + repair.num, &pos.func.dfg.value_lists)
|
||||||
"Too few branch arguments",
|
.expect("Too few branch arguments");
|
||||||
);
|
|
||||||
|
|
||||||
// It's possible that the CFG's predecessor list has duplicates. Detect them here.
|
// It's possible that the CFG's predecessor list has duplicates. Detect them here.
|
||||||
if dfg.value_type(old_arg) == repair.split_type {
|
if pos.func.dfg.value_type(old_arg) == repair.split_type {
|
||||||
dfg[inst].put_value_list(args);
|
pos.func.dfg[inst].put_value_list(args);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split the old argument, possibly causing more repairs to be scheduled.
|
// Split the old argument, possibly causing more repairs to be scheduled.
|
||||||
pos.goto_inst(inst);
|
pos.goto_inst(inst);
|
||||||
let (lo, hi) = split_value(dfg, &mut pos, old_arg, repair.concat, &mut repairs);
|
let (lo, hi) = split_value(pos, old_arg, repair.concat, &mut repairs);
|
||||||
|
|
||||||
// The `lo` part replaces the original argument.
|
// The `lo` part replaces the original argument.
|
||||||
*args.get_mut(fixed_args + repair.num, &mut dfg.value_lists)
|
*args.get_mut(fixed_args + repair.num, &mut pos.func.dfg.value_lists)
|
||||||
.unwrap() = lo;
|
.unwrap() = lo;
|
||||||
|
|
||||||
// The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
|
// The `hi` part goes at the end. Since multiple repairs may have been scheduled to the
|
||||||
// same EBB, there could be multiple arguments missing.
|
// same EBB, there could be multiple arguments missing.
|
||||||
if num_args > fixed_args + repair.hi_num {
|
if num_args > fixed_args + repair.hi_num {
|
||||||
*args.get_mut(fixed_args + repair.hi_num, &mut dfg.value_lists)
|
*args.get_mut(fixed_args + repair.hi_num, &mut pos.func.dfg.value_lists)
|
||||||
.unwrap() = hi;
|
.unwrap() = hi;
|
||||||
} else {
|
} else {
|
||||||
// We need to append one or more arguments. If we're adding more than one argument,
|
// We need to append one or more arguments. If we're adding more than one argument,
|
||||||
@@ -167,12 +166,12 @@ fn split_any(
|
|||||||
// instead of `hi`.
|
// instead of `hi`.
|
||||||
args.extend(
|
args.extend(
|
||||||
iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args),
|
iter::repeat(hi).take(1 + fixed_args + repair.hi_num - num_args),
|
||||||
&mut dfg.value_lists,
|
&mut pos.func.dfg.value_lists,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the value list back after manipulating it.
|
// Put the value list back after manipulating it.
|
||||||
dfg[inst].put_value_list(args);
|
pos.func.dfg[inst].put_value_list(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,20 +185,19 @@ fn split_any(
|
|||||||
///
|
///
|
||||||
/// Return the two new values representing the parts of `value`.
|
/// Return the two new values representing the parts of `value`.
|
||||||
fn split_value(
|
fn split_value(
|
||||||
dfg: &mut ir::DataFlowGraph,
|
pos: &mut FuncCursor,
|
||||||
pos: &mut ir::Cursor,
|
|
||||||
value: Value,
|
value: Value,
|
||||||
concat: Opcode,
|
concat: Opcode,
|
||||||
repairs: &mut Vec<Repair>,
|
repairs: &mut Vec<Repair>,
|
||||||
) -> (Value, Value) {
|
) -> (Value, Value) {
|
||||||
let value = dfg.resolve_copies(value);
|
let value = pos.func.dfg.resolve_copies(value);
|
||||||
let mut reuse = None;
|
let mut reuse = None;
|
||||||
|
|
||||||
match dfg.value_def(value) {
|
match pos.func.dfg.value_def(value) {
|
||||||
ValueDef::Res(inst, num) => {
|
ValueDef::Res(inst, num) => {
|
||||||
// This is an instruction result. See if the value was created by a `concat`
|
// This is an instruction result. See if the value was created by a `concat`
|
||||||
// instruction.
|
// instruction.
|
||||||
if let InstructionData::Binary { opcode, args, .. } = dfg[inst] {
|
if let InstructionData::Binary { opcode, args, .. } = pos.func.dfg[inst] {
|
||||||
assert_eq!(num, 0);
|
assert_eq!(num, 0);
|
||||||
if opcode == concat {
|
if opcode == concat {
|
||||||
reuse = Some((args[0], args[1]));
|
reuse = Some((args[0], args[1]));
|
||||||
@@ -209,10 +207,10 @@ fn split_value(
|
|||||||
ValueDef::Arg(ebb, num) => {
|
ValueDef::Arg(ebb, num) => {
|
||||||
// This is an EBB argument. We can split the argument value unless this is the entry
|
// This is an EBB argument. We can split the argument value unless this is the entry
|
||||||
// block.
|
// block.
|
||||||
if pos.layout.entry_block() != Some(ebb) {
|
if pos.func.layout.entry_block() != Some(ebb) {
|
||||||
// We are going to replace the argument at `num` with two new arguments.
|
// We are going to replace the argument at `num` with two new arguments.
|
||||||
// Determine the new value types.
|
// Determine the new value types.
|
||||||
let ty = dfg.value_type(value);
|
let ty = pos.func.dfg.value_type(value);
|
||||||
let split_type = match concat {
|
let split_type = match concat {
|
||||||
Opcode::Iconcat => ty.half_width().expect("Invalid type for isplit"),
|
Opcode::Iconcat => ty.half_width().expect("Invalid type for isplit"),
|
||||||
Opcode::Vconcat => ty.half_vector().expect("Invalid type for vsplit"),
|
Opcode::Vconcat => ty.half_vector().expect("Invalid type for vsplit"),
|
||||||
@@ -225,9 +223,9 @@ fn split_value(
|
|||||||
//
|
//
|
||||||
// Replace the original `value` with the low part, and append the high part at the
|
// Replace the original `value` with the low part, and append the high part at the
|
||||||
// end of the argument list.
|
// end of the argument list.
|
||||||
let lo = dfg.replace_ebb_arg(value, split_type);
|
let lo = pos.func.dfg.replace_ebb_arg(value, split_type);
|
||||||
let hi_num = dfg.num_ebb_args(ebb);
|
let hi_num = pos.func.dfg.num_ebb_args(ebb);
|
||||||
let hi = dfg.append_ebb_arg(ebb, split_type);
|
let hi = pos.func.dfg.append_ebb_arg(ebb, split_type);
|
||||||
reuse = Some((lo, hi));
|
reuse = Some((lo, hi));
|
||||||
|
|
||||||
|
|
||||||
@@ -238,7 +236,7 @@ fn split_value(
|
|||||||
// Note that it is safe to move `pos` here since `reuse` was set above, so we don't
|
// Note that it is safe to move `pos` here since `reuse` was set above, so we don't
|
||||||
// need to insert a split instruction before returning.
|
// need to insert a split instruction before returning.
|
||||||
pos.goto_first_inst(ebb);
|
pos.goto_first_inst(ebb);
|
||||||
dfg.ins(pos).with_result(value).Binary(
|
pos.ins().with_result(value).Binary(
|
||||||
concat,
|
concat,
|
||||||
split_type,
|
split_type,
|
||||||
lo,
|
lo,
|
||||||
@@ -259,8 +257,8 @@ fn split_value(
|
|||||||
// No, we'll just have to insert the requested split instruction at `pos`. Note that `pos`
|
// No, we'll just have to insert the requested split instruction at `pos`. Note that `pos`
|
||||||
// has not been moved by the EBB argument code above when `reuse` is `None`.
|
// has not been moved by the EBB argument code above when `reuse` is `None`.
|
||||||
match concat {
|
match concat {
|
||||||
Opcode::Iconcat => dfg.ins(pos).isplit(value),
|
Opcode::Iconcat => pos.ins().isplit(value),
|
||||||
Opcode::Vconcat => dfg.ins(pos).vsplit(value),
|
Opcode::Vconcat => pos.ins().vsplit(value),
|
||||||
_ => panic!("Unhandled concat opcode: {}", concat),
|
_ => panic!("Unhandled concat opcode: {}", concat),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user