aboutsummaryrefslogtreecommitdiffstats
path: root/compile.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-10-23 02:58:22 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-10-23 02:58:22 +0000
commitae8f8fddb0f8e89e86d27a7710a9c07addf7901b (patch)
tree5694e105b2b199b5830807dd0aca43c1461bdeba /compile.c
parent4f9ded5cdd9a6f8cd1273b9d7e0887b7b2ed2c83 (diff)
downloadruby-ae8f8fddb0f8e89e86d27a7710a9c07addf7901b.tar.gz
compile.c: optimize method chain
* compile.c (iseq_peephole_optimize): optimize lengthy safe navigation method chain. [Feature #11537] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52237 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c51
1 files changed, 27 insertions, 24 deletions
diff --git a/compile.c b/compile.c
index 8d12fc0e01..50560ba973 100644
--- a/compile.c
+++ b/compile.c
@@ -1967,33 +1967,36 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* if L2
*/
INSN *nobj = (INSN *)get_destination_insn(iobj);
- if (nobj->insn_id == BIN(jump)) {
- OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0);
- }
+ INSN *pobj = (INSN *)iobj->link.prev;
+ int prev_dup = (pobj && pobj->insn_id == BIN(dup));
- if (nobj->insn_id == BIN(dup)) {
- /*
- * dup
- * if L1
- * ...
- * L1:
- * dup
- * if L2
- * =>
- * dup
- * if L2
- * ...
- * L1:
- * dup
- * if L2
- */
- INSN *pobj = (INSN *)iobj->link.prev;
- nobj = (INSN *)nobj->link.next;
- /* basic blocks, with no labels in the middle */
- if ((pobj && pobj->insn_id == BIN(dup)) &&
- (nobj && nobj->insn_id == iobj->insn_id)) {
+ for (;;) {
+ if (nobj->insn_id == BIN(jump)) {
+ OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0);
+ }
+ else if (prev_dup && nobj->insn_id == BIN(dup) &&
+ !!(nobj = (INSN *)nobj->link.next) &&
+ /* basic blocks, with no labels in the middle */
+ nobj->insn_id == iobj->insn_id) {
+ /*
+ * dup
+ * if L1
+ * ...
+ * L1:
+ * dup
+ * if L2
+ * =>
+ * dup
+ * if L2
+ * ...
+ * L1:
+ * dup
+ * if L2
+ */
OPERAND_AT(iobj, 0) = OPERAND_AT(nobj, 0);
}
+ else break;
+ nobj = (INSN *)get_destination_insn(nobj);
}
}