GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

Commit 30226d91 authored by qinsoon's avatar qinsoon

Merge remote-tracking branch 'origin/develop' into trace-scheduling

parents 0b2bb763 5a939029
......@@ -307,6 +307,8 @@ impl MuFunctionVersion {
ret
}
// TODO: It may be more efficient to compute this when the instructions
// are added to the function version and store the result in a field
pub fn has_throw(&self) -> bool {
let f_content = self.content.as_ref().unwrap();
......@@ -332,6 +334,32 @@ impl MuFunctionVersion {
false
}
pub fn has_tailcall(&self) -> bool {
let f_content = self.content.as_ref().unwrap();
for (_, block) in f_content.blocks.iter() {
let block_content = block.content.as_ref().unwrap();
for inst in block_content.body.iter() {
match inst.v {
TreeNode_::Instruction(ref inst) => {
match inst.v {
Instruction_::TailCall(_) => {return true;}
_ => {
// do nothing
}
}
},
_ => {
unreachable!()
}
}
}
}
false
}
}
/// FunctionContent contains all blocks (which include all instructions) for the function
......
......@@ -13,6 +13,7 @@
// limitations under the License.
use ast::ir::*;
use ast::ptr::P;
use runtime::ValueLocation;
use compiler::machine_code::MachineCode;
......@@ -47,10 +48,6 @@ pub trait CodeGenerator {
// emit code to adjust frame
fn emit_frame_grow(&mut self); // Emits a SUB
// Used to pass a string that the assembler will interpret as an immediate argument
// (This is neccesary to support the use of ELF relocations like ':tprel_hi12:foo')
fn emit_add_str(&mut self, dest: Reg, src1: Reg, src2: &str);
// stack minimpulation
fn emit_push_pair(&mut self, src1: Reg, src2: Reg, stack: Reg); // Emits a STP
fn emit_pop_pair(&mut self, dest1: Reg, dest2: Reg, stack: Reg); // Emits a LDP
......@@ -59,6 +56,8 @@ pub trait CodeGenerator {
fn emit_ldr_callee_saved(&mut self, dest: Reg, src: Mem);
fn emit_str_callee_saved(&mut self, dest: Mem, src: Reg);
//==================================================================================================
/* Bellow ar all ARMv8-A Aarch64 instruction menmonics (with all operand modes) except:
PRFM, PRFUM, CRC32*
All advanced SIMD instructions (except MOVI)
......@@ -102,15 +101,15 @@ pub trait CodeGenerator {
fn emit_stnp(&mut self, dest: Mem, src1: Reg/*GPR or FPR*/, src2: Reg/*GPR or FPR*/); // [base, #simm7]
// Calls
fn emit_bl(&mut self, callsite: String, func: MuName, pe: Option<MuName>, is_native: bool) -> ValueLocation;
fn emit_blr(&mut self, callsite: String, func: Reg, pe: Option<MuName>) -> ValueLocation;
fn emit_bl(&mut self, callsite: String, func: MuName, pe: Option<MuName>, args: Vec<P<Value>>, is_native: bool) -> ValueLocation;
fn emit_blr(&mut self, callsite: String, func: Reg, pe: Option<MuName>, args: Vec<P<Value>>) -> ValueLocation;
// Branches
fn emit_b(&mut self, dest_name: MuName);
fn emit_b_func(&mut self, func: MuName);
fn emit_b_func(&mut self, func: MuName, args: Vec<P<Value>>); // For tail calls
fn emit_b_cond(&mut self, cond: &str, dest_name: MuName);
fn emit_br(&mut self, dest_address: Reg);
fn emit_br_func(&mut self, func_address: Reg);
fn emit_br_func(&mut self, func_address: Reg, args: Vec<P<Value>>); // For tail calls
fn emit_ret(&mut self, src: Reg);
fn emit_cbnz(&mut self, src: Reg, dest_name: MuName);
......@@ -123,8 +122,8 @@ pub trait CodeGenerator {
fn emit_mrs(&mut self, dest: Reg, src: &str);
// Address calculation
fn emit_adr(&mut self, dest: Reg, src: Reg);
fn emit_adrp(&mut self, dest: Reg, src: Reg);
fn emit_adr(&mut self, dest: Reg, src: Mem);
fn emit_adrp(&mut self, dest: Reg, src: Mem);
// Unary ops
fn emit_mov(&mut self, dest: Reg/*GPR or SP or ZR*/, src: Reg/*GPR or SP or ZR*/); // The SP and ZR cannot both be used
......
......@@ -1746,7 +1746,7 @@ fn emit_madd_u64(backend: &mut CodeGenerator, dest: &P<Value>, src1: &P<Value>,
let shift = log2(val as u64) as u8;
// dest = src1 << log2(val) + src2
if shift <= 4 {
backend.emit_add_ext(&dest, &dest, &src2, false, shift);
backend.emit_add_ext(&dest, &src2, &src1, false, shift);
} else {
backend.emit_lsl_imm(&dest, &src1, shift);
backend.emit_add(&dest, &dest, &src2);
......@@ -2012,6 +2012,7 @@ fn split_int128(int128: &P<Value>, f_context: &mut FunctionContext, vm: &VM) ->
f_context.get_value_mut(int128.id()).unwrap().set_split(vec![arg_l.clone(), arg_h.clone()]);
trace!("ISAAC <- make temporary ({}, {})", &arg_l, &arg_h);
(arg_l, arg_h)
}
}
......@@ -2030,6 +2031,7 @@ pub fn emit_ireg_ex_value(backend: &mut CodeGenerator, pv: &P<Value>, f_context:
emit_mov_u64(backend, &tmp_l, val[0]);
emit_mov_u64(backend, &tmp_h, val[1]);
trace!("ISAAC <- ({}, {}) = ({}, {})", &tmp_l, &tmp_h, val[0], val[1]);
(tmp_l, tmp_h)
},
_ => panic!("expected ireg_ex")
......
......@@ -362,8 +362,13 @@ pub fn build_interference_graph_chaitin_briggs(cf: &mut CompiledFunction, func:
};
trace_if!(TRACE_LIVENESS, "Block{}: Inst{}: src={:?}", block, i, src);
let defines = cf.mc().get_inst_reg_defines(i);
for d in defines.iter() {
current_live.insert(*d);
}
// for every definition D in I
for d in cf.mc().get_inst_reg_defines(i) {
for d in defines {
trace_if!(TRACE_LIVENESS, "Block{}: Inst{}: for definition {}",
block, i, func.context.get_temp_display(d));
// add an interference from D to every element E in Current_Live - {D}
......
......@@ -125,12 +125,13 @@ impl Inlining {
let n_insts = estimate_insts(&fv);
let out_calls = fv.get_static_call_edges();
let has_throw = fv.has_throw();
let has_tailcall = fv.has_tailcall();
// simple heuristic here:
// * estimated machine insts are fewer than 10 insts
// * leaf in call graph (no out calls)
// * no throw (otherwise we will need to rearrange catch)
let should_inline = n_insts <= 25 && out_calls.len() == 0 && !has_throw;
let should_inline = n_insts <= 25 && out_calls.len() == 0 && !has_throw && !has_tailcall;
trace!("func {} has {} insts (estimated)", callee, n_insts);
trace!(" has {} out calls", out_calls.len());
......
# Copyright 2017 The Australian National University
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
......@@ -25,7 +25,9 @@ proj_dir = py.path.local(MU_ZEBU) if MU_ZEBU else py.path.local(__file__).join('
test_jit_dir = proj_dir.join('tests', 'test_jit')
testsuite_dir = test_jit_dir.join('suite')
# testsuite_dir = py.path.local('/Users/johnz/Documents/Work/mu-client-pypy/rpython/translator/mu/test_impl')
bin_dir = py.path.local('/tmp')
bin_dir = py.path.local('emit') # put everything under emit
if not bin_dir.exists():
bin_dir.mkdir()
if sys.platform.startswith('darwin'):
libext = '.dylib'
......
......@@ -78,16 +78,16 @@ def test_add():
def test_except_stack_args():
compile_bundle(
"""
.funcsig stack_sig = (int<64> int<64> int<64> int<64> int<64> int<64> int<64>)->()
.funcsig stack_sig = (int<64> int<64> int<64> int<64> int<64> int<64> int<64> int<64> int<64>)->()
.funcdef stack_args <stack_sig>
{
entry(<int<64>> v0 <int<64>> v1 <int<64>> v2 <int<64>> v3 <int<64>> v4 <int<64>> v5 <int<64>> v6):
entry(<int<64>> v0 <int<64>> v1 <int<64>> v2 <int<64>> v3 <int<64>> v4 <int<64>> v5 <int<64>> v6 <int<64>> v7 <int<64>> v8):
THROW <ref<void>> NULL
}
.funcdef test_except_stack_args <main_sig>
{
entry(<int<32>>argc <uptr<uptr<char>>>argv):
CALL <stack_sig> stack_args(<int<32>>0 <int<32>>1 <int<32>>2 <int<32>>3 <int<32>>4 <int<32>>5 <int<32>>6)
CALL <stack_sig> stack_args(<int<32>>0 <int<32>>1 <int<32>>2 <int<32>>3 <int<32>>4 <int<32>>5 <int<32>>6 <int<32>>7 <int<32>>8)
EXC (exit(<int<32>> 0) exit(<int<32>> 1))
exit(<int<32>> status):
......@@ -95,4 +95,16 @@ def test_except_stack_args():
}
""",
"test_except_stack_args");
assert(execute("test_except_stack_args") == 1);
\ No newline at end of file
assert(execute("test_except_stack_args") == 1);
def test_ldp_bug():
compile_bundle(
"""
.funcdef foo <(int<128> int<128> int<128> int<128> int<128> int<128>)->(int<128>)>
{
entry(<int<128>>a0 <int<128>>a1 <int<128>>a2 <int<128>>a3 <int<128>>a4 <int<128>>a5):
RET a5
}
""", "test_taillcall_smaller_stack");
assert(execute("test_taillcall_smaller_stack") == 12);
\ No newline at end of file
# Copyright 2017 The Australian National University
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from util import execute, compile_bundle, load_bundle, get_function;
import pytest;
import ctypes;
def test_taillcall_simple():
compile_bundle(
"""
.funcdef test_taillcall_simple <main_sig>
{
entry(<int<32>>argc <uptr<uptr<char>>>argv):
TAILCALL <main_sig>taillcallee(argc argv)
}
.funcdef taillcallee <main_sig>
{
entry(<int<32>>argc <uptr<uptr<char>>>argv):
RET argc
}
""", "test_taillcall_simple");
assert(execute("test_taillcall_simple", ["2", "3", "4"]) == 4);
#TODO: WHy does returning a pair of int<128>'s fail?
def test_taillcall_smaller_stack():
compile_bundle(
"""
.funcsig big_sig = (int<128> int<128> int<128> int<128> int<128> int<128>)->(int<128>)
.funcsig small_sig = (int<128> int<128> int<128> int<128> int<128>) ->(int<128>)
.funcdef test_taillcall_smaller_stack <main_sig>
{
entry(<int<32>>argc <uptr<uptr<char>>>argv):
res_128 = CALL <big_sig> bigger_stack(<int<128>>0 <int<128>>1 <int<128>>2 <int<128>>3 <int<128>>4 <int<128>>5)
res = TRUNC <int<128> int<32>> res_128
RET res
}
.funcdef bigger_stack <big_sig>
{
entry(<int<128>>a0 <int<128>>a1 <int<128>>a2 <int<128>>a3 <int<128>>a4 <int<128>>a5):
TAILCALL <small_sig> smaller_stack(a0 a1 a2 a3 a4)
}
.funcdef smaller_stack <small_sig>
{
entry(<int<128>>a0 <int<128>>a1 <int<128>>a2 <int<128>>a3 <int<128>>a4):
res_01 = ADD<int<128>> a0 a1
res_013 = ADD<int<128>> res_01 a3
res_24 = MUL<int<128>> a2 a4
res_013_24 = ADD<int<128>> res_013 res_24
RET res_013_24
}
""", "test_taillcall_smaller_stack");
assert(execute("test_taillcall_smaller_stack") == 12);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment