diff --git a/ext/opcache/jit/ir/ir.c b/ext/opcache/jit/ir/ir.c index 2721de4a6e0..d9f7e3d0f78 100644 --- a/ext/opcache/jit/ir/ir.c +++ b/ext/opcache/jit/ir/ir.c @@ -2413,10 +2413,18 @@ static ir_ref _ir_fold_condition(ir_ctx *ctx, ir_ref ref) if (IR_IS_TYPE_INT(op2_insn->type) && op2_insn->val.u64 == 0) { ref = insn->op1; insn = &ctx->ir_base[ref]; + if (insn->op == IR_ALLOCA || insn->op == IR_VADDR) { + return IR_TRUE; + } } } else if (insn->op == IR_EQ && insn->op2 == IR_TRUE) { ref = insn->op1; insn = &ctx->ir_base[ref]; + } else if (insn->op == IR_EQ && insn->op2 == IR_NULL) { + ir_insn *op1_insn = &ctx->ir_base[insn->op1]; + if (op1_insn->op == IR_ALLOCA || op1_insn->op == IR_VADDR) { + return IR_FALSE; + } } // while (insn->op == IR_SEXT || insn->op == IR_ZEXT || insn->op == IR_BITCAST) { // ref = insn->op1; diff --git a/ext/opcache/jit/ir/ir_fold.h b/ext/opcache/jit/ir/ir_fold.h index 6f0bfea4782..c7745a8c687 100644 --- a/ext/opcache/jit/ir/ir_fold.h +++ b/ext/opcache/jit/ir/ir_fold.h @@ -1464,7 +1464,9 @@ IR_FOLD(EQ(SEXT, C_I32)) IR_FOLD(EQ(SEXT, C_I64)) IR_FOLD(EQ(SEXT, C_ADDR)) { - if (op2_insn->val.u64 == 0 && ctx->ir_base[op1_insn->op1].type == IR_BOOL) { + if (ctx->use_lists && ctx->use_lists[op1_insn->op1].count != 1) { + /* pass */ + } else if (op2_insn->val.u64 == 0 && ctx->ir_base[op1_insn->op1].type == IR_BOOL) { opt = IR_OPT(IR_NOT, IR_BOOL); op1 = op1_insn->op1; op2 = IR_UNUSED; @@ -1509,7 +1511,9 @@ IR_FOLD(NE(SEXT, C_I32)) IR_FOLD(NE(SEXT, C_I64)) IR_FOLD(NE(SEXT, C_ADDR)) { - if (op2_insn->val.u64 == 0 && ctx->ir_base[op1_insn->op1].type == IR_BOOL) { + if (ctx->use_lists && ctx->use_lists[op1_insn->op1].count != 1) { + /* pass */ + } else if (op2_insn->val.u64 == 0 && ctx->ir_base[op1_insn->op1].type == IR_BOOL) { IR_FOLD_COPY(op1_insn->op1); } else { ir_type type = ctx->ir_base[op1_insn->op1].type; @@ -2464,6 +2468,17 @@ IR_FOLD(SEXT(AND)) IR_FOLD_NEXT; } +IR_FOLD(SEXT(SHR)) +{ + if (IR_IS_CONST_REF(op1_insn->op2) + && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op) + && ctx->ir_base[op1_insn->op2].val.u64 != 0) { + opt = IR_OPT(IR_ZEXT, IR_OPT_TYPE(opt)); + IR_FOLD_RESTART; + } + IR_FOLD_NEXT; +} + IR_FOLD(TRUNC(AND)) { if (IR_IS_CONST_REF(op1_insn->op2)) { @@ -2490,6 +2505,44 @@ IR_FOLD(TRUNC(AND)) IR_FOLD_NEXT; } +IR_FOLD(AND(ZEXT, C_I16)) +IR_FOLD(AND(ZEXT, C_U16)) +IR_FOLD(AND(ZEXT, C_I32)) +IR_FOLD(AND(ZEXT, C_U32)) +IR_FOLD(AND(ZEXT, C_I64)) +IR_FOLD(AND(ZEXT, C_U64)) +IR_FOLD(AND(ZEXT, C_ADDR)) +{ + ir_type src_size = ir_type_size[ctx->ir_base[op1_insn->op1].type]; + + if ((src_size == 1 && op2_insn->val.u64 == 0xff) + || (src_size == 2 && op2_insn->val.u64 == 0xffff) + || (src_size == 4 && op2_insn->val.u64 == 0xffffffff)) { + IR_FOLD_COPY(op1); + } + IR_FOLD_NEXT; +} + +IR_FOLD(AND(SEXT, C_I16)) +IR_FOLD(AND(SEXT, C_U16)) +IR_FOLD(AND(SEXT, C_I32)) +IR_FOLD(AND(SEXT, C_U32)) +IR_FOLD(AND(SEXT, C_I64)) +IR_FOLD(AND(SEXT, C_U64)) +IR_FOLD(AND(SEXT, C_ADDR)) +{ + ir_type src_size = ir_type_size[ctx->ir_base[op1_insn->op1].type]; + + if ((src_size == 1 && op2_insn->val.u64 == 0xff) + || (src_size == 2 && op2_insn->val.u64 == 0xffff) + || (src_size == 4 && op2_insn->val.u64 == 0xffffffff)) { + opt = IR_OPT(IR_ZEXT, IR_OPT_TYPE(opt)); + op1 = op1_insn->op1; + op2 = IR_UNUSED; + IR_FOLD_RESTART; + } + IR_FOLD_NEXT; +} IR_FOLD(AND(SHR, C_I8)) IR_FOLD(AND(SHR, C_U8)) { diff --git a/ext/opcache/jit/ir/ir_sccp.c b/ext/opcache/jit/ir/ir_sccp.c index 42012f222f7..af039aaef82 100644 --- a/ext/opcache/jit/ir/ir_sccp.c +++ b/ext/opcache/jit/ir/ir_sccp.c @@ -927,7 +927,7 @@ static bool ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_ref ref, ir_i IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN); old_merge_inputs = insn->inputs_count; new_merge_inputs = 0; - life_inputs = (old_merge_inputs - IR_BITSET_BITS) ? &holder : ir_bitset_malloc(old_merge_inputs + 1); + life_inputs = (old_merge_inputs < IR_BITSET_BITS) ? &holder : ir_bitset_malloc(old_merge_inputs + 1); for (i = 1; i <= old_merge_inputs; i++) { ir_ref input = ir_insn_op(insn, i); @@ -3328,6 +3328,10 @@ static ir_ref ir_iter_optimize_condition(ir_ctx *ctx, ir_ref control, ir_ref con condition_insn = &ctx->ir_base[condition]; } + if (condition_insn->op == IR_ALLOCA || condition_insn->op == IR_VADDR) { + return IR_TRUE; + } + if (!IR_IS_CONST_REF(condition) && ctx->use_lists[condition].count > 1) { condition = ir_check_dominating_predicates(ctx, control, condition); }