1919namespace rir {
2020namespace pir {
2121
22- static SEXP isConst (Value* instr) {
22+ static SEXP isConst (Value* instr, Preserve& p ) {
2323 instr = instr->followCastsAndForce ();
2424
25+ if (auto cst = LdConst::Cast (instr))
26+ return cst->c ();
27+
2528 if (instr->asRValue () && instr != MissingArg::instance ())
2629 return instr->asRValue ();
2730
28- if (auto cst = LdConst::Cast (instr)) {
29- return cst->c ();
30- }
3131 return nullptr ;
3232}
33+
34+ SEXP qt (SEXP c, Preserve& p) {
35+ if (TYPEOF (c) == SYMSXP)
36+ return p.operator ()(Rf_lang2 (symbol::quote, c));
37+ return c;
38+ }
39+
3340#define FOLD_BINARY_NATIVE (Instruction, Operation ) \
3441 do { \
3542 if (auto instr = Instruction::Cast (i)) { \
36- if (auto lhs = isConst (instr->arg <0 >().val ())) { \
37- if (auto rhs = isConst (instr->arg <1 >().val ())) { \
38- auto res = \
39- Rf_eval (Rf_lang3 (Operation, lhs, rhs), R_BaseEnv); \
43+ if (auto lhs = isConst (instr->arg <0 >().val (), p)) { \
44+ if (auto rhs = isConst (instr->arg <1 >().val (), p)) { \
45+ auto res = Rf_eval ( \
46+ p (Rf_lang3 (Operation, qt (lhs, p), qt (rhs, p))), \
47+ R_BaseEnv); \
4048 if (res == R_TrueValue || res == R_FalseValue) { \
4149 instr->replaceUsesWith ( \
4250 res == R_TrueValue ? (Value*)True::instance () \
4351 : (Value*)False::instance ()); \
4452 next = bb->remove (ip); \
4553 } else { \
46- cmp. preserve (res); \
54+ p (res); \
4755 auto resi = new LdConst (res); \
4856 anyChange = true ; \
4957 instr->replaceUsesWith (resi); \
@@ -56,15 +64,15 @@ static SEXP isConst(Value* instr) {
5664#define FOLD_UNARY (Instruction, Operation ) \
5765 do { \
5866 if (auto instr = Instruction::Cast (i)) { \
59- if (auto arg = isConst (instr->arg <0 >().val ())) \
67+ if (auto arg = isConst (instr->arg <0 >().val (), p)) \
6068 Operation (arg); \
6169 } \
6270 } while (false )
6371#define FOLD_BINARY (Instruction, Operation ) \
6472 do { \
6573 if (auto instr = Instruction::Cast (i)) { \
66- if (auto lhs = isConst (instr->arg <0 >().val ())) { \
67- if (auto rhs = isConst (instr->arg <1 >().val ())) { \
74+ if (auto lhs = isConst (instr->arg <0 >().val (), p )) { \
75+ if (auto rhs = isConst (instr->arg <1 >().val (), p )) { \
6876 Operation (lhs, rhs); \
6977 } \
7078 } \
@@ -73,11 +81,11 @@ static SEXP isConst(Value* instr) {
7381#define FOLD_BINARY_EITHER (Instruction, Operation ) \
7482 do { \
7583 if (auto instr = Instruction::Cast (i)) { \
76- if (auto lhs = isConst (instr->arg <0 >().val ())) { \
84+ if (auto lhs = isConst (instr->arg <0 >().val (), p )) { \
7785 if (Operation (lhs, instr->arg <1 >().val ())) \
7886 break ; \
7987 } \
80- if (auto rhs = isConst (instr->arg <1 >().val ())) { \
88+ if (auto rhs = isConst (instr->arg <1 >().val (), p )) { \
8189 Operation (rhs, instr->arg <0 >().val ()); \
8290 } \
8391 } \
@@ -158,6 +166,7 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
158166
159167 bool anyChange = false ;
160168
169+ Preserve p;
161170 std::unordered_map<BB*, bool > branchRemoval;
162171
163172 DominanceGraph dom (code);
@@ -317,7 +326,7 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
317326 };
318327
319328 auto foldLglCmp = [&](SEXP carg, Value* varg, bool isEq) {
320- if (!isConst (varg) && // If this is true, was already folded
329+ if (!isConst (varg, p ) && // was already folded
321330 IS_SIMPLE_SCALAR (carg, LGLSXP) &&
322331 varg->type .isA (PirType::simpleScalarLogical ())) {
323332 int larg = *LOGICAL (carg);
@@ -375,9 +384,9 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
375384 : (Value*)False::instance ();
376385 i->replaceUsesWith (replace);
377386 next = bb->remove (ip);
378- } else if (isConst (a) &&
379- convertsToLogicalWithoutWarning (isConst (a))) {
380- auto replace = Rf_asLogical (isConst (a)) == TRUE
387+ } else if (isConst (a, p ) &&
388+ convertsToLogicalWithoutWarning (isConst (a, p ))) {
389+ auto replace = Rf_asLogical (isConst (a, p )) == TRUE
381390 ? (Value*)True::instance ()
382391 : (Value*)False::instance ();
383392 i->replaceUsesWith (replace);
@@ -484,28 +493,28 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
484493 i->replaceUsesWith (False::instance ());
485494 next = bb->remove (ip);
486495 }
487- } else if (isConst (i->arg (0 ).val ()) &&
488- isConst (i->arg (0 ).val ()) == R_TrueValue &&
496+ } else if (isConst (i->arg (0 ).val (), p ) &&
497+ isConst (i->arg (0 ).val (), p ) == R_TrueValue &&
489498 i->arg (1 ).val ()->type .isA (PirType::test ())) {
490499 iterAnyChange = true ;
491500 i->replaceUsesWith (i->arg (1 ).val ());
492501 next = bb->remove (ip);
493- } else if (isConst (i->arg (1 ).val ()) &&
494- isConst (i->arg (1 ).val ()) == R_TrueValue &&
502+ } else if (isConst (i->arg (1 ).val (), p ) &&
503+ isConst (i->arg (1 ).val (), p ) == R_TrueValue &&
495504 i->arg (0 ).val ()->type .isA (PirType::test ())) {
496505 iterAnyChange = true ;
497506 i->replaceUsesWith (i->arg (0 ).val ());
498507 next = bb->remove (ip);
499- } else if (isConst (i->arg (0 ).val ()) &&
500- isConst (i->arg (0 ).val ()) == R_FalseValue &&
508+ } else if (isConst (i->arg (0 ).val (), p ) &&
509+ isConst (i->arg (0 ).val (), p ) == R_FalseValue &&
501510 i->arg (1 ).val ()->type .isA (PirType::test ())) {
502511 iterAnyChange = true ;
503512 auto neg =
504513 new Not (i->arg (1 ).val (), Env::elided (), i->srcIdx );
505514 neg->type = PirType::test ();
506515 i->replaceUsesAndSwapWith (neg, ip);
507- } else if (isConst (i->arg (1 ).val ()) &&
508- isConst (i->arg (1 ).val ()) == R_FalseValue &&
516+ } else if (isConst (i->arg (1 ).val (), p ) &&
517+ isConst (i->arg (1 ).val (), p ) == R_FalseValue &&
509518 i->arg (0 ).val ()->type .isA (PirType::test ())) {
510519 iterAnyChange = true ;
511520 auto neg =
@@ -570,7 +579,7 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
570579 }
571580 }
572581 if (auto cl = Colon::Cast (i)) {
573- if (auto a = isConst (cl->arg (0 ).val ())) {
582+ if (auto a = isConst (cl->arg (0 ).val (), p )) {
574583 if (TYPEOF (a) == REALSXP && Rf_length (a) == 1 &&
575584 REAL (a)[0 ] == (double )(int )REAL (a)[0 ]) {
576585 iterAnyChange = true ;
@@ -579,7 +588,7 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
579588 ip++;
580589 }
581590 }
582- if (auto a = isConst (cl->arg (1 ).val ())) {
591+ if (auto a = isConst (cl->arg (1 ).val (), p )) {
583592 if (TYPEOF (a) == REALSXP && Rf_length (a) == 1 &&
584593 REAL (a)[0 ] == (double )(int )REAL (a)[0 ]) {
585594 iterAnyChange = true ;
@@ -665,12 +674,13 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
665674 iterAnyChange = true ;
666675 i->replaceUsesWith (i->arg (0 ).val ());
667676 next = bb->remove (ip);
668- } else if (auto con = isConst (i->arg (0 ).val ())) {
677+ } else if (auto con = isConst (i->arg (0 ).val (), p )) {
669678 auto t = TYPEOF (con);
670679 if (t == REALSXP || t == INTSXP || t == LGLSXP) {
671- auto res = Rf_eval (
672- Rf_lang2 (Rf_install (" as.character" ), con),
673- R_BaseEnv);
680+ auto res =
681+ p (Rf_eval (p (Rf_lang2 (symbol::ascharacter,
682+ qt (con, p))),
683+ R_BaseEnv));
674684 iterAnyChange = true ;
675685 i->replaceUsesAndSwapWith (new LdConst (res), ip);
676686 }
@@ -683,7 +693,7 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
683693 iterAnyChange = true ;
684694 i->replaceUsesWith (i->arg (0 ).val ());
685695 next = bb->remove (ip);
686- } else if (auto con = isConst (i->arg (0 ).val ())) {
696+ } else if (auto con = isConst (i->arg (0 ).val (), p )) {
687697 if (IS_SIMPLE_SCALAR (con, REALSXP)) {
688698 if (REAL (con)[0 ] == REAL (con)[0 ]) {
689699 iterAnyChange = true ;
@@ -880,7 +890,7 @@ bool Constantfold::apply(Compiler& cmp, ClosureVersion* cls, Code* code,
880890 }
881891 if (auto not_ = Not::Cast (i)) {
882892 Value* arg = not_->arg <0 >().val ();
883- if (auto carg = isConst (arg)) {
893+ if (auto carg = isConst (arg, p )) {
884894 if (IS_SIMPLE_SCALAR (carg, LGLSXP) ||
885895 IS_SIMPLE_SCALAR (carg, INTSXP) ||
886896 IS_SIMPLE_SCALAR (carg, REALSXP)) {
0 commit comments