A prototype for intrinsifying Math.addExact(int, int), version 1 (original) (raw)

diff -r 6f8f439e247d src/cpu/x86/vm/x86_64.ad

--- a/src/cpu/x86/vm/x86_64.ad Tue Jun 19 15:12:56 2012 -0700

+++ b/src/cpu/x86/vm/x86_64.ad Thu Jun 21 08:41:21 2012 +0800

@@ -1674,6 +1674,16 @@

return LONG_RDX_REG_mask();

}

+// Register for AddI projection of checkedAddI

+RegMask Matcher::checkedAddI_sum_proj_mask() {

+}

+// Register for conditions projection

+RegMask Matcher::overflow_proj_mask() {

+}

const RegMask Matcher::method_handle_invoke_SP_save_mask() {

return PTR_RBP_REG_mask();

}

@@ -4173,6 +4183,8 @@

greater_equal(0xD, "ge");

less_equal(0xE, "le");

greater(0xF, "g");

%}

%}

@@ -4191,6 +4203,8 @@

greater_equal(0x3, "nb");

less_equal(0x6, "be");

greater(0x7, "nbe");

%}

%}

@@ -4210,6 +4224,8 @@

greater_equal(0x3, "nb");

less_equal(0x6, "be");

greater(0x7, "nbe");

%}

%}

@@ -4227,6 +4243,8 @@

greater_equal(0x3, "nb");

less_equal(0x6, "be");

greater(0x7, "nbe");

%}

%}

@@ -7673,6 +7691,20 @@

ins_pipe(ialu_reg_reg_alu0);

%}

+// Integer addition with overflow checking

+instruct checkedAddI_rReg(rRegI dst, rRegI src, rFlagsReg cr)

+%{

+%}

// Integer DIVMOD with Register, both quotient and mod results

instruct divModI_rReg_divmod(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,

rFlagsReg cr)

diff -r 6f8f439e247d src/share/vm/adlc/adlparse.cpp

--- a/src/share/vm/adlc/adlparse.cpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/adlc/adlparse.cpp Thu Jun 21 08:41:21 2012 +0800

@@ -3388,12 +3388,16 @@

char *greater_equal;

char *less_equal;

char *greater;

const char *equal_format = "eq";

const char *not_equal_format = "ne";

const char *less_format = "lt";

const char *greater_equal_format = "ge";

const char *less_equal_format = "le";

const char *greater_format = "gt";

if (_curchar != '%') {

parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n");

@@ -3430,6 +3434,12 @@

else if ( strcmp(field,"greater") == 0 ) {

greater = interface_field_parse(&greater_format);

}

else {

parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n");

return NULL;

@@ -3448,7 +3458,9 @@

less, less_format,

greater_equal, greater_equal_format,

less_equal, less_equal_format,

- greater, greater_format);

return inter;

}

diff -r 6f8f439e247d src/share/vm/adlc/formssel.cpp

--- a/src/share/vm/adlc/formssel.cpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/adlc/formssel.cpp Thu Jun 21 08:41:21 2012 +0800

@@ -2694,14 +2694,18 @@

const char* less, const char* less_format,

const char* greater_equal, const char* greater_equal_format,

const char* less_equal, const char* less_equal_format,

- const char* greater, const char* greater_format)

: Interface("COND_INTER"),

_equal(equal), _equal_format(equal_format),

_not_equal(not_equal), _not_equal_format(not_equal_format),

_less(less), _less_format(less_format),

_greater_equal(greater_equal), _greater_equal_format(greater_equal_format),

_less_equal(less_equal), _less_equal_format(less_equal_format),

- _greater(greater), _greater_format(greater_format) {

}

CondInterface::~CondInterface() {

// not owner of any character arrays

@@ -2720,6 +2724,8 @@

if ( _greater_equal != NULL ) fprintf(fp," greater_equal == %s\n", _greater_equal);

if ( _less_equal != NULL ) fprintf(fp," less_equal == %s\n", _less_equal);

if ( _greater != NULL ) fprintf(fp," greater == %s\n", _greater);

// fprintf(fp,"\n");

}

diff -r 6f8f439e247d src/share/vm/adlc/formssel.hpp

--- a/src/share/vm/adlc/formssel.hpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/adlc/formssel.hpp Thu Jun 21 08:41:21 2012 +0800

@@ -786,7 +786,7 @@

//------------------------------CondInterface----------------------------------

class CondInterface : public Interface {

private:

-

+// TODO fix comments of COND_INTER in *.ad files

public:

const char *_equal;

const char *_not_equal;

@@ -794,12 +794,16 @@

const char *_greater_equal;

const char *_less_equal;

const char *_greater;

const char *_equal_format;

const char *_not_equal_format;

const char *_less_format;

const char *_greater_equal_format;

const char *_less_equal_format;

const char *_greater_format;

// Public Methods

CondInterface(const char* equal, const char* equal_format,

@@ -807,7 +811,9 @@

const char* less, const char* less_format,

const char* greater_equal, const char* greater_equal_format,

const char* less_equal, const char* less_equal_format,

- const char* greater, const char* greater_format);

~CondInterface();

void dump();

diff -r 6f8f439e247d src/share/vm/adlc/output_h.cpp

--- a/src/share/vm/adlc/output_h.cpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/adlc/output_h.cpp Thu Jun 21 08:41:21 2012 +0800

@@ -364,6 +364,8 @@

fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format);

fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format);

fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format);

}

// Output code that dumps constant values, increment "i" if type is constant

@@ -1178,6 +1180,8 @@

fprintf(fp," case BoolTest::ne : return not_equal();\n");

fprintf(fp," case BoolTest::le : return less_equal();\n");

fprintf(fp," case BoolTest::ge : return greater_equal();\n");

fprintf(fp," default : ShouldNotReachHere(); return 0;\n");

fprintf(fp," }\n");

fprintf(fp," };\n");

@@ -1343,6 +1347,14 @@

if( greater != NULL ) {

define_oper_interface(fp, *oper, _globalNames, "greater", greater);

}

} // end Conditional Interface

// Check if it is a Constant Interface

else if (oper->_interface->is_ConstInterface() != NULL ) {

diff -r 6f8f439e247d src/share/vm/opto/classes.hpp

--- a/src/share/vm/opto/classes.hpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/opto/classes.hpp Thu Jun 21 08:41:21 2012 +0800

@@ -60,6 +60,8 @@

macro(Catch)

macro(CatchProj)

macro(CheckCastPP)

+macro(CheckedAdd)

+macro(CheckedAddI)

macro(ClearArray)

macro(ConstraintCast)

macro(CMoveD)

@@ -68,6 +70,7 @@

macro(CMoveL)

macro(CMoveP)

macro(CMoveN)

+macro(CmpAddI)

macro(CmpN)

macro(CmpD)

macro(CmpD3)

diff -r 6f8f439e247d src/share/vm/opto/compile.cpp

--- a/src/share/vm/opto/compile.cpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/opto/compile.cpp Thu Jun 21 08:41:21 2012 +0800

@@ -2137,6 +2137,48 @@

}

}

+//-------------------------------is_checked_addi--------------------------------

+// return the AddI node if an overflowing checking pattern is found

+// Upon success return, disconnect the input edges of the intermediate nodes.

+static Node* is_checked_addi(Node* n) {

+}

//------------------------------final_graph_reshaping_impl----------------------

// Implement items 1-5 from final_graph_reshaping below.

static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {

@@ -2591,6 +2633,23 @@

}

break;

case Op_LoadVector:

case Op_StoreVector:

break;

diff -r 6f8f439e247d src/share/vm/opto/matcher.hpp

--- a/src/share/vm/opto/matcher.hpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/opto/matcher.hpp Thu Jun 21 08:41:21 2012 +0800

@@ -317,6 +317,12 @@

// Register for MODL projection of divmodL

static RegMask modL_proj_mask();

// Use hardware DIV instruction when it is faster than

// a code which use multiply for division by constant.

static bool use_asm_for_ldiv_by_con( jlong divisor );

diff -r 6f8f439e247d src/share/vm/opto/subnode.cpp

--- a/src/share/vm/opto/subnode.cpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/opto/subnode.cpp Thu Jun 21 08:41:21 2012 +0800

@@ -1035,6 +1035,45 @@

}

+//==============================================================================

+const Type* CmpAddINode::Value(PhaseTransform *phase) const {

+}

+CheckedAddNode::CheckedAddNode(Node* c, Node* in1, Node* in2) : MultiNode(3) {

+}

+//-------------------------------make-------------------------------------------

+CheckedAddINode* CheckedAddINode::make(Compile* C, Node* cmpadd) {

+}

+//------------------------------match------------------------------------------

+// return result(s) along with their RegMask info

+Node* CheckedAddINode::match(const ProjNode* proj, const Matcher* match) {

+}

//=============================================================================

//------------------------------cc2logical-------------------------------------

// Convert a condition code type to a logical type

@@ -1065,7 +1104,7 @@

// Print special per-node info

#ifndef PRODUCT

void BoolTest::dump_on(outputStream *st) const {

- const char *msg[] = {"eq","gt","??","lt","ne","le","??","ge"};

st->print(msg[_test]);

}

#endif

diff -r 6f8f439e247d src/share/vm/opto/subnode.hpp

--- a/src/share/vm/opto/subnode.hpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/opto/subnode.hpp Thu Jun 21 08:41:21 2012 +0800

@@ -257,21 +257,69 @@

};

+//------------------------------CmpAddINode-------------------------------------

+// Check the sum of two values for overflow, returning condition codes.

+class CmpAddINode : public CmpINode {

+public:

+};

+//-----------------------------CheckedAddNode-----------------------------------

+// Addition with overflow condition

+class CheckedAddNode : public MultiNode {

+protected:

+public:

+};

+//-----------------------------CheckedAddINode----------------------------------

+// Integer addition with overflow condition

+class CheckedAddINode : public CheckedAddNode {

+public:

+};

//------------------------------BoolTest---------------------------------------

// Convert condition codes to a boolean test value (0 or -1).

// We pick the values as 3 bits; the low order 2 bits we compare against the

// condition codes, the high bit flips the sense of the result.

struct BoolTest VALUE_OBJ_CLASS_SPEC {

- enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, illegal = 8 };

mask _test;

BoolTest( mask btm ) : _test(btm) {}

const Type *cc2logical( const Type *CC ) const;

// Commute the test. I use a small table lookup. The table is created as

// a simple char array where each element is the ASCII version of a 'mask'

// enum from above.

- mask commute( ) const { return mask("038147858"[_test]-'0'); }

mask negate( ) const { return mask(_test^4); }

- bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le); }

#ifndef PRODUCT

void dump_on(outputStream *st) const;

#endif

diff -r 6f8f439e247d src/share/vm/opto/type.cpp

--- a/src/share/vm/opto/type.cpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/opto/type.cpp Thu Jun 21 08:41:21 2012 +0800

@@ -386,6 +386,11 @@

longpair[1] = TypeLong::LONG;

TypeTuple::LONG_PAIR = TypeTuple::make(2, longpair);

_const_basic_type[T_NARROWOOP] = TypeNarrowOop::BOTTOM;

_const_basic_type[T_BOOLEAN] = TypeInt::BOOL;

_const_basic_type[T_CHAR] = TypeInt::CHAR;

@@ -1618,6 +1623,7 @@

const TypeTuple *TypeTuple::START_I2C;

const TypeTuple *TypeTuple::INT_PAIR;

const TypeTuple *TypeTuple::LONG_PAIR;

+const TypeTuple *TypeTuple::INT_CC_PAIR;

//------------------------------make-------------------------------------------

diff -r 6f8f439e247d src/share/vm/opto/type.hpp

--- a/src/share/vm/opto/type.hpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/opto/type.hpp Thu Jun 21 08:41:21 2012 +0800

@@ -549,6 +549,7 @@

static const TypeTuple *START_I2C;

static const TypeTuple *INT_PAIR;

static const TypeTuple *LONG_PAIR;

#ifndef PRODUCT

virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping

#endif

diff -r 6f8f439e247d src/share/vm/runtime/vmStructs.cpp

--- a/src/share/vm/runtime/vmStructs.cpp Tue Jun 19 15:12:56 2012 -0700

+++ b/src/share/vm/runtime/vmStructs.cpp Thu Jun 21 08:41:21 2012 +0800

@@ -1922,6 +1922,9 @@

declare_c2_type(CmpF3Node, CmpFNode) \

declare_c2_type(CmpDNode, CmpNode) \

declare_c2_type(CmpD3Node, CmpDNode) \

declare_c2_type(BoolNode, Node) \

declare_c2_type(AbsNode, Node) \

declare_c2_type(AbsINode, AbsNode) \