8183390: Fix and re-enable post loop vectorization
Reviewed-by: roland, thartmann, kvn
This commit is contained in:
parent
500f9a577b
commit
741be46138
src/hotspot
cpu/x86
share
test/hotspot/jtreg/compiler
c2/irTests
vectorization/runner
ArrayCopyTest.javaArrayIndexFillTest.javaArrayInvariantFillTest.javaArrayShiftOpTest.javaArrayTypeConvertTest.javaArrayUnsafeOpTest.javaBasicBooleanOpTest.javaBasicByteOpTest.javaBasicCharOpTest.javaBasicDoubleOpTest.javaBasicFloatOpTest.javaBasicIntOpTest.javaBasicLongOpTest.javaBasicShortOpTest.javaLoopArrayIndexComputeTest.javaLoopCombinedOpTest.javaLoopControlFlowTest.javaLoopLiveOutNodesTest.javaLoopRangeStrideTest.javaLoopReductionOpTest.javaMultipleLoopsTest.javaStripMinedLoopTest.javaVectorizationTestRunner.java
@ -48,20 +48,6 @@ inline Assembler::AvxVectorLen C2_MacroAssembler::vector_length_encoding(int vle
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::setvectmask(Register dst, Register src, KRegister mask) {
|
||||
guarantee(PostLoopMultiversioning, "must be");
|
||||
Assembler::movl(dst, 1);
|
||||
Assembler::shlxl(dst, dst, src);
|
||||
Assembler::decl(dst);
|
||||
Assembler::kmovdl(mask, dst);
|
||||
Assembler::movl(dst, src);
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::restorevectmask(KRegister mask) {
|
||||
guarantee(PostLoopMultiversioning, "must be");
|
||||
Assembler::knotwl(mask, k0);
|
||||
}
|
||||
|
||||
#if INCLUDE_RTM_OPT
|
||||
|
||||
// Update rtm_counters based on abort status
|
||||
@ -1947,7 +1933,6 @@ void C2_MacroAssembler::reduce8L(int opcode, Register dst, Register src1, XMMReg
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::genmask(KRegister dst, Register len, Register temp) {
|
||||
assert(ArrayOperationPartialInlineSize > 0 && ArrayOperationPartialInlineSize <= 64, "invalid");
|
||||
mov64(temp, -1L);
|
||||
bzhiq(temp, temp, len);
|
||||
kmovql(dst, temp);
|
||||
|
@ -30,10 +30,6 @@
|
||||
public:
|
||||
Assembler::AvxVectorLen vector_length_encoding(int vlen_in_bytes);
|
||||
|
||||
// special instructions for EVEX
|
||||
void setvectmask(Register dst, Register src, KRegister mask);
|
||||
void restorevectmask(KRegister mask);
|
||||
|
||||
// Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file.
|
||||
// See full desription in macroAssembler_x86.cpp.
|
||||
void fast_lock(Register obj, Register box, Register tmp,
|
||||
|
@ -4671,16 +4671,6 @@ void MacroAssembler::restore_cpu_control_state_after_jni() {
|
||||
}
|
||||
// Clear upper bits of YMM registers to avoid SSE <-> AVX transition penalty.
|
||||
vzeroupper();
|
||||
// Reset k1 to 0xffff.
|
||||
|
||||
#ifdef COMPILER2
|
||||
if (PostLoopMultiversioning && VM_Version::supports_evex()) {
|
||||
push(rcx);
|
||||
movl(rcx, 0xffff);
|
||||
kmovwl(k1, rcx);
|
||||
pop(rcx);
|
||||
}
|
||||
#endif // COMPILER2
|
||||
|
||||
#ifndef _LP64
|
||||
// Either restore the x87 floating pointer control word after returning
|
||||
|
@ -2846,23 +2846,6 @@ instruct ShouldNotReachHere() %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// =================================EVEX special===============================
|
||||
// Existing partial implementation for post-loop multi-versioning computes
|
||||
// the mask corresponding to tail loop in K1 opmask register. This may then be
|
||||
// used for predicating instructions in loop body during last post-loop iteration.
|
||||
// TODO: Remove hard-coded K1 usage while fixing existing post-loop
|
||||
// multiversioning support.
|
||||
instruct setMask(rRegI dst, rRegI src, kReg_K1 mask) %{
|
||||
predicate(PostLoopMultiversioning && Matcher::has_predicated_vectors());
|
||||
match(Set dst (SetVectMaskI src));
|
||||
effect(TEMP dst);
|
||||
format %{ "setvectmask $dst, $src" %}
|
||||
ins_encode %{
|
||||
__ setvectmask($dst$$Register, $src$$Register, $mask$$KRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
instruct addF_reg(regF dst, regF src) %{
|
||||
|
@ -260,17 +260,7 @@ source %{
|
||||
// instructions, to allow sign-masking or sign-bit flipping. They allow
|
||||
// fast versions of NegF/NegD and AbsF/AbsD.
|
||||
|
||||
void reg_mask_init() {
|
||||
if (Matcher::has_predicated_vectors()) {
|
||||
// Post-loop multi-versioning expects mask to be present in K1 register, till the time
|
||||
// its fixed, RA should not be allocting K1 register, this shall prevent any accidental
|
||||
// curruption of value held in K1 register.
|
||||
if (PostLoopMultiversioning) {
|
||||
const_cast<RegMask*>(&_VECTMASK_REG_mask)->Remove(OptoReg::as_OptoReg(k1->as_VMReg()));
|
||||
const_cast<RegMask*>(&_VECTMASK_REG_mask)->Remove(OptoReg::as_OptoReg(k1->as_VMReg()->next()));
|
||||
}
|
||||
}
|
||||
}
|
||||
void reg_mask_init() {}
|
||||
|
||||
// Note: 'double' and 'long long' have 32-bits alignment on x86.
|
||||
static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) {
|
||||
@ -12610,7 +12600,6 @@ instruct jmpCon(cmpOp cop, eFlagsReg cr, label labl) %{
|
||||
|
||||
// Jump Direct Conditional - Label defines a relative address from Jcc+1
|
||||
instruct jmpLoopEnd(cmpOp cop, eFlagsReg cr, label labl) %{
|
||||
predicate(!n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cr);
|
||||
effect(USE labl);
|
||||
|
||||
@ -12626,7 +12615,6 @@ instruct jmpLoopEnd(cmpOp cop, eFlagsReg cr, label labl) %{
|
||||
|
||||
// Jump Direct Conditional - Label defines a relative address from Jcc+1
|
||||
instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
|
||||
predicate(!n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cmp);
|
||||
effect(USE labl);
|
||||
|
||||
@ -12641,7 +12629,6 @@ instruct jmpLoopEndU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
|
||||
%}
|
||||
|
||||
instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
|
||||
predicate(!n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cmp);
|
||||
effect(USE labl);
|
||||
|
||||
@ -12655,66 +12642,6 @@ instruct jmpLoopEndUCF(cmpOpUCF cop, eFlagsRegUCF cmp, label labl) %{
|
||||
ins_pipe( pipe_jcc );
|
||||
%}
|
||||
|
||||
// mask version
|
||||
// Jump Direct Conditional - Label defines a relative address from Jcc+1
|
||||
// Bounded mask operand used in following patten is needed for
|
||||
// post-loop multiversioning.
|
||||
instruct jmpLoopEnd_and_restoreMask(cmpOp cop, kReg_K1 ktmp, eFlagsReg cr, label labl) %{
|
||||
predicate(PostLoopMultiversioning && n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cr);
|
||||
effect(USE labl, TEMP ktmp);
|
||||
|
||||
ins_cost(400);
|
||||
format %{ "J$cop $labl\t# Loop end\n\t"
|
||||
"restorevectmask \t# vector mask restore for loops" %}
|
||||
size(10);
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
|
||||
__ restorevectmask($ktmp$$KRegister);
|
||||
%}
|
||||
ins_pipe( pipe_jcc );
|
||||
%}
|
||||
|
||||
// Jump Direct Conditional - Label defines a relative address from Jcc+1
|
||||
// Bounded mask operand used in following patten is needed for
|
||||
// post-loop multiversioning.
|
||||
instruct jmpLoopEndU_and_restoreMask(cmpOpU cop, kReg_K1 ktmp, eFlagsRegU cmp, label labl) %{
|
||||
predicate(PostLoopMultiversioning && n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cmp);
|
||||
effect(USE labl, TEMP ktmp);
|
||||
|
||||
ins_cost(400);
|
||||
format %{ "J$cop,u $labl\t# Loop end\n\t"
|
||||
"restorevectmask \t# vector mask restore for loops" %}
|
||||
size(10);
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
|
||||
__ restorevectmask($ktmp$$KRegister);
|
||||
%}
|
||||
ins_pipe( pipe_jcc );
|
||||
%}
|
||||
|
||||
// Bounded mask operand used in following patten is needed for
|
||||
// post-loop multiversioning.
|
||||
instruct jmpLoopEndUCF_and_restoreMask(cmpOpUCF cop, kReg_K1 ktmp, eFlagsRegUCF cmp, label labl) %{
|
||||
predicate(PostLoopMultiversioning && n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cmp);
|
||||
effect(USE labl, TEMP ktmp);
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "J$cop,u $labl\t# Loop end\n\t"
|
||||
"restorevectmask \t# vector mask restore for loops" %}
|
||||
size(10);
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
|
||||
__ restorevectmask($ktmp$$KRegister);
|
||||
%}
|
||||
ins_pipe( pipe_jcc );
|
||||
%}
|
||||
|
||||
// Jump Direct Conditional - using unsigned comparison
|
||||
instruct jmpConU(cmpOpU cop, eFlagsRegU cmp, label labl) %{
|
||||
match(If cop cmp);
|
||||
|
@ -454,16 +454,6 @@ void reg_mask_init() {
|
||||
// _FLOAT_REG_LEGACY_mask/_FLOAT_REG_EVEX_mask is generated by adlc
|
||||
// from the float_reg_legacy/float_reg_evex register class.
|
||||
_FLOAT_REG_mask = VM_Version::supports_evex() ? _FLOAT_REG_EVEX_mask : _FLOAT_REG_LEGACY_mask;
|
||||
|
||||
if (Matcher::has_predicated_vectors()) {
|
||||
// Post-loop multi-versioning expects mask to be present in K1 register, till the time
|
||||
// its fixed, RA should not be allocting K1 register, this shall prevent any accidental
|
||||
// curruption of value held in K1 register.
|
||||
if (PostLoopMultiversioning) {
|
||||
const_cast<RegMask*>(&_VECTMASK_REG_mask)->Remove(OptoReg::as_OptoReg(k1->as_VMReg()));
|
||||
const_cast<RegMask*>(&_VECTMASK_REG_mask)->Remove(OptoReg::as_OptoReg(k1->as_VMReg()->next()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool generate_vzeroupper(Compile* C) {
|
||||
@ -12713,7 +12703,6 @@ instruct jmpCon(cmpOp cop, rFlagsReg cr, label labl)
|
||||
// Jump Direct Conditional - Label defines a relative address from Jcc+1
|
||||
instruct jmpLoopEnd(cmpOp cop, rFlagsReg cr, label labl)
|
||||
%{
|
||||
predicate(!n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cr);
|
||||
effect(USE labl);
|
||||
|
||||
@ -12729,7 +12718,6 @@ instruct jmpLoopEnd(cmpOp cop, rFlagsReg cr, label labl)
|
||||
|
||||
// Jump Direct Conditional - Label defines a relative address from Jcc+1
|
||||
instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
|
||||
predicate(!n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cmp);
|
||||
effect(USE labl);
|
||||
|
||||
@ -12744,7 +12732,6 @@ instruct jmpLoopEndU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
|
||||
%}
|
||||
|
||||
instruct jmpLoopEndUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
|
||||
predicate(!n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cmp);
|
||||
effect(USE labl);
|
||||
|
||||
@ -12758,67 +12745,6 @@ instruct jmpLoopEndUCF(cmpOpUCF cop, rFlagsRegUCF cmp, label labl) %{
|
||||
ins_pipe(pipe_jcc);
|
||||
%}
|
||||
|
||||
// mask version
|
||||
// Jump Direct Conditional - Label defines a relative address from Jcc+1
|
||||
// Bounded mask operand used in following patten is needed for
|
||||
// post-loop multiversioning.
|
||||
instruct jmpLoopEnd_and_restoreMask(cmpOp cop, kReg_K1 ktmp, rFlagsReg cr, label labl)
|
||||
%{
|
||||
predicate(PostLoopMultiversioning && n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cr);
|
||||
effect(USE labl, TEMP ktmp);
|
||||
|
||||
ins_cost(400);
|
||||
format %{ "j$cop $labl\t# loop end\n\t"
|
||||
"restorevectmask \t# vector mask restore for loops" %}
|
||||
size(10);
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
|
||||
__ restorevectmask($ktmp$$KRegister);
|
||||
%}
|
||||
ins_pipe(pipe_jcc);
|
||||
%}
|
||||
|
||||
// Jump Direct Conditional - Label defines a relative address from Jcc+1
|
||||
// Bounded mask operand used in following patten is needed for
|
||||
// post-loop multiversioning.
|
||||
instruct jmpLoopEndU_and_restoreMask(cmpOpU cop, kReg_K1 ktmp, rFlagsRegU cmp, label labl) %{
|
||||
predicate(PostLoopMultiversioning && n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cmp);
|
||||
effect(USE labl, TEMP ktmp);
|
||||
|
||||
ins_cost(400);
|
||||
format %{ "j$cop,u $labl\t# loop end\n\t"
|
||||
"restorevectmask \t# vector mask restore for loops" %}
|
||||
size(10);
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
|
||||
__ restorevectmask($ktmp$$KRegister);
|
||||
%}
|
||||
ins_pipe(pipe_jcc);
|
||||
%}
|
||||
|
||||
// Bounded mask operand used in following patten is needed for
|
||||
// post-loop multiversioning.
|
||||
instruct jmpLoopEndUCF_and_restoreMask(cmpOpUCF cop, kReg_K1 ktmp, rFlagsRegUCF cmp, label labl) %{
|
||||
predicate(PostLoopMultiversioning && n->has_vector_mask_set());
|
||||
match(CountedLoopEnd cop cmp);
|
||||
effect(USE labl, TEMP ktmp);
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "j$cop,u $labl\t# loop end\n\t"
|
||||
"restorevectmask \t# vector mask restore for loops" %}
|
||||
size(10);
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
|
||||
__ restorevectmask($ktmp$$KRegister);
|
||||
%}
|
||||
ins_pipe(pipe_jcc);
|
||||
%}
|
||||
|
||||
// Jump Direct Conditional - using unsigned comparison
|
||||
instruct jmpConU(cmpOpU cop, rFlagsRegU cmp, label labl) %{
|
||||
match(If cop cmp);
|
||||
|
@ -214,7 +214,6 @@ macro(MaxD)
|
||||
macro(MaxF)
|
||||
macro(MemBarAcquire)
|
||||
macro(LoadFence)
|
||||
macro(SetVectMaskI)
|
||||
macro(MemBarAcquireLock)
|
||||
macro(MemBarCPUOrder)
|
||||
macro(MemBarRelease)
|
||||
|
@ -3671,7 +3671,8 @@ bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_n
|
||||
phase->has_range_checks(this);
|
||||
}
|
||||
|
||||
if (should_unroll && !should_peel && PostLoopMultiversioning) {
|
||||
if (should_unroll && !should_peel && PostLoopMultiversioning &&
|
||||
Matcher::has_predicated_vectors()) {
|
||||
// Try to setup multiversioning on main loops before they are unrolled
|
||||
if (cl->is_main_loop() && (cl->unrolled_count() == 1)) {
|
||||
phase->insert_scalar_rced_post_loop(this, old_new);
|
||||
|
@ -4547,7 +4547,8 @@ void PhaseIdealLoop::build_and_optimize() {
|
||||
if (lpt->is_counted()) {
|
||||
CountedLoopNode *cl = lpt->_head->as_CountedLoop();
|
||||
|
||||
if (PostLoopMultiversioning && cl->is_rce_post_loop() && !cl->is_vectorized_loop()) {
|
||||
if (cl->is_rce_post_loop() && !cl->is_vectorized_loop()) {
|
||||
assert(PostLoopMultiversioning, "multiversioning must be enabled");
|
||||
// Check that the rce'd post loop is encountered first, multiversion after all
|
||||
// major main loop optimization are concluded
|
||||
if (!C->major_progress()) {
|
||||
|
@ -246,11 +246,14 @@ class CountedLoopNode : public BaseCountedLoopNode {
|
||||
// vector mapped unroll factor here
|
||||
int _slp_maximum_unroll_factor;
|
||||
|
||||
// The eventual count of vectorizable packs in slp
|
||||
int _slp_vector_pack_count;
|
||||
|
||||
public:
|
||||
CountedLoopNode(Node *entry, Node *backedge)
|
||||
: BaseCountedLoopNode(entry, backedge), _main_idx(0), _trip_count(max_juint),
|
||||
_unrolled_count_log2(0), _node_count_before_unroll(0),
|
||||
_slp_maximum_unroll_factor(0) {
|
||||
_slp_maximum_unroll_factor(0), _slp_vector_pack_count(0) {
|
||||
init_class_id(Class_CountedLoop);
|
||||
// Initialize _trip_count to the largest possible value.
|
||||
// Will be reset (lower) if the loop's trip count is known.
|
||||
@ -327,6 +330,8 @@ public:
|
||||
int node_count_before_unroll() { return _node_count_before_unroll; }
|
||||
void set_slp_max_unroll(int unroll_factor) { _slp_maximum_unroll_factor = unroll_factor; }
|
||||
int slp_max_unroll() const { return _slp_maximum_unroll_factor; }
|
||||
void set_slp_pack_count(int pack_count) { _slp_vector_pack_count = pack_count; }
|
||||
int slp_pack_count() const { return _slp_vector_pack_count; }
|
||||
|
||||
virtual LoopNode* skip_strip_mined(int expect_skeleton = 1);
|
||||
OuterStripMinedLoopNode* outer_loop() const;
|
||||
|
@ -782,11 +782,10 @@ public:
|
||||
Flag_has_call = 1 << 10,
|
||||
Flag_is_reduction = 1 << 11,
|
||||
Flag_is_scheduled = 1 << 12,
|
||||
Flag_has_vector_mask_set = 1 << 13,
|
||||
Flag_is_expensive = 1 << 14,
|
||||
Flag_is_predicated_vector = 1 << 15,
|
||||
Flag_for_post_loop_opts_igvn = 1 << 16,
|
||||
Flag_is_removed_by_peephole = 1 << 17,
|
||||
Flag_is_expensive = 1 << 13,
|
||||
Flag_is_predicated_vector = 1 << 14,
|
||||
Flag_for_post_loop_opts_igvn = 1 << 15,
|
||||
Flag_is_removed_by_peephole = 1 << 16,
|
||||
_last_flag = Flag_is_removed_by_peephole
|
||||
};
|
||||
|
||||
@ -1001,9 +1000,6 @@ public:
|
||||
|
||||
bool is_predicated_vector() const { return (_flags & Flag_is_predicated_vector) != 0; }
|
||||
|
||||
// The node is a CountedLoopEnd with a mask annotation so as to emit a restore context
|
||||
bool has_vector_mask_set() const { return (_flags & Flag_has_vector_mask_set) != 0; }
|
||||
|
||||
// Used in lcm to mark nodes that have scheduled
|
||||
bool is_scheduled() const { return (_flags & Flag_is_scheduled) != 0; }
|
||||
|
||||
|
@ -110,26 +110,9 @@ bool SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) {
|
||||
return false; // skip malformed counted loop
|
||||
}
|
||||
|
||||
bool post_loop_allowed = (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop());
|
||||
if (post_loop_allowed) {
|
||||
if (cl->is_reduction_loop()) {
|
||||
return false; // no predication mapping
|
||||
}
|
||||
Node *limit = cl->limit();
|
||||
if (limit->is_Con()) {
|
||||
return false; // non constant limits only
|
||||
}
|
||||
// Now check the limit for expressions we do not handle
|
||||
if (limit->is_Add()) {
|
||||
Node *in2 = limit->in(2);
|
||||
if (in2->is_Con()) {
|
||||
int val = in2->get_int();
|
||||
// should not try to program these cases
|
||||
if (val < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cl->is_rce_post_loop() && cl->is_reduction_loop()) {
|
||||
// Post loop vectorization doesn't support reductions
|
||||
return false;
|
||||
}
|
||||
|
||||
// skip any loop that has not been assigned max unroll by analysis
|
||||
@ -193,15 +176,21 @@ bool SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) {
|
||||
if (do_optimization) {
|
||||
assert(_packset.length() == 0, "packset must be empty");
|
||||
success = SLP_extract();
|
||||
if (PostLoopMultiversioning && Matcher::has_predicated_vectors()) {
|
||||
if (PostLoopMultiversioning) {
|
||||
if (cl->is_vectorized_loop() && cl->is_main_loop() && !cl->is_reduction_loop()) {
|
||||
IdealLoopTree *lpt_next = lpt->_next;
|
||||
IdealLoopTree *lpt_next = cl->is_strip_mined() ? lpt->_parent->_next : lpt->_next;
|
||||
CountedLoopNode *cl_next = lpt_next->_head->as_CountedLoop();
|
||||
_phase->has_range_checks(lpt_next);
|
||||
if (cl_next->is_post_loop() && !cl_next->range_checks_present()) {
|
||||
// Main loop SLP works well for manually unrolled loops. But post loop
|
||||
// vectorization doesn't work for these. To bail out the optimization
|
||||
// earlier, we have range check and loop stride conditions below.
|
||||
if (cl_next->is_post_loop() && !cl_next->range_checks_present() &&
|
||||
cl_next->stride_is_con() && abs(cl_next->stride_con()) == 1) {
|
||||
if (!cl_next->is_vectorized_loop()) {
|
||||
int slp_max_unroll_factor = cl->slp_max_unroll();
|
||||
cl_next->set_slp_max_unroll(slp_max_unroll_factor);
|
||||
// Propagate some main loop attributes to its corresponding scalar
|
||||
// rce'd post loop for vectorization with vector masks
|
||||
cl_next->set_slp_max_unroll(cl->slp_max_unroll());
|
||||
cl_next->set_slp_pack_count(cl->slp_pack_count());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,7 +218,6 @@ void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) {
|
||||
}
|
||||
|
||||
int max_vector = Matcher::max_vector_size(T_BYTE);
|
||||
bool post_loop_allowed = (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop());
|
||||
|
||||
// Process the loop, some/all of the stack entries will not be in order, ergo
|
||||
// need to preprocess the ignored initial state before we process the loop
|
||||
@ -239,6 +227,7 @@ void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) {
|
||||
n->is_reduction() ||
|
||||
n->is_AddP() ||
|
||||
n->is_Cmp() ||
|
||||
n->is_Bool() ||
|
||||
n->is_IfTrue() ||
|
||||
n->is_CountedLoop() ||
|
||||
(n == cl_exit)) {
|
||||
@ -326,9 +315,29 @@ void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) {
|
||||
}
|
||||
|
||||
if (is_slp) {
|
||||
// In the main loop, SLP works well if parts of the operations in the loop body
|
||||
// are not vectorizable and those non-vectorizable parts will be unrolled only.
|
||||
// But in post loops with vector masks, we create singleton packs directly from
|
||||
// scalars so all operations should be vectorized together. This compares the
|
||||
// number of packs in the post loop with the main loop and bail out if the post
|
||||
// loop potentially has more packs.
|
||||
if (cl->is_rce_post_loop()) {
|
||||
for (uint i = 0; i < lpt()->_body.size(); i++) {
|
||||
if (ignored_loop_nodes[i] == -1) {
|
||||
_post_block.at_put_grow(rpo_idx++, lpt()->_body.at(i));
|
||||
}
|
||||
}
|
||||
if (_post_block.length() > cl->slp_pack_count()) {
|
||||
// Clear local_loop_unroll_factor and bail out directly from here
|
||||
local_loop_unroll_factor = 0;
|
||||
cl->mark_was_slp();
|
||||
cl->set_slp_max_unroll(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we try to find the maximum supported consistent vector which the machine
|
||||
// description can use
|
||||
bool small_basic_type = false;
|
||||
bool flag_small_bt = false;
|
||||
for (uint i = 0; i < lpt()->_body.size(); i++) {
|
||||
if (ignored_loop_nodes[i] != -1) continue;
|
||||
@ -341,31 +350,9 @@ void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) {
|
||||
bt = n->bottom_type()->basic_type();
|
||||
}
|
||||
|
||||
if (post_loop_allowed) {
|
||||
if (!small_basic_type) {
|
||||
switch (bt) {
|
||||
case T_CHAR:
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
small_basic_type = true;
|
||||
break;
|
||||
|
||||
case T_LONG:
|
||||
// TODO: Remove when support completed for mask context with LONG.
|
||||
// Support needs to be augmented for logical qword operations, currently we map to dword
|
||||
// buckets for vectors on logicals as these were legacy.
|
||||
small_basic_type = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_java_primitive(bt) == false) continue;
|
||||
|
||||
int cur_max_vector = Matcher::max_vector_size(bt);
|
||||
int cur_max_vector = Matcher::max_vector_size(bt);
|
||||
|
||||
// If a max vector exists which is not larger than _local_loop_unroll_factor
|
||||
// stop looking, we already have the max vector to map to.
|
||||
@ -410,11 +397,6 @@ void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// We only process post loops on predicated targets where we want to
|
||||
// mask map the loop to a single iteration
|
||||
if (post_loop_allowed) {
|
||||
_post_block.at_put_grow(rpo_idx++, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_slp) {
|
||||
@ -422,14 +404,7 @@ void SuperWord::unrolling_analysis(int &local_loop_unroll_factor) {
|
||||
cl->mark_passed_slp();
|
||||
}
|
||||
cl->mark_was_slp();
|
||||
if (cl->is_main_loop()) {
|
||||
cl->set_slp_max_unroll(local_loop_unroll_factor);
|
||||
} else if (post_loop_allowed) {
|
||||
if (!small_basic_type) {
|
||||
// avoid replication context for small basic types in programmable masked loops
|
||||
cl->set_slp_max_unroll(local_loop_unroll_factor);
|
||||
}
|
||||
}
|
||||
cl->set_slp_max_unroll(local_loop_unroll_factor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,7 +467,6 @@ bool SuperWord::SLP_extract() {
|
||||
compute_max_depth();
|
||||
|
||||
CountedLoopNode *cl = lpt()->_head->as_CountedLoop();
|
||||
bool post_loop_allowed = (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop());
|
||||
if (cl->is_main_loop()) {
|
||||
if (_do_vector_loop_experimental) {
|
||||
if (mark_generations() != -1) {
|
||||
@ -553,7 +527,13 @@ bool SuperWord::SLP_extract() {
|
||||
filter_packs();
|
||||
|
||||
schedule();
|
||||
} else if (post_loop_allowed) {
|
||||
|
||||
// Record eventual count of vector packs for checks in post loop vectorization
|
||||
if (PostLoopMultiversioning) {
|
||||
cl->set_slp_pack_count(_packset.length());
|
||||
}
|
||||
} else {
|
||||
assert(cl->is_rce_post_loop(), "Must be an rce'd post loop");
|
||||
int saved_mapped_unroll_factor = cl->slp_max_unroll();
|
||||
if (saved_mapped_unroll_factor) {
|
||||
int vector_mapped_unroll_factor = saved_mapped_unroll_factor;
|
||||
@ -2429,7 +2409,6 @@ bool SuperWord::output() {
|
||||
|
||||
uint max_vlen_in_bytes = 0;
|
||||
uint max_vlen = 0;
|
||||
bool can_process_post_loop = (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop());
|
||||
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);})
|
||||
|
||||
@ -2442,6 +2421,15 @@ bool SuperWord::output() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Node* vmask = NULL;
|
||||
if (cl->is_rce_post_loop() && do_reserve_copy()) {
|
||||
// Create a vector mask node for post loop, bail out if not created
|
||||
vmask = create_post_loop_vmask();
|
||||
if (vmask == NULL) {
|
||||
return false; // and reverse to backup IG
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _block.length(); i++) {
|
||||
Node* n = _block.at(i);
|
||||
Node_List* p = my_pack(n);
|
||||
@ -2451,7 +2439,7 @@ bool SuperWord::output() {
|
||||
Node* vn = NULL;
|
||||
Node* low_adr = p->at(0);
|
||||
Node* first = executed_first(p);
|
||||
if (can_process_post_loop) {
|
||||
if (cl->is_rce_post_loop()) {
|
||||
// override vlen with the main loops vector length
|
||||
vlen = cl->slp_max_unroll();
|
||||
}
|
||||
@ -2476,7 +2464,13 @@ bool SuperWord::output() {
|
||||
}
|
||||
Node* adr = low_adr->in(MemNode::Address);
|
||||
const TypePtr* atyp = n->adr_type();
|
||||
vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n), control_dependency(p));
|
||||
if (cl->is_rce_post_loop()) {
|
||||
assert(vmask != NULL, "vector mask should be generated");
|
||||
const TypeVect* vt = TypeVect::make(velt_basic_type(n), vlen);
|
||||
vn = new LoadVectorMaskedNode(ctl, mem, adr, atyp, vt, vmask);
|
||||
} else {
|
||||
vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n), control_dependency(p));
|
||||
}
|
||||
vlen_in_bytes = vn->as_LoadVector()->memory_size();
|
||||
} else if (n->is_Store()) {
|
||||
// Promote value to be stored to vector
|
||||
@ -2493,7 +2487,13 @@ bool SuperWord::output() {
|
||||
Node* mem = first->in(MemNode::Memory);
|
||||
Node* adr = low_adr->in(MemNode::Address);
|
||||
const TypePtr* atyp = n->adr_type();
|
||||
vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen);
|
||||
if (cl->is_rce_post_loop()) {
|
||||
assert(vmask != NULL, "vector mask should be generated");
|
||||
const TypeVect* vt = TypeVect::make(velt_basic_type(n), vlen);
|
||||
vn = new StoreVectorMaskedNode(ctl, mem, adr, val, atyp, vmask);
|
||||
} else {
|
||||
vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen);
|
||||
}
|
||||
vlen_in_bytes = vn->as_StoreVector()->memory_size();
|
||||
} else if (VectorNode::is_scalar_rotate(n)) {
|
||||
Node* in1 = low_adr->in(1);
|
||||
@ -2578,7 +2578,7 @@ bool SuperWord::output() {
|
||||
vn = VectorCastNode::make(vopc, in, bt, vlen);
|
||||
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
|
||||
} else if (is_cmov_pack(p)) {
|
||||
if (can_process_post_loop) {
|
||||
if (cl->is_rce_post_loop()) {
|
||||
// do not refactor of flow in post loop context
|
||||
return false;
|
||||
}
|
||||
@ -2668,14 +2668,6 @@ bool SuperWord::output() {
|
||||
}
|
||||
_igvn._worklist.push(vn);
|
||||
|
||||
if (can_process_post_loop) {
|
||||
// first check if the vector size if the maximum vector which we can use on the machine,
|
||||
// other vector size have reduced values for predicated data mapping.
|
||||
if (vlen_in_bytes != (uint)MaxVectorSize) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (vlen > max_vlen) {
|
||||
max_vlen = vlen;
|
||||
}
|
||||
@ -2717,25 +2709,8 @@ bool SuperWord::output() {
|
||||
cl->mark_do_unroll_only();
|
||||
}
|
||||
}
|
||||
|
||||
if (do_reserve_copy()) {
|
||||
if (can_process_post_loop) {
|
||||
// Now create the difference of trip and limit and use it as our mask index.
|
||||
// Note: We limited the unroll of the vectorized loop so that
|
||||
// only vlen-1 size iterations can remain to be mask programmed.
|
||||
Node *incr = cl->incr();
|
||||
SubINode *index = new SubINode(cl->limit(), cl->init_trip());
|
||||
_igvn.register_new_node_with_optimizer(index);
|
||||
SetVectMaskINode *mask = new SetVectMaskINode(_phase->get_ctrl(cl->init_trip()), index);
|
||||
_igvn.register_new_node_with_optimizer(mask);
|
||||
// make this a single iteration loop
|
||||
AddINode *new_incr = new AddINode(incr->in(1), mask);
|
||||
_igvn.register_new_node_with_optimizer(new_incr);
|
||||
_phase->set_ctrl(new_incr, _phase->get_ctrl(incr));
|
||||
_igvn.replace_node(incr, new_incr);
|
||||
cl->mark_is_multiversioned();
|
||||
cl->loopexit()->add_flag(Node::Flag_has_vector_mask_set);
|
||||
}
|
||||
if (cl->is_rce_post_loop() && do_reserve_copy()) {
|
||||
cl->mark_is_multiversioned();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2748,6 +2723,107 @@ bool SuperWord::output() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------create_post_loop_vmask-------------------------
|
||||
// Check the post loop vectorizability and create a vector mask if yes.
|
||||
// Return NULL to bail out if post loop is not vectorizable.
|
||||
Node* SuperWord::create_post_loop_vmask() {
|
||||
CountedLoopNode *cl = lpt()->_head->as_CountedLoop();
|
||||
assert(cl->is_rce_post_loop(), "Must be an rce post loop");
|
||||
assert(!cl->is_reduction_loop(), "no vector reduction in post loop");
|
||||
assert(abs(cl->stride_con()) == 1, "post loop stride can only be +/-1");
|
||||
|
||||
// Collect vector element types of all post loop packs. Also collect
|
||||
// superword pointers of each memory access operation if the address
|
||||
// expression is supported. (Note that vectorizable post loop should
|
||||
// only have positive scale in counting-up loop and negative scale in
|
||||
// counting-down loop.) Collected SWPointer(s) are also used for data
|
||||
// dependence check next.
|
||||
VectorElementSizeStats stats(_arena);
|
||||
GrowableArray<SWPointer*> swptrs(_arena, _packset.length(), 0, NULL);
|
||||
for (int i = 0; i < _packset.length(); i++) {
|
||||
Node_List* p = _packset.at(i);
|
||||
assert(p->size() == 1, "all post loop packs should be singleton");
|
||||
Node* n = p->at(0);
|
||||
BasicType bt = velt_basic_type(n);
|
||||
if (!is_java_primitive(bt)) {
|
||||
return NULL;
|
||||
}
|
||||
if (n->is_Mem()) {
|
||||
SWPointer* mem_p = new (_arena) SWPointer(n->as_Mem(), this, NULL, false);
|
||||
// For each memory access, we check if the scale (in bytes) in its
|
||||
// address expression is equal to the data size times loop stride.
|
||||
// With this, Only positive scales exist in counting-up loops and
|
||||
// negative scales exist in counting-down loops.
|
||||
if (mem_p->scale_in_bytes() != type2aelembytes(bt) * cl->stride_con()) {
|
||||
return NULL;
|
||||
}
|
||||
swptrs.append(mem_p);
|
||||
}
|
||||
stats.record_size(type2aelembytes(bt));
|
||||
}
|
||||
|
||||
// Find the vector data type for generating vector masks. Currently we
|
||||
// don't support post loops with mixed vector data sizes
|
||||
int unique_size = stats.unique_size();
|
||||
BasicType vmask_bt;
|
||||
switch (unique_size) {
|
||||
case 1: vmask_bt = T_BYTE; break;
|
||||
case 2: vmask_bt = T_SHORT; break;
|
||||
case 4: vmask_bt = T_INT; break;
|
||||
case 8: vmask_bt = T_LONG; break;
|
||||
default: return NULL;
|
||||
}
|
||||
|
||||
// Currently we can't remove this MaxVectorSize constraint. Without it,
|
||||
// it's not guaranteed that the RCE'd post loop runs at most "vlen - 1"
|
||||
// iterations, because the vector drain loop may not be cloned from the
|
||||
// vectorized main loop. We should re-engineer PostLoopMultiversioning
|
||||
// to fix this problem.
|
||||
int vlen = cl->slp_max_unroll();
|
||||
if (unique_size * vlen != MaxVectorSize) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Bail out if target doesn't support mask generator or masked load/store
|
||||
if (!Matcher::match_rule_supported_vector(Op_LoadVectorMasked, vlen, vmask_bt) ||
|
||||
!Matcher::match_rule_supported_vector(Op_StoreVectorMasked, vlen, vmask_bt) ||
|
||||
!Matcher::match_rule_supported_vector(Op_VectorMaskGen, vlen, vmask_bt)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Bail out if potential data dependence exists between memory accesses
|
||||
if (SWPointer::has_potential_dependence(swptrs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create vector mask with the post loop trip count. Note there's another
|
||||
// vector drain loop which is cloned from main loop before super-unrolling
|
||||
// so the scalar post loop runs at most vlen-1 trips. Hence, this version
|
||||
// only runs at most 1 iteration after vector mask transformation.
|
||||
Node* trip_cnt;
|
||||
Node* new_incr;
|
||||
if (cl->stride_con() > 0) {
|
||||
trip_cnt = new SubINode(cl->limit(), cl->init_trip());
|
||||
new_incr = new AddINode(cl->phi(), trip_cnt);
|
||||
} else {
|
||||
trip_cnt = new SubINode(cl->init_trip(), cl->limit());
|
||||
new_incr = new SubINode(cl->phi(), trip_cnt);
|
||||
}
|
||||
_igvn.register_new_node_with_optimizer(trip_cnt);
|
||||
_igvn.register_new_node_with_optimizer(new_incr);
|
||||
_igvn.replace_node(cl->incr(), new_incr);
|
||||
Node* length = new ConvI2LNode(trip_cnt);
|
||||
_igvn.register_new_node_with_optimizer(length);
|
||||
Node* vmask = VectorMaskGenNode::make(length, vmask_bt);
|
||||
_igvn.register_new_node_with_optimizer(vmask);
|
||||
|
||||
// Remove exit test to transform 1-iteration loop to straight-line code.
|
||||
// This results in redundant cmp+branch instructions been eliminated.
|
||||
Node *cl_exit = cl->loopexit();
|
||||
_igvn.replace_input_of(cl_exit, 1, _igvn.intcon(0));
|
||||
return vmask;
|
||||
}
|
||||
|
||||
//------------------------------vector_opd---------------------------
|
||||
// Create a vector operand for the nodes in pack p for operand: in(opd_idx)
|
||||
Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
|
||||
@ -2756,7 +2832,7 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
|
||||
Node* opd = p0->in(opd_idx);
|
||||
CountedLoopNode *cl = lpt()->_head->as_CountedLoop();
|
||||
|
||||
if (PostLoopMultiversioning && Matcher::has_predicated_vectors() && cl->is_post_loop()) {
|
||||
if (cl->is_rce_post_loop()) {
|
||||
// override vlen with the main loops vector length
|
||||
vlen = cl->slp_max_unroll();
|
||||
}
|
||||
@ -3767,7 +3843,7 @@ SWPointer::SWPointer(MemNode* mem, SuperWord* slp, Node_Stack *nstack, bool anal
|
||||
// Match AddP(base, AddP(ptr, k*iv [+ invariant]), constant)
|
||||
Node* base = adr->in(AddPNode::Base);
|
||||
// The base address should be loop invariant
|
||||
if (is_main_loop_member(base)) {
|
||||
if (is_loop_member(base)) {
|
||||
assert(!valid(), "base address is loop variant");
|
||||
return;
|
||||
}
|
||||
@ -3796,7 +3872,7 @@ SWPointer::SWPointer(MemNode* mem, SuperWord* slp, Node_Stack *nstack, bool anal
|
||||
break; // stop looking at addp's
|
||||
}
|
||||
}
|
||||
if (is_main_loop_member(adr)) {
|
||||
if (is_loop_member(adr)) {
|
||||
assert(!valid(), "adr is loop variant");
|
||||
return;
|
||||
}
|
||||
@ -3827,7 +3903,7 @@ SWPointer::SWPointer(SWPointer* p) :
|
||||
#endif
|
||||
{}
|
||||
|
||||
bool SWPointer::is_main_loop_member(Node* n) const {
|
||||
bool SWPointer::is_loop_member(Node* n) const {
|
||||
Node* n_c = phase()->get_ctrl(n);
|
||||
return lpt()->is_member(phase()->get_loop(n_c));
|
||||
}
|
||||
@ -3836,7 +3912,7 @@ bool SWPointer::invariant(Node* n) const {
|
||||
NOT_PRODUCT(Tracer::Depth dd;)
|
||||
Node* n_c = phase()->get_ctrl(n);
|
||||
NOT_PRODUCT(_tracer.invariant_1(n, n_c);)
|
||||
bool is_not_member = !is_main_loop_member(n);
|
||||
bool is_not_member = !is_loop_member(n);
|
||||
if (is_not_member && _slp->lp()->is_main_loop()) {
|
||||
// Check that n_c dominates the pre loop head node. If it does not, then we cannot use n as invariant for the pre loop
|
||||
// CountedLoopEndNode check because n_c is either part of the pre loop or between the pre and the main loop (illegal
|
||||
@ -3906,7 +3982,7 @@ bool SWPointer::scaled_iv(Node* n) {
|
||||
NOT_PRODUCT(_tracer.scaled_iv_3(n, _scale);)
|
||||
return true;
|
||||
}
|
||||
if (_analyze_only && (is_main_loop_member(n))) {
|
||||
if (_analyze_only && (is_loop_member(n))) {
|
||||
_nstack->push(n, _stack_idx++);
|
||||
}
|
||||
|
||||
@ -3989,7 +4065,7 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_analyze_only && is_main_loop_member(n)) {
|
||||
if (_analyze_only && is_loop_member(n)) {
|
||||
_nstack->push(n, _stack_idx++);
|
||||
}
|
||||
if (opc == Op_AddI) {
|
||||
@ -4023,14 +4099,14 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_main_loop_member(n)) {
|
||||
if (!is_loop_member(n)) {
|
||||
// 'n' is loop invariant. Skip ConvI2L and CastII nodes before checking if 'n' is dominating the pre loop.
|
||||
if (opc == Op_ConvI2L) {
|
||||
n = n->in(1);
|
||||
}
|
||||
if (n->Opcode() == Op_CastII) {
|
||||
// Skip CastII nodes
|
||||
assert(!is_main_loop_member(n), "sanity");
|
||||
assert(!is_loop_member(n), "sanity");
|
||||
n = n->in(1);
|
||||
}
|
||||
// Check if 'n' can really be used as invariant (not in main loop and dominating the pre loop).
|
||||
@ -4046,6 +4122,34 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------has_potential_dependence-----------------
|
||||
// Check potential data dependence among all memory accesses.
|
||||
// We require every two accesses (with at least one store) of
|
||||
// the same element type has the same address expression.
|
||||
bool SWPointer::has_potential_dependence(GrowableArray<SWPointer*> swptrs) {
|
||||
for (int i1 = 0; i1 < swptrs.length(); i1++) {
|
||||
SWPointer* p1 = swptrs.at(i1);
|
||||
MemNode* n1 = p1->mem();
|
||||
BasicType bt1 = n1->memory_type();
|
||||
|
||||
// Iterate over remaining SWPointers
|
||||
for (int i2 = i1 + 1; i2 < swptrs.length(); i2++) {
|
||||
SWPointer* p2 = swptrs.at(i2);
|
||||
MemNode* n2 = p2->mem();
|
||||
BasicType bt2 = n2->memory_type();
|
||||
|
||||
// Data dependence exists between load-store, store-load
|
||||
// or store-store with the same element type or subword
|
||||
// size (subword load/store may have inaccurate type)
|
||||
if ((n1->is_Store() || n2->is_Store()) &&
|
||||
same_type_or_subword_size(bt1, bt2) && !p1->equal(*p2)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------print------------------------
|
||||
void SWPointer::print() {
|
||||
#ifndef PRODUCT
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2022, 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
|
||||
@ -244,6 +244,45 @@ class OrderedPair {
|
||||
static const OrderedPair initial;
|
||||
};
|
||||
|
||||
// -----------------------VectorElementSizeStats-----------------------
|
||||
// Vector lane size statistics for loop vectorization with vector masks
|
||||
class VectorElementSizeStats {
|
||||
private:
|
||||
static const int NO_SIZE = -1;
|
||||
static const int MIXED_SIZE = -2;
|
||||
int* _stats;
|
||||
|
||||
public:
|
||||
VectorElementSizeStats(Arena* a) : _stats(NEW_ARENA_ARRAY(a, int, 4)) {
|
||||
memset(_stats, 0, sizeof(int) * 4);
|
||||
}
|
||||
|
||||
void record_size(int size) {
|
||||
assert(1 <= size && size <= 8 && is_power_of_2(size), "Illegal size");
|
||||
_stats[exact_log2(size)]++;
|
||||
}
|
||||
|
||||
int smallest_size() {
|
||||
for (int i = 0; i <= 3; i++) {
|
||||
if (_stats[i] > 0) return (1 << i);
|
||||
}
|
||||
return NO_SIZE;
|
||||
}
|
||||
|
||||
int largest_size() {
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
if (_stats[i] > 0) return (1 << i);
|
||||
}
|
||||
return NO_SIZE;
|
||||
}
|
||||
|
||||
int unique_size() {
|
||||
int small = smallest_size();
|
||||
int large = largest_size();
|
||||
return (small == large) ? small : MIXED_SIZE;
|
||||
}
|
||||
};
|
||||
|
||||
// -----------------------------SuperWord---------------------------------
|
||||
// Transforms scalar operations into packed (superword) operations.
|
||||
class SuperWord : public ResourceObj {
|
||||
@ -510,6 +549,8 @@ class SuperWord : public ResourceObj {
|
||||
|
||||
// Convert packs into vector node operations
|
||||
bool output();
|
||||
// Create vector mask for post loop vectorization
|
||||
Node* create_post_loop_vmask();
|
||||
// Create a vector operand for the nodes in pack p for operand: in(opd_idx)
|
||||
Node* vector_opd(Node_List* p, int opd_idx);
|
||||
// Can code be generated for pack p?
|
||||
@ -572,7 +613,7 @@ class SuperWord : public ResourceObj {
|
||||
|
||||
//------------------------------SWPointer---------------------------
|
||||
// Information about an address for dependence checking and vector alignment
|
||||
class SWPointer {
|
||||
class SWPointer : public ResourceObj {
|
||||
protected:
|
||||
MemNode* _mem; // My memory reference node
|
||||
SuperWord* _slp; // SuperWord class
|
||||
@ -594,7 +635,7 @@ class SWPointer {
|
||||
IdealLoopTree* lpt() const { return _slp->lpt(); }
|
||||
PhiNode* iv() const { return _slp->iv(); } // Induction var
|
||||
|
||||
bool is_main_loop_member(Node* n) const;
|
||||
bool is_loop_member(Node* n) const;
|
||||
bool invariant(Node* n) const;
|
||||
|
||||
// Match: k*iv + offset
|
||||
@ -658,6 +699,8 @@ class SWPointer {
|
||||
static bool equal(int cmp) { return cmp == Equal; }
|
||||
static bool comparable(int cmp) { return cmp < NotComparable; }
|
||||
|
||||
static bool has_potential_dependence(GrowableArray<SWPointer*> swptrs);
|
||||
|
||||
void print();
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
@ -1296,17 +1296,6 @@ class ExtractDNode : public ExtractNode {
|
||||
virtual uint ideal_reg() const { return Op_RegD; }
|
||||
};
|
||||
|
||||
//------------------------------SetVectMaskINode-------------------------------
|
||||
// Provide a mask for a vector predicate machine
|
||||
class SetVectMaskINode : public Node {
|
||||
public:
|
||||
SetVectMaskINode(Node *c, Node *in1) : Node(c, in1) {}
|
||||
virtual int Opcode() const;
|
||||
const Type *bottom_type() const { return TypeInt::INT; }
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
virtual const Type *Value(PhaseGVN *phase) const { return TypeInt::INT; }
|
||||
};
|
||||
|
||||
//------------------------------MacroLogicVNode-------------------------------
|
||||
// Vector logical operations packing node.
|
||||
class MacroLogicVNode : public VectorNode {
|
||||
|
@ -1557,7 +1557,6 @@
|
||||
declare_c2_type(ConvL2INode, Node) \
|
||||
declare_c2_type(CastX2PNode, Node) \
|
||||
declare_c2_type(CastP2XNode, Node) \
|
||||
declare_c2_type(SetVectMaskINode, Node) \
|
||||
declare_c2_type(MemBarNode, MultiNode) \
|
||||
declare_c2_type(MemBarAcquireNode, MemBarNode) \
|
||||
declare_c2_type(MemBarReleaseNode, MemBarNode) \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2022, 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
|
||||
@ -813,6 +813,9 @@ extern int type2aelembytes(BasicType t, bool allow_address = false); // asserts
|
||||
inline int type2aelembytes(BasicType t, bool allow_address = false) { return _type2aelembytes[t]; }
|
||||
#endif
|
||||
|
||||
inline bool same_type_or_subword_size(BasicType t1, BasicType t2) {
|
||||
return (t1 == t2) || (is_subword_type(t1) && type2aelembytes(t1) == type2aelembytes(t2));
|
||||
}
|
||||
|
||||
// JavaValue serves as a container for arbitrary Java values.
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class TestSuperwordFailsUnrolling {
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(applyIf = { "UsePopCountInstruction", "true" }, counts = { IRNode.POPCOUNT_L, "10" })
|
||||
@IR(applyIf = { "UsePopCountInstruction", "true" }, counts = { IRNode.POPCOUNT_L, ">=10" })
|
||||
private static int test(long[] array1, long[] array2) {
|
||||
v = 0;
|
||||
for (int i = 0; i < array1.length; i++) {
|
||||
|
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on array copy
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.ArrayCopyTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class ArrayCopyTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private byte[] bytes;
|
||||
private short[] shorts;
|
||||
private char[] chars;
|
||||
private int[] ints;
|
||||
private long[] longs;
|
||||
private float[] floats;
|
||||
private double[] doubles;
|
||||
|
||||
public ArrayCopyTest() {
|
||||
bytes = new byte[SIZE];
|
||||
shorts = new short[SIZE];
|
||||
chars = new char[SIZE];
|
||||
ints = new int[SIZE];
|
||||
longs = new long[SIZE];
|
||||
floats = new float[SIZE];
|
||||
doubles = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
bytes[i] = (byte) (-i / 100);
|
||||
shorts[i] = (short) (30 * i - 12345);
|
||||
chars[i] = (char) (i * 55);
|
||||
ints[i] = -4444 * i;
|
||||
longs[i] = -999999999L * i + 99999999999L;
|
||||
floats[i] = (float) (i * 2.3e7f);
|
||||
doubles[i] = -3e30 * i * i;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Simple Copy ----------------
|
||||
@Test
|
||||
public byte[] copyByteArray() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = bytes[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] copyShortArray() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = shorts[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] copyCharArray() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = chars[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] copyIntArray() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = ints[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] copyLongArray() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = longs[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] copyFloatArray() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = floats[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] copyDoubleArray() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = doubles[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Multiple Copies ----------------
|
||||
@Test
|
||||
public float[] chainedCopy() {
|
||||
float[] res1 = new float[SIZE];
|
||||
float[] res2 = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res2[i] = res1[i] = floats[i];
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] copy2ArraysSameSize() {
|
||||
int[] res1 = new int[SIZE];
|
||||
float[] res2 = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = ints[i];
|
||||
res2[i] = floats[i];
|
||||
}
|
||||
return res1;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] copy2ArraysDifferentSizes() {
|
||||
int[] res1 = new int[SIZE];
|
||||
double[] res2 = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = ints[i];
|
||||
res2[i] = doubles[i];
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
|
||||
// ---------------- Copy Between Signed & Unsigned ----------------
|
||||
@Test
|
||||
public char[] copyFromSignedToUnsigned() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) shorts[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] copyFromUnsignedToSigned() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) chars[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on array index fill
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.ArrayIndexFillTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class ArrayIndexFillTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] a;
|
||||
|
||||
public ArrayIndexFillTest() {
|
||||
a = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = -5050 * i;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] fillByteArray() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] fillShortArray() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] fillCharArray() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] fillIntArray() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] fillLongArray() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] fillShortArrayWithShortIndex() {
|
||||
short[] res = new short[SIZE];
|
||||
for (short i = 0; i < SIZE; i++) {
|
||||
res[i] = i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] fillMultipleArraysDifferentTypes1() {
|
||||
int[] res1 = new int[SIZE];
|
||||
short[] res2 = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = i;
|
||||
res2[i] = (short) i;
|
||||
}
|
||||
return res1;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] fillMultipleArraysDifferentTypes2() {
|
||||
int[] res1 = new int[SIZE];
|
||||
char[] res2 = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = i;
|
||||
res2[i] = (char) i;
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] fillNonIndexValue() {
|
||||
int[] res = new int[SIZE];
|
||||
int val = 10000;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = val++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on array invariant fill
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -XX:-OptimizeFill
|
||||
* compiler.vectorization.runner.ArrayInvariantFillTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class ArrayInvariantFillTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int intInv;
|
||||
private char charInv;
|
||||
private float floatInv;
|
||||
private double doubleInv;
|
||||
|
||||
public ArrayInvariantFillTest() {
|
||||
Random ran = new Random(10);
|
||||
intInv = ran.nextInt();
|
||||
charInv = (char) ran.nextInt();
|
||||
floatInv = ran.nextFloat();
|
||||
doubleInv = ran.nextDouble();
|
||||
}
|
||||
|
||||
// ---------------- Simple Fill ----------------
|
||||
@Test
|
||||
public byte[] fillByteArray() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) 10;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] fillShortArray() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) -3333;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] fillCharArray() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) 55555;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] fillIntArray() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = 2147483647;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] fillLongArray() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = -2222222222222222L;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] fillFloatArray() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = 3.234567e8f;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] fillDoubleArray() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = -9.87654321e50;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Fill With Type Change ----------------
|
||||
@Test
|
||||
public long[] fillLongArrayWithInt() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = intInv;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] fillLongArrayWithUnsigned() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = charInv;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] fillLongArrayWithFloat() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (long) floatInv;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] fillIntArrayWithDouble() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (int) doubleInv;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on bug-prone shift operation
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.ArrayShiftOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class ArrayShiftOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] ints;
|
||||
private long[] longs;
|
||||
private short[] shorts1;
|
||||
private short[] shorts2;
|
||||
private int largeDist;
|
||||
|
||||
public ArrayShiftOpTest() {
|
||||
ints = new int[SIZE];
|
||||
longs = new long[SIZE];
|
||||
shorts1 = new short[SIZE];
|
||||
shorts2 = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
ints[i] = -888999 * i;
|
||||
longs[i] = 999998888800000L * i;
|
||||
shorts1[i] = (short) (4 * i);
|
||||
shorts2[i] = (short) (-3 * i);
|
||||
}
|
||||
Random ran = new Random(999);
|
||||
largeDist = 123;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] intCombinedRotateShift() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (ints[i] << 14) | (ints[i] >>> 18);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] longCombinedRotateShift() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (longs[i] << 55) | (longs[i] >>> 9);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] intShiftLargeDistConstant() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = ints[i] >> 35;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] intShiftLargeDistInvariant() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = ints[i] >> largeDist;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] longShiftLargeDistConstant() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = longs[i] << 77;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] longShiftLargeDistInvariant() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = longs[i] >>> largeDist;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that any shift operation with distance value from another array
|
||||
// cannot be vectorized since C2 vector shift node doesn't support it.
|
||||
public long[] variantShiftDistance() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = longs[i] >> ints[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that unsigned shift right on subword signed integer types can't
|
||||
// be vectorized since the sign extension bits would be lost.
|
||||
public short[] vectorUnsignedShiftRight() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (shorts2[i] >>> 3);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that right shift operations on subword expressions cannot be
|
||||
// vectorized since precise type info about signness is missing.
|
||||
public short[] subwordExpressionRightShift() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) ((shorts1[i] + shorts2[i]) >> 4);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on array type conversions
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.ArrayTypeConvertTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class ArrayTypeConvertTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private byte[] bytes;
|
||||
private short[] shorts;
|
||||
private char[] chars;
|
||||
private int[] ints;
|
||||
private long[] longs;
|
||||
private float[] floats;
|
||||
private double[] doubles;
|
||||
|
||||
public ArrayTypeConvertTest() {
|
||||
bytes = new byte[SIZE];
|
||||
shorts = new short[SIZE];
|
||||
chars = new char[SIZE];
|
||||
ints = new int[SIZE];
|
||||
longs = new long[SIZE];
|
||||
floats = new float[SIZE];
|
||||
doubles = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
bytes[i] = (byte) (-i / 128);
|
||||
shorts[i] = (short) (i / 3 - 12345);
|
||||
chars[i] = (char) (i * 2);
|
||||
ints[i] = -22 * i;
|
||||
longs[i] = -258L * i + 99L;
|
||||
floats[i] = (float) (i * 2.498f);
|
||||
doubles[i] = -3 * i;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Integer Extension ----------------
|
||||
@Test
|
||||
public int[] signExtension() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = shorts[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] zeroExtension() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = chars[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] signExtensionFromByte() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = bytes[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Integer Narrow ----------------
|
||||
@Test
|
||||
public short[] narrowToSigned() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) ints[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] narrowToUnsigned() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) ints[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] NarrowToByte() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) ints[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Convert I/L to F/D ----------------
|
||||
@Test
|
||||
public float[] convertIntToFloat() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (float) ints[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] convertIntToDouble() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (double) ints[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] convertLongToFloat() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (float) longs[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] convertLongToDouble() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (double) longs[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Convert Subword-I to F/D ----------------
|
||||
@Test
|
||||
public float[] convertShortToFloat() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (float) shorts[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] convertShortToDouble() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (double) shorts[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] convertCharToFloat() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (float) chars[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] convertCharToDouble() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (double) chars[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Convert F/D to I/L ----------------
|
||||
@Test
|
||||
public int[] convertFloatToInt() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (int) floats[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] convertFloatToLong() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (long) floats[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] convertDoubleToInt() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (int) doubles[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] convertDoubleToLong() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (long) doubles[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Convert F/D to Subword-I ----------------
|
||||
@Test
|
||||
public short[] convertFloatToShort() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) floats[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] convertFloatToChar() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) floats[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] convertDoubleToShort() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) doubles[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] convertDoubleToChar() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) doubles[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Convert Between F & D ----------------
|
||||
@Test
|
||||
public double[] convertFloatToDouble() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (double) floats[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] convertDoubleToFloat() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (float) doubles[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on array unsafe operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.ArrayUnsafeOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
public class ArrayUnsafeOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private static Unsafe unsafe;
|
||||
|
||||
public ArrayUnsafeOpTest() throws Exception {
|
||||
Class klass = Unsafe.class;
|
||||
Field field = klass.getDeclaredField("theUnsafe");
|
||||
field.setAccessible(true);
|
||||
unsafe = (Unsafe) field.get(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] arrayUnsafeFill() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < 500; i++) {
|
||||
unsafe.putByte(res, i + 24, (byte) i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] arrayUnsafeFillWithOneAddp() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 123; i < 500; i++) {
|
||||
unsafe.putByte(res, i, (byte) i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized since data dependence
|
||||
// exists between two unsafe stores of different types on the same
|
||||
// array reference.
|
||||
public int[] arrayUnsafeFillTypeMismatch() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < 500; i++) {
|
||||
unsafe.putByte(res, i + 24, (byte) i);
|
||||
unsafe.putShort(res, i + 28, (short) 0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized since data dependence
|
||||
// exists between adjacent iterations. (The memory address storing
|
||||
// an int array is not increased by 4 per iteration.)
|
||||
public int[] arrayUnsafeFillAddrIncrMismatch() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < 500; i++) {
|
||||
unsafe.putInt(res, i + 24, i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on basic boolean operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.BasicBooleanOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class BasicBooleanOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private boolean[] a;
|
||||
private boolean[] b;
|
||||
private boolean[] c;
|
||||
|
||||
public BasicBooleanOpTest() {
|
||||
a = new boolean[SIZE];
|
||||
b = new boolean[SIZE];
|
||||
c = new boolean[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = true;
|
||||
b[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Logic ----------------
|
||||
@Test
|
||||
public boolean[] vectorNot() {
|
||||
boolean[] res = new boolean[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = !a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public boolean[] vectorAnd() {
|
||||
boolean[] res = new boolean[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] & b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public boolean[] vectorOr() {
|
||||
boolean[] res = new boolean[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] | b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public boolean[] vectorXor() {
|
||||
boolean[] res = new boolean[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] ^ b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on basic byte operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.BasicByteOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class BasicByteOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private byte[] a;
|
||||
private byte[] b;
|
||||
private byte[] c;
|
||||
|
||||
public BasicByteOpTest() {
|
||||
a = new byte[SIZE];
|
||||
b = new byte[SIZE];
|
||||
c = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = (byte) (-3 * i);
|
||||
b[i] = (byte) (i + 4);
|
||||
c[i] = (byte) -90;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Arithmetic ----------------
|
||||
@Test
|
||||
public byte[] vectorNeg() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) -a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorAbs() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) Math.abs(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorAdd() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] + b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorSub() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] - b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorMul() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorMulAdd() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (c[i] + a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorMulSub() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (c[i] - a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Logic ----------------
|
||||
@Test
|
||||
public byte[] vectorNot() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) ~a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorAnd() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] & b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorOr() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] | b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorXor() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] ^ b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Shift ----------------
|
||||
@Test
|
||||
public byte[] vectorShiftLeft() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] << 3);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public byte[] vectorSignedShiftRight() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] >> 2);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that unsigned shift right on subword signed integer types can
|
||||
// not be vectorized since the sign extension bit would be lost.
|
||||
public byte[] vectorUnsignedShiftRight() {
|
||||
byte[] res = new byte[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (byte) (a[i] >>> 5);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on basic char operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.BasicCharOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class BasicCharOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private char[] a;
|
||||
private char[] b;
|
||||
private char[] c;
|
||||
|
||||
public BasicCharOpTest() {
|
||||
a = new char[SIZE];
|
||||
b = new char[SIZE];
|
||||
c = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = (char) (20 * i);
|
||||
b[i] = (char) (i + 44444);
|
||||
c[i] = (char) 10000;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Arithmetic ----------------
|
||||
@Test
|
||||
public char[] vectorNeg() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) -a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that Math.abs() on unsigned subword types can NOT be vectorized
|
||||
// since all the values are non-negative according to the semantics.
|
||||
public char[] vectorAbs() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) Math.abs(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorAdd() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] + b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorSub() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] - b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorMul() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorMulAdd() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (c[i] + a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorMulSub() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (c[i] - a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Logic ----------------
|
||||
@Test
|
||||
public char[] vectorNot() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) ~a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorAnd() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] & b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorOr() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] | b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorXor() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] ^ b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Shift ----------------
|
||||
@Test
|
||||
public char[] vectorShiftLeft() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] << 3);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorSignedShiftRight() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] >> 2);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public char[] vectorUnsignedShiftRight() {
|
||||
char[] res = new char[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (char) (a[i] >>> 5);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on basic double operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.BasicDoubleOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class BasicDoubleOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private double[] a;
|
||||
private double[] b;
|
||||
private double[] c;
|
||||
|
||||
public BasicDoubleOpTest() {
|
||||
a = new double[SIZE];
|
||||
b = new double[SIZE];
|
||||
c = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = 850.0 * i + 22222.22;
|
||||
b[i] = -12345.678;
|
||||
c[i] = -1.23456e7;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Arithmetic ----------------
|
||||
@Test
|
||||
public double[] vectorNeg() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = -a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorAbs() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.abs(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorSqrt() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.sqrt(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorCeil() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.ceil(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorFloor() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.floor(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorRint() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.rint(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorAdd() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] + b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorSub() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] - b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorMul() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorDiv() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] / b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorMax() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.max(a[i], b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorMin() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.min(a[i], b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorMulAdd() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(a[i], b[i], c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorMulSub1() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(-a[i], b[i], c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorMulSub2() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(a[i], -b[i], c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorNegateMulAdd1() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(-a[i], b[i], -c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorNegateMulAdd2() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(a[i], -b[i], -c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double[] vectorNegateMulSub() {
|
||||
double[] res = new double[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(a[i], b[i], -c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Reduction ----------------
|
||||
@Test
|
||||
public double reductionAdd() {
|
||||
double res = 0.0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double reductionMax() {
|
||||
double res = Double.MIN_VALUE;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res = Math.max(res, a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double reductionMin() {
|
||||
double res = Double.MAX_VALUE;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res = Math.min(res, a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on basic float operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.BasicFloatOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class BasicFloatOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private float[] a;
|
||||
private float[] b;
|
||||
private float[] c;
|
||||
|
||||
public BasicFloatOpTest() {
|
||||
a = new float[SIZE];
|
||||
b = new float[SIZE];
|
||||
c = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = 850.0f * i + 22222.22f;
|
||||
b[i] = -12345.678f;
|
||||
c[i] = -1.23456e7f;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Arithmetic ----------------
|
||||
@Test
|
||||
public float[] vectorNeg() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = -a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorAbs() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.abs(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorSqrt() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (float) Math.sqrt(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorAdd() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] + b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorSub() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] - b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorMul() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorDiv() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] / b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorMax() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.max(a[i], b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorMin() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.min(a[i], b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorMulAdd() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(a[i], b[i], c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorMulSub1() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(-a[i], b[i], c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorMulSub2() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(a[i], -b[i], c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorNegateMulAdd1() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(-a[i], b[i], -c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorNegateMulAdd2() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(a[i], -b[i], -c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float[] vectorNegateMulSub() {
|
||||
float[] res = new float[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.fma(a[i], b[i], -c[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Reduction ----------------
|
||||
@Test
|
||||
public float reductionAdd() {
|
||||
float res = 0.0f;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float reductionMax() {
|
||||
float res = Float.MIN_VALUE;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res = Math.max(res, a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float reductionMin() {
|
||||
float res = Float.MAX_VALUE;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res = Math.min(res, a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on basic int operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.BasicIntOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class BasicIntOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] a;
|
||||
private int[] b;
|
||||
private int[] c;
|
||||
|
||||
public BasicIntOpTest() {
|
||||
a = new int[SIZE];
|
||||
b = new int[SIZE];
|
||||
c = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = -25 * i;
|
||||
b[i] = 333 * i + 9999;
|
||||
c[i] = -987654321;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Arithmetic ----------------
|
||||
@Test
|
||||
public int[] vectorNeg() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = -a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorAbs() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.abs(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorAdd() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] + b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorSub() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] - b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorMul() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorMulAdd() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = c[i] + a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorMulSub() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = c[i] - a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorPopCount() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Integer.bitCount(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Logic ----------------
|
||||
@Test
|
||||
public int[] vectorNot() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = ~a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorAnd() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] & b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorOr() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] | b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorXor() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] ^ b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Shift ----------------
|
||||
@Test
|
||||
public int[] vectorShiftLeft() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] << 3;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorSignedShiftRight() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] >> 2;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] vectorUnsignedShiftRight() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] >>> 5;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Reduction ----------------
|
||||
@Test
|
||||
public int reductionAdd() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionAnd() {
|
||||
int res = 0xffffffff;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res &= a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionOr() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res |= a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionXor() {
|
||||
int res = 0x0f0f0f0f;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res ^= a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionMax() {
|
||||
int res = Integer.MIN_VALUE;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res = Math.max(res, a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionMin() {
|
||||
int res = Integer.MAX_VALUE;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res = Math.min(res, a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on basic long operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.BasicLongOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class BasicLongOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private long[] a;
|
||||
private long[] b;
|
||||
private long[] c;
|
||||
|
||||
public BasicLongOpTest() {
|
||||
a = new long[SIZE];
|
||||
b = new long[SIZE];
|
||||
c = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = -123456789L * i;
|
||||
b[i] = 66666666L * i + 8888888888888888888L;
|
||||
c[i] = -987654321098765L;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Arithmetic ----------------
|
||||
@Test
|
||||
public long[] vectorNeg() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = -a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorAbs() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = Math.abs(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorAdd() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] + b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorSub() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] - b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorMul() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorMulAdd() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = c[i] + a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorMulSub() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = c[i] - a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Logic ----------------
|
||||
@Test
|
||||
public long[] vectorNot() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = ~a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorAnd() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] & b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorOr() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] | b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorXor() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] ^ b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Shift ----------------
|
||||
@Test
|
||||
public long[] vectorShiftLeft() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] << 3;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorSignedShiftRight() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] >> 2;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] vectorUnsignedShiftRight() {
|
||||
long[] res = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] >>> 5;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Reduction ----------------
|
||||
@Test
|
||||
public long reductionAdd() {
|
||||
long res = 0L;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long reductionAnd() {
|
||||
long res = 0xffffffffffffffffL;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res &= a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long reductionOr() {
|
||||
long res = 0L;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res |= a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long reductionXor() {
|
||||
long res = 0xf0f0f0f0f0f0f0f0L;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res ^= a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long reductionMax() {
|
||||
long res = Long.MIN_VALUE;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res = Math.max(res, a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long reductionMin() {
|
||||
long res = Long.MAX_VALUE;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res = Math.min(res, a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on basic short operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.BasicShortOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class BasicShortOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private short[] a;
|
||||
private short[] b;
|
||||
private short[] c;
|
||||
|
||||
public BasicShortOpTest() {
|
||||
a = new short[SIZE];
|
||||
b = new short[SIZE];
|
||||
c = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = (short) (-12 * i);
|
||||
b[i] = (short) (9 * i + 8888);
|
||||
c[i] = (short) -32323;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------- Arithmetic ----------------
|
||||
@Test
|
||||
public short[] vectorNeg() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) -a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorAbs() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) Math.abs(a[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorAdd() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] + b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorSub() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] - b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorMul() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorMulAdd() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (c[i] + a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorMulSub() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (c[i] - a[i] * b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Logic ----------------
|
||||
@Test
|
||||
public short[] vectorNot() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) ~a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorAnd() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] & b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorOr() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] | b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorXor() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] ^ b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Shift ----------------
|
||||
@Test
|
||||
public short[] vectorShiftLeft() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] << 3);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] vectorSignedShiftRight() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] >> 2);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that unsigned shift right on subword signed integer types can
|
||||
// not be vectorized since the sign extension bits would be lost.
|
||||
public short[] vectorUnsignedShiftRight() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (a[i] >>> 5);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on loop array index computation
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.LoopArrayIndexComputeTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class LoopArrayIndexComputeTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] ints;
|
||||
private short[] shorts;
|
||||
private char[] chars;
|
||||
private byte[] bytes;
|
||||
private boolean[] booleans;
|
||||
|
||||
private int inv1;
|
||||
private int inv2;
|
||||
|
||||
public LoopArrayIndexComputeTest() {
|
||||
ints = new int[SIZE];
|
||||
shorts = new short[SIZE];
|
||||
chars = new char[SIZE];
|
||||
bytes = new byte[SIZE];
|
||||
booleans = new boolean[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
ints[i] = 499 * i;
|
||||
shorts[i] = (short) (-13 * i + 5);
|
||||
chars[i] = (char) (i << 3);
|
||||
bytes[i] = (byte) (i >> 2 + 3);
|
||||
booleans[i] = (i % 5 == 0);
|
||||
}
|
||||
Random ran = new Random(10);
|
||||
inv1 = Math.abs(ran.nextInt() % 10) + 1;
|
||||
inv2 = Math.abs(ran.nextInt() % 10) + 1;
|
||||
}
|
||||
|
||||
// ---------------- Linear Indexes ----------------
|
||||
@Test
|
||||
public int[] indexPlusConstant() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res[i + 1] = ints[i + 1] + 999;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] indexMinusConstant() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = SIZE / 2; i < SIZE; i++) {
|
||||
res[i - 49] = ints[i - 49] * i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] indexPlusInvariant() {
|
||||
int[] res = new int[SIZE];
|
||||
System.arraycopy(ints, 0, res, 0, SIZE);
|
||||
for (int i = 0; i < SIZE / 4; i++) {
|
||||
res[i + inv1] *= ints[i + inv1];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] indexMinusInvariant() {
|
||||
int[] res = new int[SIZE];
|
||||
System.arraycopy(ints, 0, res, 0, SIZE);
|
||||
for (int i = SIZE / 3; i < SIZE / 2; i++) {
|
||||
res[i - inv2] *= (ints[i - inv2] + (i >> 2));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] indexWithInvariantAndConstant() {
|
||||
int[] res = new int[SIZE];
|
||||
System.arraycopy(ints, 0, res, 0, SIZE);
|
||||
for (int i = 10; i < SIZE / 4; i++) {
|
||||
res[i + inv1 - 1] *= (ints[i + inv1 - 1] + 1);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] indexWithTwoInvariants() {
|
||||
int[] res = new int[SIZE];
|
||||
System.arraycopy(ints, 0, res, 0, SIZE);
|
||||
for (int i = 10; i < SIZE / 4; i++) {
|
||||
res[i + inv1 + inv2] -= ints[i + inv1 + inv2];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized due to data dependence
|
||||
public int[] indexWithDifferentConstants() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE / 4; i++) {
|
||||
res[i] = ints[i + 1];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized due to data dependence
|
||||
public int[] indexWithDifferentInvariants() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = SIZE / 4; i < SIZE / 2; i++) {
|
||||
res[i + inv1] = ints[i - inv2];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int indexWithDifferentConstantsLoadOnly() {
|
||||
int res1 = 0;
|
||||
int res2 = 0;
|
||||
for (int i = 0; i < SIZE / 4; i++) {
|
||||
res1 += ints[i + 2];
|
||||
res2 += ints[i + 15];
|
||||
}
|
||||
return res1 * res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int indexWithDifferentInvariantsLoadOnly() {
|
||||
int res1 = 0;
|
||||
int res2 = 0;
|
||||
for (int i = SIZE / 4; i < SIZE / 2; i++) {
|
||||
res1 += ints[i + inv1];
|
||||
res2 += ints[i - inv2];
|
||||
}
|
||||
return res1 * res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] scaledIndex() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE / 3; i++) {
|
||||
res[2 * i] = ints[2 * i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] scaledIndexWithConstantOffset() {
|
||||
int[] res = new int[SIZE];
|
||||
System.arraycopy(ints, 0, res, 0, SIZE);
|
||||
for (int i = 0; i < SIZE / 4; i++) {
|
||||
res[2 * i + 3] *= ints[2 * i + 3];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] scaledIndexWithInvariantOffset() {
|
||||
int[] res = new int[SIZE];
|
||||
System.arraycopy(ints, 0, res, 0, SIZE);
|
||||
for (int i = 0; i < SIZE / 4; i++) {
|
||||
res[2 * i + inv1] *= ints[2 * i + inv1];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized due to data dependence
|
||||
// between src and dest of the assignment.
|
||||
public int[] sameArrayWithDifferentIndex() {
|
||||
int[] res = new int[SIZE];
|
||||
System.arraycopy(ints, 0, res, 0, SIZE);
|
||||
for (int i = 1, j = 0; i < 100; i++, j++) {
|
||||
res[i] += res[j];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Subword Type Arrays ----------------
|
||||
@Test
|
||||
// Note that this case cannot be vectorized due to data dependence
|
||||
public short[] shortArrayWithDependence() {
|
||||
short[] res = new short[SIZE];
|
||||
System.arraycopy(shorts, 0, res, 0, SIZE);
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res[i] *= shorts[i + 1];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized due to data dependence
|
||||
public char[] charArrayWithDependence() {
|
||||
char[] res = new char[SIZE];
|
||||
System.arraycopy(chars, 0, res, 0, SIZE);
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res[i] *= chars[i + 2];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized due to data dependence
|
||||
public byte[] byteArrayWithDependence() {
|
||||
byte[] res = new byte[SIZE];
|
||||
System.arraycopy(bytes, 0, res, 0, SIZE);
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res[i] *= bytes[i + 3];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized due to data dependence
|
||||
public boolean[] booleanArrayWithDependence() {
|
||||
boolean[] res = new boolean[SIZE];
|
||||
System.arraycopy(booleans, 0, res, 0, SIZE);
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res[i] |= booleans[i + 4];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Multiple Operations ----------------
|
||||
@Test
|
||||
public int[] differentIndexWithDifferentTypes() {
|
||||
int[] res1 = new int[SIZE];
|
||||
short[] res2 = new short[SIZE];
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res1[i + 1] = ints[i + 1];
|
||||
res2[i + inv2] = shorts[i + inv2];
|
||||
}
|
||||
return res1;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that this case cannot be vectorized due to data dependence
|
||||
public int[] differentIndexWithSameType() {
|
||||
int[] res1 = new int[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res1[i + 3] = ints[i + 3];
|
||||
res2[i + inv1] = ints[i + inv1];
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on combined operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.LoopCombinedOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class LoopCombinedOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] a;
|
||||
private int[] b;
|
||||
private int[] c;
|
||||
private int[] d;
|
||||
private long[] l1;
|
||||
private long[] l2;
|
||||
private short[] s1;
|
||||
private short[] s2;
|
||||
private int intInv;
|
||||
|
||||
public LoopCombinedOpTest() {
|
||||
a = new int[SIZE];
|
||||
b = new int[SIZE];
|
||||
c = new int[SIZE];
|
||||
d = new int[SIZE];
|
||||
l1 = new long[SIZE];
|
||||
l2 = new long[SIZE];
|
||||
s1 = new short[SIZE];
|
||||
s2 = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = -654321 * i;
|
||||
b[i] = 123456 * i;
|
||||
c[i] = -998877 * i;
|
||||
d[i] = 778899 * i;
|
||||
l1[i] = 5000000000L * i;
|
||||
l2[i] = -600000000L * i;
|
||||
s1[i] = (short) (3 * i);
|
||||
s2[i] = (short) (-2 * i);
|
||||
}
|
||||
Random ran = new Random(999);
|
||||
intInv = ran.nextInt();
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] opWithConstant() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] + 1234567890;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] opWithLoopInvariant() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = b[i] * intInv;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] opWithConstantAndLoopInvariant() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = c[i] * (intInv & 0xfff);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multipleOps() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] & b[i] + c[i] & d[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multipleOpsWithMultipleConstants() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] * 12345678 + 87654321 + b[i] & 0xffff - c[i] * d[i] * 2;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multipleStores() {
|
||||
int[] res1 = new int[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
int[] res3 = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = a[i] & b[i];
|
||||
res2[i] = c[i] | d[i];
|
||||
res3[i] = res1[i] * res2[i];
|
||||
}
|
||||
return res3;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multipleStoresWithCommonSubExpression() {
|
||||
int[] res1 = new int[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
int[] res3 = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = a[i] * b[i];
|
||||
res2[i] = c[i] * d[i];
|
||||
res3[i] = res1[i] + res2[i];
|
||||
}
|
||||
return res3;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multipleOpsWith2DifferentTypes() {
|
||||
short[] res1 = new short[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = (short) (s1[i] + s2[i]);
|
||||
res2[i] = a[i] + b[i];
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] multipleOpsWith3DifferentTypes() {
|
||||
short[] res1 = new short[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
long[] res3 = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = (short) (s1[i] + s2[i]);
|
||||
res2[i] = a[i] + b[i];
|
||||
res3[i] = l1[i] + l2[i];
|
||||
}
|
||||
return res3;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long[] multipleOpsWith2NonAdjacentTypes() {
|
||||
short[] res1 = new short[SIZE];
|
||||
long[] res2 = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = (short) (s1[i] + s2[i]);
|
||||
res2[i] = l1[i] + l2[i];
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multipleOpsWith2DifferentTypesAndConstant() {
|
||||
short[] res1 = new short[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = (short) (s1[i] + s2[i]);
|
||||
res2[i] = a[i] + 88888888;;
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multipleOpsWith2DifferentTypesAndInvariant() {
|
||||
short[] res1 = new short[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = (short) (s1[i] + s2[i]);
|
||||
res2[i] = a[i] * intInv;
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multipleOpsWith2DifferentTypesAndComplexExpression() {
|
||||
short[] res1 = new short[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = (short) (s1[i] + s2[i]);
|
||||
res2[i] = a[i] * (b[i] + intInv * c[i] & 0xfffffa);
|
||||
}
|
||||
return res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] fillIndexPlusStride() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = i + 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] addArrayWithIndex() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] + i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public short[] multiplyAddShortIndex() {
|
||||
short[] res = new short[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = (short) (i * i + i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] multiplyBySumOfIndexAndInvariant() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] * (i + 10 + intInv);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] manuallyUnrolledStride2() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE - 1; i += 2) {
|
||||
res[i] = a[i] * b[i];
|
||||
res[i + 1] = a[i + 1] * b[i + 1];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int partialVectorizableLoop() {
|
||||
int[] res = new int[SIZE];
|
||||
int k = 9;
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res[i] = a[i] * b[i];
|
||||
k = 3 * k + 1;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on simple control flow in loop
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.LoopControlFlowTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class LoopControlFlowTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] a;
|
||||
private int[] b;
|
||||
private boolean invCond;
|
||||
|
||||
public LoopControlFlowTest() {
|
||||
a = new int[SIZE];
|
||||
b = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = i + 80000;;
|
||||
b[i] = 80 * i;
|
||||
}
|
||||
Random ran = new Random(505050);
|
||||
invCond = (ran.nextInt() % 2 == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] loopInvariantCondition() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
if (invCond) {
|
||||
res[i] = a[i] + b[i];
|
||||
} else {
|
||||
res[i] = a[i] - b[i];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] arrayElementCondition() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
if (b[i] > 10000) {
|
||||
res[i] = a[i] + b[i];
|
||||
} else {
|
||||
res[i] = a[i] - b[i];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on loops with live out nodes
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.LoopLiveOutNodesTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class LoopLiveOutNodesTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 3333;
|
||||
|
||||
private int[] a;
|
||||
private int start;
|
||||
private int limit;
|
||||
|
||||
public LoopLiveOutNodesTest() {
|
||||
a = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = -697989 * i;
|
||||
}
|
||||
Random ran = new Random(31415926);
|
||||
start = 999 + ran.nextInt() % 100;
|
||||
limit = start + 1357;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int SimpleIvUsed() {
|
||||
int i = 0;
|
||||
int[] res = new int[SIZE];
|
||||
for (i = start; i < limit; i++) {
|
||||
res[i] = a[i] * 2757;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int indexedByIvUsed() {
|
||||
int i = 0;
|
||||
int[] res = new int[SIZE];
|
||||
for (i = start; i < limit; i++) {
|
||||
res[i] = a[i] & 0x77ff77ff;
|
||||
}
|
||||
return a[i - 1];
|
||||
}
|
||||
|
||||
@Test
|
||||
public int ivUsedMultiple() {
|
||||
int i = 0;
|
||||
int[] res = new int[SIZE];
|
||||
for (i = start; i < limit; i++) {
|
||||
res[i] = a[i] | 65535;
|
||||
}
|
||||
return i * i;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int ivUsedComplexExpr() {
|
||||
int i = 0;
|
||||
int[] res = new int[SIZE];
|
||||
for (i = start; i < limit; i++) {
|
||||
res[i] = a[i] - 100550;
|
||||
}
|
||||
return a[i] + a[i - 2] + i * i;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] ivUsedAnotherLoop() {
|
||||
int i = 0;
|
||||
int[] res = new int[SIZE];
|
||||
for (i = start; i < limit; i++) {
|
||||
res[i] = a[i] * 100;
|
||||
}
|
||||
for (int j = i; j < i + 55; j++) {
|
||||
res[j] = a[j - 500] + 2323;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int ivUsedInParallel() {
|
||||
int i = 0, j = 0;
|
||||
int[] res = new int[SIZE];
|
||||
for (i = start; i < limit; i++, j++) {
|
||||
res[i] = a[i] + i;
|
||||
}
|
||||
return i * j + a[i] * a[j];
|
||||
}
|
||||
|
||||
@Test
|
||||
public int valueLiveOut() {
|
||||
int val = 0;
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = start; i < limit; i++) {
|
||||
val = a[i] - 101;
|
||||
res[i] = val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on different loop ranges and strides
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.LoopRangeStrideTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class LoopRangeStrideTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] a;
|
||||
private int[] b;
|
||||
private int start;
|
||||
private int end;
|
||||
|
||||
public LoopRangeStrideTest() {
|
||||
a = new int[SIZE];
|
||||
b = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = -i / 2;
|
||||
b[i] = 444 * i - 12345;
|
||||
}
|
||||
|
||||
Random ran = new Random(0);
|
||||
start = Math.abs(ran.nextInt() % 1000);
|
||||
end = start + 1315;
|
||||
}
|
||||
|
||||
// ---------------- Range ----------------
|
||||
@Test
|
||||
public int[] smallConstantRange() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 20; i < 27; i++) {
|
||||
res[i] = a[i] + b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] nonConstantRange() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = start; i < end; i++) {
|
||||
res[i] = a[i] - b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] crossZeroRange() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = -20; i < 20; i++) {
|
||||
res[i + 50] = a[i + 50] + b[i + 50];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] nonEqualTestRange() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = start; i != end; i++) {
|
||||
res[i] = a[i] - b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] shortInductionLoop() {
|
||||
int[] res = new int[SIZE];
|
||||
for (short s = 123; s < 789; s++) {
|
||||
res[s] = a[s] * b[s];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] whileLoop() {
|
||||
int[] res = new int[SIZE];
|
||||
int i = start;
|
||||
while (i < end) {
|
||||
res[i] = a[i] & b[i];
|
||||
i++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] doWhileLoop() {
|
||||
int[] res = new int[SIZE];
|
||||
int i = start;
|
||||
do {
|
||||
res[i] = a[i] | b[i];
|
||||
i++;
|
||||
} while (i < end);
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------------- Stride ----------------
|
||||
@Test
|
||||
public int[] stride2Loop() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i += 2) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] stride3Loop() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i += 3) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] stride4Loop() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i += 4) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public int[] countDownLoop() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = SIZE - 1; i > 0; i--) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] strideMinus2Loop() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = SIZE - 1; i > 0; i -= 2) {
|
||||
res[i] = a[i] * b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// ---------- Stride with scale ----------
|
||||
@Test
|
||||
public int[] countupLoopWithNegScale() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = SIZE / 2; i < SIZE; i++) {
|
||||
res[SIZE - i] = a[SIZE - i] * b[SIZE - i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] countDownLoopWithNegScale() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = SIZE / 2; i > 0; i--) {
|
||||
res[SIZE - i] = a[SIZE - i] * b[SIZE - i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on reduction operations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.LoopReductionOpTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class LoopReductionOpTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] a;
|
||||
private int[] b;
|
||||
private int[] c;
|
||||
private double[] d;
|
||||
private float[] f;
|
||||
private long[] l;
|
||||
private int intInv;
|
||||
|
||||
public LoopReductionOpTest() {
|
||||
a = new int[SIZE];
|
||||
b = new int[SIZE];
|
||||
c = new int[SIZE];
|
||||
d = new double[SIZE];
|
||||
f = new float[SIZE];
|
||||
l = new long[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = -531 * i;
|
||||
b[i] = 2222 * i + 8;
|
||||
c[i] = 2147480000;
|
||||
d[i] = i * 2.5;
|
||||
f[i] = i * -(333.3f);
|
||||
l[i] = 444444444L * i;
|
||||
}
|
||||
Random ran = new Random(10001);
|
||||
intInv = ran.nextInt();
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionAddSumOfArray() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += (a[i] + b[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionAddIndex() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += i;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
// Note that adding constant in loop would be directly optimized to
|
||||
// scalar operations, hence this case is not vectorized.
|
||||
public int reductionAddConstant() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += 222;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionAddLoopInv() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += intInv;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int reductionAddSumOfMultiple() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += (a[i] + b[i]) * i << 2;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int twoReductions() {
|
||||
int res1 = 0;
|
||||
int res2 = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1 += a[i];
|
||||
res2 += b[i];
|
||||
}
|
||||
return res1 * res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public float twoReductionsSameElementSize() {
|
||||
int res1 = 0;
|
||||
float res2 = 0.0f;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1 += a[i];
|
||||
res2 += f[i];
|
||||
}
|
||||
return res1 * res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double twoReductionsDifferentSizes1() {
|
||||
int res1 = 0;
|
||||
double res2 = 0.0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1 += a[i];
|
||||
res2 += d[i];
|
||||
}
|
||||
return res1 * res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public double twoReductionsDifferentSizes2() {
|
||||
long res1 = 0L;
|
||||
float res2 = 0.0f;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1 += l[i];
|
||||
res2 += f[i];
|
||||
}
|
||||
return res1 * res2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long reductionWithNonReductionDifferentSizes() {
|
||||
long res = 0L;
|
||||
int[] arr = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
arr[i] = a[i] + b[i];
|
||||
res += l[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public long reductionLoopIndexSumDifferentSizes() {
|
||||
int intSum = 0;
|
||||
long longSum = 0L;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
intSum += i;
|
||||
longSum += i;
|
||||
}
|
||||
return intSum + 2 * longSum;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test on multiple loops in a method
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* compiler.vectorization.runner.MultipleLoopsTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
public class MultipleLoopsTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 543;
|
||||
|
||||
private int[] a;
|
||||
private int[] b;
|
||||
private int[] c;
|
||||
|
||||
public MultipleLoopsTest() {
|
||||
a = new int[SIZE];
|
||||
b = new int[SIZE];
|
||||
c = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = -654321 * i;
|
||||
b[i] = 123456 * i;
|
||||
c[i] = -998877 * i;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] consecutiveLoops() {
|
||||
int[] res1 = new int[SIZE];
|
||||
int[] res2 = new int[SIZE];
|
||||
int[] res3 = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res1[i] = a[i] + b[i];
|
||||
}
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res2[i] = a[i] - b[i];
|
||||
}
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res3[i] = res1[i] * res2[i];
|
||||
}
|
||||
return res3;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] consecutiveLoopsNested() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int outer = 0; outer < 30; outer++) {
|
||||
for (int i = 0; i < SIZE / 2; i++) {
|
||||
res[i] += a[i];
|
||||
}
|
||||
for (int i = SIZE / 2; i < SIZE; i++) {
|
||||
res[i] *= b[i];
|
||||
}
|
||||
} // Outer loop is counted
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] nestedLoopOuterNonCounted() {
|
||||
int i = 1;
|
||||
int[] res = new int[SIZE];
|
||||
while (i < SIZE) {
|
||||
int val = i * a[i];
|
||||
for (int j = 0; j < SIZE; j++) {
|
||||
res[j] = b[j] * val;
|
||||
}
|
||||
i *= 2;
|
||||
} // Outer loop is non-counted
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] nestedLoopIndexCompute() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 50; i < 100; i++) {
|
||||
for (int j = 0; j < 200 - i; j++) {
|
||||
res[i + j] = a[i + j] * b[i + j];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Vectorization test with small strip mining iterations
|
||||
* @library /test/lib /
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* compiler.vectorization.runner.VectorizationTestRunner
|
||||
*
|
||||
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main/othervm -Xbootclasspath/a:.
|
||||
* -XX:+UnlockDiagnosticVMOptions
|
||||
* -XX:+WhiteBoxAPI
|
||||
* -XX:LoopStripMiningIter=10
|
||||
* compiler.vectorization.runner.StripMinedLoopTest
|
||||
*
|
||||
* @requires vm.compiler2.enabled & vm.flagless
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class StripMinedLoopTest extends VectorizationTestRunner {
|
||||
|
||||
private static final int SIZE = 2345;
|
||||
|
||||
private int[] a = new int[SIZE];
|
||||
private int[] b = new int[SIZE];
|
||||
|
||||
public StripMinedLoopTest() {
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
a[i] = 2;
|
||||
b[i] = 3;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public int[] stripMinedVectorLoop() {
|
||||
int[] res = new int[SIZE];
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res[i] = a[i] + b[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Test
|
||||
public int stripMinedReductionLoop() {
|
||||
int res = 0;
|
||||
for (int i = 0; i < SIZE; i++) {
|
||||
res += a[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Arm Limited. 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.
|
||||
*/
|
||||
|
||||
package compiler.vectorization.runner;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import jdk.test.lib.Utils;
|
||||
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class VectorizationTestRunner {
|
||||
|
||||
private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||
|
||||
private static final int COMP_LEVEL_INTP = 0;
|
||||
private static final int COMP_LEVEL_C2 = 4;
|
||||
|
||||
private static final int NMETHOD_COMP_LEVEL_IDX = 1;
|
||||
private static final int NMETHOD_INSTS_IDX = 2;
|
||||
|
||||
private static final long COMP_THRES_SECONDS = 30;
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
protected @interface Test {}
|
||||
|
||||
protected void run() {
|
||||
// Add extra VM options to enable post loop vectorization
|
||||
WB.setBooleanVMFlag("UnlockExperimentalVMOptions", true);
|
||||
WB.setBooleanVMFlag("PostLoopMultiversioning", true);
|
||||
|
||||
// For each method annotated with @Test in the test method, this test runner
|
||||
// invokes it twice - first time in the interpreter and second time compiled
|
||||
// by C2. Then this runner compares the two return values. Hence we require
|
||||
// each test method returning a primitive value or an array of primitive type.
|
||||
// And each test method should not throw any exceptions.
|
||||
Class klass = getClass();
|
||||
for (Method method : klass.getDeclaredMethods()) {
|
||||
try {
|
||||
if (method.isAnnotationPresent(Test.class)) {
|
||||
verifyTestMethod(method);
|
||||
runTestOnMethod(method);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Test failed in " + klass.getName() +
|
||||
"." + method.getName() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyTestMethod(Method method) {
|
||||
// Check method parameter count
|
||||
if (method.getParameterCount() > 0) {
|
||||
fail("Test method should have no parameter.");
|
||||
}
|
||||
|
||||
// Check method modifiers
|
||||
int modifiers = method.getModifiers();
|
||||
if (!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers)) {
|
||||
fail("Test method should be public and non-static.");
|
||||
}
|
||||
|
||||
// Check method return type
|
||||
Class retType = method.getReturnType();
|
||||
if (retType.isPrimitive()) {
|
||||
if (retType == Void.TYPE) {
|
||||
fail("Test method should return non-void.");
|
||||
}
|
||||
} else if (retType.isArray()) {
|
||||
Class elemType = retType.getComponentType();
|
||||
if (!elemType.isPrimitive()) {
|
||||
fail("Only primitive array types are supported.");
|
||||
}
|
||||
} else {
|
||||
fail("Test method should not return Object type.");
|
||||
}
|
||||
}
|
||||
|
||||
private void runTestOnMethod(Method method) throws InterruptedException {
|
||||
Object expected = null;
|
||||
Object actual = null;
|
||||
|
||||
// Lock compilation and inovke the method to get reference result from
|
||||
// the interpreter
|
||||
WB.lockCompilation();
|
||||
try {
|
||||
expected = method.invoke(this);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail("Exception is thrown in test method invocation (interpreter).");
|
||||
}
|
||||
assert(WB.getMethodCompilationLevel(method) == COMP_LEVEL_INTP);
|
||||
WB.unlockCompilation();
|
||||
|
||||
// Compile the method and invoke it again
|
||||
long enqueueTime = System.currentTimeMillis();
|
||||
WB.enqueueMethodForCompilation(method, COMP_LEVEL_C2);
|
||||
while (WB.getMethodCompilationLevel(method) != COMP_LEVEL_C2) {
|
||||
if (System.currentTimeMillis() - enqueueTime > COMP_THRES_SECONDS * 1000) {
|
||||
fail("Method is not compiled after " + COMP_THRES_SECONDS + "s.");
|
||||
}
|
||||
Thread.sleep(50 /*ms*/);
|
||||
}
|
||||
try {
|
||||
actual = method.invoke(this);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail("Exception is thrown in test method invocation (C2).");
|
||||
}
|
||||
assert(WB.getMethodCompilationLevel(method) == COMP_LEVEL_C2);
|
||||
|
||||
// Check if two invocations return the same
|
||||
Class retType = method.getReturnType();
|
||||
if (retType.isArray()) {
|
||||
// Method invocations from Java reflection API always return a boxed object.
|
||||
// Hence, for methods return primitive array, we can only use reflection API
|
||||
// to check the consistency of the elements one by one.
|
||||
if (expected == null && actual == null) {
|
||||
return;
|
||||
}
|
||||
if (expected == null ^ actual == null) {
|
||||
fail("Inconsistent return value: null/non-null.");
|
||||
}
|
||||
int length = Array.getLength(expected);
|
||||
if (Array.getLength(actual) != length) {
|
||||
fail("Inconsistent array length: expected = " + length + ", actual = " +
|
||||
Array.getLength(actual));
|
||||
}
|
||||
for (int idx = 0; idx < length; idx++) {
|
||||
Object e1 = Array.get(expected, idx);
|
||||
Object e2 = Array.get(actual, idx);
|
||||
if (!e1.equals(e2)) {
|
||||
fail("Inconsistent value at array index [" + idx + "], expected = " +
|
||||
e1 + ", actual = " + e2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Method invocations from Java reflection API always return a boxed object.
|
||||
// Hence, we should use equals() to check the consistency for methods which
|
||||
// return primitive type.
|
||||
if (!expected.equals(actual)) {
|
||||
fail("Inconsistent return value: expected = " + expected
|
||||
+ ", actual = " + actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static VectorizationTestRunner createTestInstance(String testName) {
|
||||
if (!testName.toLowerCase().endsWith(".java")) {
|
||||
fail("Invalid test file name " + testName);
|
||||
}
|
||||
testName = testName.substring(0, testName.length() - 5);
|
||||
testName = testName.replace('/', '.');
|
||||
|
||||
VectorizationTestRunner instance = null;
|
||||
try {
|
||||
Class klass = Class.forName(testName);
|
||||
Constructor ctor = klass.getConstructor();
|
||||
instance = (VectorizationTestRunner) ctor.newInstance();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail("Cannot create test instance for class " + testName);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static void fail(String reason) {
|
||||
throw new RuntimeException(reason);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
VectorizationTestRunner testObj = createTestInstance(Utils.TEST_NAME);
|
||||
testObj.run();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user