Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
6ea208d0
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
6ea208d0
编写于
4月 16, 2013
作者:
N
neliasso
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
70f344ea
e5a807c0
变更
21
展开全部
隐藏空白更改
内联
并排
Showing
21 changed file
with
734 addition
and
772 deletion
+734
-772
make/bsd/makefiles/vm.make
make/bsd/makefiles/vm.make
+1
-1
make/linux/makefiles/vm.make
make/linux/makefiles/vm.make
+1
-1
make/solaris/makefiles/vm.make
make/solaris/makefiles/vm.make
+1
-1
make/windows/create_obj_files.sh
make/windows/create_obj_files.sh
+1
-1
src/os/bsd/vm/chaitin_bsd.cpp
src/os/bsd/vm/chaitin_bsd.cpp
+0
-42
src/os/linux/vm/chaitin_linux.cpp
src/os/linux/vm/chaitin_linux.cpp
+0
-42
src/os/solaris/vm/chaitin_solaris.cpp
src/os/solaris/vm/chaitin_solaris.cpp
+0
-46
src/os/windows/vm/chaitin_windows.cpp
src/os/windows/vm/chaitin_windows.cpp
+0
-78
src/share/vm/opto/chaitin.cpp
src/share/vm/opto/chaitin.cpp
+311
-137
src/share/vm/opto/chaitin.hpp
src/share/vm/opto/chaitin.hpp
+141
-46
src/share/vm/opto/coalesce.cpp
src/share/vm/opto/coalesce.cpp
+96
-225
src/share/vm/opto/coalesce.hpp
src/share/vm/opto/coalesce.hpp
+8
-6
src/share/vm/opto/compile.cpp
src/share/vm/opto/compile.cpp
+4
-10
src/share/vm/opto/idealGraphPrinter.cpp
src/share/vm/opto/idealGraphPrinter.cpp
+1
-1
src/share/vm/opto/ifg.cpp
src/share/vm/opto/ifg.cpp
+41
-33
src/share/vm/opto/live.cpp
src/share/vm/opto/live.cpp
+1
-1
src/share/vm/opto/live.hpp
src/share/vm/opto/live.hpp
+2
-2
src/share/vm/opto/postaloc.cpp
src/share/vm/opto/postaloc.cpp
+26
-19
src/share/vm/opto/reg_split.cpp
src/share/vm/opto/reg_split.cpp
+98
-69
src/share/vm/opto/regalloc.hpp
src/share/vm/opto/regalloc.hpp
+1
-10
src/share/vm/runtime/vmStructs.cpp
src/share/vm/runtime/vmStructs.cpp
+0
-1
未找到文件。
make/bsd/makefiles/vm.make
浏览文件 @
6ea208d0
...
...
@@ -187,7 +187,7 @@ Src_Dirs/ZERO := $(CORE_PATHS)
Src_Dirs/SHARK
:
= $(CORE_PATHS) $(SHARK_PATHS)
Src_Dirs
:=
$
(
Src_Dirs/
$(TYPE)
)
COMPILER2_SPECIFIC_FILES
:=
opto libadt bcEscapeAnalyzer.cpp c
haitin
\*
c
2_
\*
runtime_
\*
COMPILER2_SPECIFIC_FILES
:=
opto libadt bcEscapeAnalyzer.cpp c2_
\*
runtime_
\*
COMPILER1_SPECIFIC_FILES
:=
c1_
\*
SHARK_SPECIFIC_FILES
:=
shark
ZERO_SPECIFIC_FILES
:=
zero
...
...
make/linux/makefiles/vm.make
浏览文件 @
6ea208d0
...
...
@@ -189,7 +189,7 @@ Src_Dirs/ZERO := $(CORE_PATHS)
Src_Dirs/SHARK
:
= $(CORE_PATHS) $(SHARK_PATHS)
Src_Dirs
:=
$
(
Src_Dirs/
$(TYPE)
)
COMPILER2_SPECIFIC_FILES
:=
opto libadt bcEscapeAnalyzer.cpp c
haitin
\*
c
2_
\*
runtime_
\*
COMPILER2_SPECIFIC_FILES
:=
opto libadt bcEscapeAnalyzer.cpp c2_
\*
runtime_
\*
COMPILER1_SPECIFIC_FILES
:=
c1_
\*
SHARK_SPECIFIC_FILES
:=
shark
ZERO_SPECIFIC_FILES
:=
zero
...
...
make/solaris/makefiles/vm.make
浏览文件 @
6ea208d0
...
...
@@ -202,7 +202,7 @@ Src_Dirs/ZERO := $(CORE_PATHS)
Src_Dirs/SHARK
:
= $(CORE_PATHS)
Src_Dirs
:=
$
(
Src_Dirs/
$(TYPE)
)
COMPILER2_SPECIFIC_FILES
:=
opto libadt bcEscapeAnalyzer.cpp c
haitin
\*
c
2_
\*
runtime_
\*
COMPILER2_SPECIFIC_FILES
:=
opto libadt bcEscapeAnalyzer.cpp c2_
\*
runtime_
\*
COMPILER1_SPECIFIC_FILES
:=
c1_
\*
SHARK_SPECIFIC_FILES
:=
shark
ZERO_SPECIFIC_FILES
:=
zero
...
...
make/windows/create_obj_files.sh
浏览文件 @
6ea208d0
...
...
@@ -114,7 +114,7 @@ case "${TYPE}" in
"shark"
)
Src_Dirs
=
"
${
CORE_PATHS
}
"
;;
esac
COMPILER2_SPECIFIC_FILES
=
"opto libadt bcEscapeAnalyzer.cpp c
haitin* c
2_* runtime_*"
COMPILER2_SPECIFIC_FILES
=
"opto libadt bcEscapeAnalyzer.cpp c2_* runtime_*"
COMPILER1_SPECIFIC_FILES
=
"c1_*"
SHARK_SPECIFIC_FILES
=
"shark"
ZERO_SPECIFIC_FILES
=
"zero"
...
...
src/os/bsd/vm/chaitin_bsd.cpp
已删除
100644 → 0
浏览文件 @
70f344ea
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
void
PhaseRegAlloc
::
pd_preallocate_hook
()
{
// no action
}
#ifdef ASSERT
void
PhaseRegAlloc
::
pd_postallocate_verify_hook
()
{
// no action
}
#endif
// Reconciliation History
// chaitin_solaris.cpp 1.7 99/07/12 23:54:22
// End
src/os/linux/vm/chaitin_linux.cpp
已删除
100644 → 0
浏览文件 @
70f344ea
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
void
PhaseRegAlloc
::
pd_preallocate_hook
()
{
// no action
}
#ifdef ASSERT
void
PhaseRegAlloc
::
pd_postallocate_verify_hook
()
{
// no action
}
#endif
// Reconciliation History
// chaitin_solaris.cpp 1.7 99/07/12 23:54:22
// End
src/os/solaris/vm/chaitin_solaris.cpp
已删除
100644 → 0
浏览文件 @
70f344ea
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
void
PhaseRegAlloc
::
pd_preallocate_hook
()
{
// no action
}
#ifdef ASSERT
void
PhaseRegAlloc
::
pd_postallocate_verify_hook
()
{
// no action
}
#endif
//Reconciliation History
// 1.1 99/02/12 15:35:26 chaitin_win32.cpp
// 1.2 99/02/18 15:38:56 chaitin_win32.cpp
// 1.4 99/03/09 10:37:48 chaitin_win32.cpp
// 1.6 99/03/25 11:07:44 chaitin_win32.cpp
// 1.8 99/06/22 16:38:58 chaitin_win32.cpp
//End
src/os/windows/vm/chaitin_windows.cpp
已删除
100644 → 0
浏览文件 @
70f344ea
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
// Disallow the use of the frame pointer (EBP) for implicit null exceptions
// on win95/98. If we do not do this, the OS gets confused and gives a stack
// error.
void
PhaseRegAlloc
::
pd_preallocate_hook
()
{
#ifndef _WIN64
if
(
ImplicitNullChecks
&&
!
os
::
win32
::
is_nt
())
{
for
(
uint
block_num
=
1
;
block_num
<
_cfg
.
_num_blocks
;
block_num
++
)
{
Block
*
block
=
_cfg
.
_blocks
[
block_num
];
Node
*
block_end
=
block
->
end
();
if
(
block_end
->
is_MachNullCheck
()
&&
block_end
->
as_Mach
()
->
ideal_Opcode
()
!=
Op_Con
)
{
// The last instruction in the block is an implicit null check.
// Fix its input so that it does not load into the frame pointer.
_matcher
.
pd_implicit_null_fixup
(
block_end
->
in
(
1
)
->
as_Mach
(),
block_end
->
as_MachNullCheck
()
->
_vidx
);
}
}
}
#else
// WIN64==itanium on XP
#endif
}
#ifdef ASSERT
// Verify that no implicit null check uses the frame pointer (EBP) as
// its register on win95/98. Use of the frame pointer in an implicit
// null check confuses the OS, yielding a stack error.
void
PhaseRegAlloc
::
pd_postallocate_verify_hook
()
{
#ifndef _WIN64
if
(
ImplicitNullChecks
&&
!
os
::
win32
::
is_nt
())
{
for
(
uint
block_num
=
1
;
block_num
<
_cfg
.
_num_blocks
;
block_num
++
)
{
Block
*
block
=
_cfg
.
_blocks
[
block_num
];
Node
*
block_end
=
block
->
_nodes
[
block
->
_nodes
.
size
()
-
1
];
if
(
block_end
->
is_MachNullCheck
()
&&
block_end
->
as_Mach
()
->
ideal_Opcode
()
!=
Op_Con
)
{
// The last instruction in the block is an implicit
// null check. Verify that this instruction does not
// use the frame pointer.
int
reg
=
get_reg_first
(
block_end
->
in
(
1
)
->
in
(
block_end
->
as_MachNullCheck
()
->
_vidx
));
assert
(
reg
!=
EBP_num
,
"implicit null check using frame pointer on win95/98"
);
}
}
}
#else
// WIN64==itanium on XP
#endif
}
#endif
src/share/vm/opto/chaitin.cpp
浏览文件 @
6ea208d0
此差异已折叠。
点击以展开。
src/share/vm/opto/chaitin.hpp
浏览文件 @
6ea208d0
...
...
@@ -265,18 +265,118 @@ public:
int
effective_degree
(
uint
lidx
)
const
;
};
// TEMPORARILY REPLACED WITH COMMAND LINE FLAG
//// !!!!! Magic Constants need to move into ad file
#ifdef SPARC
//#define FLOAT_PRESSURE 30 /* SFLT_REG_mask.Size() - 1 */
//#define INT_PRESSURE 23 /* NOTEMP_I_REG_mask.Size() - 1 */
#define FLOAT_INCREMENT(regs) regs
#else
//#define FLOAT_PRESSURE 6
//#define INT_PRESSURE 6
#define FLOAT_INCREMENT(regs) 1
#endif
// The LiveRangeMap class is responsible for storing node to live range id mapping.
// Each node is mapped to a live range id (a virtual register). Nodes that are
// not considered for register allocation are given live range id 0.
class
LiveRangeMap
VALUE_OBJ_CLASS_SPEC
{
private:
uint
_max_lrg_id
;
// Union-find map. Declared as a short for speed.
// Indexed by live-range number, it returns the compacted live-range number
LRG_List
_uf_map
;
// Map from Nodes to live ranges
LRG_List
_names
;
// Straight out of Tarjan's union-find algorithm
uint
find_compress
(
const
Node
*
node
)
{
uint
lrg_id
=
find_compress
(
_names
[
node
->
_idx
]);
_names
.
map
(
node
->
_idx
,
lrg_id
);
return
lrg_id
;
}
uint
find_compress
(
uint
lrg
);
public:
const
LRG_List
&
names
()
{
return
_names
;
}
uint
max_lrg_id
()
const
{
return
_max_lrg_id
;
}
void
set_max_lrg_id
(
uint
max_lrg_id
)
{
_max_lrg_id
=
max_lrg_id
;
}
uint
size
()
const
{
return
_names
.
Size
();
}
uint
live_range_id
(
uint
idx
)
const
{
return
_names
[
idx
];
}
uint
live_range_id
(
const
Node
*
node
)
const
{
return
_names
[
node
->
_idx
];
}
uint
uf_live_range_id
(
uint
lrg_id
)
const
{
return
_uf_map
[
lrg_id
];
}
void
map
(
uint
idx
,
uint
lrg_id
)
{
_names
.
map
(
idx
,
lrg_id
);
}
void
uf_map
(
uint
dst_lrg_id
,
uint
src_lrg_id
)
{
_uf_map
.
map
(
dst_lrg_id
,
src_lrg_id
);
}
void
extend
(
uint
idx
,
uint
lrg_id
)
{
_names
.
extend
(
idx
,
lrg_id
);
}
void
uf_extend
(
uint
dst_lrg_id
,
uint
src_lrg_id
)
{
_uf_map
.
extend
(
dst_lrg_id
,
src_lrg_id
);
}
LiveRangeMap
(
uint
unique
)
:
_names
(
unique
)
,
_uf_map
(
unique
)
,
_max_lrg_id
(
0
)
{}
uint
find_id
(
const
Node
*
n
)
{
uint
retval
=
live_range_id
(
n
);
assert
(
retval
==
find
(
n
),
"Invalid node to lidx mapping"
);
return
retval
;
}
// Reset the Union-Find map to identity
void
reset_uf_map
(
uint
max_lrg_id
);
// Make all Nodes map directly to their final live range; no need for
// the Union-Find mapping after this call.
void
compress_uf_map_for_nodes
();
uint
find
(
uint
lidx
)
{
uint
uf_lidx
=
_uf_map
[
lidx
];
return
(
uf_lidx
==
lidx
)
?
uf_lidx
:
find_compress
(
lidx
);
}
// Convert a Node into a Live Range Index - a lidx
uint
find
(
const
Node
*
node
)
{
uint
lidx
=
live_range_id
(
node
);
uint
uf_lidx
=
_uf_map
[
lidx
];
return
(
uf_lidx
==
lidx
)
?
uf_lidx
:
find_compress
(
node
);
}
// Like Find above, but no path compress, so bad asymptotic behavior
uint
find_const
(
uint
lrg
)
const
;
// Like Find above, but no path compress, so bad asymptotic behavior
uint
find_const
(
const
Node
*
node
)
const
{
if
(
node
->
_idx
>=
_names
.
Size
())
{
return
0
;
// not mapped, usual for debug dump
}
return
find_const
(
_names
[
node
->
_idx
]);
}
};
//------------------------------Chaitin----------------------------------------
// Briggs-Chaitin style allocation, mostly.
...
...
@@ -286,7 +386,6 @@ class PhaseChaitin : public PhaseRegAlloc {
int
_trip_cnt
;
int
_alternate
;
uint
_maxlrg
;
// Max live range number
LRG
&
lrgs
(
uint
idx
)
const
{
return
_ifg
->
lrgs
(
idx
);
}
PhaseLive
*
_live
;
// Liveness, used in the interference graph
PhaseIFG
*
_ifg
;
// Interference graph (for original chunk)
...
...
@@ -294,16 +393,6 @@ class PhaseChaitin : public PhaseRegAlloc {
VectorSet
_spilled_once
;
// Nodes that have been spilled
VectorSet
_spilled_twice
;
// Nodes that have been spilled twice
LRG_List
_names
;
// Map from Nodes to Live RanGes
// Union-find map. Declared as a short for speed.
// Indexed by live-range number, it returns the compacted live-range number
LRG_List
_uf_map
;
// Reset the Union-Find map to identity
void
reset_uf_map
(
uint
maxlrg
);
// Remove the need for the Union-Find mapping
void
compress_uf_map_for_nodes
(
);
// Combine the Live Range Indices for these 2 Nodes into a single live
// range. Future requests for any Node in either live range will
// return the live range index for the combined live range.
...
...
@@ -322,7 +411,34 @@ class PhaseChaitin : public PhaseRegAlloc {
// Helper functions for Split()
uint
split_DEF
(
Node
*
def
,
Block
*
b
,
int
loc
,
uint
max
,
Node
**
Reachblock
,
Node
**
debug_defs
,
GrowableArray
<
uint
>
splits
,
int
slidx
);
uint
split_USE
(
Node
*
def
,
Block
*
b
,
Node
*
use
,
uint
useidx
,
uint
max
,
bool
def_down
,
bool
cisc_sp
,
GrowableArray
<
uint
>
splits
,
int
slidx
);
int
clone_projs
(
Block
*
b
,
uint
idx
,
Node
*
con
,
Node
*
copy
,
uint
&
maxlrg
);
bool
clone_projs
(
Block
*
b
,
uint
idx
,
Node
*
con
,
Node
*
copy
,
LiveRangeMap
&
lrg_map
)
{
bool
found_projs
=
clone_projs_shared
(
b
,
idx
,
con
,
copy
,
lrg_map
.
max_lrg_id
());
if
(
found_projs
)
{
uint
max_lrg_id
=
lrg_map
.
max_lrg_id
();
lrg_map
.
set_max_lrg_id
(
max_lrg_id
+
1
);
}
return
found_projs
;
}
//------------------------------clone_projs------------------------------------
// After cloning some rematerialized instruction, clone any MachProj's that
// follow it. Example: Intel zero is XOR, kills flags. Sparc FP constants
// use G3 as an address temp.
bool
clone_projs
(
Block
*
b
,
uint
idx
,
Node
*
con
,
Node
*
copy
,
uint
&
max_lrg_id
)
{
bool
found_projs
=
clone_projs_shared
(
b
,
idx
,
con
,
copy
,
max_lrg_id
);
if
(
found_projs
)
{
max_lrg_id
++
;
}
return
found_projs
;
}
bool
clone_projs_shared
(
Block
*
b
,
uint
idx
,
Node
*
con
,
Node
*
copy
,
uint
max_lrg_id
);
Node
*
split_Rematerialize
(
Node
*
def
,
Block
*
b
,
uint
insidx
,
uint
&
maxlrg
,
GrowableArray
<
uint
>
splits
,
int
slidx
,
uint
*
lrg2reach
,
Node
**
Reachblock
,
bool
walkThru
);
// True if lidx is used before any real register is def'd in the block
...
...
@@ -349,20 +465,11 @@ public:
PhaseChaitin
(
uint
unique
,
PhaseCFG
&
cfg
,
Matcher
&
matcher
);
~
PhaseChaitin
()
{}
// Convert a Node into a Live Range Index - a lidx
uint
Find
(
const
Node
*
n
)
{
uint
lidx
=
n2lidx
(
n
);
uint
uf_lidx
=
_uf_map
[
lidx
];
return
(
uf_lidx
==
lidx
)
?
uf_lidx
:
Find_compress
(
n
);
}
uint
Find_const
(
uint
lrg
)
const
;
uint
Find_const
(
const
Node
*
n
)
const
;
LiveRangeMap
_lrg_map
;
// Do all the real work of allocate
void
Register_Allocate
();
uint
n2lidx
(
const
Node
*
n
)
const
{
return
_names
[
n
->
_idx
];
}
float
high_frequency_lrg
()
const
{
return
_high_frequency_lrg
;
}
#ifndef PRODUCT
...
...
@@ -374,18 +481,6 @@ private:
// all inputs to a PhiNode, effectively coalescing live ranges. Insert
// copies as needed.
void
de_ssa
();
uint
Find_compress
(
const
Node
*
n
);
uint
Find
(
uint
lidx
)
{
uint
uf_lidx
=
_uf_map
[
lidx
];
return
(
uf_lidx
==
lidx
)
?
uf_lidx
:
Find_compress
(
lidx
);
}
uint
Find_compress
(
uint
lidx
);
uint
Find_id
(
const
Node
*
n
)
{
uint
retval
=
n2lidx
(
n
);
assert
(
retval
==
Find
(
n
),
"Invalid node to lidx mapping"
);
return
retval
;
}
// Add edge between reg and everything in the vector.
// Same as _ifg->add_vector(reg,live) EXCEPT use the RegMask
...
...
src/share/vm/opto/coalesce.cpp
浏览文件 @
6ea208d0
此差异已折叠。
点击以展开。
src/share/vm/opto/coalesce.hpp
浏览文件 @
6ea208d0
...
...
@@ -41,23 +41,25 @@ protected:
public:
// Coalesce copies
PhaseCoalesce
(
PhaseChaitin
&
chaitin
)
:
Phase
(
Coalesce
),
_phc
(
chaitin
)
{
}
PhaseCoalesce
(
PhaseChaitin
&
phc
)
:
Phase
(
Coalesce
)
,
_phc
(
phc
)
{}
virtual
void
verify
()
=
0
;
// Coalesce copies
void
coalesce_driver
(
);
void
coalesce_driver
();
// Coalesce copies in this block
virtual
void
coalesce
(
Block
*
b
)
=
0
;
virtual
void
coalesce
(
Block
*
b
)
=
0
;
// Attempt to coalesce live ranges defined by these 2
void
combine_these_two
(
Node
*
n1
,
Node
*
n2
);
void
combine_these_two
(
Node
*
n1
,
Node
*
n2
);
LRG
&
lrgs
(
uint
lidx
)
{
return
_phc
.
lrgs
(
lidx
);
}
LRG
&
lrgs
(
uint
lidx
)
{
return
_phc
.
lrgs
(
lidx
);
}
#ifndef PRODUCT
// Dump internally name
void
dump
(
Node
*
n
)
const
;
void
dump
(
Node
*
n
)
const
;
// Dump whole shebang
void
dump
()
const
;
#endif
...
...
src/share/vm/opto/compile.cpp
浏览文件 @
6ea208d0
...
...
@@ -2127,22 +2127,19 @@ void Compile::Code_Gen() {
}
NOT_PRODUCT
(
verify_graph_edges
();
)
PhaseChaitin
regalloc
(
unique
(),
cfg
,
m
);
PhaseChaitin
regalloc
(
unique
(),
cfg
,
m
);
_regalloc
=
&
regalloc
;
{
TracePhase
t2
(
"regalloc"
,
&
_t_registerAllocation
,
true
);
// Perform any platform dependent preallocation actions. This is used,
// for example, to avoid taking an implicit null pointer exception
// using the frame pointer on win95.
_regalloc
->
pd_preallocate_hook
();
// Perform register allocation. After Chaitin, use-def chains are
// no longer accurate (at spill code) and so must be ignored.
// Node->LRG->reg mappings are still accurate.
_regalloc
->
Register_Allocate
();
// Bail out if the allocator builds too many nodes
if
(
failing
())
return
;
if
(
failing
())
{
return
;
}
}
// Prior to register allocation we kept empty basic blocks in case the
...
...
@@ -2160,9 +2157,6 @@ void Compile::Code_Gen() {
cfg
.
fixup_flow
();
}
// Perform any platform dependent postallocation verifications.
debug_only
(
_regalloc
->
pd_postallocate_verify_hook
();
)
// Apply peephole optimizations
if
(
OptoPeephole
)
{
NOT_PRODUCT
(
TracePhase
t2
(
"peephole"
,
&
_t_peephole
,
TimeCompiler
);
)
...
...
src/share/vm/opto/idealGraphPrinter.cpp
浏览文件 @
6ea208d0
...
...
@@ -616,7 +616,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
buffer
[
0
]
=
0
;
_chaitin
->
dump_register
(
node
,
buffer
);
print_prop
(
"reg"
,
buffer
);
print_prop
(
"lrg"
,
_chaitin
->
n2lidx
(
node
));
print_prop
(
"lrg"
,
_chaitin
->
_lrg_map
.
live_range_id
(
node
));
}
node
->
_in_dump_cnt
--
;
...
...
src/share/vm/opto/ifg.cpp
浏览文件 @
6ea208d0
...
...
@@ -286,15 +286,14 @@ void PhaseIFG::verify( const PhaseChaitin *pc ) const {
uint
idx
;
uint
last
=
0
;
while
((
idx
=
elements
.
next
())
!=
0
)
{
assert
(
idx
!=
i
,
"Must have empty diagonal"
);
assert
(
pc
->
Find_const
(
idx
)
==
idx
,
"Must not need Find"
);
assert
(
_adjs
[
idx
].
member
(
i
),
"IFG not square"
);
assert
(
!
(
*
_yanked
)[
idx
],
"No yanked neighbors"
);
assert
(
last
<
idx
,
"not sorted increasing"
);
assert
(
idx
!=
i
,
"Must have empty diagonal"
);
assert
(
pc
->
_lrg_map
.
find_const
(
idx
)
==
idx
,
"Must not need Find"
);
assert
(
_adjs
[
idx
].
member
(
i
),
"IFG not square"
);
assert
(
!
(
*
_yanked
)[
idx
],
"No yanked neighbors"
);
assert
(
last
<
idx
,
"not sorted increasing"
);
last
=
idx
;
}
assert
(
!
lrgs
(
i
).
_degree_valid
||
effective_degree
(
i
)
==
lrgs
(
i
).
degree
(),
"degree is valid but wrong"
);
assert
(
!
lrgs
(
i
).
_degree_valid
||
effective_degree
(
i
)
==
lrgs
(
i
).
degree
(),
"degree is valid but wrong"
);
}
}
#endif
...
...
@@ -342,10 +341,10 @@ void PhaseChaitin::build_ifg_virtual( ) {
Node
*
n
=
b
->
_nodes
[
j
-
1
];
// Get value being defined
uint
r
=
n2lidx
(
n
);
uint
r
=
_lrg_map
.
live_range_id
(
n
);
// Some special values do not allocate
if
(
r
)
{
if
(
r
)
{
// Remove from live-out set
liveout
->
remove
(
r
);
...
...
@@ -353,16 +352,19 @@ void PhaseChaitin::build_ifg_virtual( ) {
// Copies do not define a new value and so do not interfere.
// Remove the copies source from the liveout set before interfering.
uint
idx
=
n
->
is_Copy
();
if
(
idx
)
liveout
->
remove
(
n2lidx
(
n
->
in
(
idx
))
);
if
(
idx
)
{
liveout
->
remove
(
_lrg_map
.
live_range_id
(
n
->
in
(
idx
)));
}
// Interfere with everything live
interfere_with_live
(
r
,
liveout
);
interfere_with_live
(
r
,
liveout
);
}
// Make all inputs live
if
(
!
n
->
is_Phi
()
)
{
// Phi function uses come from prior block
for
(
uint
k
=
1
;
k
<
n
->
req
();
k
++
)
liveout
->
insert
(
n2lidx
(
n
->
in
(
k
))
);
if
(
!
n
->
is_Phi
())
{
// Phi function uses come from prior block
for
(
uint
k
=
1
;
k
<
n
->
req
();
k
++
)
{
liveout
->
insert
(
_lrg_map
.
live_range_id
(
n
->
in
(
k
)));
}
}
// 2-address instructions always have the defined value live
...
...
@@ -394,11 +396,12 @@ void PhaseChaitin::build_ifg_virtual( ) {
n
->
set_req
(
2
,
tmp
);
}
// Defined value interferes with all inputs
uint
lidx
=
n2lidx
(
n
->
in
(
idx
));
for
(
uint
k
=
1
;
k
<
n
->
req
();
k
++
)
{
uint
kidx
=
n2lidx
(
n
->
in
(
k
));
if
(
kidx
!=
lidx
)
_ifg
->
add_edge
(
r
,
kidx
);
uint
lidx
=
_lrg_map
.
live_range_id
(
n
->
in
(
idx
));
for
(
uint
k
=
1
;
k
<
n
->
req
();
k
++
)
{
uint
kidx
=
_lrg_map
.
live_range_id
(
n
->
in
(
k
));
if
(
kidx
!=
lidx
)
{
_ifg
->
add_edge
(
r
,
kidx
);
}
}
}
}
// End of forall instructions in block
...
...
@@ -542,10 +545,10 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
Node
*
n
=
b
->
_nodes
[
j
-
1
];
// Get value being defined
uint
r
=
n2lidx
(
n
);
uint
r
=
_lrg_map
.
live_range_id
(
n
);
// Some special values do not allocate
if
(
r
)
{
if
(
r
)
{
// A DEF normally costs block frequency; rematerialized values are
// removed from the DEF sight, so LOWER costs here.
lrgs
(
r
).
_cost
+=
n
->
rematerialize
()
?
0
:
b
->
_freq
;
...
...
@@ -556,9 +559,11 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
Node
*
def
=
n
->
in
(
0
);
if
(
!
n
->
is_Proj
()
||
// Could also be a flags-projection of a dead ADD or such.
(
n2lidx
(
def
)
&&
!
liveout
.
member
(
n2lidx
(
def
))
)
)
{
(
_lrg_map
.
live_range_id
(
def
)
&&
!
liveout
.
member
(
_lrg_map
.
live_range_id
(
def
)))
)
{
b
->
_nodes
.
remove
(
j
-
1
);
if
(
lrgs
(
r
).
_def
==
n
)
lrgs
(
r
).
_def
=
0
;
if
(
lrgs
(
r
).
_def
==
n
)
{
lrgs
(
r
).
_def
=
0
;
}
n
->
disconnect_inputs
(
NULL
,
C
);
_cfg
.
_bbs
.
map
(
n
->
_idx
,
NULL
);
n
->
replace_by
(
C
->
top
());
...
...
@@ -570,7 +575,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
// Fat-projections kill many registers which cannot be used to
// hold live ranges.
if
(
lrgs
(
r
).
_fat_proj
)
{
if
(
lrgs
(
r
).
_fat_proj
)
{
// Count the int-only registers
RegMask
itmp
=
lrgs
(
r
).
mask
();
itmp
.
AND
(
*
Matcher
::
idealreg2regmask
[
Op_RegI
]);
...
...
@@ -636,12 +641,12 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
// Copies do not define a new value and so do not interfere.
// Remove the copies source from the liveout set before interfering.
uint
idx
=
n
->
is_Copy
();
if
(
idx
)
{
uint
x
=
n2lidx
(
n
->
in
(
idx
));
if
(
liveout
.
remove
(
x
)
)
{
if
(
idx
)
{
uint
x
=
_lrg_map
.
live_range_id
(
n
->
in
(
idx
));
if
(
liveout
.
remove
(
x
)
)
{
lrgs
(
x
).
_area
-=
cost
;
// Adjust register pressure.
lower_pressure
(
&
lrgs
(
x
),
j
-
1
,
b
,
pressure
,
hrp_index
);
lower_pressure
(
&
lrgs
(
x
),
j
-
1
,
b
,
pressure
,
hrp_index
);
assert
(
pressure
[
0
]
==
count_int_pressure
(
&
liveout
),
""
);
assert
(
pressure
[
1
]
==
count_float_pressure
(
&
liveout
),
""
);
}
...
...
@@ -727,18 +732,21 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
// the flags and assumes it's dead. This keeps the (useless)
// flag-setting behavior alive while also keeping the (useful)
// memory update effect.
for
(
uint
k
=
((
n
->
Opcode
()
==
Op_SCMemProj
)
?
0
:
1
);
k
<
n
->
req
();
k
++
)
{
for
(
uint
k
=
((
n
->
Opcode
()
==
Op_SCMemProj
)
?
0
:
1
);
k
<
n
->
req
();
k
++
)
{
Node
*
def
=
n
->
in
(
k
);
uint
x
=
n2lidx
(
def
);
if
(
!
x
)
continue
;
uint
x
=
_lrg_map
.
live_range_id
(
def
);
if
(
!
x
)
{
continue
;
}
LRG
&
lrg
=
lrgs
(
x
);
// No use-side cost for spilling debug info
if
(
k
<
debug_start
)
if
(
k
<
debug_start
)
{
// A USE costs twice block frequency (once for the Load, once
// for a Load-delay). Rematerialized uses only cost once.
lrg
.
_cost
+=
(
def
->
rematerialize
()
?
b
->
_freq
:
(
b
->
_freq
+
b
->
_freq
));
}
// It is live now
if
(
liveout
.
insert
(
x
)
)
{
if
(
liveout
.
insert
(
x
)
)
{
// Newly live things assumed live from here to top of block
lrg
.
_area
+=
cost
;
// Adjust register pressure
...
...
src/share/vm/opto/live.cpp
浏览文件 @
6ea208d0
...
...
@@ -44,7 +44,7 @@
// block is put on the worklist.
// The locally live-in stuff is computed once and added to predecessor
// live-out sets. This separate compilation is done in the outer loop below.
PhaseLive
::
PhaseLive
(
const
PhaseCFG
&
cfg
,
LRG_List
&
names
,
Arena
*
arena
)
:
Phase
(
LIVE
),
_cfg
(
cfg
),
_names
(
names
),
_arena
(
arena
),
_live
(
0
)
{
PhaseLive
::
PhaseLive
(
const
PhaseCFG
&
cfg
,
const
LRG_List
&
names
,
Arena
*
arena
)
:
Phase
(
LIVE
),
_cfg
(
cfg
),
_names
(
names
),
_arena
(
arena
),
_live
(
0
)
{
}
void
PhaseLive
::
compute
(
uint
maxlrg
)
{
...
...
src/share/vm/opto/live.hpp
浏览文件 @
6ea208d0
...
...
@@ -80,7 +80,7 @@ class PhaseLive : public Phase {
Block_List
*
_worklist
;
// Worklist for iterative solution
const
PhaseCFG
&
_cfg
;
// Basic blocks
LRG_List
&
_names
;
// Mapping from Nodes to live ranges
const
LRG_List
&
_names
;
// Mapping from Nodes to live ranges
uint
_maxlrg
;
// Largest live-range number
Arena
*
_arena
;
...
...
@@ -91,7 +91,7 @@ class PhaseLive : public Phase {
void
add_liveout
(
Block
*
p
,
IndexSet
*
lo
,
VectorSet
&
first_pass
);
public:
PhaseLive
(
const
PhaseCFG
&
cfg
,
LRG_List
&
names
,
Arena
*
arena
);
PhaseLive
(
const
PhaseCFG
&
cfg
,
const
LRG_List
&
names
,
Arena
*
arena
);
~
PhaseLive
()
{}
// Compute liveness info
void
compute
(
uint
maxlrg
);
...
...
src/share/vm/opto/postaloc.cpp
浏览文件 @
6ea208d0
...
...
@@ -56,7 +56,7 @@ bool PhaseChaitin::may_be_copy_of_callee( Node *def ) const {
int
i
;
for
(
i
=
0
;
i
<
limit
;
i
++
)
{
if
(
def
->
is_Proj
()
&&
def
->
in
(
0
)
->
is_Start
()
&&
_matcher
.
is_save_on_entry
(
lrgs
(
n2lidx
(
def
)).
reg
())
)
_matcher
.
is_save_on_entry
(
lrgs
(
_lrg_map
.
live_range_id
(
def
)).
reg
())
)
return
true
;
// Direct use of callee-save proj
if
(
def
->
is_Copy
()
)
// Copies carry value through
def
=
def
->
in
(
def
->
is_Copy
());
...
...
@@ -83,7 +83,7 @@ int PhaseChaitin::yank( Node *old, Block *current_block, Node_List *value, Node_
// Count 1 if deleting an instruction from the current block
if
(
oldb
==
current_block
)
blk_adjust
++
;
_cfg
.
_bbs
.
map
(
old
->
_idx
,
NULL
);
OptoReg
::
Name
old_reg
=
lrgs
(
n2lidx
(
old
)).
reg
();
OptoReg
::
Name
old_reg
=
lrgs
(
_lrg_map
.
live_range_id
(
old
)).
reg
();
if
(
regnd
&&
(
*
regnd
)[
old_reg
]
==
old
)
{
// Instruction is currently available?
value
->
map
(
old_reg
,
NULL
);
// Yank from value/regnd maps
regnd
->
map
(
old_reg
,
NULL
);
// This register's value is now unknown
...
...
@@ -164,7 +164,7 @@ int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *curre
// Not every pair of physical registers are assignment compatible,
// e.g. on sparc floating point registers are not assignable to integer
// registers.
const
LRG
&
def_lrg
=
lrgs
(
n2lidx
(
def
));
const
LRG
&
def_lrg
=
lrgs
(
_lrg_map
.
live_range_id
(
def
));
OptoReg
::
Name
def_reg
=
def_lrg
.
reg
();
const
RegMask
&
use_mask
=
n
->
in_RegMask
(
idx
);
bool
can_use
=
(
RegMask
::
can_represent
(
def_reg
)
?
(
use_mask
.
Member
(
def_reg
)
!=
0
)
...
...
@@ -209,11 +209,12 @@ int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *curre
// Skip through any number of copies (that don't mod oop-i-ness)
Node
*
PhaseChaitin
::
skip_copies
(
Node
*
c
)
{
int
idx
=
c
->
is_Copy
();
uint
is_oop
=
lrgs
(
n2lidx
(
c
)).
_is_oop
;
uint
is_oop
=
lrgs
(
_lrg_map
.
live_range_id
(
c
)).
_is_oop
;
while
(
idx
!=
0
)
{
guarantee
(
c
->
in
(
idx
)
!=
NULL
,
"must not resurrect dead copy"
);
if
(
lrgs
(
n2lidx
(
c
->
in
(
idx
))).
_is_oop
!=
is_oop
)
if
(
lrgs
(
_lrg_map
.
live_range_id
(
c
->
in
(
idx
))).
_is_oop
!=
is_oop
)
{
break
;
// casting copy, not the same value
}
c
=
c
->
in
(
idx
);
idx
=
c
->
is_Copy
();
}
...
...
@@ -225,8 +226,8 @@ Node *PhaseChaitin::skip_copies( Node *c ) {
int
PhaseChaitin
::
elide_copy
(
Node
*
n
,
int
k
,
Block
*
current_block
,
Node_List
&
value
,
Node_List
&
regnd
,
bool
can_change_regs
)
{
int
blk_adjust
=
0
;
uint
nk_idx
=
n2lidx
(
n
->
in
(
k
));
OptoReg
::
Name
nk_reg
=
lrgs
(
nk_idx
).
reg
();
uint
nk_idx
=
_lrg_map
.
live_range_id
(
n
->
in
(
k
));
OptoReg
::
Name
nk_reg
=
lrgs
(
nk_idx
).
reg
();
// Remove obvious same-register copies
Node
*
x
=
n
->
in
(
k
);
...
...
@@ -234,9 +235,13 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v
while
(
(
idx
=
x
->
is_Copy
())
!=
0
)
{
Node
*
copy
=
x
->
in
(
idx
);
guarantee
(
copy
!=
NULL
,
"must not resurrect dead copy"
);
if
(
lrgs
(
n2lidx
(
copy
)).
reg
()
!=
nk_reg
)
break
;
if
(
lrgs
(
_lrg_map
.
live_range_id
(
copy
)).
reg
()
!=
nk_reg
)
{
break
;
}
blk_adjust
+=
use_prior_register
(
n
,
k
,
copy
,
current_block
,
value
,
regnd
);
if
(
n
->
in
(
k
)
!=
copy
)
break
;
// Failed for some cutout?
if
(
n
->
in
(
k
)
!=
copy
)
{
break
;
// Failed for some cutout?
}
x
=
copy
;
// Progress, try again
}
...
...
@@ -256,7 +261,7 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v
if
(
val
==
x
&&
nk_idx
!=
0
&&
regnd
[
nk_reg
]
!=
NULL
&&
regnd
[
nk_reg
]
!=
x
&&
n2lidx
(
x
)
==
n2lidx
(
regnd
[
nk_reg
]))
{
_lrg_map
.
live_range_id
(
x
)
==
_lrg_map
.
live_range_id
(
regnd
[
nk_reg
]))
{
// When rematerialzing nodes and stretching lifetimes, the
// allocator will reuse the original def for multidef LRG instead
// of the current reaching def because it can't know it's safe to
...
...
@@ -270,7 +275,7 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v
if
(
val
==
x
)
return
blk_adjust
;
// No progress?
int
n_regs
=
RegMask
::
num_registers
(
val
->
ideal_reg
());
uint
val_idx
=
n2lidx
(
val
);
uint
val_idx
=
_lrg_map
.
live_range_id
(
val
);
OptoReg
::
Name
val_reg
=
lrgs
(
val_idx
).
reg
();
// See if it happens to already be in the correct register!
...
...
@@ -499,12 +504,12 @@ void PhaseChaitin::post_allocate_copy_removal() {
for
(
j
=
1
;
j
<
phi_dex
;
j
++
)
{
uint
k
;
Node
*
phi
=
b
->
_nodes
[
j
];
uint
pidx
=
n2lidx
(
phi
);
OptoReg
::
Name
preg
=
lrgs
(
n2lidx
(
phi
)).
reg
();
uint
pidx
=
_lrg_map
.
live_range_id
(
phi
);
OptoReg
::
Name
preg
=
lrgs
(
_lrg_map
.
live_range_id
(
phi
)).
reg
();
// Remove copies remaining on edges. Check for junk phi.
Node
*
u
=
NULL
;
for
(
k
=
1
;
k
<
phi
->
req
();
k
++
)
{
for
(
k
=
1
;
k
<
phi
->
req
();
k
++
)
{
Node
*
x
=
phi
->
in
(
k
);
if
(
phi
!=
x
&&
u
!=
x
)
// Found a different input
u
=
u
?
NodeSentinel
:
x
;
// Capture unique input, or NodeSentinel for 2nd input
...
...
@@ -555,10 +560,10 @@ void PhaseChaitin::post_allocate_copy_removal() {
// alive and well at the use (or else the allocator fubar'd). Take
// advantage of this info to set a reaching def for the use-reg.
uint
k
;
for
(
k
=
1
;
k
<
n
->
req
();
k
++
)
{
for
(
k
=
1
;
k
<
n
->
req
();
k
++
)
{
Node
*
def
=
n
->
in
(
k
);
// n->in(k) is a USE; def is the DEF for this USE
guarantee
(
def
!=
NULL
,
"no disconnected nodes at this point"
);
uint
useidx
=
n2lidx
(
def
);
// useidx is the live range index for this USE
uint
useidx
=
_lrg_map
.
live_range_id
(
def
);
// useidx is the live range index for this USE
if
(
useidx
)
{
OptoReg
::
Name
ureg
=
lrgs
(
useidx
).
reg
();
...
...
@@ -566,7 +571,7 @@ void PhaseChaitin::post_allocate_copy_removal() {
int
idx
;
// Skip occasional useless copy
while
(
(
idx
=
def
->
is_Copy
())
!=
0
&&
def
->
in
(
idx
)
!=
NULL
&&
// NULL should not happen
ureg
==
lrgs
(
n2lidx
(
def
->
in
(
idx
))).
reg
()
)
ureg
==
lrgs
(
_lrg_map
.
live_range_id
(
def
->
in
(
idx
))).
reg
()
)
def
=
def
->
in
(
idx
);
Node
*
valdef
=
skip_copies
(
def
);
// tighten up val through non-useless copies
value
.
map
(
ureg
,
valdef
);
// record improved reaching-def info
...
...
@@ -594,8 +599,10 @@ void PhaseChaitin::post_allocate_copy_removal() {
j
-=
elide_copy
(
n
,
k
,
b
,
value
,
regnd
,
two_adr
!=
k
);
// Unallocated Nodes define no registers
uint
lidx
=
n2lidx
(
n
);
if
(
!
lidx
)
continue
;
uint
lidx
=
_lrg_map
.
live_range_id
(
n
);
if
(
!
lidx
)
{
continue
;
}
// Update the register defined by this instruction
OptoReg
::
Name
nreg
=
lrgs
(
lidx
).
reg
();
...
...
src/share/vm/opto/reg_split.cpp
浏览文件 @
6ea208d0
...
...
@@ -318,9 +318,13 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint
for
(
uint
i
=
1
;
i
<
def
->
req
();
i
++
)
{
Node
*
in
=
def
->
in
(
i
);
// Check for single-def (LRG cannot redefined)
uint
lidx
=
n2lidx
(
in
);
if
(
lidx
>=
_maxlrg
)
continue
;
// Value is a recent spill-copy
if
(
lrgs
(
lidx
).
is_singledef
())
continue
;
uint
lidx
=
_lrg_map
.
live_range_id
(
in
);
if
(
lidx
>=
_lrg_map
.
max_lrg_id
())
{
continue
;
// Value is a recent spill-copy
}
if
(
lrgs
(
lidx
).
is_singledef
())
{
continue
;
}
Block
*
b_def
=
_cfg
.
_bbs
[
def
->
_idx
];
int
idx_def
=
b_def
->
find_node
(
def
);
...
...
@@ -344,26 +348,28 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint
if
(
spill
->
req
()
>
1
)
{
for
(
uint
i
=
1
;
i
<
spill
->
req
();
i
++
)
{
Node
*
in
=
spill
->
in
(
i
);
uint
lidx
=
F
ind_id
(
in
);
uint
lidx
=
_lrg_map
.
f
ind_id
(
in
);
// Walk backwards thru spill copy node intermediates
if
(
walkThru
)
{
while
(
in
->
is_SpillCopy
()
&&
lidx
>=
_maxlrg
)
{
while
(
in
->
is_SpillCopy
()
&&
lidx
>=
_lrg_map
.
max_lrg_id
()
)
{
in
=
in
->
in
(
1
);
lidx
=
F
ind_id
(
in
);
lidx
=
_lrg_map
.
f
ind_id
(
in
);
}
if
(
lidx
<
_
maxlrg
&&
lrgs
(
lidx
).
is_multidef
())
{
if
(
lidx
<
_
lrg_map
.
max_lrg_id
()
&&
lrgs
(
lidx
).
is_multidef
())
{
// walkThru found a multidef LRG, which is unsafe to use, so
// just keep the original def used in the clone.
in
=
spill
->
in
(
i
);
lidx
=
F
ind_id
(
in
);
lidx
=
_lrg_map
.
f
ind_id
(
in
);
}
}
if
(
lidx
<
_maxlrg
&&
lrgs
(
lidx
).
reg
()
>=
LRG
::
SPILL_REG
)
{
if
(
lidx
<
_lrg_map
.
max_lrg_id
()
&&
lrgs
(
lidx
).
reg
()
>=
LRG
::
SPILL_REG
)
{
Node
*
rdef
=
Reachblock
[
lrg2reach
[
lidx
]];
if
(
rdef
)
spill
->
set_req
(
i
,
rdef
);
if
(
rdef
)
{
spill
->
set_req
(
i
,
rdef
);
}
}
}
}
...
...
@@ -382,7 +388,7 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint
#endif
// See if the cloned def kills any flags, and copy those kills as well
uint
i
=
insidx
+
1
;
if
(
clone_projs
(
b
,
i
,
def
,
spill
,
maxlrg
)
)
{
if
(
clone_projs
(
b
,
i
,
def
,
spill
,
maxlrg
)
)
{
// Adjust the point where we go hi-pressure
if
(
i
<=
b
->
_ihrp_index
)
b
->
_ihrp_index
++
;
if
(
i
<=
b
->
_fhrp_index
)
b
->
_fhrp_index
++
;
...
...
@@ -424,17 +430,25 @@ bool PhaseChaitin::is_high_pressure( Block *b, LRG *lrg, uint insidx ) {
//------------------------------prompt_use---------------------------------
// True if lidx is used before any real register is def'd in the block
bool
PhaseChaitin
::
prompt_use
(
Block
*
b
,
uint
lidx
)
{
if
(
lrgs
(
lidx
).
_was_spilled2
)
return
false
;
if
(
lrgs
(
lidx
).
_was_spilled2
)
{
return
false
;
}
// Scan block for 1st use.
for
(
uint
i
=
1
;
i
<=
b
->
end_idx
();
i
++
)
{
Node
*
n
=
b
->
_nodes
[
i
];
// Ignore PHI use, these can be up or down
if
(
n
->
is_Phi
()
)
continue
;
for
(
uint
j
=
1
;
j
<
n
->
req
();
j
++
)
if
(
Find_id
(
n
->
in
(
j
))
==
lidx
)
if
(
n
->
is_Phi
())
{
continue
;
}
for
(
uint
j
=
1
;
j
<
n
->
req
();
j
++
)
{
if
(
_lrg_map
.
find_id
(
n
->
in
(
j
))
==
lidx
)
{
return
true
;
// Found 1st use!
if
(
n
->
out_RegMask
().
is_NotEmpty
()
)
return
false
;
}
}
if
(
n
->
out_RegMask
().
is_NotEmpty
())
{
return
false
;
}
}
return
false
;
}
...
...
@@ -464,23 +478,23 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
bool
u1
,
u2
,
u3
;
Block
*
b
,
*
pred
;
PhiNode
*
phi
;
GrowableArray
<
uint
>
lidxs
(
split_arena
,
_
maxlrg
,
0
,
0
);
GrowableArray
<
uint
>
lidxs
(
split_arena
,
maxlrg
,
0
,
0
);
// Array of counters to count splits per live range
GrowableArray
<
uint
>
splits
(
split_arena
,
_
maxlrg
,
0
,
0
);
GrowableArray
<
uint
>
splits
(
split_arena
,
maxlrg
,
0
,
0
);
#define NEW_SPLIT_ARRAY(type, size)\
(type*) split_arena->allocate_bytes((size) * sizeof(type))
//----------Setup Code----------
// Create a convenient mapping from lrg numbers to reaches/leaves indices
uint
*
lrg2reach
=
NEW_SPLIT_ARRAY
(
uint
,
_maxlrg
);
uint
*
lrg2reach
=
NEW_SPLIT_ARRAY
(
uint
,
maxlrg
);
// Keep track of DEFS & Phis for later passes
defs
=
new
Node_List
();
phis
=
new
Node_List
();
// Gather info on which LRG's are spilling, and build maps
for
(
bidx
=
1
;
bidx
<
_maxlrg
;
bidx
++
)
{
if
(
lrgs
(
bidx
).
alive
()
&&
lrgs
(
bidx
).
reg
()
>=
LRG
::
SPILL_REG
)
{
for
(
bidx
=
1
;
bidx
<
maxlrg
;
bidx
++
)
{
if
(
lrgs
(
bidx
).
alive
()
&&
lrgs
(
bidx
).
reg
()
>=
LRG
::
SPILL_REG
)
{
assert
(
!
lrgs
(
bidx
).
mask
().
is_AllStack
(),
"AllStack should color"
);
lrg2reach
[
bidx
]
=
spill_cnt
;
spill_cnt
++
;
...
...
@@ -629,7 +643,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
break
;
}
// must be looking at a phi
if
(
Find_id
(
n1
)
==
lidxs
.
at
(
slidx
)
)
{
if
(
_lrg_map
.
find_id
(
n1
)
==
lidxs
.
at
(
slidx
)
)
{
// found the necessary phi
needs_phi
=
false
;
has_phi
=
true
;
...
...
@@ -651,11 +665,11 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
Reachblock
[
slidx
]
=
phi
;
// add node to block & node_to_block mapping
insert_proj
(
b
,
insidx
++
,
phi
,
maxlrg
++
);
insert_proj
(
b
,
insidx
++
,
phi
,
maxlrg
++
);
non_phi
++
;
// Reset new phi's mapping to be the spilling live range
_
names
.
map
(
phi
->
_idx
,
lidx
);
assert
(
Find_id
(
phi
)
==
lidx
,
"Bad update on Union-Find mapping"
);
_
lrg_map
.
map
(
phi
->
_idx
,
lidx
);
assert
(
_lrg_map
.
find_id
(
phi
)
==
lidx
,
"Bad update on Union-Find mapping"
);
}
// end if not found correct phi
// Here you have either found or created the Phi, so record it
assert
(
phi
!=
NULL
,
"Must have a Phi Node here"
);
...
...
@@ -721,12 +735,12 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
for
(
insidx
=
1
;
insidx
<=
b
->
end_idx
();
insidx
++
)
{
Node
*
n
=
b
->
_nodes
[
insidx
];
// Find the defining Node's live range index
uint
defidx
=
F
ind_id
(
n
);
uint
defidx
=
_lrg_map
.
f
ind_id
(
n
);
uint
cnt
=
n
->
req
();
if
(
n
->
is_Phi
()
)
{
if
(
n
->
is_Phi
()
)
{
// Skip phi nodes after removing dead copies.
if
(
defidx
<
_maxlrg
)
{
if
(
defidx
<
_lrg_map
.
max_lrg_id
()
)
{
// Check for useless Phis. These appear if we spill, then
// coalesce away copies. Dont touch Phis in spilling live
// ranges; they are busy getting modifed in this pass.
...
...
@@ -744,8 +758,8 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
}
}
assert
(
u
,
"at least 1 valid input expected"
);
if
(
i
>=
cnt
)
{
// Found one unique input
assert
(
Find_id
(
n
)
==
F
ind_id
(
u
),
"should be the same lrg"
);
if
(
i
>=
cnt
)
{
// Found one unique input
assert
(
_lrg_map
.
find_id
(
n
)
==
_lrg_map
.
f
ind_id
(
u
),
"should be the same lrg"
);
n
->
replace_by
(
u
);
// Then replace with unique input
n
->
disconnect_inputs
(
NULL
,
C
);
b
->
_nodes
.
remove
(
insidx
);
...
...
@@ -793,16 +807,24 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
while
(
insert_point
>
0
)
{
Node
*
n
=
b
->
_nodes
[
insert_point
];
// Hit top of block? Quit going backwards
if
(
n
->
is_Phi
()
)
break
;
if
(
n
->
is_Phi
())
{
break
;
}
// Found a def? Better split after it.
if
(
n2lidx
(
n
)
==
lidx
)
break
;
if
(
_lrg_map
.
live_range_id
(
n
)
==
lidx
)
{
break
;
}
// Look for a use
uint
i
;
for
(
i
=
1
;
i
<
n
->
req
();
i
++
)
if
(
n2lidx
(
n
->
in
(
i
))
==
lidx
)
for
(
i
=
1
;
i
<
n
->
req
();
i
++
)
{
if
(
_lrg_map
.
live_range_id
(
n
->
in
(
i
))
==
lidx
)
{
break
;
}
}
// Found a use? Better split after it.
if
(
i
<
n
->
req
()
)
break
;
if
(
i
<
n
->
req
())
{
break
;
}
insert_point
--
;
}
uint
orig_eidx
=
b
->
end_idx
();
...
...
@@ -812,8 +834,9 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
return
0
;
}
// Spill of NULL check mem op goes into the following block.
if
(
b
->
end_idx
()
>
orig_eidx
)
if
(
b
->
end_idx
()
>
orig_eidx
)
{
insidx
++
;
}
}
// This is a new DEF, so update UP
UPblock
[
slidx
]
=
false
;
...
...
@@ -832,13 +855,13 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
}
// end if crossing HRP Boundry
// If the LRG index is oob, then this is a new spillcopy, skip it.
if
(
defidx
>=
_maxlrg
)
{
if
(
defidx
>=
_lrg_map
.
max_lrg_id
()
)
{
continue
;
}
LRG
&
deflrg
=
lrgs
(
defidx
);
uint
copyidx
=
n
->
is_Copy
();
// Remove coalesced copy from CFG
if
(
copyidx
&&
defidx
==
n2lidx
(
n
->
in
(
copyidx
))
)
{
if
(
copyidx
&&
defidx
==
_lrg_map
.
live_range_id
(
n
->
in
(
copyidx
))
)
{
n
->
replace_by
(
n
->
in
(
copyidx
)
);
n
->
set_req
(
copyidx
,
NULL
);
b
->
_nodes
.
remove
(
insidx
--
);
...
...
@@ -864,13 +887,13 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
// If inpidx > old_last, then one of these new inputs is being
// handled. Skip the derived part of the pair, but process
// the base like any other input.
if
(
inpidx
>
old_last
&&
((
inpidx
-
oopoff
)
&
1
)
==
DERIVED
)
{
if
(
inpidx
>
old_last
&&
((
inpidx
-
oopoff
)
&
1
)
==
DERIVED
)
{
continue
;
// skip derived_debug added below
}
// Get lidx of input
uint
useidx
=
F
ind_id
(
n
->
in
(
inpidx
));
uint
useidx
=
_lrg_map
.
f
ind_id
(
n
->
in
(
inpidx
));
// Not a brand-new split, and it is a spill use
if
(
useidx
<
_maxlrg
&&
lrgs
(
useidx
).
reg
()
>=
LRG
::
SPILL_REG
)
{
if
(
useidx
<
_lrg_map
.
max_lrg_id
()
&&
lrgs
(
useidx
).
reg
()
>=
LRG
::
SPILL_REG
)
{
// Check for valid reaching DEF
slidx
=
lrg2reach
[
useidx
];
Node
*
def
=
Reachblock
[
slidx
];
...
...
@@ -886,7 +909,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
if
(
def
==
NULL
||
C
->
check_node_count
(
NodeLimitFudgeFactor
,
out_of_nodes
))
{
return
0
;
}
_
names
.
extend
(
def
->
_idx
,
0
);
_
lrg_map
.
extend
(
def
->
_idx
,
0
);
_cfg
.
_bbs
.
map
(
def
->
_idx
,
b
);
n
->
set_req
(
inpidx
,
def
);
continue
;
...
...
@@ -1186,10 +1209,10 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
// ********** Split Left Over Mem-Mem Moves **********
// Check for mem-mem copies and split them now. Do not do this
// to copies about to be spilled; they will be Split shortly.
if
(
copyidx
)
{
if
(
copyidx
)
{
Node
*
use
=
n
->
in
(
copyidx
);
uint
useidx
=
F
ind_id
(
use
);
if
(
useidx
<
_maxlrg
&&
// This is not a new split
uint
useidx
=
_lrg_map
.
f
ind_id
(
use
);
if
(
useidx
<
_lrg_map
.
max_lrg_id
()
&&
// This is not a new split
OptoReg
::
is_stack
(
deflrg
.
reg
())
&&
deflrg
.
reg
()
<
LRG
::
SPILL_REG
)
{
// And DEF is from stack
LRG
&
uselrg
=
lrgs
(
useidx
);
...
...
@@ -1228,7 +1251,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
uint
member
;
IndexSetIterator
isi
(
liveout
);
while
((
member
=
isi
.
next
())
!=
0
)
{
assert
(
defidx
!=
F
ind_const
(
member
),
"Live out member has not been compressed"
);
assert
(
defidx
!=
_lrg_map
.
f
ind_const
(
member
),
"Live out member has not been compressed"
);
}
#endif
Reachblock
[
slidx
]
=
NULL
;
...
...
@@ -1261,7 +1284,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
assert
(
phi
->
is_Phi
(),
"This list must only contain Phi Nodes"
);
Block
*
b
=
_cfg
.
_bbs
[
phi
->
_idx
];
// Grab the live range number
uint
lidx
=
F
ind_id
(
phi
);
uint
lidx
=
_lrg_map
.
f
ind_id
(
phi
);
uint
slidx
=
lrg2reach
[
lidx
];
// Update node to lidx map
new_lrg
(
phi
,
maxlrg
++
);
...
...
@@ -1296,11 +1319,13 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
int
insert
=
pred
->
end_idx
();
while
(
insert
>=
1
&&
pred
->
_nodes
[
insert
-
1
]
->
is_SpillCopy
()
&&
F
ind
(
pred
->
_nodes
[
insert
-
1
])
>=
lrgs_before_phi_split
)
{
_lrg_map
.
f
ind
(
pred
->
_nodes
[
insert
-
1
])
>=
lrgs_before_phi_split
)
{
insert
--
;
}
def
=
split_Rematerialize
(
def
,
pred
,
insert
,
maxlrg
,
splits
,
slidx
,
lrg2reach
,
Reachblock
,
false
);
if
(
!
def
)
return
0
;
// Bail out
def
=
split_Rematerialize
(
def
,
pred
,
insert
,
maxlrg
,
splits
,
slidx
,
lrg2reach
,
Reachblock
,
false
);
if
(
!
def
)
{
return
0
;
// Bail out
}
}
// Update the Phi's input edge array
phi
->
set_req
(
i
,
def
);
...
...
@@ -1316,7 +1341,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
}
// End for all inputs to the Phi
}
// End for all Phi Nodes
// Update _maxlrg to save Union asserts
_
maxlrg
=
maxlrg
;
_
lrg_map
.
set_max_lrg_id
(
maxlrg
)
;
//----------PASS 3----------
...
...
@@ -1328,47 +1353,51 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
for
(
uint
i
=
1
;
i
<
phi
->
req
();
i
++
)
{
// Grab the input node
Node
*
n
=
phi
->
in
(
i
);
assert
(
n
,
""
);
uint
lidx
=
F
ind
(
n
);
uint
pidx
=
F
ind
(
phi
);
if
(
lidx
<
pidx
)
assert
(
n
,
"node should exist"
);
uint
lidx
=
_lrg_map
.
f
ind
(
n
);
uint
pidx
=
_lrg_map
.
f
ind
(
phi
);
if
(
lidx
<
pidx
)
{
Union
(
n
,
phi
);
else
if
(
lidx
>
pidx
)
}
else
if
(
lidx
>
pidx
)
{
Union
(
phi
,
n
);
}
}
// End for all inputs to the Phi Node
}
// End for all Phi Nodes
// Now union all two address instructions
for
(
insidx
=
0
;
insidx
<
defs
->
size
();
insidx
++
)
{
for
(
insidx
=
0
;
insidx
<
defs
->
size
();
insidx
++
)
{
// Grab the def
n1
=
defs
->
at
(
insidx
);
// Set new lidx for DEF & handle 2-addr instructions
if
(
n1
->
is_Mach
()
&&
((
twoidx
=
n1
->
as_Mach
()
->
two_adr
())
!=
0
)
)
{
assert
(
F
ind
(
n1
->
in
(
twoidx
))
<
maxlrg
,
"Assigning bad live range index"
);
if
(
n1
->
is_Mach
()
&&
((
twoidx
=
n1
->
as_Mach
()
->
two_adr
())
!=
0
)
)
{
assert
(
_lrg_map
.
f
ind
(
n1
->
in
(
twoidx
))
<
maxlrg
,
"Assigning bad live range index"
);
// Union the input and output live ranges
uint
lr1
=
F
ind
(
n1
);
uint
lr2
=
F
ind
(
n1
->
in
(
twoidx
));
if
(
lr1
<
lr2
)
uint
lr1
=
_lrg_map
.
f
ind
(
n1
);
uint
lr2
=
_lrg_map
.
f
ind
(
n1
->
in
(
twoidx
));
if
(
lr1
<
lr2
)
{
Union
(
n1
,
n1
->
in
(
twoidx
));
else
if
(
lr1
>
lr2
)
}
else
if
(
lr1
>
lr2
)
{
Union
(
n1
->
in
(
twoidx
),
n1
);
}
}
// End if two address
}
// End for all defs
// DEBUG
#ifdef ASSERT
// Validate all live range index assignments
for
(
bidx
=
0
;
bidx
<
_cfg
.
_num_blocks
;
bidx
++
)
{
for
(
bidx
=
0
;
bidx
<
_cfg
.
_num_blocks
;
bidx
++
)
{
b
=
_cfg
.
_blocks
[
bidx
];
for
(
insidx
=
0
;
insidx
<=
b
->
end_idx
();
insidx
++
)
{
for
(
insidx
=
0
;
insidx
<=
b
->
end_idx
();
insidx
++
)
{
Node
*
n
=
b
->
_nodes
[
insidx
];
uint
defidx
=
F
ind
(
n
);
assert
(
defidx
<
_
maxlrg
,
"Bad live range index in Split"
);
uint
defidx
=
_lrg_map
.
f
ind
(
n
);
assert
(
defidx
<
_
lrg_map
.
max_lrg_id
(),
"Bad live range index in Split"
);
assert
(
defidx
<
maxlrg
,
"Bad live range index in Split"
);
}
}
// Issue a warning if splitting made no progress
int
noprogress
=
0
;
for
(
slidx
=
0
;
slidx
<
spill_cnt
;
slidx
++
)
{
if
(
PrintOpto
&&
WizardMode
&&
splits
.
at
(
slidx
)
==
0
)
{
for
(
slidx
=
0
;
slidx
<
spill_cnt
;
slidx
++
)
{
if
(
PrintOpto
&&
WizardMode
&&
splits
.
at
(
slidx
)
==
0
)
{
tty
->
print_cr
(
"Failed to split live range %d"
,
lidxs
.
at
(
slidx
));
//BREAKPOINT;
}
...
...
src/share/vm/opto/regalloc.hpp
浏览文件 @
6ea208d0
...
...
@@ -113,7 +113,7 @@ public:
OptoReg
::
Name
offset2reg
(
int
stk_offset
)
const
;
// Get the register encoding associated with the Node
int
get_encode
(
const
Node
*
n
)
const
{
int
get_encode
(
const
Node
*
n
)
const
{
assert
(
n
->
_idx
<
_node_regs_max_index
,
"Exceeded _node_regs array"
);
OptoReg
::
Name
first
=
_node_regs
[
n
->
_idx
].
first
();
OptoReg
::
Name
second
=
_node_regs
[
n
->
_idx
].
second
();
...
...
@@ -122,15 +122,6 @@ public:
return
Matcher
::
_regEncode
[
first
];
}
// Platform dependent hook for actions prior to allocation
void
pd_preallocate_hook
();
#ifdef ASSERT
// Platform dependent hook for verification after allocation. Will
// only get called when compiling with asserts.
void
pd_postallocate_verify_hook
();
#endif
#ifndef PRODUCT
static
int
_total_framesize
;
static
int
_max_framesize
;
...
...
src/share/vm/runtime/vmStructs.cpp
浏览文件 @
6ea208d0
...
...
@@ -1115,7 +1115,6 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
c2_nonstatic_field(PhaseChaitin, _lo_stk_degree, uint) \
c2_nonstatic_field(PhaseChaitin, _hi_degree, uint) \
c2_nonstatic_field(PhaseChaitin, _simplified, uint) \
c2_nonstatic_field(PhaseChaitin, _maxlrg, uint) \
\
c2_nonstatic_field(Block, _nodes, Node_List) \
c2_nonstatic_field(Block, _succs, Block_Array) \
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录