@@ -584,18 +584,15 @@ impure fn trans_binary(@block_ctxt cx, ast.binop op,
584
584
auto rhs_cx = new_sub_block_ctxt ( cx, "rhs" ) ;
585
585
auto rhs_res = trans_expr ( rhs_cx, b) ;
586
586
587
- auto next_cx = new_sub_block_ctxt ( cx, "next " ) ;
588
- rhs_res . bcx . build . Br ( next_cx . llbb ) ;
587
+ auto lhs_false_cx = new_sub_block_ctxt ( cx, "lhs false " ) ;
588
+ auto lhs_false_res = res ( lhs_false_cx , C_bool ( false ) ) ;
589
589
590
590
lhs_res. bcx . build . CondBr ( lhs_res. val ,
591
591
rhs_cx. llbb ,
592
- next_cx. llbb ) ;
593
- auto phi = next_cx. build . Phi ( T_bool ( ) ,
594
- vec ( lhs_res. val ,
595
- rhs_res. val ) ,
596
- vec ( lhs_res. bcx . llbb ,
597
- rhs_res. bcx . llbb ) ) ;
598
- ret res( next_cx, phi) ;
592
+ lhs_false_cx. llbb ) ;
593
+
594
+ ret join_results ( cx, T_bool ( ) ,
595
+ vec ( lhs_false_res, rhs_res) ) ;
599
596
}
600
597
601
598
case ( ast. or ) {
@@ -605,18 +602,15 @@ impure fn trans_binary(@block_ctxt cx, ast.binop op,
605
602
auto rhs_cx = new_sub_block_ctxt ( cx, "rhs" ) ;
606
603
auto rhs_res = trans_expr ( rhs_cx, b) ;
607
604
608
- auto next_cx = new_sub_block_ctxt ( cx, "next " ) ;
609
- rhs_res . bcx . build . Br ( next_cx . llbb ) ;
605
+ auto lhs_true_cx = new_sub_block_ctxt ( cx, "lhs true " ) ;
606
+ auto lhs_true_res = res ( lhs_true_cx , C_bool ( true ) ) ;
610
607
611
608
lhs_res. bcx . build . CondBr ( lhs_res. val ,
612
- next_cx . llbb ,
609
+ lhs_true_cx . llbb ,
613
610
rhs_cx. llbb ) ;
614
- auto phi = next_cx. build . Phi ( T_bool ( ) ,
615
- vec ( lhs_res. val ,
616
- rhs_res. val ) ,
617
- vec ( lhs_res. bcx . llbb ,
618
- rhs_res. bcx . llbb ) ) ;
619
- ret res( next_cx, phi) ;
611
+
612
+ ret join_results ( cx, T_bool ( ) ,
613
+ vec ( lhs_true_res, rhs_res) ) ;
620
614
}
621
615
}
622
616
@@ -722,6 +716,48 @@ impure fn trans_binary(@block_ctxt cx, ast.binop op,
722
716
fail;
723
717
}
724
718
719
+ fn join_results ( @block_ctxt parent_cx ,
720
+ TypeRef t,
721
+ vec[ result] ins )
722
+ -> result {
723
+
724
+ let vec[ result] live = vec ( ) ;
725
+ let vec[ ValueRef ] vals = vec ( ) ;
726
+ let vec[ BasicBlockRef ] bbs = vec ( ) ;
727
+
728
+ for ( result r in ins) {
729
+ if ( ! is_terminated ( r. bcx ) ) {
730
+ live += r;
731
+ vals += r. val ;
732
+ bbs += r. bcx . llbb ;
733
+ }
734
+ }
735
+
736
+ alt ( _vec. len [ result] ( live) ) {
737
+ case ( 0 u) {
738
+ // No incoming edges are live, so we're in dead-code-land.
739
+ // Arbitrarily pick the first dead edge, since the caller
740
+ // is just going to propagate it outward.
741
+ check ( _vec. len [ result] ( ins) >= 1 u) ;
742
+ ret ins. ( 0 ) ;
743
+ }
744
+
745
+ case ( 1 u) {
746
+ // Only one incoming edge is live, so we just feed that block
747
+ // onward.
748
+ ret live. ( 0 ) ;
749
+ }
750
+ }
751
+
752
+ // We have >1 incoming edges. Make a join block and br+phi them into it.
753
+ auto join_cx = new_sub_block_ctxt ( parent_cx, "join" ) ;
754
+ for ( result r in live) {
755
+ r. bcx . build . Br ( join_cx. llbb ) ;
756
+ }
757
+ auto phi = join_cx. build . Phi ( t, vals, bbs) ;
758
+ ret res( join_cx, phi) ;
759
+ }
760
+
725
761
impure fn trans_if ( @block_ctxt cx , & ast. expr cond ,
726
762
& ast. block thn , & option. t[ ast. block] els ) -> result {
727
763
@@ -730,37 +766,22 @@ impure fn trans_if(@block_ctxt cx, &ast.expr cond,
730
766
auto then_cx = new_sub_block_ctxt ( cx, "then" ) ;
731
767
auto then_res = trans_block ( then_cx, thn) ;
732
768
733
- auto next_cx = new_sub_block_ctxt ( cx, "next" ) ;
734
- then_res. bcx . build . Br ( next_cx. llbb ) ;
735
- auto phi;
769
+ auto else_cx = new_sub_block_ctxt ( cx, "else" ) ;
770
+ auto else_res = res ( else_cx, C_nil ( ) ) ;
736
771
737
772
alt ( els) {
738
773
case ( some[ ast. block ] ( ?eblk) ) {
739
- auto else_cx = new_sub_block_ctxt ( cx, "else" ) ;
740
- auto else_res = trans_block ( else_cx, eblk) ;
741
- cond_res. bcx . build . CondBr ( cond_res. val ,
742
- then_cx. llbb ,
743
- else_cx. llbb ) ;
744
- else_res. bcx . build . Br ( next_cx. llbb ) ;
745
- phi = next_cx. build . Phi ( T_nil ( ) ,
746
- vec ( then_res. val ,
747
- else_res. val ) ,
748
- vec ( then_res. bcx . llbb ,
749
- else_res. bcx . llbb ) ) ;
750
- }
751
-
752
- case ( _) {
753
- cond_res. bcx . build . CondBr ( cond_res. val ,
754
- then_cx. llbb ,
755
- next_cx. llbb ) ;
756
- phi = next_cx. build . Phi ( T_nil ( ) ,
757
- vec ( then_res. val , C_nil ( ) ) ,
758
- vec ( then_res. bcx . llbb ,
759
- cond_res. bcx . llbb ) ) ;
774
+ else_res = trans_block ( else_cx, eblk) ;
760
775
}
761
776
}
762
777
763
- ret res( next_cx, phi) ;
778
+ cond_res. bcx . build . CondBr ( cond_res. val ,
779
+ then_res. bcx . llbb ,
780
+ else_res. bcx . llbb ) ;
781
+
782
+ // FIXME: use inferred type when available.
783
+ ret join_results ( cx, T_nil ( ) ,
784
+ vec ( then_res, else_res) ) ;
764
785
}
765
786
766
787
impure fn trans_while ( @block_ctxt cx , & ast. expr cond ,
0 commit comments