Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions src/hotspot/cpu/x86/x86.ad
Original file line number Diff line number Diff line change
Expand Up @@ -4514,18 +4514,43 @@ instruct vReplS_reg(vec dst, rRegI src) %{
%}

#ifdef _LP64
instruct ReplS_imm(vec dst, immH con, rRegI rtmp) %{
predicate(VM_Version::supports_avx512_fp16() && Matcher::vector_element_basic_type(n) == T_SHORT);
instruct ReplH_imm(vec dst, immH con, rRegI rtmp) %{
match(Set dst (Replicate con));
effect(TEMP rtmp);
format %{ "replicateS $dst, $con" %}
format %{ "replicateH $dst, $con \t! using $rtmp as TEMP" %}
ins_encode %{
int vlen_enc = vector_length_encoding(this);
BasicType bt = Matcher::vector_element_basic_type(this);
assert(VM_Version::supports_avx512_fp16() && bt == T_SHORT, "");
__ movl($rtmp$$Register, $con$$constant);
__ evpbroadcastw($dst$$XMMRegister, $rtmp$$Register, vlen_enc);
%}
ins_pipe( pipe_slow );
%}

instruct ReplH_short_reg(vec dst, rRegI src) %{
predicate(VM_Version::supports_avx512_fp16() && Matcher::vector_element_basic_type(n) == T_SHORT);
match(Set dst (Replicate (ReinterpretS2HF src)));
format %{ "replicateH $dst, $src" %}
ins_encode %{
int vlen_enc = vector_length_encoding(this);
__ evpbroadcastw($dst$$XMMRegister, $src$$Register, vlen_enc);
%}
ins_pipe( pipe_slow );
%}

instruct ReplH_reg(vec dst, regF src, rRegI rtmp) %{
predicate(VM_Version::supports_avx512_fp16() && Matcher::vector_element_basic_type(n) == T_SHORT);
match(Set dst (Replicate src));
effect(TEMP rtmp);
format %{ "replicateH $dst, $src \t! using $rtmp as TEMP" %}
ins_encode %{
int vlen_enc = vector_length_encoding(this);
__ vmovw($rtmp$$Register, $src$$XMMRegister);
__ evpbroadcastw($dst$$XMMRegister, $rtmp$$Register, vlen_enc);
%}
ins_pipe( pipe_slow );
%}
#endif

instruct ReplS_mem(vec dst, memory mem) %{
Expand Down Expand Up @@ -10902,7 +10927,7 @@ instruct reinterpretH2S(rRegI dst, regF src)
ins_pipe(pipe_slow);
%}

instruct scalar_sqrt_fp16(regF dst, regF src)
instruct scalar_sqrt_fp16_reg(regF dst, regF src)
%{
match(Set dst (SqrtHF src));
format %{ "vsqrtsh $dst, $src" %}
Expand All @@ -10912,7 +10937,7 @@ instruct scalar_sqrt_fp16(regF dst, regF src)
ins_pipe(pipe_slow);
%}

instruct scalar_binOps_fp16(regF dst, regF src1, regF src2)
instruct scalar_binOps_fp16_reg(regF dst, regF src1, regF src2)
%{
match(Set dst (AddHF src1 src2));
match(Set dst (DivHF src1 src2));
Expand All @@ -10928,7 +10953,7 @@ instruct scalar_binOps_fp16(regF dst, regF src1, regF src2)
ins_pipe(pipe_slow);
%}

instruct scalar_fma_fp16(regF dst, regF src1, regF src2)
instruct scalar_fma_fp16_reg(regF dst, regF src1, regF src2)
%{
match(Set dst (FmaHF src2 (Binary dst src1)));
effect(DEF dst);
Expand Down Expand Up @@ -11008,7 +11033,7 @@ instruct vector_fma_fp16_reg(vec dst, vec src1, vec src2)
ins_pipe( pipe_slow );
%}

instruct vector_fmah_fp16_mem(vec dst, memory src1, vec src2)
instruct vector_fma_fp16_mem(vec dst, memory src1, vec src2)
%{
match(Set dst (FmaVHF src2 (Binary dst (VectorReinterpret (LoadVector src1)))));
effect(DEF dst);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/adlc/output_h.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, 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
Expand Down
19 changes: 10 additions & 9 deletions src/hotspot/share/opto/addnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,15 +710,15 @@ Node *AddFNode::Ideal(PhaseGVN *phase, bool can_reshape) {
//=============================================================================
//------------------------------add_of_identity--------------------------------
// Check for addition of the identity
const Type *AddHFNode::add_of_identity( const Type *t1, const Type *t2 ) const {
const Type *AddHFNode::add_of_identity(const Type *t1, const Type *t2) const {
return nullptr;
}

//------------------------------add_ring---------------------------------------
// Supplied function returns the sum of the inputs.
// This also type-checks the inputs for sanity. Guaranteed never to
// be passed a TOP or BOTTOM type, these are filtered out by pre-check.
const Type *AddHFNode::add_ring( const Type *t0, const Type *t1 ) const {
const Type *AddHFNode::add_ring(const Type *t0, const Type *t1) const {
if (!t0->isa_half_float_constant() || !t1->isa_half_float_constant()) {
return bottom_type();
}
Expand Down Expand Up @@ -1601,7 +1601,7 @@ Node* MaxNode::Identity(PhaseGVN* phase) {
}

//------------------------------add_ring---------------------------------------
const Type* MinHFNode::add_ring(const Type* t0, const Type* t1 ) const {
const Type* MinHFNode::add_ring(const Type* t0, const Type* t1) const {
const TypeH* r0 = t0->isa_half_float_constant();
const TypeH* r1 = t1->isa_half_float_constant();
if (r0 == nullptr || r1 == nullptr) {
Expand Down Expand Up @@ -1676,9 +1676,9 @@ const Type* MinDNode::add_ring(const Type* t0, const Type* t1) const {
}

//------------------------------add_ring---------------------------------------
const Type* MaxFNode::add_ring(const Type* t0, const Type* t1) const {
const TypeF* r0 = t0->isa_float_constant();
const TypeF* r1 = t1->isa_float_constant();
const Type* MaxHFNode::add_ring(const Type* t0, const Type* t1) const {
const TypeH* r0 = t0->isa_half_float_constant();
const TypeH* r1 = t1->isa_half_float_constant();
if (r0 == nullptr || r1 == nullptr) {
return bottom_type();
}
Expand All @@ -1700,10 +1700,11 @@ const Type* MaxFNode::add_ring(const Type* t0, const Type* t1) const {
return (jint_cast(f0) > jint_cast(f1)) ? r0 : r1;
}


//------------------------------add_ring---------------------------------------
const Type* MaxHFNode::add_ring(const Type* t0, const Type* t1) const {
const TypeH* r0 = t0->isa_half_float_constant();
const TypeH* r1 = t1->isa_half_float_constant();
const Type* MaxFNode::add_ring(const Type* t0, const Type* t1) const {
const TypeF* r0 = t0->isa_float_constant();
const TypeF* r1 = t1->isa_float_constant();
if (r0 == nullptr || r1 == nullptr) {
return bottom_type();
}
Expand Down
10 changes: 5 additions & 5 deletions src/hotspot/share/opto/addnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,12 @@ class AddDNode : public AddNode {
// Add 2 half-precision floats
class AddHFNode : public AddNode {
public:
AddHFNode( Node *in1, Node *in2 ) : AddNode(in1,in2) {}
AddHFNode(Node *in1, Node *in2) : AddNode(in1,in2) {}
virtual int Opcode() const;
virtual const Type *add_of_identity( const Type *t1, const Type *t2 ) const;
virtual const Type *add_ring( const Type *, const Type * ) const;
virtual const Type *add_id() const { return TypeH::ZERO; }
virtual const Type *bottom_type() const { return Type::HALF_FLOAT; }
virtual const Type* add_of_identity(const Type *t1, const Type *t2) const;
virtual const Type* add_ring(const Type*, const Type*) const;
virtual const Type* add_id() const { return TypeH::ZERO; }
virtual const Type* bottom_type() const { return Type::HALF_FLOAT; }
int max_opcode() const { return Op_MaxHF; }
int min_opcode() const { return Op_MinHF; }
virtual Node* Identity(PhaseGVN* phase) { return this; }
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/opto/connode.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/opto/connode.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/opto/constantTable.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2024, 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
Expand Down Expand Up @@ -88,7 +88,7 @@ static int constant_size(ConstantTable::Constant* con) {
return type2aelembytes(con->type()) * con->get_array()->length();
}
switch (con->type()) {
case T_SHORT: return sizeof(jshort );
case T_SHORT: return sizeof(jint );
case T_INT: return sizeof(jint );
case T_LONG: return sizeof(jlong );
case T_FLOAT: return sizeof(jfloat );
Expand Down
21 changes: 20 additions & 1 deletion src/hotspot/share/opto/convertnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ Node* ConvF2HFNode::Ideal(PhaseGVN* phase, bool can_reshape) {
if (Float16NodeFactory::is_binary_oper(in(1)->Opcode()) &&
in(1)->in(1)->Opcode() == Op_ConvHF2F &&
in(1)->in(2)->Opcode() == Op_ConvHF2F) {
if (Matcher::match_rule_supported(in(1)->Opcode()) &&
if (Matcher::match_rule_supported(Float16NodeFactory::get_float16_binary_oper(in(1)->Opcode())) &&
Matcher::match_rule_supported(Op_ReinterpretS2HF) &&
Matcher::match_rule_supported(Op_ReinterpretHF2S)) {
Node* in1 = phase->transform(new ReinterpretS2HFNode(in(1)->in(1)->in(1)));
Expand Down Expand Up @@ -959,6 +959,25 @@ bool Float16NodeFactory::is_binary_oper(int opc) {
}
}

int Float16NodeFactory::get_float16_binary_oper(int opc) {
switch(opc) {
case Op_AddF:
return Op_AddHF;
case Op_SubF:
return Op_SubHF;
case Op_MulF:
return Op_MulHF;
case Op_DivF:
return Op_DivHF;
case Op_MaxF:
return Op_MaxHF;
case Op_MinF:
return Op_MinHF;
default:
return false;
}
}

Node* Float16NodeFactory::make(int opc, Node* c, Node* in1, Node* in2) {
switch(opc) {
case Op_AddF: return new AddHFNode(in1, in2);
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/convertnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ class RoundDoubleModeNode: public Node {
class Float16NodeFactory {
public:
static bool is_binary_oper(int opc);
static int get_float16_binary_oper(int opc);
static Node* make(int opc, Node* c, Node* in1, Node* in2);
};

Expand Down
52 changes: 26 additions & 26 deletions src/hotspot/share/opto/divnode.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
Expand Down Expand Up @@ -753,15 +753,15 @@ Node *DivFNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// prevent hoisting the divide above an unsafe test.
const Type* DivHFNode::Value(PhaseGVN* phase) const {
// Either input is TOP ==> the result is TOP
const Type *t1 = phase->type( in(1) );
const Type *t2 = phase->type( in(2) );
if( t1 == Type::TOP ) return Type::TOP;
if( t2 == Type::TOP ) return Type::TOP;
const Type* t1 = phase->type(in(1));
const Type* t2 = phase->type(in(2));
if(t1 == Type::TOP) return Type::TOP;
if(t2 == Type::TOP) return Type::TOP;

// Either input is BOTTOM ==> the result is the local BOTTOM
const Type *bot = bottom_type();
if( (t1 == bot) || (t2 == bot) ||
(t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
const Type* bot = bottom_type();
if((t1 == bot) || (t2 == bot) ||
(t1 == Type::BOTTOM) || (t2 == Type::BOTTOM))
return bot;

// x/x == 1, we ignore 0/0.
Expand All @@ -772,20 +772,20 @@ const Type* DivHFNode::Value(PhaseGVN* phase) const {
return TypeH::ONE;
}

if( t2 == TypeH::ONE )
if(t2 == TypeH::ONE)
return t1;

// If divisor is a constant and not zero, divide them numbers
if( t1->base() == Type::HalfFloatCon &&
t2->base() == Type::HalfFloatCon &&
t2->getf() != 0.0 ) // could be negative zero
return TypeH::make( t1->getf()/t2->getf() );
if(t1->base() == Type::HalfFloatCon &&
t2->base() == Type::HalfFloatCon &&
t2->getf() != 0.0) // could be negative zero
return TypeH::make(t1->getf()/t2->getf());

// If the dividend is a constant zero
// Note: if t1 and t2 are zero then result is NaN (JVMS page 213)
// Test TypeF::ZERO is not sufficient as it could be negative zero

if( t1 == TypeH::ZERO && !g_isnan(t2->getf()) && t2->getf() != 0.0 )
if(t1 == TypeH::ZERO && !g_isnan(t2->getf()) && t2->getf() != 0.0)
return TypeH::ZERO;

// Otherwise we give up all hope
Expand All @@ -801,36 +801,36 @@ Node* DivHFNode::Identity(PhaseGVN* phase) {


//------------------------------Idealize---------------------------------------
Node *DivHFNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node *DivHFNode::Ideal(PhaseGVN* phase, bool can_reshape) {
if (in(0) && remove_dead_region(phase, can_reshape)) return this;
// Don't bother trying to transform a dead node
if( in(0) && in(0)->is_top() ) return nullptr;
if(in(0) && in(0)->is_top()) return nullptr;

const Type *t2 = phase->type( in(2) );
if( t2 == TypeH::ONE ) // Identity?
return nullptr; // Skip it
const Type* t2 = phase->type(in(2));
if(t2 == TypeH::ONE) // Identity?
return nullptr; // Skip it

const TypeH *tf = t2->isa_half_float_constant();
if( !tf ) return nullptr;
if( tf->base() != Type::HalfFloatCon ) return nullptr;
const TypeH* tf = t2->isa_half_float_constant();
if(!tf) return nullptr;
if(tf->base() != Type::HalfFloatCon) return nullptr;

// Check for out of range values
if( tf->is_nan() || !tf->is_finite() ) return nullptr;
if(tf->is_nan() || !tf->is_finite()) return nullptr;

// Get the value
float f = tf->getf();
int exp;

// Only for special case of dividing by a power of 2
if( frexp((double)f, &exp) != 0.5 ) return nullptr;
if(frexp((double)f, &exp) != 0.5) return nullptr;

// Limit the range of acceptable exponents
if( exp < -14 || exp > 15 ) return nullptr;
if(exp < -14 || exp > 15) return nullptr;

// Compute the reciprocal
float reciprocal = ((float)1.0) / f;

assert( frexp((double)reciprocal, &exp) == 0.5, "reciprocal should be power of 2" );
assert(frexp((double)reciprocal, &exp) == 0.5, "reciprocal should be power of 2");

// return multiplication by the reciprocal
return (new MulHFNode(in(1), phase->makecon(TypeH::make(reciprocal))));
Expand Down
8 changes: 4 additions & 4 deletions src/hotspot/share/opto/divnode.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
Expand Down Expand Up @@ -82,12 +82,12 @@ class DivFNode : public Node {
// Half float division
class DivHFNode : public Node {
public:
DivHFNode( Node *c, Node *dividend, Node *divisor ) : Node(c, dividend, divisor) {}
DivHFNode(Node* c, Node* dividend, Node* divisor) : Node(c, dividend, divisor) {}
virtual int Opcode() const;
virtual Node* Identity(PhaseGVN* phase);
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
virtual const Type* Value(PhaseGVN* phase) const;
virtual const Type *bottom_type() const { return Type::HALF_FLOAT; }
virtual const Type* bottom_type() const { return Type::HALF_FLOAT; }
virtual uint ideal_reg() const { return Op_RegF; }
};

Expand Down
Loading