Under Review
over 1 year ago

The optimizer constant folds Char comparisons incorrectly

Given:

const MY_CHAR as Char = '*'; // note that MY_CHAR.toNumber() == 42
const MY_NUMBER as Number = 42;
const MY_LONG as Long = 42l;
const MY_FLOAT as Float = 42f;
const MY_DOUBLE as Double = 42d;

function check_equal(a as Char, b as Numeric) {
  return a == b;
}

function testequality() {
  System.println("MY_CHAR == MY_NUMBER: " + (MY_CHAR == MY_NUMBER).toString());
  System.println("check_equal(MY_CHAR, MY_NUMBER): " + check_equal(MY_CHAR, MY_NUMBER).toString());

  System.println("MY_CHAR == MY_LONG: " + (MY_CHAR == MY_LONG).toString());
  System.println("check_equal(MY_CHAR, MY_LONG): " + check_equal(MY_CHAR, MY_LONG).toString());

  System.println("MY_CHAR == MY_FLOAT: " + (MY_CHAR == MY_FLOAT).toString());
  System.println("check_equal(MY_CHAR, MY_FLOAT): " + check_equal(MY_CHAR, MY_FLOAT).toString());

  System.println("MY_CHAR == MY_DOUBLE: " + (MY_CHAR == MY_DOUBLE).toString());
  System.println("check_equal(MY_CHAR, MY_DOUBLE): " + check_equal(MY_CHAR, MY_DOUBLE).toString());
}

Then at O0, all the comparisons are "true" (as expected):

MY_CHAR == MY_NUMBER: true
check_equal(MY_CHAR, MY_NUMBER): true
MY_CHAR == MY_LONG: true
check_equal(MY_CHAR, MY_LONG): true
MY_CHAR == MY_FLOAT: true
check_equal(MY_CHAR, MY_FLOAT): true
MY_CHAR == MY_DOUBLE: true
check_equal(MY_CHAR, MY_DOUBLE): true

At O1, O2, and O3, MY_CHAR==MY_NUMBER is (correctly) constant folded to "true", but the other three direct comparisons are constant folded to "false". Here's the (now incorrect) output of the program:

MY_CHAR == MY_NUMBER: true
check_equal(MY_CHAR, MY_NUMBER): true
MY_CHAR == MY_LONG: false
check_equal(MY_CHAR, MY_LONG): true
MY_CHAR == MY_FLOAT: false
check_equal(MY_CHAR, MY_FLOAT): true
MY_CHAR == MY_DOUBLE: false
check_equal(MY_CHAR, MY_DOUBLE): true

Note that "check_equal" returns the correct result, regardless of optimization level. Also, if I change the program to use "var" instead of "const" for MY_LONG through MY_DOUBLE, I get the correct results regardless of the optimization level.

Similarly, MY_NUMBER.toChar() == MY_LONG is never constant folded, and correctly returns true regardless of optimization level. As does 42.toChar() == 42L.

I get the same behavior with sdk-4.1.7 through 4.2.4