8213754: PPC64: Add Intrinsics for isDigit/isLowerCase/isUpperCase/isWhitespace
authormhorie
Tue, 11 Dec 2018 20:31:18 -0500
changeset 52979 7384e00d5860
parent 52978 95efb32d390b
child 52980 24525070d934
child 57072 29604aafa0fc
8213754: PPC64: Add Intrinsics for isDigit/isLowerCase/isUpperCase/isWhitespace Reviewed-by: kvn, rriggs, mdoerr, gromero
make/data/characterdata/CharacterData00.java.template
make/data/characterdata/CharacterData01.java.template
make/data/characterdata/CharacterData02.java.template
make/data/characterdata/CharacterData0E.java.template
make/data/characterdata/CharacterDataLatin1.java.template
make/data/characterdata/CharacterDataPrivateUse.java.template
make/data/characterdata/CharacterDataUndefined.java.template
src/hotspot/cpu/ppc/assembler_ppc.hpp
src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
src/hotspot/cpu/ppc/ppc.ad
src/hotspot/cpu/ppc/vm_version_ppc.cpp
src/hotspot/share/classfile/vmSymbols.cpp
src/hotspot/share/classfile/vmSymbols.hpp
src/hotspot/share/opto/c2_globals.hpp
src/hotspot/share/opto/c2compiler.cpp
src/hotspot/share/opto/classes.hpp
src/hotspot/share/opto/intrinsicnode.hpp
src/hotspot/share/opto/library_call.cpp
src/java.base/share/classes/java/lang/Character.java
src/java.base/share/classes/java/lang/CharacterData.java
test/micro/org/openjdk/bench/java/lang/Characters.java
--- a/make/data/characterdata/CharacterData00.java.template	Wed Dec 12 13:28:50 2018 +0100
+++ b/make/data/characterdata/CharacterData00.java.template	Tue Dec 11 20:31:18 2018 -0500
@@ -754,6 +754,21 @@
         return retval;
     }
 
+    boolean isDigit(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER;
+    }
+
+    boolean isLowerCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.LOWERCASE_LETTER;
+    }
+
+    boolean isUpperCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.UPPERCASE_LETTER;
+    }
+
     boolean isWhitespace(int ch) {
         int props = getProperties(ch);
         return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);
--- a/make/data/characterdata/CharacterData01.java.template	Wed Dec 12 13:28:50 2018 +0100
+++ b/make/data/characterdata/CharacterData01.java.template	Tue Dec 11 20:31:18 2018 -0500
@@ -460,6 +460,21 @@
         return retval;
     }
 
+    boolean isDigit(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER;
+    }
+
+    boolean isLowerCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.LOWERCASE_LETTER;
+    }
+
+    boolean isUpperCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.UPPERCASE_LETTER;
+    }
+
     boolean isWhitespace(int ch) {
         int props = getProperties(ch);
         return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);
--- a/make/data/characterdata/CharacterData02.java.template	Wed Dec 12 13:28:50 2018 +0100
+++ b/make/data/characterdata/CharacterData02.java.template	Tue Dec 11 20:31:18 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -217,6 +217,21 @@
         return retval;
     }
 
+    boolean isDigit(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER;
+    }
+
+    boolean isLowerCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.LOWERCASE_LETTER;
+    }
+
+    boolean isUpperCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.UPPERCASE_LETTER;
+    }
+
     boolean isWhitespace(int ch) {
         return (getProperties(ch) & $$maskIdentifierInfo) == $$valueJavaWhitespace;
     }
--- a/make/data/characterdata/CharacterData0E.java.template	Wed Dec 12 13:28:50 2018 +0100
+++ b/make/data/characterdata/CharacterData0E.java.template	Tue Dec 11 20:31:18 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -217,6 +217,21 @@
         return retval;
     }
 
+    boolean isDigit(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.DECIMAL_DIGIT_NUMBER;
+    }
+
+    boolean isLowerCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.LOWERCASE_LETTER;
+    }
+
+    boolean isUpperCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.UPPERCASE_LETTER;
+    }
+
     boolean isWhitespace(int ch) {
         int props = getProperties(ch);
         return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);
--- a/make/data/characterdata/CharacterDataLatin1.java.template	Wed Dec 12 13:28:50 2018 +0100
+++ b/make/data/characterdata/CharacterDataLatin1.java.template	Tue Dec 11 20:31:18 2018 -0500
@@ -25,6 +25,8 @@
 
 package java.lang;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+
 /** The CharacterData class encapsulates the large tables found in
     Java.lang.Character. */
 
@@ -78,6 +80,23 @@
         return props;
     }
 
+    @HotSpotIntrinsicCandidate
+    boolean isDigit(int ch) {
+        return '0' <= ch && ch <= '9';
+    }
+
+    @HotSpotIntrinsicCandidate
+    boolean isLowerCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.LOWERCASE_LETTER;
+    }
+
+    @HotSpotIntrinsicCandidate
+    boolean isUpperCase(int ch) {
+        int props = getProperties(ch);
+        return (props & $$maskType) == Character.UPPERCASE_LETTER;
+    }
+
     boolean isOtherLowercase(int ch) {
         int props = getPropertiesEx(ch);
         return (props & $$maskOtherLowercase) != 0;
@@ -214,6 +233,7 @@
         return retval;
     }
 
+    @HotSpotIntrinsicCandidate
     boolean isWhitespace(int ch) {
         int props = getProperties(ch);
         return ((props & $$maskIdentifierInfo) == $$valueJavaWhitespace);
--- a/make/data/characterdata/CharacterDataPrivateUse.java.template	Wed Dec 12 13:28:50 2018 +0100
+++ b/make/data/characterdata/CharacterDataPrivateUse.java.template	Tue Dec 11 20:31:18 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -41,47 +41,59 @@
     }
 
     boolean isJavaIdentifierStart(int ch) {
-		return false;
+	return false;
     }
 
     boolean isJavaIdentifierPart(int ch) {
-		return false;
+	return false;
     }
 
     boolean isUnicodeIdentifierStart(int ch) {
-		return false;
+        return false;
     }
 
     boolean isUnicodeIdentifierPart(int ch) {
-		return false;
+        return false;
     }
 
     boolean isIdentifierIgnorable(int ch) {
-		return false;
+        return false;
     }
 
     int toLowerCase(int ch) {
-		return ch;
+        return ch;
     }
 
     int toUpperCase(int ch) {
-		return ch;
+        return ch;
     }
 
     int toTitleCase(int ch) {
-		return ch;
+        return ch;
     }
 
     int digit(int ch, int radix) {
-		return -1;
+        return -1;
     }
 
     int getNumericValue(int ch) {
-		return -1;
+        return -1;
+    }
+
+    boolean isDigit(int ch) {
+        return false;
+    }
+
+    boolean isLowerCase(int ch) {
+	return false;
+    }
+
+    boolean isUpperCase(int ch) {
+	return false;
     }
 
     boolean isWhitespace(int ch) {
-		return false;
+	return false;
     }
 
     byte getDirectionality(int ch) {
@@ -91,7 +103,7 @@
     }
 
     boolean isMirrored(int ch) {
-		return false;
+        return false;
     }
 
     static final CharacterData instance = new CharacterDataPrivateUse();
--- a/make/data/characterdata/CharacterDataUndefined.java.template	Wed Dec 12 13:28:50 2018 +0100
+++ b/make/data/characterdata/CharacterDataUndefined.java.template	Tue Dec 11 20:31:18 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -35,59 +35,71 @@
     }
 
     int getType(int ch) {
-	return Character.UNASSIGNED;
+        return Character.UNASSIGNED;
     }
 
     boolean isJavaIdentifierStart(int ch) {
-		return false;
+        return false;
     }
 
     boolean isJavaIdentifierPart(int ch) {
-		return false;
+        return false;
     }
 
     boolean isUnicodeIdentifierStart(int ch) {
-		return false;
+        return false;
     }
 
     boolean isUnicodeIdentifierPart(int ch) {
-		return false;
+        return false;
     }
 
     boolean isIdentifierIgnorable(int ch) {
-		return false;
+        return false;
     }
 
     int toLowerCase(int ch) {
-		return ch;
+        return ch;
     }
 
     int toUpperCase(int ch) {
-		return ch;
+        return ch;
     }
 
     int toTitleCase(int ch) {
-		return ch;
+        return ch;
     }
 
     int digit(int ch, int radix) {
-		return -1;
+        return -1;
     }
 
     int getNumericValue(int ch) {
-		return -1;
+        return -1;
+    }
+
+    boolean isDigit(int ch) {
+        return false;
+    }
+
+    boolean isLowerCase(int ch) {
+        return false;
+    }
+
+    boolean isUpperCase(int ch) {
+        return false;
     }
 
     boolean isWhitespace(int ch) {
-		return false;
+        return false;
     }
 
     byte getDirectionality(int ch) {
-		return Character.DIRECTIONALITY_UNDEFINED;
+        return Character.DIRECTIONALITY_UNDEFINED;
     }
 
     boolean isMirrored(int ch) {
-		return false;
+        return false;
     }
 
     static final CharacterData instance = new CharacterDataUndefined();
--- a/src/hotspot/cpu/ppc/assembler_ppc.hpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp	Tue Dec 11 20:31:18 2018 -0500
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2017 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 2018 SAP SE. 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
@@ -299,6 +299,8 @@
     CMPI_OPCODE   = (11u << OPCODE_SHIFT),
     CMPL_OPCODE   = (31u << OPCODE_SHIFT |  32u << 1),
     CMPLI_OPCODE  = (10u << OPCODE_SHIFT),
+    CMPRB_OPCODE  = (31u << OPCODE_SHIFT | 192u << 1),
+    CMPEQB_OPCODE = (31u << OPCODE_SHIFT | 224u << 1),
 
     ISEL_OPCODE   = (31u << OPCODE_SHIFT |  15u << 1),
 
@@ -336,6 +338,7 @@
     MTCRF_OPCODE  = (31u << OPCODE_SHIFT | 144u << 1),
     MFCR_OPCODE   = (31u << OPCODE_SHIFT | 19u << 1),
     MCRF_OPCODE   = (19u << OPCODE_SHIFT | 0u << 1),
+    SETB_OPCODE   = (31u << OPCODE_SHIFT | 128u << 1),
 
     // condition register logic instructions
     CRAND_OPCODE  = (19u << OPCODE_SHIFT | 257u << 1),
@@ -1076,7 +1079,7 @@
   static int frs(      int         x)  { return  opp_u_field(x,             10,  6); }
   static int frt(      int         x)  { return  opp_u_field(x,             10,  6); }
   static int fxm(      int         x)  { return  opp_u_field(x,             19, 12); }
-  static int l10(      int         x)  { return  opp_u_field(x,             10, 10); }
+  static int l10(      int         x)  { assert(x == 0 || x == 1,  "must be 0 or 1"); return opp_u_field(x, 10, 10); }
   static int l14(      int         x)  { return  opp_u_field(x,             15, 14); }
   static int l15(      int         x)  { return  opp_u_field(x,             15, 15); }
   static int l910(     int         x)  { return  opp_u_field(x,             10,  9); }
@@ -1443,6 +1446,10 @@
   inline void cmplw( ConditionRegister crx, Register a, Register b);
   inline void cmpld( ConditionRegister crx, Register a, Register b);
 
+  // >= Power9
+  inline void cmprb( ConditionRegister bf, int l, Register a, Register b);
+  inline void cmpeqb(ConditionRegister bf, Register a, Register b);
+
   inline void isel(   Register d, Register a, Register b, int bc);
   // Convenient version which takes: Condition register, Condition code and invert flag. Omit b to keep old value.
   inline void isel(   Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b = noreg);
@@ -1642,6 +1649,8 @@
   inline void mfcr( Register d);
   inline void mcrf( ConditionRegister crd, ConditionRegister cra);
   inline void mtcr( Register s);
+  // >= Power9
+  inline void setb( Register d, ConditionRegister cra);
 
   // Special purpose registers
   // Exception Register
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp	Tue Dec 11 20:31:18 2018 -0500
@@ -171,6 +171,8 @@
 inline void Assembler::cmp(   ConditionRegister f, int l, Register a, Register b) { emit_int32( CMP_OPCODE   | bf(f) | l10(l) | ra(a) | rb(b)); }
 inline void Assembler::cmpli( ConditionRegister f, int l, Register a, int ui16)   { emit_int32( CMPLI_OPCODE | bf(f) | l10(l) | ra(a) | uimm(ui16,16)); }
 inline void Assembler::cmpl(  ConditionRegister f, int l, Register a, Register b) { emit_int32( CMPL_OPCODE  | bf(f) | l10(l) | ra(a) | rb(b)); }
+inline void Assembler::cmprb( ConditionRegister f, int l, Register a, Register b) { emit_int32( CMPRB_OPCODE | bf(f) | l10(l) | ra(a) | rb(b)); }
+inline void Assembler::cmpeqb(ConditionRegister f, Register a, Register b)        { emit_int32( CMPEQB_OPCODE| bf(f) | ra(a)  | rb(b)); }
 
 // extended mnemonics of Compare Instructions
 inline void Assembler::cmpwi( ConditionRegister crx, Register a, int si16)   { Assembler::cmpi( crx, 0, a, si16); }
@@ -371,6 +373,8 @@
 inline void Assembler::mcrf( ConditionRegister crd, ConditionRegister cra)
                                                       { emit_int32(MCRF_OPCODE | bf(crd) | bfa(cra)); }
 inline void Assembler::mtcr( Register s)          { Assembler::mtcrf(0xff, s); }
+inline void Assembler::setb(Register d, ConditionRegister cra)
+                                                  { emit_int32(SETB_OPCODE | rt(d) | bfa(cra)); }
 
 // Special purpose registers
 // Exception Register
--- a/src/hotspot/cpu/ppc/ppc.ad	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/cpu/ppc/ppc.ad	Tue Dec 11 20:31:18 2018 -0500
@@ -2257,6 +2257,11 @@
     return SuperwordUseVSX;
   case Op_PopCountVI:
     return (SuperwordUseVSX && UsePopCountInstruction);
+  case Op_Digit:
+  case Op_LowerCase:
+  case Op_UpperCase:
+  case Op_Whitespace:
+    return UseCharacterCompareIntrinsics;
   }
 
   return true;  // Per default match rules are supported.
@@ -12400,6 +12405,132 @@
   %}
 %}
 
+// Compare char
+instruct cmprb_Digit_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{
+  match(Set dst (Digit src1));
+  effect(TEMP src2, TEMP crx);
+  ins_cost(3 * DEFAULT_COST);
+
+  format %{ "LI      $src2, 0x3930\n\t"
+            "CMPRB   $crx, 0, $src1, $src2\n\t"
+            "SETB    $dst, $crx" %}
+  size(12);
+  ins_encode %{
+    // 0x30: 0, 0x39: 9
+    __ li($src2$$Register, 0x3930);
+    // compare src1 with ranges 0x30 to 0x39
+    __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register);
+    __ setb($dst$$Register, $crx$$CondRegister);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmprb_LowerCase_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{
+  match(Set dst (LowerCase src1));
+  effect(TEMP src2, TEMP crx);
+  ins_cost(12 * DEFAULT_COST);
+
+  format %{ "LI      $src2, 0x7A61\n\t"
+            "CMPRB   $crx, 0, $src1, $src2\n\t"
+            "BGT     $crx, done\n\t"
+            "LIS     $src2, (signed short)0xF6DF\n\t"
+            "ORI     $src2, $src2, 0xFFF8\n\t"
+            "CMPRB   $crx, 1, $src1, $src2\n\t"
+            "BGT     $crx, done\n\t"
+            "LIS     $src2, (signed short)0xAAB5\n\t"
+            "ORI     $src2, $src2, 0xBABA\n\t"
+            "INSRDI  $src2, $src2, 32, 0\n\t"
+            "CMPEQB  $crx, 1, $src1, $src2\n"
+            "done:\n\t"
+            "SETB    $dst, $crx" %}
+
+  size(48);
+  ins_encode %{
+    Label done;
+    // 0x61: a, 0x7A: z
+    __ li($src2$$Register, 0x7A61);
+    // compare src1 with ranges 0x61 to 0x7A
+    __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register);
+    __ bgt($crx$$CondRegister, done);
+
+    // 0xDF: sharp s, 0xFF: y with diaeresis, 0xF7 is not the lower case
+    __ lis($src2$$Register, (signed short)0xF6DF);
+    __ ori($src2$$Register, $src2$$Register, 0xFFF8);
+    // compare src1 with ranges 0xDF to 0xF6 and 0xF8 to 0xFF
+    __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register);
+    __ bgt($crx$$CondRegister, done);
+
+    // 0xAA: feminine ordinal indicator
+    // 0xB5: micro sign
+    // 0xBA: masculine ordinal indicator
+    __ lis($src2$$Register, (signed short)0xAAB5);
+    __ ori($src2$$Register, $src2$$Register, 0xBABA);
+    __ insrdi($src2$$Register, $src2$$Register, 32, 0);
+    // compare src1 with 0xAA, 0xB5, and 0xBA
+    __ cmpeqb($crx$$CondRegister, $src1$$Register, $src2$$Register);
+
+    __ bind(done);
+    __ setb($dst$$Register, $crx$$CondRegister);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmprb_UpperCase_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{
+  match(Set dst (UpperCase src1));
+  effect(TEMP src2, TEMP crx);
+  ins_cost(7 * DEFAULT_COST);
+
+  format %{ "LI      $src2, 0x5A41\n\t"
+            "CMPRB   $crx, 0, $src1, $src2\n\t"
+            "BGT     $crx, done\n\t"
+            "LIS     $src2, (signed short)0xD6C0\n\t"
+            "ORI     $src2, $src2, 0xDED8\n\t"
+            "CMPRB   $crx, 1, $src1, $src2\n"
+            "done:\n\t"
+            "SETB    $dst, $crx" %}
+
+  size(28);
+  ins_encode %{
+    Label done;
+    // 0x41: A, 0x5A: Z
+    __ li($src2$$Register, 0x5A41);
+    // compare src1 with a range 0x41 to 0x5A
+    __ cmprb($crx$$CondRegister, 0, $src1$$Register, $src2$$Register);
+    __ bgt($crx$$CondRegister, done);
+
+    // 0xC0: a with grave, 0xDE: thorn, 0xD7 is not the upper case
+    __ lis($src2$$Register, (signed short)0xD6C0);
+    __ ori($src2$$Register, $src2$$Register, 0xDED8);
+    // compare src1 with ranges 0xC0 to 0xD6 and 0xD8 to 0xDE
+    __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register);
+
+    __ bind(done);
+    __ setb($dst$$Register, $crx$$CondRegister);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct cmprb_Whitespace_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsReg crx) %{
+  match(Set dst (Whitespace src1));
+  effect(TEMP src2, TEMP crx);
+  ins_cost(4 * DEFAULT_COST);
+
+  format %{ "LI      $src2, 0x0D09\n\t"
+            "ADDIS   $src2, 0x201C\n\t"
+            "CMPRB   $crx, 1, $src1, $src2\n\t"
+            "SETB    $dst, $crx" %}
+  size(16);
+  ins_encode %{
+    // 0x09 to 0x0D, 0x1C to 0x20
+    __ li($src2$$Register, 0x0D09);
+    __ addis($src2$$Register, $src2$$Register, 0x0201C);
+    // compare src with ranges 0x09 to 0x0D and 0x1C to 0x20
+    __ cmprb($crx$$CondRegister, 1, $src1$$Register, $src2$$Register);
+    __ setb($dst$$Register, $crx$$CondRegister);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 //----------Branches---------------------------------------------------------
 // Jump
 
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp	Tue Dec 11 20:31:18 2018 -0500
@@ -134,11 +134,18 @@
     if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstructionsPPC64)) {
       FLAG_SET_ERGO(bool, UseCountTrailingZerosInstructionsPPC64, true);
     }
+    if (FLAG_IS_DEFAULT(UseCharacterCompareIntrinsics)) {
+      FLAG_SET_ERGO(bool, UseCharacterCompareIntrinsics, true);
+    }
   } else {
     if (UseCountTrailingZerosInstructionsPPC64) {
       warning("UseCountTrailingZerosInstructionsPPC64 specified, but needs at least Power9.");
       FLAG_SET_DEFAULT(UseCountTrailingZerosInstructionsPPC64, false);
     }
+    if (UseCharacterCompareIntrinsics) {
+      warning("UseCharacterCompareIntrinsics specified, but needs at least Power9.");
+      FLAG_SET_DEFAULT(UseCharacterCompareIntrinsics, false);
+    }
   }
 #endif
 
--- a/src/hotspot/share/classfile/vmSymbols.cpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/share/classfile/vmSymbols.cpp	Tue Dec 11 20:31:18 2018 -0500
@@ -379,6 +379,10 @@
   case vmIntrinsics::_vectorizedMismatch:
   case vmIntrinsics::_fmaD:
   case vmIntrinsics::_fmaF:
+  case vmIntrinsics::_isDigit:
+  case vmIntrinsics::_isLowerCase:
+  case vmIntrinsics::_isUpperCase:
+  case vmIntrinsics::_isWhitespace:
     return true;
   default:
     return false;
@@ -828,6 +832,12 @@
   case vmIntrinsics::_subtractExactL:
     if (!UseMathExactIntrinsics || !InlineMathNatives) return true;
     break;
+  case vmIntrinsics::_isDigit:
+  case vmIntrinsics::_isLowerCase:
+  case vmIntrinsics::_isUpperCase:
+  case vmIntrinsics::_isWhitespace:
+    if (!UseCharacterCompareIntrinsics) return true;
+    break;
 #endif // COMPILER2
   default:
     return false;
--- a/src/hotspot/share/classfile/vmSymbols.hpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/share/classfile/vmSymbols.hpp	Tue Dec 11 20:31:18 2018 -0500
@@ -71,6 +71,7 @@
   template(java_lang_Boolean,                         "java/lang/Boolean")                        \
   template(java_lang_Character,                       "java/lang/Character")                      \
   template(java_lang_Character_CharacterCache,        "java/lang/Character$CharacterCache")       \
+  template(java_lang_CharacterDataLatin1,             "java/lang/CharacterDataLatin1")            \
   template(java_lang_Float,                           "java/lang/Float")                          \
   template(java_lang_Double,                          "java/lang/Double")                         \
   template(java_lang_Byte,                            "java/lang/Byte")                           \
@@ -933,6 +934,15 @@
   do_intrinsic(_equalsL,                  java_lang_StringLatin1,equals_name, equalsB_signature,                 F_S)   \
   do_intrinsic(_equalsU,                  java_lang_StringUTF16, equals_name, equalsB_signature,                 F_S)   \
                                                                                                                         \
+  do_intrinsic(_isDigit,                  java_lang_CharacterDataLatin1, isDigit_name,      int_bool_signature,  F_R)   \
+   do_name(     isDigit_name,                                           "isDigit")                                      \
+  do_intrinsic(_isLowerCase,              java_lang_CharacterDataLatin1, isLowerCase_name,  int_bool_signature,  F_R)   \
+   do_name(     isLowerCase_name,                                       "isLowerCase")                                  \
+  do_intrinsic(_isUpperCase,              java_lang_CharacterDataLatin1, isUpperCase_name,  int_bool_signature,  F_R)   \
+   do_name(     isUpperCase_name,                                       "isUpperCase")                                  \
+  do_intrinsic(_isWhitespace,             java_lang_CharacterDataLatin1, isWhitespace_name, int_bool_signature,  F_R)   \
+   do_name(     isWhitespace_name,                                      "isWhitespace")                                 \
+                                                                                                                        \
   do_intrinsic(_Preconditions_checkIndex, jdk_internal_util_Preconditions, checkIndex_name, Preconditions_checkIndex_signature, F_S)   \
    do_signature(Preconditions_checkIndex_signature,              "(IILjava/util/function/BiFunction;)I")                \
                                                                                                                         \
--- a/src/hotspot/share/opto/c2_globals.hpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/share/opto/c2_globals.hpp	Tue Dec 11 20:31:18 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -710,6 +710,9 @@
   diagnostic(bool, UseMathExactIntrinsics, true,                            \
           "Enables intrinsification of various java.lang.Math functions")   \
                                                                             \
+  diagnostic(bool, UseCharacterCompareIntrinsics, false,                    \
+          "Enables intrinsification of java.lang.Character functions")      \
+                                                                            \
   diagnostic(bool, UseMultiplyToLenIntrinsic, false,                        \
           "Enables intrinsification of BigInteger.multiplyToLen()")         \
                                                                             \
--- a/src/hotspot/share/opto/c2compiler.cpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/share/opto/c2compiler.cpp	Tue Dec 11 20:31:18 2018 -0500
@@ -428,6 +428,18 @@
   case vmIntrinsics::_fmaF:
     if (!UseFMA || !Matcher::match_rule_supported(Op_FmaF)) return false;
     break;
+  case vmIntrinsics::_isDigit:
+    if (!Matcher::match_rule_supported(Op_Digit)) return false;
+    break;
+  case vmIntrinsics::_isLowerCase:
+    if (!Matcher::match_rule_supported(Op_LowerCase)) return false;
+    break;
+  case vmIntrinsics::_isUpperCase:
+    if (!Matcher::match_rule_supported(Op_UpperCase)) return false;
+    break;
+  case vmIntrinsics::_isWhitespace:
+    if (!Matcher::match_rule_supported(Op_Whitespace)) return false;
+    break;
   case vmIntrinsics::_hashCode:
   case vmIntrinsics::_identityHashCode:
   case vmIntrinsics::_getClass:
--- a/src/hotspot/share/opto/classes.hpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/share/opto/classes.hpp	Tue Dec 11 20:31:18 2018 -0500
@@ -394,3 +394,7 @@
 macro(ExtractL)
 macro(ExtractF)
 macro(ExtractD)
+macro(Digit)
+macro(LowerCase)
+macro(UpperCase)
+macro(Whitespace)
--- a/src/hotspot/share/opto/intrinsicnode.hpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/share/opto/intrinsicnode.hpp	Tue Dec 11 20:31:18 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -180,4 +180,40 @@
   virtual const Type* Value(PhaseGVN* phase) const;
 };
 
+//-------------------------------DigitNode----------------------------------------
+class DigitNode : public Node {
+public:
+  DigitNode(Node* control, Node *in1) : Node(control, in1) {}
+  virtual int Opcode() const;
+  const Type* bottom_type() const { return TypeInt::BOOL; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+};
+
+//------------------------------LowerCaseNode------------------------------------
+class LowerCaseNode : public Node {
+public:
+  LowerCaseNode(Node* control, Node *in1) : Node(control, in1) {}
+  virtual int Opcode() const;
+  const Type* bottom_type() const { return TypeInt::BOOL; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+};
+
+//------------------------------UpperCaseNode------------------------------------
+class UpperCaseNode : public Node {
+public:
+  UpperCaseNode(Node* control, Node *in1) : Node(control, in1) {}
+  virtual int Opcode() const;
+  const Type* bottom_type() const { return TypeInt::BOOL; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+};
+
+//------------------------------WhitespaceCode-----------------------------------
+class WhitespaceNode : public Node {
+public:
+  WhitespaceNode(Node* control, Node *in1) : Node(control, in1) {}
+  virtual int Opcode() const;
+  const Type* bottom_type() const { return TypeInt::BOOL; }
+  virtual uint ideal_reg() const { return Op_RegI; }
+};
+
 #endif // SHARE_VM_OPTO_INTRINSICNODE_HPP
--- a/src/hotspot/share/opto/library_call.cpp	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/hotspot/share/opto/library_call.cpp	Tue Dec 11 20:31:18 2018 -0500
@@ -324,6 +324,7 @@
   bool inline_montgomerySquare();
   bool inline_vectorizedMismatch();
   bool inline_fma(vmIntrinsics::ID id);
+  bool inline_character_compare(vmIntrinsics::ID id);
 
   bool inline_profileBoolean();
   bool inline_isCompileConstant();
@@ -867,6 +868,12 @@
   case vmIntrinsics::_fmaF:
     return inline_fma(intrinsic_id());
 
+  case vmIntrinsics::_isDigit:
+  case vmIntrinsics::_isLowerCase:
+  case vmIntrinsics::_isUpperCase:
+  case vmIntrinsics::_isWhitespace:
+    return inline_character_compare(intrinsic_id());
+
   default:
     // If you get here, it may be that someone has added a new intrinsic
     // to the list in vmSymbols.hpp without implementing it here.
@@ -6555,6 +6562,32 @@
   return true;
 }
 
+bool LibraryCallKit::inline_character_compare(vmIntrinsics::ID id) {
+  // argument(0) is receiver
+  Node* codePoint = argument(1);
+  Node* n = NULL;
+
+  switch (id) {
+    case vmIntrinsics::_isDigit :
+      n = new DigitNode(control(), codePoint);
+      break;
+    case vmIntrinsics::_isLowerCase :
+      n = new LowerCaseNode(control(), codePoint);
+      break;
+    case vmIntrinsics::_isUpperCase :
+      n = new UpperCaseNode(control(), codePoint);
+      break;
+    case vmIntrinsics::_isWhitespace :
+      n = new WhitespaceNode(control(), codePoint);
+      break;
+    default:
+      fatal_unexpected_iid(id);
+  }
+
+  set_result(_gvn.transform(n));
+  return true;
+}
+
 bool LibraryCallKit::inline_profileBoolean() {
   Node* counts = argument(1);
   const TypeAryPtr* ary = NULL;
--- a/src/java.base/share/classes/java/lang/Character.java	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/java.base/share/classes/java/lang/Character.java	Tue Dec 11 20:31:18 2018 -0500
@@ -9085,7 +9085,7 @@
      * @since   1.5
      */
     public static boolean isLowerCase(int codePoint) {
-        return getType(codePoint) == Character.LOWERCASE_LETTER ||
+        return CharacterData.of(codePoint).isLowerCase(codePoint) ||
                CharacterData.of(codePoint).isOtherLowercase(codePoint);
     }
 
@@ -9151,7 +9151,7 @@
      * @since   1.5
      */
     public static boolean isUpperCase(int codePoint) {
-        return getType(codePoint) == Character.UPPERCASE_LETTER ||
+        return CharacterData.of(codePoint).isUpperCase(codePoint) ||
                CharacterData.of(codePoint).isOtherUppercase(codePoint);
     }
 
@@ -9302,7 +9302,7 @@
      * @since   1.5
      */
     public static boolean isDigit(int codePoint) {
-        return getType(codePoint) == Character.DECIMAL_DIGIT_NUMBER;
+        return CharacterData.of(codePoint).isDigit(codePoint);
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/CharacterData.java	Wed Dec 12 13:28:50 2018 +0100
+++ b/src/java.base/share/classes/java/lang/CharacterData.java	Tue Dec 11 20:31:18 2018 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, 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
@@ -28,6 +28,9 @@
 abstract class CharacterData {
     abstract int getProperties(int ch);
     abstract int getType(int ch);
+    abstract boolean isDigit(int ch);
+    abstract boolean isLowerCase(int ch);
+    abstract boolean isUpperCase(int ch);
     abstract boolean isWhitespace(int ch);
     abstract boolean isMirrored(int ch);
     abstract boolean isJavaIdentifierStart(int ch);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/micro/org/openjdk/bench/java/lang/Characters.java	Tue Dec 11 20:31:18 2018 -0500
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 org.openjdk.bench.java.lang;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@State(Scope.Thread)
+public class Characters {
+
+    @Param({"9", "48", "65", "97", "128", "170", "192", "223"})
+    private int codePoint;
+
+    @Benchmark
+    public boolean isDigit() {
+        return Character.isDigit(codePoint);
+    }
+
+    @Benchmark
+    public boolean isLowerCase() {
+        return Character.isLowerCase(codePoint);
+    }
+
+    @Benchmark
+    public boolean isUpperCase() {
+        return Character.isUpperCase(codePoint);
+    }
+
+    @Benchmark
+    public boolean isWhitespace() {
+        return Character.isWhitespace(codePoint);
+    }
+}