eclipse-openj9/openj9

Incorrect output for test involving switch with fall-through case

hzongaro opened this issue · 3 comments

The following test produces incorrect output with OpenJ9:

class Test {
  final int N = 256;
  long instanceCount;
  float fFld;
  int iFld;
  short sFld;
  long vMeth_check_sum;

  void vMeth(int i2) {
    int i17 = -244, i19 = 23560, iArr[] = new int[N], iArr2[][] = new int[N][N];
    init(iArr2, 11);
    for (int i3 : iArr) {
      int i16;
      i3 = (int) instanceCount++;
      i2 *= instanceCount;
      switch ((i2 >>> 1) % 6 + 6) {
        case 6:
          for (i17 = 2; i17 > 1; i17 -= 3) i16 = (int) instanceCount;
        case 7:
          iArr2[(i17 >>> 1) % N][i19 % N] *= fFld;
        case 8:
          break;
        case 10:
          vMeth_check_sum += checkSum(iArr2);
      }
    }
  }

  void vSmallMeth(int i, short s, int i1) {
    vMeth(i);
  }

  void mainTest(String[] strArr1) {
    for (int smallinvoc = 0; smallinvoc < 238; smallinvoc++) vSmallMeth(25982, sFld, iFld);
    System.out.println(vMeth_check_sum);
  }

  public static void main(String[] strArr) {
    boolean ax$16;
    Test _instance = new Test();
    _instance.mainTest(strArr);
  }

  public static void init(int[][] a, int seed) {
    for (int j = 0; j < a.length; j++) {
      init(a[j], seed);
    }
  }

  public static void init(int[] a, int seed) {
    for (int j = 0; j < a.length; j++) {
      a[j] = (j % 2 == 0) ? seed + j : seed - j;
    }
  }

  public static long checkSum(int[] a) {
    long sum = 0;
    for (int j = 0; j < a.length; j++) {
      sum += (a[j] / (j + 1) + a[j] % (j + 1));
    }
    return sum;
  }

  public static long checkSum(int[][] a) {
    long sum = 0;
    for (int j = 0; j < a.length; j++) {
      sum += checkSum(a[j]);
    }
    return sum;
  }
}

FYI. The result of HotSpot JDK8/11/17 and the Android Runtime is -7725525924.

Originally posted by @connglli in #15306 (comment)

The problem appears to be that Global VP folds the first array index for iArr2 in case 7 to be 255 - it's ignoring the reaching definition for i17 from i17 = -244:

    int i17 = -244
    ...
      switch ((i2 >>> 1) % 6 + 6) {
        case 6:
          for (i17 = 2; i17 > 1; i17 -= 3) i16 = (int) instanceCount;
        case 7:
          iArr2[(i17 >>> 1) % N][i19 % N] *= fFld;

Before Global VP:

15n      BBStart <block_2> (freq 153)                                                        [0x7f46017585c0] bci=[-1,0,10] rc=0 vc=419 vn=74 li=- udi=- nc=0
n18n      istore  <auto slot 2>[#419  Auto] [flags 0x3 0x0 ]                                  [0x7f46017586b0] bci=[-1,3,10] rc=0 vc=419 vn=10 li=3 udi=1 nc=1
n17n        iconst -244 (X!=0 X<=0 )                                                          [0x7f4601758660] bci=[-1,0,10] rc=1 vc=419 vn=10 li=- udi=- nc=0 flg=0x204
...
n78n      treetop                                                                             [0x7f46017d3820] bci=[-1,81,15] rc=0 vc=47 vn=104 li=- udi=- nc=1
n77n        irem                                                                              [0x7f46017d37d0] bci=[-1,81,15] rc=2 vc=47 vn=38 li=- udi=- nc=2
n75n          iushr                                                                           [0x7f46017d3730] bci=[-1,78,15] rc=1 vc=47 vn=37 li=- udi=- nc=2
n73n            iload  <parm 1 I>[#418  Parm] [flags 0x40000103 0x0 ]                         [0x7f46017d3690] bci=[-1,76,15] rc=1 vc=47 vn=34 li=11 udi=21 nc=0
n74n            iconst 1                                                                      [0x7f46017d36e0] bci=[-1,77,15] rc=1 vc=47 vn=3 li=- udi=- nc=0
n76n          iconst 6                                                                        [0x7f46017d3780] bci=[-1,79,15] rc=1 vc=47 vn=36 li=- udi=- nc=0
n84n      table ()                                                                            [0x7f46017d3a00] bci=[-1,85,15] rc=0 vc=47 vn=111 li=- udi=- nc=7 flg=0x20
n82n        iadd                                                                              [0x7f46017d3960] bci=[-1,85,15] rc=1 vc=47 vn=39 li=- udi=- nc=2
n77n          ==>irem
n81n          iconst 0                                                                        [0x7f46017d3910] bci=[-1,85,15] rc=1 vc=47 vn=16 li=- udi=- nc=0
n83n        default  --> block_9 BBStart at n3n                                               [0x7f46017d39b0] bci=[-1,85,15] rc=1 vc=47 vn=105 li=- udi=- nc=0
n85n        0 --> block_5 BBStart at n5n                                                      [0x7f46017d3a50] bci=[-1,85,15] rc=1 vc=47 vn=106 li=- udi=- nc=0
n86n        1 --> block_6 BBStart at n7n                                                      [0x7f46017d3aa0] bci=[-1,85,15] rc=1 vc=47 vn=107 li=- udi=- nc=0
n87n        2 --> block_9 BBStart at n3n                                                      [0x7f46017d3af0] bci=[-1,85,15] rc=1 vc=47 vn=108 li=- udi=- nc=0
n88n        3 --> block_9 BBStart at n3n                                                      [0x7f46017d3b40] bci=[-1,85,15] rc=1 vc=47 vn=109 li=- udi=- nc=0
n89n        4 --> block_8 BBStart at n11n                                                     [0x7f46017d3b90] bci=[-1,85,15] rc=1 vc=47 vn=110 li=- udi=- nc=0
n48n      BBEnd </block_4> =====                                                              [0x7f4601759010] bci=[-1,85,15] rc=0 vc=47 vn=112 li=- udi=- nc=0


n5n       BBStart <block_5> (freq 9077) (in loop 3)                                           [0x7f46017582a0] bci=[-1,120,17] rc=0 vc=47 vn=113 li=- udi=- nc=0
n98n      istore  <auto slot 2>[#419  Auto] [flags 0x3 0x0 ]                                  [0x7f46017d3e60] bci=[-1,121,17] rc=0 vc=47 vn=17 li=6 udi=10 nc=1
n97n        iconst -1                                                                         [0x7f46017d3e10] bci=[-1,120,17] rc=1 vc=47 vn=17 li=- udi=- nc=0
n6n       BBEnd </block_5> =====                                                              [0x7f46017582f0] bci=[-1,121,17] rc=0 vc=47 vn=114 li=- udi=- nc=0

n7n       BBStart <block_6> (freq 9107) (in loop 3)                                           [0x7f4601758340] bci=[-1,147,21] rc=0 vc=47 vn=115 li=- udi=- nc=0
n105n     treetop                                                                             [0x7f46017d4090] bci=[-1,130,19] rc=0 vc=47 vn=116 li=- udi=- nc=1
n104n       isub                                                                              [0x7f46017d4040] bci=[-1,130,19] rc=3 vc=47 vn=49 li=- udi=- nc=2
n102n         iushr                                                                           [0x7f46017d3fa0] bci=[-1,126,19] rc=3 vc=47 vn=42 li=- udi=- nc=2
n100n           iload  <auto slot 2>[#419  Auto] [flags 0x3 0x0 ]                             [0x7f46017d3f00] bci=[-1,124,19] rc=1 vc=47 vn=41 li=12 udi=22 nc=0
n101n           iconst 1                                                                      [0x7f46017d3f50] bci=[-1,125,19] rc=1 vc=47 vn=3 li=- udi=- nc=0
n267n         iand                                                                            [0x7f46017d7330] bci=[-1,130,19] rc=1 vc=47 vn=48 li=- udi=- nc=2
n266n           iadd                                                                          [0x7f46017d72e0] bci=[-1,130,19] rc=1 vc=47 vn=47 li=- udi=- nc=2
n264n             iushr                                                                       [0x7f46017d7240] bci=[-1,130,19] rc=1 vc=47 vn=46 li=- udi=- nc=2
n262n               ishr                                                                      [0x7f46017d71a0] bci=[-1,130,19] rc=1 vc=47 vn=45 li=- udi=- nc=2
n102n                 ==>iushr
n263n                 iconst 7                                                                [0x7f46017d71f0] bci=[-1,130,19] rc=1 vc=47 vn=44 li=- udi=- nc=0
n265n               iconst 24                                                                 [0x7f46017d7290] bci=[-1,130,19] rc=1 vc=47 vn=43 li=- udi=- nc=0
n102n             ==>iushr
n268n           iconst -256                                                                   [0x7f46017d7380] bci=[-1,130,19] rc=1 vc=47 vn=40 li=- udi=- nc=0
...
n117n     compressedRefs                                                                      [0x7f46017d4450] bci=[-1,131,19] rc=0 vc=47 vn=117 li=- udi=- nc=2
n115n       aloadi  <array-shadow>[#232  Shadow] [flags 0x80000607 0x0 ]                      [0x7f46017d43b0] bci=[-1,131,19] rc=5 vc=47 vn=58 li=- udi=- nc=1
n114n         aladd (X>=0 internalPtr sharedMemory )                                          [0x7f46017d4360] bci=[-1,131,19] rc=1 vc=47 vn=57 li=- udi=- nc=2 flg=0x8100
n99n            ==>aload
n113n           lsub                                                                          [0x7f46017d4310] bci=[-1,131,19] rc=1 vc=47 vn=56 li=- udi=- nc=2
n111n             lmul                                                                        [0x7f46017d4270] bci=[-1,131,19] rc=1 vc=47 vn=55 li=- udi=- nc=2
n110n               i2l (X>=0 )                                                               [0x7f46017d4220] bci=[-1,131,19] rc=1 vc=47 vn=54 li=- udi=- nc=1 flg=0x100
n104n                 ==>isub
n109n               lconst 4                                                                  [0x7f46017d41d0] bci=[-1,131,19] rc=1 vc=47 vn=24 li=- udi=- nc=0
n112n             lconst -16                                                                  [0x7f46017d42c0] bci=[-1,131,19] rc=1 vc=47 vn=23 li=- udi=- nc=0
n116n       lconst 0 (highWordZero )                                                          [0x7f46017d4400] bci=[-1,131,19] rc=1 vc=47 vn=53 li=- udi=- nc=0 flg=0x4000

After Global VP, node n113n is folded from an lsub to an lconst 1036:

n78n      treetop                                                                             [0x7f46017d3820] bci=[-1,81,15] rc=0 vc=419 vn=95 li=- udi=- nc=1
n77n        irem (cannotOverflow )                                                            [0x7f46017d37d0] bci=[-1,81,15] rc=2 vc=419 vn=34 li=- udi=- nc=2 flg=0x1000
n75n          iushr (X>=0 cannotOverflow )                                                    [0x7f46017d3730] bci=[-1,78,15] rc=1 vc=419 vn=33 li=- udi=- nc=2 flg=0x1100
n73n            iload  <parm 1 I>[#418  Parm] [flags 0x40000103 0x0 ] (cannotOverflow )       [0x7f46017d3690] bci=[-1,76,15] rc=2 vc=419 vn=30 li=12 udi=20 nc=0 flg=0x1000
n74n            iconst 1 (X!=0 X>=0 )                                                         [0x7f46017d36e0] bci=[-1,77,15] rc=1 vc=419 vn=8 li=- udi=- nc=0 flg=0x104
n76n          iconst 6 (X!=0 X>=0 )                                                           [0x7f46017d3780] bci=[-1,79,15] rc=1 vc=419 vn=32 li=- udi=- nc=0 flg=0x104
n324n     treetop                                                                             [0x7f46017d8500] bci=[-1,76,15] rc=0 vc=419 vn=96 li=- udi=- nc=1
n73n        ==>iload
n84n      table ()                                                                            [0x7f46017d3a00] bci=[-1,85,15] rc=0 vc=419 vn=103 li=- udi=- nc=7 flg=0x20
n77n        ==>irem
n83n        default  --> block_9 BBStart at n3n                                               [0x7f46017d39b0] bci=[-1,85,15] rc=1 vc=419 vn=97 li=- udi=- nc=0
n85n        0 --> block_5 BBStart at n5n                                                      [0x7f46017d3a50] bci=[-1,85,15] rc=1 vc=419 vn=98 li=- udi=- nc=0
n86n        1 --> block_6 BBStart at n7n                                                      [0x7f46017d3aa0] bci=[-1,85,15] rc=1 vc=419 vn=99 li=- udi=- nc=0
n87n        2 --> block_9 BBStart at n3n                                                      [0x7f46017d3af0] bci=[-1,85,15] rc=1 vc=419 vn=100 li=- udi=- nc=0
n88n        3 --> block_9 BBStart at n3n                                                      [0x7f46017d3b40] bci=[-1,85,15] rc=1 vc=419 vn=101 li=- udi=- nc=0
n89n        4 --> block_8 BBStart at n11n                                                     [0x7f46017d3b90] bci=[-1,85,15] rc=1 vc=419 vn=102 li=- udi=- nc=0
n48n      BBEnd </block_4> =====                                                              [0x7f4601759010] bci=[-1,85,15] rc=0 vc=419 vn=104 li=- udi=- nc=0

n5n       BBStart <block_5> (freq 9077) (in loop 4)                                           [0x7f46017582a0] bci=[-1,120,17] rc=0 vc=419 vn=105 li=- udi=- nc=0
n98n      istore  <auto slot 2>[#419  Auto] [flags 0x3 0x0 ]                                  [0x7f46017d3e60] bci=[-1,121,17] rc=0 vc=419 vn=16 li=6 udi=10 nc=1
n97n        iconst -1 (X!=0 X<=0 )                                                            [0x7f46017d3e10] bci=[-1,120,17] rc=1 vc=419 vn=16 li=- udi=- nc=0 flg=0x204
n6n       BBEnd </block_5> =====                                                              [0x7f46017582f0] bci=[-1,121,17] rc=0 vc=419 vn=106 li=- udi=- nc=0

n7n       BBStart <block_6> (freq 9107) (in loop 4)                                           [0x7f4601758340] bci=[-1,147,21] rc=0 vc=419 vn=107 li=- udi=- nc=0
n295n     treetop                                                                             [0x7f46017d7bf0] bci=[-1,126,19] rc=0 vc=419 vn=108 li=- udi=- nc=1
n102n       iushr (X>=0 cannotOverflow )                                                      [0x7f46017d3fa0] bci=[-1,126,19] rc=3 vc=419 vn=36 li=- udi=- nc=2 flg=0x1100
n100n         iload  <auto slot 2>[#419  Auto] [flags 0x3 0x0 ] (cannotOverflow )             [0x7f46017d3f00] bci=[-1,124,19] rc=2 vc=419 vn=35 li=13 udi=21 nc=0 flg=0x1000
n101n         iconst 1 (X!=0 X>=0 )                                                           [0x7f46017d3f50] bci=[-1,125,19] rc=1 vc=419 vn=8 li=- udi=- nc=0 flg=0x104
n325n     treetop                                                                             [0x7f46017d8550] bci=[-1,124,19] rc=0 vc=419 vn=109 li=- udi=- nc=1
n100n       ==>iload
n105n     treetop                                                                             [0x7f46017d4090] bci=[-1,130,19] rc=0 vc=419 vn=110 li=- udi=- nc=1
n104n       isub                                                                              [0x7f46017d4040] bci=[-1,130,19] rc=3 vc=419 vn=39 li=- udi=- nc=2
n102n         ==>iushr
n267n         iand (cannotOverflow )                                                          [0x7f46017d7330] bci=[-1,130,19] rc=1 vc=419 vn=38 li=- udi=- nc=2 flg=0x1000
n102n           ==>iushr
n268n           iconst -256 (X!=0 X<=0 )                                                      [0x7f46017d7380] bci=[-1,130,19] rc=1 vc=419 vn=37 li=- udi=- nc=0 flg=0x204
...
n117n     compressedRefs                                                                      [0x7f46017d4450] bci=[-1,131,19] rc=0 vc=419 vn=114 li=- udi=- nc=2
n115n       aloadi  <array-shadow>[#232  Shadow] [flags 0x80000607 0x0 ]                      [0x7f46017d43b0] bci=[-1,131,19] rc=5 vc=419 vn=44 li=- udi=- nc=1
n114n         aladd (X>=0 internalPtr sharedMemory )                                          [0x7f46017d4360] bci=[-1,131,19] rc=1 vc=419 vn=43 li=- udi=- nc=2 flg=0x8100
n99n            ==>aload
n113n           lconst 1036 (highWordZero X!=0 X>=0 cannotOverflow )                          [0x7f46017d4310] bci=[-1,131,19] rc=1 vc=419 vn=42 li=- udi=- nc=0 flg=0x5104
n116n       lconst 0 (highWordZero X==0 X>=0 X<=0 )                                           [0x7f46017d4400] bci=[-1,131,19] rc=1 vc=419 vn=41 li=- udi=- nc=0 flg=0x4302

I think I was mistaken about Global VP ignoring the reaching definition of i17 = -244. I think now that Global VP decides that the only possible value for the isub operation at node n104n (after passing through a BNDCHK) is 255. There could be an error in the constraints it computed leading up to that.

I've annotated the part of the tree for the isub computation with constraints from Global VP below:

n104n       isub     {(TR::getMinSigned<TR::Int32>() to -122)I, (255 to TR::getMaxSigned<TR::Int32>())I}4040] bci=[-1,130,19] rc=3 vc=47 vn=49 li=- udi=- nc=2
n102n         iushr                             {2147483647 to 2147483526}                    [0x7f6d818a3fa0] bci=[-1,126,19] rc=3 vc=47 vn=42 li=- udi=- nc=2
n100n           iload  <auto slot 2>[#419  Auto] [flags 0x3 0x0 ]   {-1,-244}                 [0x7f6d818a3f00] bci=[-1,124,19] rc=1 vc=47 vn=41 li=12 udi=22 nc=0
n101n           iconst 1                                                                      [0x7f6d818a3f50] bci=[-1,125,19] rc=1 vc=47 vn=3 li=- udi=- nc=0
n267n         iand                       (TR::getMinSigned<TR::Int32>() to 2147483392)        [0x7f6d818a7330] bci=[-1,130,19] rc=1 vc=47 vn=48 li=- udi=- nc=2
n266n           iadd                      {2147483647 to 2147483526}                          [0x7f6d818a72e0] bci=[-1,130,19] rc=1 vc=47 vn=47 li=- udi=- nc=2
n264n             iushr                   {0}                                                 [0x7f6d818a7240] bci=[-1,130,19] rc=1 vc=47 vn=46 li=- udi=- nc=2
n262n               ishr                  {(0 to 16777215)I}                                  [0x7f6d818a71a0] bci=[-1,130,19] rc=1 vc=47 vn=45 li=- udi=- nc=2
n102n                 ==>iushr
n263n                 iconst 7                                                                [0x7f6d818a71f0] bci=[-1,130,19] rc=1 vc=47 vn=44 li=- udi=- nc=0
n265n               iconst 24                                                                 [0x7f6d818a7290] bci=[-1,130,19] rc=1 vc=47 vn=43 li=- udi=- nc=0
n102n             ==>iushr                {2147483647 to 2147483526}
n268n           iconst -256                                                                   [0x7f6d818a7380] bci=[-1,130,19] rc=1 vc=47 vn=40 li=- udi=- nc=0

The constraint for the isub is {(TR::getMinSigned<TR::Int32>() to -122)I, (255 to TR::getMaxSigned<TR::Int32>())I}, and the subsequent BNDCHK compares with an arraylength of 255 256, so it thinks the only possible value for the isub on the path after the BNDCHK is 255.

I'll look over the constraints for the other operations in the tree for the isub to understand whether some range that's been computed is incorrect.

The problem appears to be with the range that is created for the iushr operation. The lower and upper bounds of the first operand are used to calculate the lower and upper bounds, respectively, of the result, without regard to the possible change of sign.

The incorrect behaviour can be reproduced using this simplified test case:

public class Experiment15874 {
    public static final void sub(int i) {
        int val = (i == 1) ? 0x9FFFFFFF : ((i == 2) ? 0xFFFFFFFF : 0xAFFFFFFF);
        if (val >>> 29 == 5) System.out.println("val >>> 29 is 5");
        else System.out.println("val >>> 29 is not 5");
    }

    public static final void main(String[] args) {
        sub(1);
        sub(2);
        sub(3);
    }
}

Running with the interpreter produces this output:

java -Xint Experiment15874
val >>> 29 is not 5
val >>> 29 is not 5
val >>> 29 is 5

Forcing Experiment15874.sub to be compiled results in this (incorrect output), because Value Propagation determines that val >>> 29 can never be five.

$ java -Xjit:limit={Experiment15874.sub*},count=0 Experiment15874
val >>> 29 is not 5
val >>> 29 is not 5
val >>> 29 is not 5