diff --git a/cranelift/codegen/src/isa/aarch64/mod.rs b/cranelift/codegen/src/isa/aarch64/mod.rs index 7c24281026..afd32dd40a 100644 --- a/cranelift/codegen/src/isa/aarch64/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/mod.rs @@ -239,223 +239,3 @@ pub fn isa_builder(triple: Triple) -> IsaBuilder { }, } } - -#[cfg(test)] -mod test { - use super::*; - use crate::cursor::{Cursor, FuncCursor}; - use crate::dominator_tree::DominatorTree; - use crate::flowgraph::ControlFlowGraph; - use crate::ir::types::*; - use crate::ir::{AbiParam, Function, InstBuilder, JumpTableData, Signature, UserFuncName}; - use crate::isa::CallConv; - use crate::settings; - use crate::settings::Configurable; - use core::str::FromStr; - use target_lexicon::Triple; - - #[test] - fn test_compile_function() { - let name = UserFuncName::testcase("test0"); - let mut sig = Signature::new(CallConv::SystemV); - sig.params.push(AbiParam::new(I32)); - sig.returns.push(AbiParam::new(I32)); - let mut func = Function::with_name_signature(name, sig); - - let bb0 = func.dfg.make_block(); - let arg0 = func.dfg.append_block_param(bb0, I32); - - let mut pos = FuncCursor::new(&mut func); - pos.insert_block(bb0); - let v0 = pos.ins().iconst(I32, 0x1234); - let v1 = pos.ins().iadd(arg0, v0); - pos.ins().return_(&[v1]); - - let mut shared_flags_builder = settings::builder(); - shared_flags_builder.set("opt_level", "none").unwrap(); - let shared_flags = settings::Flags::new(shared_flags_builder); - let isa_flags = aarch64_settings::Flags::new(&shared_flags, aarch64_settings::builder()); - let backend = AArch64Backend::new_with_flags( - Triple::from_str("aarch64").unwrap(), - shared_flags, - isa_flags, - ); - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - let buffer = backend - .compile_function(&mut func, &domtree, false) - .unwrap() - .buffer; - let code = buffer.data(); - - // To update this comment, write the golden bytes to a file, and run the following command - // on it to update: - // > aarch64-linux-gnu-objdump -b binary -D -m aarch64 - // - // 0: 52824682 mov w2, #0x1234 // #4660 - // 4: 0b020000 add w0, w0, w2 - // 8: d65f03c0 ret - - let golden = vec![130, 70, 130, 82, 0, 0, 2, 11, 192, 3, 95, 214]; - - assert_eq!(code, &golden[..]); - } - - #[test] - fn test_branch_lowering() { - let name = UserFuncName::testcase("test0"); - let mut sig = Signature::new(CallConv::SystemV); - sig.params.push(AbiParam::new(I32)); - sig.returns.push(AbiParam::new(I32)); - let mut func = Function::with_name_signature(name, sig); - - let bb0 = func.dfg.make_block(); - let arg0 = func.dfg.append_block_param(bb0, I32); - let bb1 = func.dfg.make_block(); - let bb2 = func.dfg.make_block(); - let bb3 = func.dfg.make_block(); - - let mut pos = FuncCursor::new(&mut func); - pos.insert_block(bb0); - let v0 = pos.ins().iconst(I32, 0x1234); - let v1 = pos.ins().iadd(arg0, v0); - pos.ins().brif(v1, bb1, &[], bb2, &[]); - pos.insert_block(bb1); - pos.ins().brif(v1, bb2, &[], bb3, &[]); - pos.insert_block(bb2); - let v2 = pos.ins().iadd(v1, v0); - pos.ins().brif(v2, bb2, &[], bb1, &[]); - pos.insert_block(bb3); - let v3 = pos.ins().isub(v1, v0); - pos.ins().return_(&[v3]); - - let mut shared_flags_builder = settings::builder(); - shared_flags_builder.set("opt_level", "none").unwrap(); - let shared_flags = settings::Flags::new(shared_flags_builder); - let isa_flags = aarch64_settings::Flags::new(&shared_flags, aarch64_settings::builder()); - let backend = AArch64Backend::new_with_flags( - Triple::from_str("aarch64").unwrap(), - shared_flags, - isa_flags, - ); - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - let result = backend - .compile_function(&mut func, &domtree, /* want_disasm = */ false) - .unwrap(); - let code = result.buffer.data(); - - // To update this comment, write the golden bytes to a file, and run the following command - // on it to update: - // > aarch64-linux-gnu-objdump -b binary -D -m aarch64 - // - // 0: 52824689 mov w9, #0x1234 // #4660 - // 4: 0b09000b add w11, w0, w9 - // 8: 2a0b03ea mov w10, w11 - // c: b40000ca cbz x10, 0x24 - // 10: 2a0b03ed mov w13, w11 - // 14: b500008d cbnz x13, 0x24 - // 18: 5282468e mov w14, #0x1234 // #4660 - // 1c: 4b0e0160 sub w0, w11, w14 - // 20: d65f03c0 ret - // 24: 5282468f mov w15, #0x1234 // #4660 - // 28: 0b0f0161 add w1, w11, w15 - // 2c: 2a0103e0 mov w0, w1 - // 30: b5ffffa0 cbnz x0, 0x24 - // 34: 17fffff7 b 0x10 - - let golden = vec![ - 137, 70, 130, 82, 11, 0, 9, 11, 234, 3, 11, 42, 202, 0, 0, 180, 237, 3, 11, 42, 141, 0, - 0, 181, 142, 70, 130, 82, 96, 1, 14, 75, 192, 3, 95, 214, 143, 70, 130, 82, 97, 1, 15, - 11, 224, 3, 1, 42, 160, 255, 255, 181, 247, 255, 255, 23, - ]; - - assert_eq!(code, &golden[..]); - } - - #[test] - fn test_br_table() { - let name = UserFuncName::testcase("test0"); - let mut sig = Signature::new(CallConv::SystemV); - sig.params.push(AbiParam::new(I32)); - sig.returns.push(AbiParam::new(I32)); - let mut func = Function::with_name_signature(name, sig); - - let bb0 = func.dfg.make_block(); - let arg0 = func.dfg.append_block_param(bb0, I32); - let bb1 = func.dfg.make_block(); - let bb2 = func.dfg.make_block(); - let bb3 = func.dfg.make_block(); - - let mut pos = FuncCursor::new(&mut func); - - pos.insert_block(bb0); - let jt_data = JumpTableData::new( - pos.func.dfg.block_call(bb3, &[]), - &[ - pos.func.dfg.block_call(bb1, &[]), - pos.func.dfg.block_call(bb2, &[]), - ], - ); - let jt = pos.func.create_jump_table(jt_data); - pos.ins().br_table(arg0, jt); - - pos.insert_block(bb1); - let v1 = pos.ins().iconst(I32, 1); - pos.ins().return_(&[v1]); - - pos.insert_block(bb2); - let v2 = pos.ins().iconst(I32, 2); - pos.ins().return_(&[v2]); - - pos.insert_block(bb3); - let v3 = pos.ins().iconst(I32, 3); - pos.ins().return_(&[v3]); - - let mut shared_flags_builder = settings::builder(); - shared_flags_builder.set("opt_level", "none").unwrap(); - shared_flags_builder.set("enable_verifier", "true").unwrap(); - let shared_flags = settings::Flags::new(shared_flags_builder); - let isa_flags = aarch64_settings::Flags::new(&shared_flags, aarch64_settings::builder()); - let backend = AArch64Backend::new_with_flags( - Triple::from_str("aarch64").unwrap(), - shared_flags, - isa_flags, - ); - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - let result = backend - .compile_function(&mut func, &domtree, /* want_disasm = */ false) - .unwrap(); - let code = result.buffer.data(); - - // To update this comment, write the golden bytes to a file, and run the following command - // on it to update: - // > aarch64-linux-gnu-objdump -b binary -D -m aarch64 - // - // 0: 7100081f cmp w0, #0x2 - // 4: 540001a2 b.cs 0x38 // b.hs, b.nlast - // 8: 9a8023e8 csel x8, xzr, x0, cs // cs = hs, nlast - // c: d503229f csdb - // 10: 10000087 adr x7, 0x20 - // 14: b8a858e8 ldrsw x8, [x7, w8, uxtw #2] - // 18: 8b0800e7 add x7, x7, x8 - // 1c: d61f00e0 br x7 - // 20: 00000010 udf #16 - // 24: 00000008 udf #8 - // 28: 52800040 mov w0, #0x2 // #2 - // 2c: d65f03c0 ret - // 30: 52800020 mov w0, #0x1 // #1 - // 34: d65f03c0 ret - // 38: 52800060 mov w0, #0x3 // #3 - // 3c: d65f03c0 ret - - let golden = vec![ - 31, 8, 0, 113, 162, 1, 0, 84, 232, 35, 128, 154, 159, 34, 3, 213, 135, 0, 0, 16, 232, - 88, 168, 184, 231, 0, 8, 139, 224, 0, 31, 214, 16, 0, 0, 0, 8, 0, 0, 0, 64, 0, 128, 82, - 192, 3, 95, 214, 32, 0, 128, 82, 192, 3, 95, 214, 96, 0, 128, 82, 192, 3, 95, 214, - ]; - - assert_eq!(code, &golden[..]); - } -} diff --git a/cranelift/codegen/src/isa/riscv64/mod.rs b/cranelift/codegen/src/isa/riscv64/mod.rs index 1a068a14d1..53d9034817 100644 --- a/cranelift/codegen/src/isa/riscv64/mod.rs +++ b/cranelift/codegen/src/isa/riscv64/mod.rs @@ -214,64 +214,3 @@ pub fn isa_builder(triple: Triple) -> IsaBuilder { }, } } - -#[cfg(test)] -mod test { - use super::*; - use crate::cursor::{Cursor, FuncCursor}; - use crate::dominator_tree::DominatorTree; - use crate::flowgraph::ControlFlowGraph; - use crate::ir::types::*; - use crate::ir::{AbiParam, Function, InstBuilder, Signature, UserFuncName}; - use crate::isa::CallConv; - use crate::settings; - use crate::settings::Configurable; - use core::str::FromStr; - use target_lexicon::Triple; - - #[test] - fn test_compile_function() { - let name = UserFuncName::testcase("test0"); - let mut sig = Signature::new(CallConv::SystemV); - sig.params.push(AbiParam::new(I32)); - sig.returns.push(AbiParam::new(I32)); - let mut func = Function::with_name_signature(name, sig); - - let bb0 = func.dfg.make_block(); - let arg0 = func.dfg.append_block_param(bb0, I32); - - let mut pos = FuncCursor::new(&mut func); - pos.insert_block(bb0); - let v0 = pos.ins().iconst(I32, 0x1234); - let v1 = pos.ins().iadd(arg0, v0); - pos.ins().return_(&[v1]); - - let mut shared_flags_builder = settings::builder(); - shared_flags_builder.set("opt_level", "none").unwrap(); - let shared_flags = settings::Flags::new(shared_flags_builder); - let isa_flags = riscv_settings::Flags::new(&shared_flags, riscv_settings::builder()); - let backend = Riscv64Backend::new_with_flags( - Triple::from_str("riscv64").unwrap(), - shared_flags, - isa_flags, - ); - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - let buffer = backend.compile_function(&mut func, &domtree, true).unwrap(); - let code = buffer.buffer.data(); - - // To update this comment, write the golden bytes to a file, and run the following command - // on it to update: - // > riscv64-linux-gnu-objdump -b binary -D -m riscv - // - // 0: 000015b7 lui a1,0x1 - // 4: 23458593 addi a1,a1,564 # 0x1234 - // 8: 00b5053b .4byte 0xb5053b - // c: 00008067 ret - - let golden = vec![ - 183, 21, 0, 0, 147, 133, 69, 35, 59, 5, 181, 0, 103, 128, 0, 0, - ]; - assert_eq!(code, &golden[..]); - } -} diff --git a/cranelift/codegen/src/isa/s390x/mod.rs b/cranelift/codegen/src/isa/s390x/mod.rs index 893e30ec11..6a6dad94c3 100644 --- a/cranelift/codegen/src/isa/s390x/mod.rs +++ b/cranelift/codegen/src/isa/s390x/mod.rs @@ -211,130 +211,3 @@ pub fn isa_builder(triple: Triple) -> IsaBuilder { }, } } - -#[cfg(test)] -mod test { - use super::*; - use crate::cursor::{Cursor, FuncCursor}; - use crate::dominator_tree::DominatorTree; - use crate::flowgraph::ControlFlowGraph; - use crate::ir::types::*; - use crate::ir::UserFuncName; - use crate::ir::{AbiParam, Function, InstBuilder, Signature}; - use crate::isa::CallConv; - use crate::settings; - use crate::settings::Configurable; - use core::str::FromStr; - use target_lexicon::Triple; - - #[test] - fn test_compile_function() { - let name = UserFuncName::testcase("test0"); - let mut sig = Signature::new(CallConv::SystemV); - sig.params.push(AbiParam::new(I32)); - sig.returns.push(AbiParam::new(I32)); - let mut func = Function::with_name_signature(name, sig); - - let bb0 = func.dfg.make_block(); - let arg0 = func.dfg.append_block_param(bb0, I32); - - let mut pos = FuncCursor::new(&mut func); - pos.insert_block(bb0); - let v0 = pos.ins().iconst(I32, 0x1234); - let v1 = pos.ins().iadd(arg0, v0); - pos.ins().return_(&[v1]); - - let mut shared_flags_builder = settings::builder(); - shared_flags_builder.set("opt_level", "none").unwrap(); - let shared_flags = settings::Flags::new(shared_flags_builder); - let isa_flags = s390x_settings::Flags::new(&shared_flags, s390x_settings::builder()); - let backend = S390xBackend::new_with_flags( - Triple::from_str("s390x").unwrap(), - shared_flags, - isa_flags, - ); - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - let result = backend - .compile_function(&mut func, &domtree, /* want_disasm = */ false) - .unwrap(); - let code = result.buffer.data(); - - // ahi %r2, 0x1234 - // br %r14 - let golden = vec![0xa7, 0x2a, 0x12, 0x34, 0x07, 0xfe]; - - assert_eq!(code, &golden[..]); - } - - #[test] - fn test_branch_lowering() { - let name = UserFuncName::testcase("test0"); - let mut sig = Signature::new(CallConv::SystemV); - sig.params.push(AbiParam::new(I32)); - sig.returns.push(AbiParam::new(I32)); - let mut func = Function::with_name_signature(name, sig); - - let bb0 = func.dfg.make_block(); - let arg0 = func.dfg.append_block_param(bb0, I32); - let bb1 = func.dfg.make_block(); - let bb2 = func.dfg.make_block(); - let bb3 = func.dfg.make_block(); - - let mut pos = FuncCursor::new(&mut func); - pos.insert_block(bb0); - let v0 = pos.ins().iconst(I32, 0x1234); - let v1 = pos.ins().iadd(arg0, v0); - pos.ins().brif(v1, bb1, &[], bb2, &[]); - pos.insert_block(bb1); - pos.ins().brif(v1, bb2, &[], bb3, &[]); - pos.insert_block(bb2); - let v2 = pos.ins().iadd(v1, v0); - pos.ins().brif(v2, bb2, &[], bb1, &[]); - pos.insert_block(bb3); - let v3 = pos.ins().isub(v1, v0); - pos.ins().return_(&[v3]); - - let mut shared_flags_builder = settings::builder(); - shared_flags_builder.set("opt_level", "none").unwrap(); - let shared_flags = settings::Flags::new(shared_flags_builder); - let isa_flags = s390x_settings::Flags::new(&shared_flags, s390x_settings::builder()); - let backend = S390xBackend::new_with_flags( - Triple::from_str("s390x").unwrap(), - shared_flags, - isa_flags, - ); - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - let result = backend - .compile_function(&mut func, &domtree, /* want_disasm = */ false) - .unwrap(); - let code = result.buffer.data(); - - // FIXME: the branching logic should be optimized more - - // To update this comment, write the golden bytes to a file, and run the following command - // on it to update: - // > s390x-linux-gnu-objdump -b binary -D -m s390 - // - // 0: a7 2a 12 34 ahi %r2,4660 - // 4: a7 2e 00 00 chi %r2,0 - // 8: c0 94 00 00 00 0b jgnlh 0x1e - // e: a7 2e 00 00 chi %r2,0 - // 12: c0 64 00 00 00 06 jglh 0x1e - // 18: a7 2a ed cc ahi %r2,-4660 - // 1c: 07 fe br %r14 - // 1e: ec 32 12 34 00 d8 ahik %r3,%r2,4660 - // 24: a7 3e 00 00 chi %r3,0 - // 28: c0 64 ff ff ff fb jglh 0x1e - // 2e: c0 f4 ff ff ff f0 jg 0xe - - let golden = vec![ - 167, 42, 18, 52, 167, 46, 0, 0, 192, 148, 0, 0, 0, 11, 167, 46, 0, 0, 192, 100, 0, 0, - 0, 6, 167, 42, 237, 204, 7, 254, 236, 50, 18, 52, 0, 216, 167, 62, 0, 0, 192, 100, 255, - 255, 255, 251, 192, 244, 255, 255, 255, 240, - ]; - - assert_eq!(code, &golden[..]); - } -} diff --git a/cranelift/codegen/src/isa/x64/mod.rs b/cranelift/codegen/src/isa/x64/mod.rs index 67c3475f74..7c085ad583 100644 --- a/cranelift/codegen/src/isa/x64/mod.rs +++ b/cranelift/codegen/src/isa/x64/mod.rs @@ -233,161 +233,8 @@ fn isa_constructor( #[cfg(test)] mod test { use super::*; - use crate::cursor::{Cursor, FuncCursor}; - use crate::dominator_tree::DominatorTree; - use crate::flowgraph::ControlFlowGraph; - use crate::ir::{types::*, RelSourceLoc, SourceLoc, UserFuncName, ValueLabel, ValueLabelStart}; - use crate::ir::{AbiParam, Function, InstBuilder, JumpTableData, Signature}; - use crate::isa::CallConv; use crate::settings; use crate::settings::Configurable; - use core::str::FromStr; - use cranelift_entity::EntityRef; - use target_lexicon::Triple; - - /// We have to test cold blocks by observing final machine code, - /// rather than VCode, because the VCode orders blocks in lowering - /// order, not emission order. (The exact difference between the - /// two is that cold blocks are sunk in the latter.) We might as - /// well do the test here, where we have a backend to use. - #[test] - fn test_cold_blocks() { - let name = UserFuncName::testcase("test0"); - let mut sig = Signature::new(CallConv::SystemV); - sig.params.push(AbiParam::new(I32)); - sig.returns.push(AbiParam::new(I32)); - let mut func = Function::with_name_signature(name, sig); - // Add debug info: this tests the debug machinery wrt cold - // blocks as well. - func.dfg.collect_debug_info(); - - let bb0 = func.dfg.make_block(); - let arg0 = func.dfg.append_block_param(bb0, I32); - let bb1 = func.dfg.make_block(); - let bb2 = func.dfg.make_block(); - let bb3 = func.dfg.make_block(); - let bb1_param = func.dfg.append_block_param(bb1, I32); - let bb3_param = func.dfg.append_block_param(bb3, I32); - - let mut pos = FuncCursor::new(&mut func); - - pos.insert_block(bb0); - pos.set_srcloc(SourceLoc::new(1)); - let v0 = pos.ins().iconst(I32, 0x1234); - pos.set_srcloc(SourceLoc::new(2)); - let v1 = pos.ins().iadd(arg0, v0); - pos.ins().brif(v1, bb1, &[v1], bb2, &[]); - - pos.insert_block(bb1); - pos.set_srcloc(SourceLoc::new(3)); - let v2 = pos.ins().isub(v1, v0); - pos.set_srcloc(SourceLoc::new(4)); - let v3 = pos.ins().iadd(v2, bb1_param); - pos.ins().brif(v1, bb2, &[], bb3, &[v3]); - - pos.func.layout.set_cold(bb2); - pos.insert_block(bb2); - pos.set_srcloc(SourceLoc::new(5)); - let v4 = pos.ins().iadd(v1, v0); - pos.ins().brif(v4, bb2, &[], bb1, &[v4]); - - pos.insert_block(bb3); - pos.set_srcloc(SourceLoc::new(6)); - pos.ins().return_(&[bb3_param]); - - // Create some debug info. Make one label that follows all the - // values around. Note that this is usually done via an API on - // the FunctionBuilder, but that's in cranelift_frontend - // (i.e., a higher level of the crate DAG) so we have to build - // it manually here. - pos.func.dfg.values_labels.as_mut().unwrap().insert( - v0, - crate::ir::ValueLabelAssignments::Starts(vec![ValueLabelStart { - from: RelSourceLoc::new(1), - label: ValueLabel::new(1), - }]), - ); - pos.func.dfg.values_labels.as_mut().unwrap().insert( - v1, - crate::ir::ValueLabelAssignments::Starts(vec![ValueLabelStart { - from: RelSourceLoc::new(2), - label: ValueLabel::new(1), - }]), - ); - pos.func.dfg.values_labels.as_mut().unwrap().insert( - v2, - crate::ir::ValueLabelAssignments::Starts(vec![ValueLabelStart { - from: RelSourceLoc::new(3), - label: ValueLabel::new(1), - }]), - ); - pos.func.dfg.values_labels.as_mut().unwrap().insert( - v3, - crate::ir::ValueLabelAssignments::Starts(vec![ValueLabelStart { - from: RelSourceLoc::new(4), - label: ValueLabel::new(1), - }]), - ); - pos.func.dfg.values_labels.as_mut().unwrap().insert( - v4, - crate::ir::ValueLabelAssignments::Starts(vec![ValueLabelStart { - from: RelSourceLoc::new(5), - label: ValueLabel::new(1), - }]), - ); - - let mut shared_flags_builder = settings::builder(); - shared_flags_builder.set("opt_level", "none").unwrap(); - shared_flags_builder.set("enable_verifier", "true").unwrap(); - let shared_flags = settings::Flags::new(shared_flags_builder); - let isa_flags = x64_settings::Flags::new(&shared_flags, x64_settings::builder()); - let backend = X64Backend::new_with_flags( - Triple::from_str("x86_64").unwrap(), - shared_flags, - isa_flags, - ); - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - let result = backend - .compile_function(&mut func, &domtree, /* want_disasm = */ false) - .unwrap(); - let code = result.buffer.data(); - - // To update this comment, write the golden bytes to a file, and run the following - // command on it: - // > objdump -b binary -D -m i386:x86-64 -M intel - // - // 0: 55 push rbp - // 1: 48 89 e5 mov rbp,rsp - // 4: 48 89 fe mov rsi,rdi - // 7: 81 c6 34 12 00 00 add esi,0x1234 - // d: 85 f6 test esi,esi - // f: 0f 84 21 00 00 00 je 0x36 - // 15: 49 89 f0 mov r8,rsi - // 18: 48 89 f0 mov rax,rsi - // 1b: 81 e8 34 12 00 00 sub eax,0x1234 - // 21: 44 01 c0 add eax,r8d - // 24: 85 f6 test esi,esi - // 26: 0f 85 0a 00 00 00 jne 0x36 - // 2c: 48 89 ec mov rsp,rbp - // 2f: 5d pop rbp - // 30: c3 ret - // 31: e9 e2 ff ff ff jmp 0x18 - // 36: 49 89 f0 mov r8,rsi - // 39: 41 81 c0 34 12 00 00 add r8d,0x1234 - // 40: 45 85 c0 test r8d,r8d - // 43: 0f 84 cf ff ff ff je 0x18 - // 49: e9 e8 ff ff ff jmp 0x36 - - let golden = vec![ - 85, 72, 137, 229, 72, 137, 254, 129, 198, 52, 18, 0, 0, 133, 246, 15, 132, 33, 0, 0, 0, - 73, 137, 240, 72, 137, 240, 129, 232, 52, 18, 0, 0, 68, 1, 192, 133, 246, 15, 133, 10, - 0, 0, 0, 72, 137, 236, 93, 195, 233, 226, 255, 255, 255, 73, 137, 240, 65, 129, 192, - 52, 18, 0, 0, 69, 133, 192, 15, 132, 207, 255, 255, 255, 233, 232, 255, 255, 255, - ]; - - assert_eq!(code, &golden[..]); - } // Check that feature tests for SIMD work correctly. #[test] @@ -405,105 +252,4 @@ mod test { Err(CodegenError::Unsupported(_)), )); } - - // Check that br_table lowers properly. We can't test this with an - // ordinary compile-test because the br_table pseudoinstruction - // expands during emission. - #[test] - fn br_table() { - let name = UserFuncName::testcase("test0"); - let mut sig = Signature::new(CallConv::SystemV); - sig.params.push(AbiParam::new(I32)); - sig.returns.push(AbiParam::new(I32)); - let mut func = Function::with_name_signature(name, sig); - - let bb0 = func.dfg.make_block(); - let arg0 = func.dfg.append_block_param(bb0, I32); - let bb1 = func.dfg.make_block(); - let bb2 = func.dfg.make_block(); - let bb3 = func.dfg.make_block(); - - let mut pos = FuncCursor::new(&mut func); - - pos.insert_block(bb0); - let jt_data = JumpTableData::new( - pos.func.dfg.block_call(bb3, &[]), - &[ - pos.func.dfg.block_call(bb1, &[]), - pos.func.dfg.block_call(bb2, &[]), - ], - ); - let jt = pos.func.create_jump_table(jt_data); - pos.ins().br_table(arg0, jt); - - pos.insert_block(bb1); - let v1 = pos.ins().iconst(I32, 1); - pos.ins().return_(&[v1]); - - pos.insert_block(bb2); - let v2 = pos.ins().iconst(I32, 2); - pos.ins().return_(&[v2]); - - pos.insert_block(bb3); - let v3 = pos.ins().iconst(I32, 3); - pos.ins().return_(&[v3]); - - let mut shared_flags_builder = settings::builder(); - shared_flags_builder.set("opt_level", "none").unwrap(); - shared_flags_builder.set("enable_verifier", "true").unwrap(); - let shared_flags = settings::Flags::new(shared_flags_builder); - let isa_flags = x64_settings::Flags::new(&shared_flags, x64_settings::builder()); - let backend = X64Backend::new_with_flags( - Triple::from_str("x86_64").unwrap(), - shared_flags, - isa_flags, - ); - let cfg = ControlFlowGraph::with_function(&func); - let domtree = DominatorTree::with_function(&func, &cfg); - let result = backend - .compile_function(&mut func, &domtree, /* want_disasm = */ false) - .unwrap(); - let code = result.buffer.data(); - - // To update this comment, write the golden bytes to a file, and run the following - // command on it: - // > objdump -b binary -D -m i386:x86-64 -M intel - // - // 0: 55 push rbp - // 1: 48 89 e5 mov rbp,rsp - // 4: 83 ff 02 cmp edi,0x2 - // 7: 0f 83 3b 00 00 00 jae 0x48 - // d: 44 8b d7 mov r10d,edi - // 10: 41 b9 00 00 00 00 mov r9d,0x0 - // 16: 4d 0f 43 d1 cmovae r10,r9 - // 1a: 4c 8d 0d 0b 00 00 00 lea r9,[rip+0xb] # 0x2c - // 21: 4f 63 54 91 00 movsxd r10,DWORD PTR [r9+r10*4+0x0] - // 26: 4d 01 d1 add r9,r10 - // 29: 41 ff e1 jmp r9 - // 2c: 12 00 adc al,BYTE PTR [rax] - // 2e: 00 00 add BYTE PTR [rax],al - // 30: 08 00 or BYTE PTR [rax],al - // 32: 00 00 add BYTE PTR [rax],al - // 34: b8 02 00 00 00 mov eax,0x2 - // 39: 48 89 ec mov rsp,rbp - // 3c: 5d pop rbp - // 3d: c3 ret - // 3e: b8 01 00 00 00 mov eax,0x1 - // 43: 48 89 ec mov rsp,rbp - // 46: 5d pop rbp - // 47: c3 ret - // 48: b8 03 00 00 00 mov eax,0x3 - // 4d: 48 89 ec mov rsp,rbp - // 50: 5d pop rbp - // 51: c3 ret - - let golden = vec![ - 85, 72, 137, 229, 131, 255, 2, 15, 131, 59, 0, 0, 0, 68, 139, 215, 65, 185, 0, 0, 0, 0, - 77, 15, 67, 209, 76, 141, 13, 11, 0, 0, 0, 79, 99, 84, 145, 0, 77, 1, 209, 65, 255, - 225, 18, 0, 0, 0, 8, 0, 0, 0, 184, 2, 0, 0, 0, 72, 137, 236, 93, 195, 184, 1, 0, 0, 0, - 72, 137, 236, 93, 195, 184, 3, 0, 0, 0, 72, 137, 236, 93, 195, - ]; - - assert_eq!(code, &golden[..]); - } } diff --git a/cranelift/filetests/filetests/isa/aarch64/cold-blocks.clif b/cranelift/filetests/filetests/isa/aarch64/cold-blocks.clif new file mode 100644 index 0000000000..329dd5fb0d --- /dev/null +++ b/cranelift/filetests/filetests/isa/aarch64/cold-blocks.clif @@ -0,0 +1,71 @@ +test compile precise-output + +target aarch64 + +function %no_cold_annotation(i32) -> i32 { +block0(v0: i32): + brif v0, block1(v0), block2 + +block1(v1: i32): + return v1 + +block2: + v2 = iconst.i32 97 + jump block1(v2) +} + +; VCode: +; block0: +; mov w5, w0 +; cbnz x5, label1 ; b label2 +; block1: +; b label3 +; block2: +; movz w0, #97 +; b label3 +; block3: +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; mov w5, w0 +; cbnz x5, #0xc +; block1: ; offset 0x8 +; mov w0, #0x61 +; block2: ; offset 0xc +; ret + +function %cold_annotation(i32) -> i32 { +block0(v0: i32): + brif v0, block1(v0), block2 + +block1(v1: i32): + return v1 + +block2 cold: + v2 = iconst.i32 97 + jump block1(v2) +} + +; VCode: +; block0: +; mov w5, w0 +; cbnz x5, label1 ; b label2 +; block1: +; b label3 +; block3: +; ret +; block2: +; movz w0, #97 +; b label3 +; +; Disassembled: +; block0: ; offset 0x0 +; mov w5, w0 +; cbz x5, #0xc +; block1: ; offset 0x8 +; ret +; block2: ; offset 0xc +; mov w0, #0x61 +; b #8 + diff --git a/cranelift/filetests/filetests/isa/riscv64/cold-blocks.clif b/cranelift/filetests/filetests/isa/riscv64/cold-blocks.clif new file mode 100644 index 0000000000..0b7a8cde0f --- /dev/null +++ b/cranelift/filetests/filetests/isa/riscv64/cold-blocks.clif @@ -0,0 +1,71 @@ +test compile precise-output + +target riscv64 + +function %no_cold_annotation(i32) -> i32 { +block0(v0: i32): + brif v0, block1(v0), block2 + +block1(v1: i32): + return v1 + +block2: + v2 = iconst.i32 97 + jump block1(v2) +} + +; VCode: +; block0: +; sext.w a2,a0 +; bne a2,zero,taken(label1),not_taken(label2) +; block1: +; j label3 +; block2: +; li a0,97 +; j label3 +; block3: +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; sext.w a2, a0 +; bnez a2, 8 +; block1: ; offset 0x8 +; addi a0, zero, 0x61 +; block2: ; offset 0xc +; ret + +function %cold_annotation(i32) -> i32 { +block0(v0: i32): + brif v0, block1(v0), block2 + +block1(v1: i32): + return v1 + +block2 cold: + v2 = iconst.i32 97 + jump block1(v2) +} + +; VCode: +; block0: +; sext.w a2,a0 +; bne a2,zero,taken(label1),not_taken(label2) +; block1: +; j label3 +; block3: +; ret +; block2: +; li a0,97 +; j label3 +; +; Disassembled: +; block0: ; offset 0x0 +; sext.w a2, a0 +; beqz a2, 8 +; block1: ; offset 0x8 +; ret +; block2: ; offset 0xc +; addi a0, zero, 0x61 +; j -8 + diff --git a/cranelift/filetests/filetests/isa/s390x/cold-blocks.clif b/cranelift/filetests/filetests/isa/s390x/cold-blocks.clif new file mode 100644 index 0000000000..9bb8e8ecdf --- /dev/null +++ b/cranelift/filetests/filetests/isa/s390x/cold-blocks.clif @@ -0,0 +1,71 @@ +test compile precise-output + +target s390x + +function %no_cold_annotation(i32) -> i32 { +block0(v0: i32): + brif v0, block1(v0), block2 + +block1(v1: i32): + return v1 + +block2: + v2 = iconst.i32 97 + jump block1(v2) +} + +; VCode: +; block0: +; chi %r2, 0 +; jglh label1 ; jg label2 +; block1: +; jg label3 +; block2: +; lhi %r2, 97 +; jg label3 +; block3: +; br %r14 +; +; Disassembled: +; block0: ; offset 0x0 +; chi %r2, 0 +; jglh 0xe +; block1: ; offset 0xa +; lhi %r2, 0x61 +; block2: ; offset 0xe +; br %r14 + +function %cold_annotation(i32) -> i32 { +block0(v0: i32): + brif v0, block1(v0), block2 + +block1(v1: i32): + return v1 + +block2 cold: + v2 = iconst.i32 97 + jump block1(v2) +} + +; VCode: +; block0: +; chi %r2, 0 +; jglh label1 ; jg label2 +; block1: +; jg label3 +; block3: +; br %r14 +; block2: +; lhi %r2, 97 +; jg label3 +; +; Disassembled: +; block0: ; offset 0x0 +; chi %r2, 0 +; jgnlh 0xc +; block1: ; offset 0xa +; br %r14 +; block2: ; offset 0xc +; lhi %r2, 0x61 +; jg 0xa + diff --git a/cranelift/filetests/filetests/isa/x64/cold-blocks.clif b/cranelift/filetests/filetests/isa/x64/cold-blocks.clif new file mode 100644 index 0000000000..76a5f53743 --- /dev/null +++ b/cranelift/filetests/filetests/isa/x64/cold-blocks.clif @@ -0,0 +1,96 @@ +test compile precise-output + +target x86_64 + +function %no_cold_annotation(i32) -> i32 { +block0(v0: i32): + brif v0, block1(v0), block2 + +block1(v1: i32): + return v1 + +block2: + v2 = iconst.i32 97 + jump block1(v2) +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; testl %edi, %edi +; jnz label1; j label2 +; block1: +; movq %rdi, %rax +; jmp label3 +; block2: +; movl $97, %eax +; jmp label3 +; block3: +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; testl %edi, %edi +; je 0x14 +; block2: ; offset 0xc +; movq %rdi, %rax +; jmp 0x19 +; block3: ; offset 0x14 +; movl $0x61, %eax +; block4: ; offset 0x19 +; movq %rbp, %rsp +; popq %rbp +; retq + +function %cold_annotation(i32) -> i32 { +block0(v0: i32): + brif v0, block1(v0), block2 + +block1(v1: i32): + return v1 + +block2 cold: + v2 = iconst.i32 97 + jump block1(v2) +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; testl %edi, %edi +; jnz label1; j label2 +; block1: +; movq %rdi, %rax +; jmp label3 +; block3: +; movq %rbp, %rsp +; popq %rbp +; ret +; block2: +; movl $97, %eax +; jmp label3 +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; testl %edi, %edi +; je 0x14 +; block2: ; offset 0xc +; movq %rdi, %rax +; block3: ; offset 0xf +; movq %rbp, %rsp +; popq %rbp +; retq +; block4: ; offset 0x14 +; movl $0x61, %eax +; jmp 0xf +