From 3c8bdba15ead65d41b9a65dd1a29482b363676af Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 13 Apr 2017 10:16:58 -0700 Subject: [PATCH] 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. --- .../filetests/isa/riscv/legalize-abi.cton | 25 +++++------ lib/cretonne/src/legalizer/boundary.rs | 45 +++++++++++-------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/cranelift/filetests/isa/riscv/legalize-abi.cton b/cranelift/filetests/isa/riscv/legalize-abi.cton index 85b06b5755..88d35e699a 100644 --- a/cranelift/filetests/isa/riscv/legalize-abi.cton +++ b/cranelift/filetests/isa/riscv/legalize-abi.cton @@ -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 diff --git a/lib/cretonne/src/legalizer/boundary.rs b/lib/cretonne/src/legalizer/boundary.rs index 272a19dfee..cb2794a49d 100644 --- a/lib/cretonne/src/legalizer/boundary.rs +++ b/lib/cretonne/src/legalizer/boundary.rs @@ -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(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(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(dfg: &mut DataFlowGraph, pos: &mut Cursor, ty: Type, + into_result: Option, get_arg: &mut GetArg) -> Value where GetArg: FnMut(&mut DataFlowGraph, Type) -> Result @@ -169,6 +171,7 @@ fn convert_from_abi(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(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) } } }