Commit e201b564 authored by Richard Henderson's avatar Richard Henderson
Browse files

tcg/optimize: Simply some logical ops to NOT



Given, of course, an appropriate constant.  These could be generated
from the "canonical" operation for inversion on the guest, or via
other optimizations.

Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Reviewed-by: default avatarAurelien Jarno <aurelien@aurel32.net>
Signed-off-by: default avatarRichard Henderson <rth@twiddle.net>
parent 23ec69ed
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -655,6 +655,63 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
                }
            }
            break;
        CASE_OP_32_64(xor):
        CASE_OP_32_64(nand):
            if (temps[args[1]].state != TCG_TEMP_CONST
                && temps[args[2]].state == TCG_TEMP_CONST
                && temps[args[2]].val == -1) {
                i = 1;
                goto try_not;
            }
            break;
        CASE_OP_32_64(nor):
            if (temps[args[1]].state != TCG_TEMP_CONST
                && temps[args[2]].state == TCG_TEMP_CONST
                && temps[args[2]].val == 0) {
                i = 1;
                goto try_not;
            }
            break;
        CASE_OP_32_64(andc):
            if (temps[args[2]].state != TCG_TEMP_CONST
                && temps[args[1]].state == TCG_TEMP_CONST
                && temps[args[1]].val == -1) {
                i = 2;
                goto try_not;
            }
            break;
        CASE_OP_32_64(orc):
        CASE_OP_32_64(eqv):
            if (temps[args[2]].state != TCG_TEMP_CONST
                && temps[args[1]].state == TCG_TEMP_CONST
                && temps[args[1]].val == 0) {
                i = 2;
                goto try_not;
            }
            break;
        try_not:
            {
                TCGOpcode not_op;
                bool have_not;

                if (def->flags & TCG_OPF_64BIT) {
                    not_op = INDEX_op_not_i64;
                    have_not = TCG_TARGET_HAS_not_i64;
                } else {
                    not_op = INDEX_op_not_i32;
                    have_not = TCG_TARGET_HAS_not_i32;
                }
                if (!have_not) {
                    break;
                }
                s->gen_opc_buf[op_index] = not_op;
                reset_temp(args[0]);
                gen_args[0] = args[0];
                gen_args[1] = args[i];
                args += 3;
                gen_args += 2;
                continue;
            }
        default:
            break;
        }