JDK-6654460 : [1.4.2] : 2 possible problems in shift operation in compiler2 (RHEL, IA64)
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 1.4.2_16
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux_redhat_3.0,linux_redhat_4.0
  • CPU: itanium
  • Submitted: 2008-01-24
  • Updated: 2010-12-03
  • Resolved: 2008-08-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other
1.4.2_18-rev b10Fixed 1.4.2_19Fixed
Related Reports
Duplicate :  
Description
The customer reported  2 possible problems in shift operation in compiler2.

-------------
1. Shift distance is more than 32 in int type variable.

PROBLEM DESCRIPTION:

Left-shift operation for int type variable causes incorrect result.
This problem occurs when the operator executes more than 32 bits shift.
Also, interpreter executes correctly. After VM context moves
to compiled code execution, incorrect result appears.

CONFIGURATION :
OS : Red Hat Enterprise Linux Server release 5 (Itanium)
     Red Hat Enterprise Linux AS release 4 (Itanium)
JDK : 1.4.2_14 / 1.4.2_16 Server VM


ABOUT REPRODUCING PROGRAM:
The attached program executes 11 << 38. The result is 0(zero).
However, the following is extracted from  "15.19 Shift Operators" of  JLS.
 "If the promoted type of the left-hand operand is int, 
   only the five lowest-order bits of the right-hand operand 
   are used as the shift distance."
 ( 11 << 38 ) = ( 11 << 6 ) = 704 seems correct.

INVESTIGATION :

The customer investigated the compiled code. The compiled code which always causes 0(zero)
is generated.

0x200000000392e076 e0 02 00 18 40 00 :             and r46=r0,r0
0x200000000392e07c 00 00 04 00 11 00 :             nop.i 0x0;;
0x200000000392e080 11 00 b8 6e 90 11 : [MIB]       st4 [r55]=r46

They think the following (source) code at 3344 in ia64.ad causes the above-mentioned 
compiled code.

---- ./hotspot/src/cpu/ia64/vm/ia64.ad in 1.4.2_16 -------

  3338    enc_class emit_shlI_reg_imm6( gRegI dst, gRegI src, immI_1to64 cnt, pReg qp ) %{
  3339      MacroAssembler _masm(&cbuf);
  3340      if ( (int)$cnt$$constant < 32 )
  3341        __ depz( as_PredicateRegister($qp$$reg), as_Register($dst$$reg), as_Register($src$$reg),
  3342                 (int)$cnt$$constant, 32 - (int)$cnt$$constant );
  3343      else
  3344        __ and3( as_PredicateRegister($qp$$reg), as_Register($dst$$reg), GR0, GR0 );
  3345    %}

At the above line, when shift distance is more than 32, compiled code always causes 0.


REPRODUCING PROGRAM : 
------- ShlI.java ------
public class ShlI {
    public static       int value = 11;
    public static final int shift = 38;
    public static final int LOOPS = 10000;

    static void foo() {
        for (int i=0; i<LOOPS; i++) {
          if (i==LOOPS-1) {
              value = 11;
              System.out.print( value + " << " + shift + " = " );
          }
          value<<=shift;
          if (i==LOOPS-1) {
              System.out.println(value);
          }
        }
    }
    public static void main(String args[]) {
       for (int i=0; i<20; i++) {
         foo();
       }
    }
}
-------

COMMAND LINE :
% java ShlI
11 << 38 = 704
11 << 38 = 704
11 << 38 = 704
11 << 38 = 704
11 << 38 = 704
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0
11 << 38 = 0


2. Shift distance is more than 64 in long type variable.

PROBLEM DESCRIPTION :

The following shift function for long type variable is provided.
However, when the shift distance is more than 64 in long type variable,
"64 - (int)$cnt$$constant"  will be negative number.
This might generate incorrect compiled code.

---- ./hotspot/src/cpu/ia64/vm/ia64.ad in 1.4.2_16 -----
.....
  3347    enc_class emit_shlL_reg_imm6( gRegL dst, gRegL src, gRegI cnt, pReg qp ) %{
  3348      MacroAssembler _masm(&cbuf);
  3349      __ depz( as_PredicateRegister($qp$$reg), as_Register($dst$$reg), as_Register($src$$reg),
  3350               (int)$cnt$$constant, 64 - (int)$cnt$$constant );
  3351    %}
......

Comments
EVALUATION In addition, ###@###.### has pointed out why the customer's second point does not cause a failure for long values with >64 bit shift distances: " In this snippet: 3347 enc_class emit_shlL_reg_imm6( gRegL dst, gRegL src, gRegI cnt, pReg qp ) %{ 3348 MacroAssembler _masm(&cbuf); 3349 __ depz( as_PredicateRegister($qp$$reg), as_Register($dst$$reg), as_Register($src$$reg), 3350 (int)$cnt$$constant, 64 - (int)$cnt$$constant ); 3351 %} cnt is actually of type immI_1to64 which guarantees it's in range. The emit functions don't actually pay any attention to the type declared in the emit definition. That are actually more like macros which are substituted back into their uses and pick up the types at the uses. " So the fix this will address 32-bit int shifts only.
20-06-2008

EVALUATION Changes required in assembly macros in ia64.ad Customer has made suggestions.
12-03-2008

SUGGESTED FIX JLE pasted: As to the problem 1. Shift distance is more than 32 in int type variable, the customer, Fujitsu provided possible fix. On the other hand, they sent a concern whether their fix might cause side-effect or not. --------> As just trial, when we modify the source code as follows, we can get the correct result. ---- ./hotspot/src/cpu/ia64/vm/ia64.ad in 1.4.2_16 ------- ...... 3338 enc_class emit_shlI_reg_imm6( gRegI dst, gRegI src, immI_1to64 cnt, pReg qp ) %{ 3339 MacroAssembler _masm(&cbuf); 3340 int cnt = (int)$cnt$$constant & 0x1f; 3341 __ depz( as_PredicateRegister($qp$$reg), as_Register($dst$$reg), as_Register($src$$reg), 3342 cnt, 32 - cnt ); 3343 %} ...... However,if there is any other cource code portion which uses the result of emit_shlI_reg_imm6() and causes correct result for more than 32 bits shift, the above modification can not be applied. That will affect serious side-effect to the portion. <-------
24-01-2008