The following two functions should give the same asm (If the branch cost is high enough): int g(void); int h(int a, int b, int c, int d) { if (a==b) if (c==d) return g(); return 0; } int h1(int a, int b, int c, int d) { if (a==b && c==d) return g(); return 0; } And these two: int j(int a, int b, int c, int d) { if (a==b) goto a; if (c==d) goto a; else goto b; a: return g(); b: return 0; } int j1(int a, int b, int c, int d) { if (a==b || c==d) return g(); return 0; }
Mine I am working on this, then we should be able to removed this optimization in fold which causes this to happen in the one statement one.
I lost the code which I was using to do this so I am no longer working on this.
Another thing we should be able to do is combine bit-tests like if (a & (1 << b)) if (a & (1 << c)) ... to a single test if (a & ((1 << b) | (1 << c)) == ((1 << b) | (1 << c))) ...
The new if-combining pass can be told to make the transformation suggested in the description.
I have a patch which implements this. I will be posting it for 4.8.
Fixed by: 2013-10-29 Andrew Pinski <apinski@cavium.com> * tree-ssa-ifcombine.c: Include rtl.h and tm_p.h. (ifcombine_ifandif): Handle cases where maybe_fold_and_comparisons fails, combining the branches anyways. (tree_ssa_ifcombine): Inverse the order of the basic block walk, increases the number of combinings. * gimple.h (gsi_start_nondebug_after_labels_bb): New function.