Constant propagation of floating-point min/max left over?
B. Blaser
bsrbnd at gmail.com
Thu Feb 14 15:03:44 UTC 2019
Hi,
I've seen in [1] that constant propagation of floating-point min/max
intrinsic has been left over.
I tried a quick (naive?) patch on double values, here under, and I did
the following small experiment on x86_64, currently without any
matching rule:
class MinMax {
public static void main(String... args) {
for (double d=0; d<100_000; d++) {
test();
}
}
static double[] d = new double[5];
public static double[] test() {
d[0] = Math.max(Math.max(-0.0, 0.0), -0.0);
d[1] = Math.min(Math.min( 0.0, -0.0), 0.0);
d[2] = Math.max(Math.max(1.0, Double.NaN), 1.0);
d[3] = Math.min(Math.min(1.0, Double.NaN), 1.0);
d[4] = Math.max(Math.min(Math.max(1.0, 2.0), -1.0), 0.5);
return d;
}
}
Running it with:
$ java -Xcomp -XX:-TieredCompilation
-XX:CompileCommand=print,MinMax.test* MinMax
Before we had one bloc per min/max invocation like:
movsd XMM0, [constant table base + #0] # load from constant
table: double=#-0.000000
movsd [rsp + #0], XMM0 # spill
movq R10, java/lang/Class:exact * # ptr
movl RBP, [R10 + #112 (8-bit)] # compressed ptr ! Field: MinMax.d
xorpd XMM1, XMM1 # double 0.0
call,static java.lang.Math::max
[ 10 other min/max invocations snipped... ]
And after we'd have:
movsd XMM0, [constant table base + #0] # load from constant
table: double=#nan
movsd XMM1, [constant table base + #8] # load from constant
table: double=#0.500000
movsd XMM2, [constant table base + #16] # load from constant
table: double=#-0.000000
xorpd XMM3, XMM3 # double 0.0
movsd [R12 + R11 << 3 + #16] (compressed oop addressing), XMM3 # double
movsd [R12 + R11 << 3 + #24] (compressed oop addressing), XMM2 # double
movsd [R12 + R11 << 3 + #32] (compressed oop addressing), XMM0 # double
movsd [R12 + R11 << 3 + #40] (compressed oop addressing), XMM0 # double
movsd [R12 + R11 << 3 + #48] (compressed oop addressing), XMM1 # double
Does this attempt look reasonable?
If yes, I'll create a JBS issue and probably send out a RFR soon (for
float and double).
Note that hotspot:tier1 is OK on x86_64 but all architectures would
benefit from this enhancement.
Thanks,
Bernard
[1] http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2018-October/031025.html
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -5456,6 +5456,22 @@
ins_pipe(pipe_slow); // XXX
%}
+instruct minD_reg(regD dst, regD a, regD b) %{
+ predicate(false);
+ match(Set dst (MinD a b));
+ format %{ "# NOP" %}
+ ins_encode %{ %}
+ ins_pipe( pipe_slow );
+%}
+
+instruct maxD_reg(regD dst, regD a, regD b) %{
+ predicate(false);
+ match(Set dst (MaxD a b));
+ format %{ "# NOP" %}
+ ins_encode %{ %}
+ ins_pipe( pipe_slow );
+%}
+
// Load Double
instruct MoveD2VL(vlRegD dst, regD src) %{
match(Set dst src);
diff --git a/src/hotspot/share/opto/addnode.cpp
b/src/hotspot/share/opto/addnode.cpp
--- a/src/hotspot/share/opto/addnode.cpp
+++ b/src/hotspot/share/opto/addnode.cpp
@@ -929,3 +929,37 @@
// Otherwise just MIN them bits.
return TypeInt::make( MIN2(r0->_lo,r1->_lo), MIN2(r0->_hi,r1->_hi),
MAX2(r0->_widen,r1->_widen) );
}
+
+const Type *MaxDNode::add_ring( const Type *t0, const Type *t1 ) const {
+ const TypeD *ta = t0->isa_double_constant();
+ const TypeD *tb = t1->isa_double_constant();
+
+ if (ta == NULL || tb == NULL) return Type::DOUBLE;
+
+ const jlong a = jlong_cast(ta->getd());
+ const jlong b = jlong_cast(tb->getd());
+
+ return
+ a == (jlong) 0x8000000000000000L && b == 0L ? tb :
+ b == (jlong) 0x8000000000000000L && a == 0L ? ta :
+ ta->is_nan() ? ta :
+ tb->is_nan() ? tb :
+ ta->getd() > tb->getd() ? ta : tb;
+}
+
+const Type *MinDNode::add_ring( const Type *t0, const Type *t1 ) const {
+ const TypeD *ta = t0->isa_double_constant();
+ const TypeD *tb = t1->isa_double_constant();
+
+ if (ta == NULL || tb == NULL) return Type::DOUBLE;
+
+ const jlong a = jlong_cast(ta->getd());
+ const jlong b = jlong_cast(tb->getd());
+
+ return
+ a == (jlong) 0x8000000000000000L && b == 0L ? ta :
+ b == (jlong) 0x8000000000000000L && a == 0L ? tb :
+ ta->is_nan() ? ta :
+ tb->is_nan() ? tb :
+ ta->getd() < tb->getd() ? ta : tb;
+}
diff --git a/src/hotspot/share/opto/addnode.hpp
b/src/hotspot/share/opto/addnode.hpp
--- a/src/hotspot/share/opto/addnode.hpp
+++ b/src/hotspot/share/opto/addnode.hpp
@@ -279,7 +279,7 @@
public:
MaxDNode(Node *in1, Node *in2) : MaxNode(in1, in2) {}
virtual int Opcode() const;
- virtual const Type *add_ring(const Type*, const Type*) const {
return Type::DOUBLE; }
+ virtual const Type *add_ring(const Type*, const Type*) const;
virtual const Type *add_id() const { return TypeD::NEG_INF; }
virtual const Type *bottom_type() const { return Type::DOUBLE; }
virtual uint ideal_reg() const { return Op_RegD; }
@@ -291,7 +291,7 @@
public:
MinDNode(Node *in1, Node *in2) : MaxNode(in1, in2) {}
virtual int Opcode() const;
- virtual const Type *add_ring(const Type*, const Type*) const {
return Type::DOUBLE; }
+ virtual const Type *add_ring(const Type*, const Type*) const;
virtual const Type *add_id() const { return TypeD::POS_INF; }
virtual const Type *bottom_type() const { return Type::DOUBLE; }
virtual uint ideal_reg() const { return Op_RegD; }
diff --git a/src/hotspot/share/opto/library_call.cpp
b/src/hotspot/share/opto/library_call.cpp
--- a/src/hotspot/share/opto/library_call.cpp
+++ b/src/hotspot/share/opto/library_call.cpp
@@ -6609,6 +6609,7 @@
//------------------------------inline_fp_min_max------------------------------
bool LibraryCallKit::inline_fp_min_max(vmIntrinsics::ID id) {
+printf("inline_fp_min_max\n");
Node *a = NULL;
Node *b = NULL;
Node *n = NULL;
@@ -6629,7 +6630,7 @@
fatal_unexpected_iid(id);
break;
}
- if (a->is_Con() || b->is_Con()) {
+ if (id != vmIntrinsics::_maxD && id != vmIntrinsics::_minD &&
(a->is_Con() || b->is_Con())) {
return false;
}
switch (id) {
More information about the hotspot-compiler-dev
mailing list