@@ -223,6 +223,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
223223
224224 void visitBlock (Block* curr) {
225225 if (curr->list .size () == 0 ) return ;
226+ if (handleUnreachable (curr)) return ;
226227 if (curr->type == i64 ) curr->type = i32 ;
227228 auto highBitsIt = labelHighBitVars.find (curr->name );
228229 if (!hasOutParam (curr->list .back ())) {
@@ -272,13 +273,15 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
272273 }
273274
274275 void visitLoop (Loop* curr) {
276+ // TODO: in flat IR, no chance for an out param
275277 assert (labelHighBitVars.find (curr->name ) == labelHighBitVars.end ());
276278 if (curr->type != i64 ) return ;
277279 curr->type = i32 ;
278280 setOutParam (curr, fetchOutParam (curr->body ));
279281 }
280282
281283 void visitBreak (Break* curr) {
284+ // TODO: in flat IR, no chance for an out param
282285 if (!hasOutParam (curr->value )) return ;
283286 assert (curr->value != nullptr );
284287 TempVar valHighBits = fetchOutParam (curr->value );
@@ -301,6 +304,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
301304 }
302305
303306 void visitSwitch (Switch* curr) {
307+ // TODO: in flat IR, no chance for an out param
304308 if (!hasOutParam (curr->value )) return ;
305309 TempVar outParam = fetchOutParam (curr->value );
306310 TempVar tmp = getTemp ();
@@ -478,8 +482,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
478482 }
479483
480484 void visitSetGlobal (SetGlobal* curr) {
481- if (handleUnreachable (curr)) return ;
482485 if (!originallyI64Globals.count (curr->name )) return ;
486+ if (handleUnreachable (curr)) return ;
483487 TempVar highBits = fetchOutParam (curr->value );
484488 auto * setHigh = builder->makeSetGlobal (
485489 makeHighName (curr->name ),
@@ -550,6 +554,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
550554 TempVar ptrTemp = getTemp ();
551555 SetLocal* setPtr = builder->makeSetLocal (ptrTemp, curr->ptr );
552556 curr->ptr = builder->makeGetLocal (ptrTemp, i32 );
557+ curr->finalize ();
553558 Store* storeHigh = builder->makeStore (
554559 4 ,
555560 curr->offset + 4 ,
@@ -941,11 +946,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
941946
942947 void visitUnary (Unary* curr) {
943948 if (!unaryNeedsLowering (curr->op )) return ;
944- if (curr->type == unreachable || curr->value ->type == unreachable) {
945- assert (!hasOutParam (curr->value ));
946- replaceCurrent (curr->value );
947- return ;
948- }
949+ if (handleUnreachable (curr)) return ;
949950 assert (hasOutParam (curr->value ) || curr->type == i64 || curr->type == f64 );
950951 switch (curr->op ) {
951952 case ClzInt64:
@@ -1463,25 +1464,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
14631464 }
14641465
14651466 void visitBinary (Binary* curr) {
1467+ if (handleUnreachable (curr)) return ;
14661468 if (!binaryNeedsLowering (curr->op )) return ;
1467- if (!hasOutParam (curr->left )) {
1468- // left unreachable, replace self with left
1469- replaceCurrent (curr->left );
1470- if (hasOutParam (curr->right )) {
1471- // free temp var
1472- fetchOutParam (curr->right );
1473- }
1474- return ;
1475- }
1476- if (!hasOutParam (curr->right )) {
1477- // right unreachable, replace self with left then right
1478- replaceCurrent (
1479- builder->blockify (builder->makeDrop (curr->left ), curr->right )
1480- );
1481- // free temp var
1482- fetchOutParam (curr->left );
1483- return ;
1484- }
14851469 // left and right reachable, lower normally
14861470 TempVar leftLow = getTemp ();
14871471 TempVar leftHigh = fetchOutParam (curr->left );
@@ -1668,16 +1652,26 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
16681652
16691653 // If e.g. a select is unreachable, then one arm may have an out param
16701654 // but not the other. In this case dce should really have been run
1671- // before; handle it in a simple way here.
1655+ // before; handle it in a simple way here by replacing the node with
1656+ // a block of its children.
1657+ // This is valid only for nodes that execute their children
1658+ // unconditionally before themselves, so it is not valid for an if,
1659+ // in particular.
16721660 bool handleUnreachable (Expression* curr) {
16731661 if (curr->type != unreachable) return false ;
16741662 std::vector<Expression*> children;
1663+ bool hasUnreachable = false ;
16751664 for (auto * child : ChildIterator (curr)) {
16761665 if (isConcreteType (child->type )) {
16771666 child = builder->makeDrop (child);
1667+ } else if (child->type == unreachable) {
1668+ hasUnreachable = true ;
16781669 }
16791670 children.push_back (child);
16801671 }
1672+ if (!hasUnreachable) return false ;
1673+ // This has an unreachable child, so we can replace it with
1674+ // the children.
16811675 auto * block = builder->makeBlock (children);
16821676 assert (block->type == unreachable);
16831677 replaceCurrent (block);
0 commit comments