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