diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-04-24 22:21:57 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-04-27 14:52:22 +0900 |
commit | c7bacf84f04201787d26e4a4be8aca61ff1e454b (patch) | |
tree | bf4b32fe97805125228deec22daf63ba12a5c2be /compile.c | |
parent | b0cb54a378f2c588a050dafe6db69cb4cdd2637e (diff) |
[Bug #19611] Remove never-reachable branch in logical expression
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/7754
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 61 |
1 files changed, 37 insertions, 24 deletions
@@ -4254,36 +4254,49 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod static int compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond, + LABEL *then_label, LABEL *else_label); + +static int +compile_logical(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond, + LABEL *then_label, LABEL *else_label) +{ + DECL_ANCHOR(seq); + INIT_ANCHOR(seq); + LABEL *label = NEW_LABEL(nd_line(cond)); + if (!then_label) then_label = label; + else if (!else_label) else_label = label; + + CHECK(compile_branch_condition(iseq, seq, cond, then_label, else_label)); + + if (LIST_INSN_SIZE_ONE(seq)) { + INSN *insn = (INSN *)ELEM_FIRST_INSN(FIRST_ELEMENT(seq)); + if (insn->insn_id == BIN(jump) && (LABEL *)(insn->operands[0]) == label) + return COMPILE_OK; + } + if (!label->refcnt) { + ADD_INSN(seq, cond, putnil); + } + else { + ADD_LABEL(seq, label); + } + ADD_SEQ(ret, seq); + return COMPILE_OK; +} + +static int +compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond, LABEL *then_label, LABEL *else_label) { again: switch (nd_type(cond)) { case NODE_AND: - { - LABEL *label = NEW_LABEL(nd_line(cond)); - CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label, - else_label)); - if (!label->refcnt) { - ADD_INSN(ret, cond, putnil); - break; - } - ADD_LABEL(ret, label); - cond = cond->nd_2nd; - goto again; - } + CHECK(compile_logical(iseq, ret, cond->nd_1st, NULL, else_label)); + cond = cond->nd_2nd; + goto again; case NODE_OR: - { - LABEL *label = NEW_LABEL(nd_line(cond)); - CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label, - label)); - if (!label->refcnt) { - ADD_INSN(ret, cond, putnil); - break; - } - ADD_LABEL(ret, label); - cond = cond->nd_2nd; - goto again; - } + CHECK(compile_logical(iseq, ret, cond->nd_1st, then_label, NULL)); + cond = cond->nd_2nd; + goto again; case NODE_LIT: /* NODE_LIT is always true */ case NODE_TRUE: case NODE_STR: |