Don't create value aliases when legalizing ABI boundaries.

When converting from ABI types to original program types, the final
conversion instruction can place its result into the original value, so
it doesn't need to be changed to an alias.
This commit is contained in:
Jakob Stoklund Olesen
2017-04-13 10:16:58 -07:00
parent 7ad882c154
commit 3c8bdba15e
2 changed files with 38 additions and 32 deletions

View File

@@ -7,7 +7,7 @@ isa riscv
function int_split_args(i64) -> i64 {
ebb0(v0: i64):
; check: $ebb0($(v0l=$V): i32, $(v0h=$V): i32):
; check: iconcat $v0l, $v0h
; check: $v0 = iconcat $v0l, $v0h
v1 = iadd_imm v0, 1
; check: $(v1l=$V), $(v1h=$V) = isplit $v1
; check: return $v1l, $v1h
@@ -33,10 +33,9 @@ ebb0:
v1 = call fn1()
; check: $ebb0:
; nextln: $(v1l=$V), $(v1h=$V) = call $fn1()
; check: $(v1new=$V) = iconcat $v1l, $v1h
; check: $v1 = iconcat $v1l, $v1h
jump ebb1(v1)
; The v1 alias gets resolved by split::simplify_branch_arguments().
; check: jump $ebb1($v1new)
; check: jump $ebb1($v1)
ebb1(v10: i64):
jump ebb1(v10)
@@ -49,10 +48,9 @@ ebb0:
v1, v2 = call fn1()
; check: $ebb0:
; nextln: $v1, $(v2l=$V), $(v2h=$V) = call $fn1()
; check: $(v2new=$V) = iconcat $v2l, $v2h
; check: $v2 = iconcat $v2l, $v2h
jump ebb1(v1, v2)
; The v2 -> v2new alias is resolved by split::simplify_branch_arguments().
; check: jump $ebb1($v1, $v2new)
; check: jump $ebb1($v1, $v2)
ebb1(v9: i32, v10: i64):
jump ebb1(v9, v10)
@@ -61,8 +59,8 @@ ebb1(v9: i32, v10: i64):
function int_ext(i8, i8 sext, i8 uext) -> i8 uext {
ebb0(v1: i8, v2: i8, v3: i8):
; check: $ebb0($v1: i8, $(v2x=$V): i32, $(v3x=$V): i32):
; check: ireduce.i8 $v2x
; check: ireduce.i8 $v3x
; check: $v2 = ireduce.i8 $v2x
; check: $v3 = ireduce.i8 $v3x
; check: $(v1x=$V) = uextend.i32 $v1
; check: return $v1x
return v1
@@ -75,10 +73,9 @@ ebb0:
v1 = call fn1()
; check: $ebb0:
; nextln: $(rv=$V) = call $fn1()
; check: $(v1new=$V) = ireduce.i8 $rv
; check: $v1 = ireduce.i8 $rv
jump ebb1(v1)
; The v1 alias gets resolved by split::simplify_branch_arguments().
; check: jump $ebb1($v1new)
; check: jump $ebb1($v1)
ebb1(v10: i8):
jump ebb1(v10)
@@ -93,9 +90,9 @@ ebb0(v0: i64x4):
; check: $(v0c=$V) = iconcat $v0cl, $v0ch
; check: $(v0d=$V) = iconcat $v0dl, $v0dh
; check: $(v0cd=$V) = vconcat $v0c, $v0d
; check: $(v0abcd=$V) = vconcat $v0ab, $v0cd
; check: $v0 = vconcat $v0ab, $v0cd
v1 = bxor v0, v0
; check: $(v1ab=$V), $(v1cd=$V) = vsplit
; check: $(v1ab=$V), $(v1cd=$V) = vsplit $v1
; check: $(v1a=$V), $(v1b=$V) = vsplit $v1ab
; check: $(v1al=$V), $(v1ah=$V) = isplit $v1a
; check: $(v1bl=$V), $(v1bh=$V) = isplit $v1b

View File

@@ -85,10 +85,11 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
Err(abi_type)
}
};
let converted = convert_from_abi(&mut func.dfg, &mut pos, arg_type, &mut get_arg);
let converted =
convert_from_abi(&mut func.dfg, &mut pos, arg_type, Some(arg), &mut get_arg);
// The old `arg` is no longer an attached EBB argument, but there are probably still
// uses of the value. Make it an alias to the converted value.
func.dfg.change_to_alias(arg, converted);
// uses of the value.
assert_eq!(func.dfg.resolve_aliases(arg), converted);
}
}
}
@@ -141,9 +142,8 @@ fn legalize_inst_results<ResType>(dfg: &mut DataFlowGraph,
Err(abi_type)
}
};
let v = convert_from_abi(dfg, pos, res_type, &mut get_res);
// The old `res` is no longer an attached result.
dfg.change_to_alias(res, v);
let v = convert_from_abi(dfg, pos, res_type, Some(res), &mut get_res);
assert_eq!(dfg.resolve_aliases(res), v);
}
}
@@ -158,9 +158,11 @@ fn legalize_inst_results<ResType>(dfg: &mut DataFlowGraph,
/// - `Ok(arg)` if the requested type matches the next ABI argument.
/// - `Err(arg_type)` if further conversions are needed from the ABI argument `arg_type`.
///
/// If the `into_result` value is provided, the converted result will be written into that value.
fn convert_from_abi<GetArg>(dfg: &mut DataFlowGraph,
pos: &mut Cursor,
ty: Type,
into_result: Option<Value>,
get_arg: &mut GetArg)
-> Value
where GetArg: FnMut(&mut DataFlowGraph, Type) -> Result<Value, ArgumentType>
@@ -169,6 +171,7 @@ fn convert_from_abi<GetArg>(dfg: &mut DataFlowGraph,
let arg_type = match get_arg(dfg, ty) {
Ok(v) => {
debug_assert_eq!(dfg.value_type(v), ty);
assert_eq!(into_result, None);
return v;
}
Err(t) => t,
@@ -184,43 +187,49 @@ fn convert_from_abi<GetArg>(dfg: &mut DataFlowGraph,
// Construct a `ty` by concatenating two ABI integers.
ValueConversion::IntSplit => {
let abi_ty = ty.half_width().expect("Invalid type for conversion");
let lo = convert_from_abi(dfg, pos, abi_ty, get_arg);
let hi = convert_from_abi(dfg, pos, abi_ty, get_arg);
let lo = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
let hi = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
dbg!("intsplit {}: {}, {}: {}",
lo,
dfg.value_type(lo),
hi,
dfg.value_type(hi));
dfg.ins(pos).iconcat(lo, hi)
dfg.ins(pos).with_results([into_result]).iconcat(lo, hi)
}
// Construct a `ty` by concatenating two halves of a vector.
ValueConversion::VectorSplit => {
let abi_ty = ty.half_vector().expect("Invalid type for conversion");
let lo = convert_from_abi(dfg, pos, abi_ty, get_arg);
let hi = convert_from_abi(dfg, pos, abi_ty, get_arg);
dfg.ins(pos).vconcat(lo, hi)
let lo = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
let hi = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
dfg.ins(pos).with_results([into_result]).vconcat(lo, hi)
}
// Construct a `ty` by bit-casting from an integer type.
ValueConversion::IntBits => {
assert!(!ty.is_int());
let abi_ty = Type::int(ty.bits()).expect("Invalid type for conversion");
let arg = convert_from_abi(dfg, pos, abi_ty, get_arg);
dfg.ins(pos).bitcast(ty, arg)
let arg = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
dfg.ins(pos)
.with_results([into_result])
.bitcast(ty, arg)
}
// ABI argument is a sign-extended version of the value we want.
ValueConversion::Sext(abi_ty) => {
let arg = convert_from_abi(dfg, pos, abi_ty, get_arg);
let arg = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
// TODO: Currently, we don't take advantage of the ABI argument being sign-extended.
// We could insert an `assert_sreduce` which would fold with a following `sextend` of
// this value.
dfg.ins(pos).ireduce(ty, arg)
dfg.ins(pos)
.with_results([into_result])
.ireduce(ty, arg)
}
ValueConversion::Uext(abi_ty) => {
let arg = convert_from_abi(dfg, pos, abi_ty, get_arg);
let arg = convert_from_abi(dfg, pos, abi_ty, None, get_arg);
// TODO: Currently, we don't take advantage of the ABI argument being sign-extended.
// We could insert an `assert_ureduce` which would fold with a following `uextend` of
// this value.
dfg.ins(pos).ireduce(ty, arg)
dfg.ins(pos)
.with_results([into_result])
.ireduce(ty, arg)
}
}
}