Add general legalization for the select instruction.
This commit is contained in:
@@ -68,3 +68,13 @@ ebb0:
|
|||||||
; check: $v1 = bitcast.f64 $tmp
|
; check: $v1 = bitcast.f64 $tmp
|
||||||
return v1
|
return v1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function %select_f64(f64, f64, i32) -> f64 {
|
||||||
|
ebb0(v0: f64, v1: f64, v2: i32):
|
||||||
|
v3 = select v2, v0, v1
|
||||||
|
; check: brnz v2, $(new=$EBB)($v0)
|
||||||
|
; nextln: jump $new($v1)
|
||||||
|
; check: $new($v3: f64):
|
||||||
|
; nextln: return $v3
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|||||||
32
cranelift/filetests/wasm/select.cton
Normal file
32
cranelift/filetests/wasm/select.cton
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
; Test basic code generation for the select WebAssembly instruction.
|
||||||
|
test compile
|
||||||
|
|
||||||
|
set is_64bit=0
|
||||||
|
isa intel haswell
|
||||||
|
|
||||||
|
set is_64bit=1
|
||||||
|
isa intel haswell
|
||||||
|
|
||||||
|
function %select_i32(i32, i32, i32) -> i32 {
|
||||||
|
ebb0(v0: i32, v1: i32, v2: i32):
|
||||||
|
v3 = select v2, v0, v1
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
function %select_i64(i64, i64, i32) -> i64 {
|
||||||
|
ebb0(v0: i64, v1: i64, v2: i32):
|
||||||
|
v3 = select v2, v0, v1
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
function %select_f32(f32, f32, i32) -> f32 {
|
||||||
|
ebb0(v0: f32, v1: f32, v2: i32):
|
||||||
|
v3 = select v2, v0, v1
|
||||||
|
return v3
|
||||||
|
}
|
||||||
|
|
||||||
|
function %select_f64(f64, f64, i32) -> f64 {
|
||||||
|
ebb0(v0: f64, v1: f64, v2: i32):
|
||||||
|
v3 = select v2, v0, v1
|
||||||
|
return v3
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ from .instructions import imul, imul_imm
|
|||||||
from .instructions import band, bor, bxor, isplit, iconcat
|
from .instructions import band, bor, bxor, isplit, iconcat
|
||||||
from .instructions import bnot, band_not, bor_not, bxor_not
|
from .instructions import bnot, band_not, bor_not, bxor_not
|
||||||
from .instructions import icmp, icmp_imm
|
from .instructions import icmp, icmp_imm
|
||||||
from .instructions import iconst, bint
|
from .instructions import iconst, bint, select
|
||||||
from .instructions import ishl, ishl_imm, sshr, sshr_imm, ushr, ushr_imm
|
from .instructions import ishl, ishl_imm, sshr, sshr_imm, ushr, ushr_imm
|
||||||
from .instructions import rotl, rotl_imm, rotr, rotr_imm
|
from .instructions import rotl, rotl_imm, rotr, rotr_imm
|
||||||
from .instructions import f32const, f64const
|
from .instructions import f32const, f64const
|
||||||
@@ -56,6 +56,7 @@ expand.custom_legalize(insts.heap_addr, 'expand_heap_addr')
|
|||||||
expand.custom_legalize(insts.trapz, 'expand_cond_trap')
|
expand.custom_legalize(insts.trapz, 'expand_cond_trap')
|
||||||
expand.custom_legalize(insts.trapnz, 'expand_cond_trap')
|
expand.custom_legalize(insts.trapnz, 'expand_cond_trap')
|
||||||
expand.custom_legalize(insts.br_table, 'expand_br_table')
|
expand.custom_legalize(insts.br_table, 'expand_br_table')
|
||||||
|
expand.custom_legalize(insts.select, 'expand_select')
|
||||||
|
|
||||||
# Custom expansions for floating point constants.
|
# Custom expansions for floating point constants.
|
||||||
# These expansions require bit-casting or creating constant pool entries.
|
# These expansions require bit-casting or creating constant pool entries.
|
||||||
@@ -116,6 +117,16 @@ for bitop in [band, bor, bxor]:
|
|||||||
a << iconcat(al, ah)
|
a << iconcat(al, ah)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
narrow.legalize(
|
||||||
|
a << select(c, x, y),
|
||||||
|
Rtl(
|
||||||
|
(xl, xh) << isplit(x),
|
||||||
|
(yl, yh) << isplit(y),
|
||||||
|
al << select(c, xl, yl),
|
||||||
|
ah << select(c, xh, yh),
|
||||||
|
a << iconcat(al, ah)
|
||||||
|
))
|
||||||
|
|
||||||
# Expand integer operations with carry for RISC architectures that don't have
|
# Expand integer operations with carry for RISC architectures that don't have
|
||||||
# the flags.
|
# the flags.
|
||||||
expand.legalize(
|
expand.legalize(
|
||||||
|
|||||||
@@ -179,6 +179,41 @@ fn expand_br_table(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFlo
|
|||||||
cfg.recompute_ebb(pos.func, ebb);
|
cfg.recompute_ebb(pos.func, ebb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Expand the select instruction.
|
||||||
|
///
|
||||||
|
/// Conditional moves are available in some ISAs for some register classes. The remaining selects
|
||||||
|
/// are handled by a branch.
|
||||||
|
fn expand_select(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFlowGraph) {
|
||||||
|
let (ctrl, tval, fval) = match func.dfg[inst] {
|
||||||
|
ir::InstructionData::Ternary {
|
||||||
|
opcode: ir::Opcode::Select,
|
||||||
|
args,
|
||||||
|
} => (args[0], args[1], args[2]),
|
||||||
|
_ => panic!("Expected select: {}", func.dfg.display_inst(inst, None)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Replace `result = select ctrl, tval, fval` with:
|
||||||
|
//
|
||||||
|
// brnz ctrl, new_ebb(tval)
|
||||||
|
// jump new_ebb(fval)
|
||||||
|
// new_ebb(result):
|
||||||
|
let old_ebb = func.layout.pp_ebb(inst);
|
||||||
|
let result = func.dfg.first_result(inst);
|
||||||
|
func.dfg.clear_results(inst);
|
||||||
|
let new_ebb = func.dfg.make_ebb();
|
||||||
|
func.dfg.attach_ebb_arg(new_ebb, result);
|
||||||
|
|
||||||
|
func.dfg.replace(inst).brnz(ctrl, new_ebb, &[tval]);
|
||||||
|
let mut pos = FuncCursor::new(func).after_inst(inst);
|
||||||
|
pos.use_srcloc(inst);
|
||||||
|
pos.ins().jump(new_ebb, &[fval]);
|
||||||
|
pos.insert_ebb(new_ebb);
|
||||||
|
|
||||||
|
cfg.recompute_ebb(pos.func, new_ebb);
|
||||||
|
cfg.recompute_ebb(pos.func, old_ebb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Expand illegal `f32const` and `f64const` instructions.
|
/// Expand illegal `f32const` and `f64const` instructions.
|
||||||
fn expand_fconst(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut ControlFlowGraph) {
|
fn expand_fconst(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut ControlFlowGraph) {
|
||||||
let ty = func.dfg.value_type(func.dfg.first_result(inst));
|
let ty = func.dfg.value_type(func.dfg.first_result(inst));
|
||||||
|
|||||||
Reference in New Issue
Block a user