Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
ec969180
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看板
提交
ec969180
编写于
3月 30, 2017
作者:
T
thartmann
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8173770: Image conversion improvements
Reviewed-by: kvn, vlivanov, dlong, rhalade, mschoene, iignatyev
上级
c6c700ed
变更
11
显示空白变更内容
内联
并排
Showing
11 changed file
with
521 addition
and
32 deletion
+521
-32
src/cpu/sparc/vm/sparc.ad
src/cpu/sparc/vm/sparc.ad
+134
-0
src/cpu/x86/vm/x86_32.ad
src/cpu/x86/vm/x86_32.ad
+151
-1
src/cpu/x86/vm/x86_64.ad
src/cpu/x86/vm/x86_64.ad
+42
-0
src/share/vm/adlc/archDesc.cpp
src/share/vm/adlc/archDesc.cpp
+1
-0
src/share/vm/opto/classes.hpp
src/share/vm/opto/classes.hpp
+1
-0
src/share/vm/opto/loopPredicate.cpp
src/share/vm/opto/loopPredicate.cpp
+125
-29
src/share/vm/opto/loopnode.hpp
src/share/vm/opto/loopnode.hpp
+2
-2
src/share/vm/opto/output.cpp
src/share/vm/opto/output.cpp
+1
-0
src/share/vm/opto/subnode.cpp
src/share/vm/opto/subnode.cpp
+54
-0
src/share/vm/opto/subnode.hpp
src/share/vm/opto/subnode.hpp
+9
-0
src/share/vm/runtime/vmStructs.cpp
src/share/vm/runtime/vmStructs.cpp
+1
-0
未找到文件。
src/cpu/sparc/vm/sparc.ad
浏览文件 @
ec969180
...
...
@@ -3458,6 +3458,16 @@ operand immI5() %{
interface(CONST_INTER);
%}
// Unsigned Long Immediate: 12-bit (non-negative that fits in simm13)
operand immUL12() %{
predicate((0 <= n->get_long()) && (n->get_long() == (int)n->get_long()) && Assembler::is_simm13((int)n->get_long()));
match(ConL);
op_cost(0);
format %{ %}
interface(CONST_INTER);
%}
// Int Immediate non-negative
operand immU31()
%{
...
...
@@ -4083,6 +4093,15 @@ operand flagsRegL() %{
interface(REG_INTER);
%}
// Condition Code Register, unsigned long comparisons.
operand flagsRegUL() %{
constraint(ALLOC_IN_RC(int_flags));
match(RegFlags);
format %{ "xcc_UL" %}
interface(REG_INTER);
%}
// Condition Code Register, floating comparisons, unordered same as "less".
operand flagsRegF() %{
constraint(ALLOC_IN_RC(float_flags));
...
...
@@ -8962,6 +8981,17 @@ instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{
ins_pipe(ialu_cconly_reg_reg);
%}
instruct compUL_iReg(flagsRegUL xcc, iRegL op1, iRegL op2) %{
match(Set xcc (CmpUL op1 op2));
effect(DEF xcc, USE op1, USE op2);
size(4);
format %{ "CMP $op1,$op2\t! unsigned long" %}
opcode(Assembler::subcc_op3, Assembler::arith_op);
ins_encode(form3_rs1_rs2_rd(op1, op2, R_G0));
ins_pipe(ialu_cconly_reg_reg);
%}
instruct compI_iReg_imm13(flagsReg icc, iRegI op1, immI13 op2) %{
match(Set icc (CmpI op1 op2));
effect( DEF icc, USE op1 );
...
...
@@ -9048,6 +9078,17 @@ instruct compU_iReg_imm13(flagsRegU icc, iRegI op1, immU12 op2 ) %{
ins_pipe(ialu_cconly_reg_imm);
%}
instruct compUL_iReg_imm13(flagsRegUL xcc, iRegL op1, immUL12 op2) %{
match(Set xcc (CmpUL op1 op2));
effect(DEF xcc, USE op1, USE op2);
size(4);
format %{ "CMP $op1,$op2\t! unsigned long" %}
opcode(Assembler::subcc_op3, Assembler::arith_op);
ins_encode(form3_rs1_simm13_rd(op1, op2, R_G0));
ins_pipe(ialu_cconly_reg_imm);
%}
// Compare Pointers
instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
match(Set pcc (CmpP op1 op2));
...
...
@@ -9421,6 +9462,44 @@ instruct cmpU_imm_branch(cmpOpU cmp, iRegI op1, immI5 op2, label labl, flagsRegU
ins_pipe(cmp_br_reg_imm);
%}
instruct cmpUL_reg_branch(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{
match(If cmp (CmpUL op1 op2));
effect(USE labl, KILL xcc);
size(12);
ins_cost(BRANCH_COST);
format %{ "CMP $op1,$op2\t! unsigned long\n\t"
"BP$cmp $labl" %}
ins_encode %{
Label* L = $labl$$label;
Assembler::Predict predict_taken =
cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
__ cmp($op1$$Register, $op2$$Register);
__ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
__ delayed()->nop();
%}
ins_pipe(cmp_br_reg_reg);
%}
instruct cmpUL_imm_branch(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{
match(If cmp (CmpUL op1 op2));
effect(USE labl, KILL xcc);
size(12);
ins_cost(BRANCH_COST);
format %{ "CMP $op1,$op2\t! unsigned long\n\t"
"BP$cmp $labl" %}
ins_encode %{
Label* L = $labl$$label;
Assembler::Predict predict_taken =
cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
__ cmp($op1$$Register, $op2$$constant);
__ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
__ delayed()->nop();
%}
ins_pipe(cmp_br_reg_imm);
%}
instruct cmpL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{
match(If cmp (CmpL op1 op2));
effect(USE labl, KILL xcc);
...
...
@@ -9649,6 +9728,42 @@ instruct cmpU_imm_branch_short(cmpOpU cmp, iRegI op1, immI5 op2, label labl, fla
ins_pipe(cbcond_reg_imm);
%}
instruct cmpUL_reg_branch_short(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{
match(If cmp (CmpUL op1 op2));
predicate(UseCBCond);
effect(USE labl, KILL xcc);
size(4);
ins_cost(BRANCH_COST);
format %{ "CXB$cmp $op1,$op2,$labl\t! unsigned long" %}
ins_encode %{
Label* L = $labl$$label;
assert(__ use_cbcond(*L), "back to back cbcond");
__ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$Register, *L);
%}
ins_short_branch(1);
ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER);
ins_pipe(cbcond_reg_reg);
%}
instruct cmpUL_imm_branch_short(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{
match(If cmp (CmpUL op1 op2));
predicate(UseCBCond);
effect(USE labl, KILL xcc);
size(4);
ins_cost(BRANCH_COST);
format %{ "CXB$cmp $op1,$op2,$labl\t! unsigned long" %}
ins_encode %{
Label* L = $labl$$label;
assert(__ use_cbcond(*L), "back to back cbcond");
__ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$constant, *L);
%}
ins_short_branch(1);
ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER);
ins_pipe(cbcond_reg_imm);
%}
instruct cmpL_reg_branch_short(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{
match(If cmp (CmpL op1 op2));
predicate(UseCBCond);
...
...
@@ -9887,6 +10002,25 @@ instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{
ins_pipe(br_cc);
%}
instruct branchConU_long(cmpOpU cmp, flagsRegUL xcc, label labl) %{
match(If cmp xcc);
effect(USE labl);
size(8);
ins_cost(BRANCH_COST);
format %{ "BP$cmp $xcc,$labl" %}
ins_encode %{
Label* L = $labl$$label;
Assembler::Predict predict_taken =
cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
__ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
__ delayed()->nop();
%}
ins_avoid_back_to_back(AVOID_BEFORE);
ins_pipe(br_cc);
%}
// Manifest a CmpL3 result in an integer register. Very painful.
// This is the test to avoid.
instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
...
...
src/cpu/x86/vm/x86_32.ad
浏览文件 @
ec969180
...
...
@@ -3948,6 +3948,26 @@ operand flagsReg_long_LEGT() %{
interface(REG_INTER);
%}
// Condition Code Register used by unsigned long compare
operand flagsReg_ulong_LTGE() %{
constraint(ALLOC_IN_RC(int_flags));
match(RegFlags);
format %{ "FLAGS_U_LTGE" %}
interface(REG_INTER);
%}
operand flagsReg_ulong_EQNE() %{
constraint(ALLOC_IN_RC(int_flags));
match(RegFlags);
format %{ "FLAGS_U_EQNE" %}
interface(REG_INTER);
%}
operand flagsReg_ulong_LEGT() %{
constraint(ALLOC_IN_RC(int_flags));
match(RegFlags);
format %{ "FLAGS_U_LEGT" %}
interface(REG_INTER);
%}
// Float register operands
operand regDPR() %{
predicate( UseSSE < 2 );
...
...
@@ -4473,7 +4493,7 @@ operand cmpOp_fcmov() %{
%}
%}
// Comparis
i
on Code used in long compares
// Comparison Code used in long compares
operand cmpOp_commute() %{
match(Bool);
...
...
@@ -4490,6 +4510,23 @@ operand cmpOp_commute() %{
%}
%}
// Comparison Code used in unsigned long compares
operand cmpOpU_commute() %{
match(Bool);
format %{ "" %}
interface(COND_INTER) %{
equal(0x4, "e");
not_equal(0x5, "ne");
less(0x7, "nbe");
greater_equal(0x6, "be");
less_equal(0x3, "nb");
greater(0x2, "b");
overflow(0x0, "o");
no_overflow(0x1, "no");
%}
%}
//----------OPERAND CLASSES----------------------------------------------------
// Operand Classes are groups of operands that are used as to simplify
// instruction definitions by not requiring the AD writer to specify separate
...
...
@@ -12382,6 +12419,44 @@ instruct cmpL_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, label labl) %{
%}
%}
//======
// Manifest a CmpUL result in the normal flags. Only good for LT or GE
// compares. Can be used for LE or GT compares by reversing arguments.
// NOT GOOD FOR EQ/NE tests.
instruct cmpUL_zero_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src, immL0 zero) %{
match(Set flags (CmpUL src zero));
ins_cost(100);
format %{ "TEST $src.hi,$src.hi" %}
opcode(0x85);
ins_encode(OpcP, RegReg_Hi2(src, src));
ins_pipe(ialu_cr_reg_reg);
%}
// Manifest a CmpUL result in the normal flags. Only good for LT or GE
// compares. Can be used for LE or GT compares by reversing arguments.
// NOT GOOD FOR EQ/NE tests.
instruct cmpUL_reg_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src1, eRegL src2, rRegI tmp) %{
match(Set flags (CmpUL src1 src2));
effect(TEMP tmp);
ins_cost(300);
format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
"MOV $tmp,$src1.hi\n\t"
"SBB $tmp,$src2.hi\t! Compute flags for unsigned long compare" %}
ins_encode(long_cmp_flags2(src1, src2, tmp));
ins_pipe(ialu_cr_reg_reg);
%}
// Unsigned long compares reg < zero/req OR reg >= zero/req.
// Just a wrapper for a normal branch, plus the predicate test.
instruct cmpUL_LTGE(cmpOpU cmp, flagsReg_ulong_LTGE flags, label labl) %{
match(If cmp flags);
effect(USE labl);
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
expand %{
jmpCon(cmp, flags, labl); // JLT or JGE...
%}
%}
// Compare 2 longs and CMOVE longs.
instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{
match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
...
...
@@ -12510,6 +12585,41 @@ instruct cmpL_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, label labl) %{
%}
%}
//======
// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares.
instruct cmpUL_zero_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src, immL0 zero, rRegI tmp) %{
match(Set flags (CmpUL src zero));
effect(TEMP tmp);
ins_cost(200);
format %{ "MOV $tmp,$src.lo\n\t"
"OR $tmp,$src.hi\t! Unsigned long is EQ/NE 0?" %}
ins_encode(long_cmp_flags0(src, tmp));
ins_pipe(ialu_reg_reg_long);
%}
// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares.
instruct cmpUL_reg_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src1, eRegL src2) %{
match(Set flags (CmpUL src1 src2));
ins_cost(200+300);
format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
"JNE,s skip\n\t"
"CMP $src1.hi,$src2.hi\n\t"
"skip:\t" %}
ins_encode(long_cmp_flags1(src1, src2));
ins_pipe(ialu_cr_reg_reg);
%}
// Unsigned long compare reg == zero/reg OR reg != zero/reg
// Just a wrapper for a normal branch, plus the predicate test.
instruct cmpUL_EQNE(cmpOpU cmp, flagsReg_ulong_EQNE flags, label labl) %{
match(If cmp flags);
effect(USE labl);
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
expand %{
jmpCon(cmp, flags, labl); // JEQ or JNE...
%}
%}
// Compare 2 longs and CMOVE longs.
instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{
match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
...
...
@@ -12643,6 +12753,46 @@ instruct cmpL_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, label labl) %{
%}
%}
//======
// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares.
// Same as cmpUL_reg_flags_LEGT except must negate src
instruct cmpUL_zero_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src, immL0 zero, rRegI tmp) %{
match(Set flags (CmpUL src zero));
effect(TEMP tmp);
ins_cost(300);
format %{ "XOR $tmp,$tmp\t# Unsigned long compare for -$src < 0, use commuted test\n\t"
"CMP $tmp,$src.lo\n\t"
"SBB $tmp,$src.hi\n\t" %}
ins_encode(long_cmp_flags3(src, tmp));
ins_pipe(ialu_reg_reg_long);
%}
// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares.
// Same as cmpUL_reg_flags_LTGE except operands swapped. Swapping operands
// requires a commuted test to get the same result.
instruct cmpUL_reg_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src1, eRegL src2, rRegI tmp) %{
match(Set flags (CmpUL src1 src2));
effect(TEMP tmp);
ins_cost(300);
format %{ "CMP $src2.lo,$src1.lo\t! Unsigned long compare, swapped operands, use with commuted test\n\t"
"MOV $tmp,$src2.hi\n\t"
"SBB $tmp,$src1.hi\t! Compute flags for unsigned long compare" %}
ins_encode(long_cmp_flags2( src2, src1, tmp));
ins_pipe(ialu_cr_reg_reg);
%}
// Unsigned long compares reg < zero/req OR reg >= zero/req.
// Just a wrapper for a normal branch, plus the predicate test
instruct cmpUL_LEGT(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, label labl) %{
match(If cmp flags);
effect(USE labl);
predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
ins_cost(300);
expand %{
jmpCon(cmp, flags, labl); // JGT or JLE...
%}
%}
// Compare 2 longs and CMOVE longs.
instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{
match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
...
...
src/cpu/x86/vm/x86_64.ad
浏览文件 @
ec969180
...
...
@@ -11068,6 +11068,48 @@ instruct cmpL3_reg_reg(rRegI dst, rRegL src1, rRegL src2, rFlagsReg flags)
ins_pipe(pipe_slow);
%}
// Unsigned long compare Instructions; really, same as signed long except they
// produce an rFlagsRegU instead of rFlagsReg.
instruct compUL_rReg(rFlagsRegU cr, rRegL op1, rRegL op2)
%{
match(Set cr (CmpUL op1 op2));
format %{ "cmpq $op1, $op2\t# unsigned" %}
opcode(0x3B); /* Opcode 3B /r */
ins_encode(REX_reg_reg_wide(op1, op2), OpcP, reg_reg(op1, op2));
ins_pipe(ialu_cr_reg_reg);
%}
instruct compUL_rReg_imm(rFlagsRegU cr, rRegL op1, immL32 op2)
%{
match(Set cr (CmpUL op1 op2));
format %{ "cmpq $op1, $op2\t# unsigned" %}
opcode(0x81, 0x07); /* Opcode 81 /7 */
ins_encode(OpcSErm_wide(op1, op2), Con8or32(op2));
ins_pipe(ialu_cr_reg_imm);
%}
instruct compUL_rReg_mem(rFlagsRegU cr, rRegL op1, memory op2)
%{
match(Set cr (CmpUL op1 (LoadL op2)));
format %{ "cmpq $op1, $op2\t# unsigned" %}
opcode(0x3B); /* Opcode 3B /r */
ins_encode(REX_reg_mem_wide(op1, op2), OpcP, reg_mem(op1, op2));
ins_pipe(ialu_cr_reg_mem);
%}
instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero)
%{
match(Set cr (CmpUL src zero));
format %{ "testq $src, $src\t# unsigned" %}
opcode(0x85);
ins_encode(REX_reg_reg_wide(src, src), OpcP, reg_reg(src, src));
ins_pipe(ialu_cr_reg_imm);
%}
//----------Max and Min--------------------------------------------------------
// Min Instructions
...
...
src/share/vm/adlc/archDesc.cpp
浏览文件 @
ec969180
...
...
@@ -1189,6 +1189,7 @@ void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) {
||
strcmp
(
idealName
,
"CmpP"
)
==
0
||
strcmp
(
idealName
,
"CmpN"
)
==
0
||
strcmp
(
idealName
,
"CmpL"
)
==
0
||
strcmp
(
idealName
,
"CmpUL"
)
==
0
||
strcmp
(
idealName
,
"CmpD"
)
==
0
||
strcmp
(
idealName
,
"CmpF"
)
==
0
||
strcmp
(
idealName
,
"FastLock"
)
==
0
...
...
src/share/vm/opto/classes.hpp
浏览文件 @
ec969180
...
...
@@ -79,6 +79,7 @@ macro(CmpL3)
macro
(
CmpLTMask
)
macro
(
CmpP
)
macro
(
CmpU
)
macro
(
CmpUL
)
macro
(
CompareAndSwapI
)
macro
(
CompareAndSwapL
)
macro
(
CompareAndSwapP
)
...
...
src/share/vm/opto/loopPredicate.cpp
浏览文件 @
ec969180
...
...
@@ -28,6 +28,7 @@
#include "opto/callnode.hpp"
#include "opto/connode.hpp"
#include "opto/loopnode.hpp"
#include "opto/matcher.hpp"
#include "opto/mulnode.hpp"
#include "opto/rootnode.hpp"
#include "opto/subnode.hpp"
...
...
@@ -593,50 +594,140 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invari
// max(scale*i + offset) = scale*init + offset
BoolNode
*
PhaseIdealLoop
::
rc_predicate
(
IdealLoopTree
*
loop
,
Node
*
ctrl
,
int
scale
,
Node
*
offset
,
Node
*
init
,
Node
*
limit
,
Node
*
stride
,
Node
*
range
,
bool
upper
)
{
Node
*
init
,
Node
*
limit
,
jint
stride
,
Node
*
range
,
bool
upper
,
bool
&
overflow
)
{
jint
con_limit
=
limit
->
is_Con
()
?
limit
->
get_int
()
:
0
;
jint
con_init
=
init
->
is_Con
()
?
init
->
get_int
()
:
0
;
jint
con_offset
=
offset
->
is_Con
()
?
offset
->
get_int
()
:
0
;
stringStream
*
predString
=
NULL
;
if
(
TraceLoopPredicate
)
{
predString
=
new
stringStream
();
predString
->
print
(
"rc_predicate "
);
}
Node
*
max_idx_expr
=
init
;
int
stride_con
=
stride
->
get_int
();
if
((
stride_con
>
0
)
==
(
scale
>
0
)
==
upper
)
{
if
(
LoopLimitCheck
)
{
// With LoopLimitCheck limit is not exact.
// Calculate exact limit here.
// Note, counted loop's test is '<' or '>'.
limit
=
exact_limit
(
loop
);
max_idx_expr
=
new
(
C
)
SubINode
(
limit
,
stride
);
register_new_node
(
max_idx_expr
,
ctrl
);
if
(
TraceLoopPredicate
)
predString
->
print
(
"(limit - stride) "
);
overflow
=
false
;
Node
*
max_idx_expr
=
NULL
;
const
TypeInt
*
idx_type
=
TypeInt
::
INT
;
if
((
stride
>
0
)
==
(
scale
>
0
)
==
upper
)
{
if
(
TraceLoopPredicate
)
{
predString
->
print
(
limit
->
is_Con
()
?
"(%d "
:
"(limit "
,
con_limit
);
predString
->
print
(
"- %d) "
,
stride
);
}
// Check if (limit - stride) may overflow
const
TypeInt
*
limit_type
=
_igvn
.
type
(
limit
)
->
isa_int
();
jint
limit_lo
=
limit_type
->
_lo
;
jint
limit_hi
=
limit_type
->
_hi
;
jint
res_lo
=
limit_lo
-
stride
;
jint
res_hi
=
limit_hi
-
stride
;
if
((
stride
>
0
&&
(
res_lo
<
limit_lo
))
||
(
stride
<
0
&&
(
res_hi
>
limit_hi
)))
{
// No overflow possible
ConINode
*
con_stride
=
_igvn
.
intcon
(
stride
);
set_ctrl
(
con_stride
,
C
->
root
());
max_idx_expr
=
new
(
C
)
SubINode
(
limit
,
con_stride
);
idx_type
=
TypeInt
::
make
(
limit_lo
-
stride
,
limit_hi
-
stride
,
limit_type
->
_widen
);
}
else
{
max_idx_expr
=
new
(
C
)
SubINode
(
limit
,
stride
);
register_new_node
(
max_idx_expr
,
ctrl
);
if
(
TraceLoopPredicate
)
predString
->
print
(
"(limit - stride) "
);
// May overflow
overflow
=
true
;
limit
=
new
(
C
)
ConvI2LNode
(
limit
);
register_new_node
(
limit
,
ctrl
);
ConLNode
*
con_stride
=
_igvn
.
longcon
(
stride
);
set_ctrl
(
con_stride
,
C
->
root
());
max_idx_expr
=
new
(
C
)
SubLNode
(
limit
,
con_stride
);
}
register_new_node
(
max_idx_expr
,
ctrl
);
}
else
{
if
(
TraceLoopPredicate
)
predString
->
print
(
"init "
);
if
(
TraceLoopPredicate
)
{
predString
->
print
(
init
->
is_Con
()
?
"%d "
:
"init "
,
con_init
);
}
idx_type
=
_igvn
.
type
(
init
)
->
isa_int
();
max_idx_expr
=
init
;
}
if
(
scale
!=
1
)
{
ConNode
*
con_scale
=
_igvn
.
intcon
(
scale
);
max_idx_expr
=
new
(
C
)
MulINode
(
max_idx_expr
,
con_scale
);
set_ctrl
(
con_scale
,
C
->
root
());
if
(
TraceLoopPredicate
)
{
predString
->
print
(
"* %d "
,
scale
);
}
// Check if (scale * max_idx_expr) may overflow
const
TypeInt
*
scale_type
=
TypeInt
::
make
(
scale
);
MulINode
*
mul
=
new
(
C
)
MulINode
(
max_idx_expr
,
con_scale
);
idx_type
=
(
TypeInt
*
)
mul
->
mul_ring
(
idx_type
,
scale_type
);
if
(
overflow
||
TypeInt
::
INT
->
higher_equal
(
idx_type
))
{
// May overflow
mul
->
destruct
();
if
(
!
overflow
)
{
max_idx_expr
=
new
(
C
)
ConvI2LNode
(
max_idx_expr
);
register_new_node
(
max_idx_expr
,
ctrl
);
}
overflow
=
true
;
con_scale
=
_igvn
.
longcon
(
scale
);
set_ctrl
(
con_scale
,
C
->
root
());
max_idx_expr
=
new
(
C
)
MulLNode
(
max_idx_expr
,
con_scale
);
}
else
{
// No overflow possible
max_idx_expr
=
mul
;
}
register_new_node
(
max_idx_expr
,
ctrl
);
if
(
TraceLoopPredicate
)
predString
->
print
(
"* %d "
,
scale
);
}
if
(
offset
&&
(
!
offset
->
is_Con
()
||
offset
->
get_int
()
!=
0
)){
if
(
offset
&&
(
!
offset
->
is_Con
()
||
con_offset
!=
0
)){
if
(
TraceLoopPredicate
)
{
predString
->
print
(
offset
->
is_Con
()
?
"+ %d "
:
"+ offset"
,
con_offset
);
}
// Check if (max_idx_expr + offset) may overflow
const
TypeInt
*
offset_type
=
_igvn
.
type
(
offset
)
->
isa_int
();
jint
lo
=
idx_type
->
_lo
+
offset_type
->
_lo
;
jint
hi
=
idx_type
->
_hi
+
offset_type
->
_hi
;
if
(
overflow
||
(
lo
>
hi
)
||
((
idx_type
->
_lo
&
offset_type
->
_lo
)
<
0
&&
lo
>=
0
)
||
((
~
(
idx_type
->
_hi
|
offset_type
->
_hi
))
<
0
&&
hi
<
0
))
{
// May overflow
if
(
!
overflow
)
{
max_idx_expr
=
new
(
C
)
ConvI2LNode
(
max_idx_expr
);
register_new_node
(
max_idx_expr
,
ctrl
);
}
overflow
=
true
;
offset
=
new
(
C
)
ConvI2LNode
(
offset
);
register_new_node
(
offset
,
ctrl
);
max_idx_expr
=
new
(
C
)
AddLNode
(
max_idx_expr
,
offset
);
}
else
{
// No overflow possible
max_idx_expr
=
new
(
C
)
AddINode
(
max_idx_expr
,
offset
);
}
register_new_node
(
max_idx_expr
,
ctrl
);
if
(
TraceLoopPredicate
)
if
(
offset
->
is_Con
())
predString
->
print
(
"+ %d "
,
offset
->
get_int
());
else
predString
->
print
(
"+ offset "
);
}
CmpUNode
*
cmp
=
new
(
C
)
CmpUNode
(
max_idx_expr
,
range
);
CmpNode
*
cmp
=
NULL
;
if
(
overflow
)
{
// Integer expressions may overflow, do long comparison
range
=
new
(
C
)
ConvI2LNode
(
range
);
register_new_node
(
range
,
ctrl
);
if
(
!
Matcher
::
has_match_rule
(
Op_CmpUL
))
{
// We don't support unsigned long comparisons. Set 'max_idx_expr'
// to max_julong if < 0 to make the signed comparison fail.
ConINode
*
sign_pos
=
_igvn
.
intcon
(
BitsPerLong
-
1
);
set_ctrl
(
sign_pos
,
C
->
root
());
Node
*
sign_bit_mask
=
new
(
C
)
RShiftLNode
(
max_idx_expr
,
sign_pos
);
register_new_node
(
sign_bit_mask
,
ctrl
);
// OR with sign bit to set all bits to 1 if negative (otherwise no change)
max_idx_expr
=
new
(
C
)
OrLNode
(
max_idx_expr
,
sign_bit_mask
);
register_new_node
(
max_idx_expr
,
ctrl
);
// AND with 0x7ff... to unset the sign bit
ConLNode
*
remove_sign_mask
=
_igvn
.
longcon
(
max_jlong
);
set_ctrl
(
remove_sign_mask
,
C
->
root
());
max_idx_expr
=
new
(
C
)
AndLNode
(
max_idx_expr
,
remove_sign_mask
);
register_new_node
(
max_idx_expr
,
ctrl
);
cmp
=
new
(
C
)
CmpLNode
(
max_idx_expr
,
range
);
}
else
{
cmp
=
new
(
C
)
CmpULNode
(
max_idx_expr
,
range
);
}
}
else
{
cmp
=
new
(
C
)
CmpUNode
(
max_idx_expr
,
range
);
}
register_new_node
(
cmp
,
ctrl
);
BoolNode
*
bol
=
new
(
C
)
BoolNode
(
cmp
,
BoolTest
::
lt
);
register_new_node
(
bol
,
ctrl
);
...
...
@@ -786,8 +877,11 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
assert
(
ok
,
"must be index expression"
);
Node
*
init
=
cl
->
init_trip
();
Node
*
limit
=
cl
->
limit
();
Node
*
stride
=
cl
->
stride
();
// Limit is not exact.
// Calculate exact limit here.
// Note, counted loop's test is '<' or '>'.
Node
*
limit
=
exact_limit
(
loop
);
int
stride
=
cl
->
stride
()
->
get_int
();
// Build if's for the upper and lower bound tests. The
// lower_bound test will dominate the upper bound test and all
...
...
@@ -805,16 +899,18 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
assert
(
invar
.
is_invariant
(
offset
),
"offset must be loop invariant"
);
offset
=
invar
.
clone
(
offset
,
ctrl
);
}
// If predicate expressions may overflow in the integer range, longs are used.
bool
overflow
=
false
;
// Test the lower bound
Node
*
lower_bound_bol
=
rc_predicate
(
loop
,
ctrl
,
scale
,
offset
,
init
,
limit
,
stride
,
rng
,
false
);
Node
*
lower_bound_bol
=
rc_predicate
(
loop
,
ctrl
,
scale
,
offset
,
init
,
limit
,
stride
,
rng
,
false
,
overflow
);
IfNode
*
lower_bound_iff
=
lower_bound_proj
->
in
(
0
)
->
as_If
();
_igvn
.
hash_delete
(
lower_bound_iff
);
lower_bound_iff
->
set_req
(
1
,
lower_bound_bol
);
if
(
TraceLoopPredicate
)
tty
->
print_cr
(
"lower bound check if: %d"
,
lower_bound_iff
->
_idx
);
// Test the upper bound
Node
*
upper_bound_bol
=
rc_predicate
(
loop
,
lower_bound_proj
,
scale
,
offset
,
init
,
limit
,
stride
,
rng
,
true
);
Node
*
upper_bound_bol
=
rc_predicate
(
loop
,
lower_bound_proj
,
scale
,
offset
,
init
,
limit
,
stride
,
rng
,
true
,
overflow
);
IfNode
*
upper_bound_iff
=
upper_bound_proj
->
in
(
0
)
->
as_If
();
_igvn
.
hash_delete
(
upper_bound_iff
);
upper_bound_iff
->
set_req
(
1
,
upper_bound_bol
);
...
...
src/share/vm/opto/loopnode.hpp
浏览文件 @
ec969180
...
...
@@ -905,8 +905,8 @@ public:
// Construct a range check for a predicate if
BoolNode
*
rc_predicate
(
IdealLoopTree
*
loop
,
Node
*
ctrl
,
int
scale
,
Node
*
offset
,
Node
*
init
,
Node
*
limit
,
Node
*
stride
,
Node
*
range
,
bool
upper
);
Node
*
init
,
Node
*
limit
,
jint
stride
,
Node
*
range
,
bool
upper
,
bool
&
overflow
);
// Implementation of the loop predication to promote checks outside the loop
bool
loop_predication_impl
(
IdealLoopTree
*
loop
);
...
...
src/share/vm/opto/output.cpp
浏览文件 @
ec969180
...
...
@@ -2095,6 +2095,7 @@ void Scheduling::AddNodeToAvailableList(Node *n) {
if
(
last
->
is_MachIf
()
&&
last
->
in
(
1
)
==
n
&&
(
op
==
Op_CmpI
||
op
==
Op_CmpU
||
op
==
Op_CmpUL
||
op
==
Op_CmpP
||
op
==
Op_CmpF
||
op
==
Op_CmpD
||
...
...
src/share/vm/opto/subnode.cpp
浏览文件 @
ec969180
...
...
@@ -707,6 +707,60 @@ const Type *CmpLNode::sub( const Type *t1, const Type *t2 ) const {
return
TypeInt
::
CC
;
// else use worst case results
}
// Simplify a CmpUL (compare 2 unsigned longs) node, based on local information.
// If both inputs are constants, compare them.
const
Type
*
CmpULNode
::
sub
(
const
Type
*
t1
,
const
Type
*
t2
)
const
{
assert
(
!
t1
->
isa_ptr
(),
"obsolete usage of CmpUL"
);
// comparing two unsigned longs
const
TypeLong
*
r0
=
t1
->
is_long
();
// Handy access
const
TypeLong
*
r1
=
t2
->
is_long
();
// Current installed version
// Compare ranges for non-overlap
julong
lo0
=
r0
->
_lo
;
julong
hi0
=
r0
->
_hi
;
julong
lo1
=
r1
->
_lo
;
julong
hi1
=
r1
->
_hi
;
// If either one has both negative and positive values,
// it therefore contains both 0 and -1, and since [0..-1] is the
// full unsigned range, the type must act as an unsigned bottom.
bool
bot0
=
((
jlong
)(
lo0
^
hi0
)
<
0
);
bool
bot1
=
((
jlong
)(
lo1
^
hi1
)
<
0
);
if
(
bot0
||
bot1
)
{
// All unsigned values are LE -1 and GE 0.
if
(
lo0
==
0
&&
hi0
==
0
)
{
return
TypeInt
::
CC_LE
;
// 0 <= bot
}
else
if
((
jlong
)
lo0
==
-
1
&&
(
jlong
)
hi0
==
-
1
)
{
return
TypeInt
::
CC_GE
;
// -1 >= bot
}
else
if
(
lo1
==
0
&&
hi1
==
0
)
{
return
TypeInt
::
CC_GE
;
// bot >= 0
}
else
if
((
jlong
)
lo1
==
-
1
&&
(
jlong
)
hi1
==
-
1
)
{
return
TypeInt
::
CC_LE
;
// bot <= -1
}
}
else
{
// We can use ranges of the form [lo..hi] if signs are the same.
assert
(
lo0
<=
hi0
&&
lo1
<=
hi1
,
"unsigned ranges are valid"
);
// results are reversed, '-' > '+' for unsigned compare
if
(
hi0
<
lo1
)
{
return
TypeInt
::
CC_LT
;
// smaller
}
else
if
(
lo0
>
hi1
)
{
return
TypeInt
::
CC_GT
;
// greater
}
else
if
(
hi0
==
lo1
&&
lo0
==
hi1
)
{
return
TypeInt
::
CC_EQ
;
// Equal results
}
else
if
(
lo0
>=
hi1
)
{
return
TypeInt
::
CC_GE
;
}
else
if
(
hi0
<=
lo1
)
{
return
TypeInt
::
CC_LE
;
}
}
return
TypeInt
::
CC
;
// else use worst case results
}
//=============================================================================
//------------------------------sub--------------------------------------------
// Simplify an CmpP (compare 2 pointers) node, based on local information.
...
...
src/share/vm/opto/subnode.hpp
浏览文件 @
ec969180
...
...
@@ -192,6 +192,15 @@ public:
virtual
const
Type
*
sub
(
const
Type
*
,
const
Type
*
)
const
;
};
//------------------------------CmpULNode---------------------------------------
// Compare 2 unsigned long values, returning condition codes (-1, 0 or 1).
class
CmpULNode
:
public
CmpNode
{
public:
CmpULNode
(
Node
*
in1
,
Node
*
in2
)
:
CmpNode
(
in1
,
in2
)
{
}
virtual
int
Opcode
()
const
;
virtual
const
Type
*
sub
(
const
Type
*
,
const
Type
*
)
const
;
};
//------------------------------CmpL3Node--------------------------------------
// Compare 2 long values, returning integer value (-1, 0 or 1).
class
CmpL3Node
:
public
CmpLNode
{
...
...
src/share/vm/runtime/vmStructs.cpp
浏览文件 @
ec969180
...
...
@@ -1942,6 +1942,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
declare_c2_type(CmpPNode, CmpNode) \
declare_c2_type(CmpNNode, CmpNode) \
declare_c2_type(CmpLNode, CmpNode) \
declare_c2_type(CmpULNode, CmpNode) \
declare_c2_type(CmpL3Node, CmpLNode) \
declare_c2_type(CmpFNode, CmpNode) \
declare_c2_type(CmpF3Node, CmpFNode) \
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录