1

I normally code in Java, but I've recently looked at ways C code is optimized manually. One thing that is often done (beyond loop hoisting) is eliminate "conditionals" using "math". This usually relies on "boolean" values (result of "a == b" for example) also being an integer type, that can be used to multiply other values. But in Java, boolean is not an integer. I could convert a boolean "flag" into an integer like this:

int i = flag ? 1 : 0;

But "syntactically", this is also a "conditional". My question is, is this normally turned into something "jump-free" by the JIT?

If not, but some other expression would result in the desired effect, I'd like to know that too.

EDIT: Based on the comments, I'll be more specific: is the expression optimized in the Oracle JVM, for x86/x64 (Intel/AMD) CPUs.

Sebastien Diot
  • 7,183
  • 6
  • 43
  • 85
  • 3
    The answer could be JIT specific, and it could also be context specific. But the way to find out is to get the JVM to dump out the native code produced by the JIT. – Stephen C Nov 02 '17 at 12:12

2 Answers2

1

The Hotspot JVM in general eliminates branches using CMOV unless the branch is fairly predictable (then branching is cheaper as it needs one less instruction, s. e.g., this answer of mine).

A direct interpretation of boolean as int in the machine code (not bytecode!) is also possible, but I can't tell if it gets done. You'd need to look at the JIT output (which requires to install some tool).

Looking at the bytecode is rather pointless w.r.t. to the performance, unless you're interested in the startup behavior, i.e., before the C1 (fast but dumb) and C2 (smart but slow) JIT compilers kick in.

maaartinus
  • 44,714
  • 32
  • 161
  • 320
-1

No the conditional is not removed.

Following code:

public static int boolToInt(boolean in) {
    return in ? 1: 0;
}

gets compiled into following JVM instructions:

 public static int boolToInt(boolean);
   Code:
     0: iload_0
     1: ifeq          8     //conditional here
     4: iconst_1
     5: goto          9
     8: iconst_0
     9: ireturn

It gets carried all the way to the machine language.

Here is why:

Flexible conditions work in C and few other languages like Ruby, Python, and JavaScript thanks to the notion of truthy and falsy.

In Java conditionals depend on conditions evaluating strictly to boolean values by the use of boolean operators (<, <=, ==, !=, >=, >, instanceof) or methods returning boolean or Boolean values.

Keep in mind that implementation of conditionals based on truthy and falsy values require additional computation and conventions which you could implement using boolean methods or Predicates relevant to your model.

It's all syntactic sugar anyway, as JVM is using conditional jumps, where conditions and coresponding instructions are (per JVM instructions spec):

  • two ints are <, <=, ==, !=, >=, > implemented by if_acmp<cond>
  • two references are equal implemented by if_icmp<cond>
  • int is zero implemented by if<cond>
  • reference is not null implemented by ifnonnull
  • reference is null implemented by ifnull

... which in turn are implemented by corresponding CPU machine instructions, few examples of which are shown in this Wikipedia article on branching.

diginoise
  • 7,352
  • 2
  • 31
  • 39
  • 2
    You're showing the bytecode, but there's nothing directly performance relevant in the bytecode. After a few iterations, it gets compiled to machine language. After some more iterations, it gets compiled again, with aggressive optimizations. At the very least, the CMOV instruction gets used unless the branch is fairly predictable (like [here](https://stackoverflow.com/a/19693809/581205)). – maaartinus Nov 05 '17 at 20:06
  • @maaartinus What I tried to show is that any conditional in a higher level language results in conditionals in lower level representations too, all the way down to CPU level. Even `cmov` is a **conditional** move, which admittedly is a better choice than conditional jumps, but it is conditional anyway. On a machine level your argument can be anything, and primitive types disappear, so discussion about `boolean`s and `int`s is a discussion about conventions. – diginoise Nov 09 '17 at 13:56