On Mon, Oct 14, 2013 at 03:10:12PM +0800, Zhenqiang Chen wrote: @@ -2131,6 +2133,155 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, return true; } +/* Optimize X == CST1 || X == CST2 + if popcount (CST1 ^ CST2) == 1 into + (X & ~(CST1 ^ CST2)) == (CST1 & ~(CST1 ^ CST2)). + Similarly for ranges. E.g. + X != 2 && X != 3 && X != 10 && X != 11 + will be transformed by the previous optimization into + (X - 2U) <= 1U && (X - 10U) <= 1U + and this loop can transform that into + ((X & ~8) - 2U) <= 1U. */ + +static bool +try_transfer_range_tests_1 (enum tree_code opcode, int i, int j, tree type, + tree lowi, tree lowj, tree highi, tree highj, + vec<operand_entry_t> *ops, + struct range_entry *ranges)
The function names are bad, you aren't transfering anything, but optimizing. Please rename try_transfer_range_tests to optimize_range_tests_1 and try_transfer_range_tests_{1,2} to optimize_range_tests_{2,3} or perhaps better yet to optimize_range_tests_{xor,diff}. Also, perhaps instead of passing ranges and i and j to these two functions you could pass struct range_entry *range1, struct range_entry *range2 (caller would pass ranges + i, ranges + j). +/* It does some common checks for function try_transfer_range_tests_1 and + try_transfer_range_tests_2. Please adjust the comment for the renaming. Please change trans_option to bool optimize_xor. + if (trans_option == 1) + { + if (try_transfer_range_tests_1 (opcode, i, j, type, lowi, lowj, + highi, highj, ops, ranges)) + { + any_changes = true; + break; + } + } + else if (trans_option == 2) + { + if (try_transfer_range_tests_2 (opcode, i, j, type, lowi, lowj, + highi, highj, ops, ranges)) + { + any_changes = true; + break; + } + } I'd prefer if (optimize_xor) any_changes = optimize_range_tests_xor (opcode, type, lowi, lowj, highi, highj, ops, ranges + i, ranges + j); else any_changes = optimize_range_tests_xor (opcode, type, lowi, lowj, highi, highj, ops, ranges + i, ranges + j); if (any_changes) break; Ok with those changes. Jakub