diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fd378bd5267565cb1dc024b7d6c6960cf01694f4..021035c81ac45203ea487270e1709c2dcc13d3c3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
 2017-11-28  Jakub Jelinek  <jakub@redhat.com>
 
+	* tree.def (SWITCH_EXPR): Change from 3 operand to 2 operand tree.
+	Adjust comment.
+	* tree.h (SWITCH_LABELS): Remove.
+	* gimplify.c (gimplify_switch_expr): Don't test SWITCH_LABELS,
+	assert SWITCH_BODY is non-NULL.
+	* tree-pretty-print.c (dump_generic_node): Remove SWITCH_LABELS
+	handling.
+	* tree.c (block_may_fallthru): Always return true; for SWITCH_EXPR.
+
 	PR tree-optimization/80788
 	* match.pd (X +- C1 CMP C2 -> X CMP C2 -+ C1): If res
 	has TREE_OVERFLOW set, call drop_tree_overflow.
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index bf899e2311970f687c3d57cbd428a95970ed29fa..1b51bd631c4576a433666b9a6258d565f1ee5f06 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,8 @@
+2017-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* gcc-interface/trans.c (Case_Statement_to_gnu): Build SWITCH_EXPR
+	using build2 instead of build3.
+
 2017-11-23  Eric Botcazou  <ebotcazou@adacore.com>
 
 	PR ada/83091
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 2544b4c3498c56fa8aa7947ac433ac1f6cc1b670..4739923a09dde8870f6d520f8f078ef98c3f9074 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -2625,8 +2625,7 @@ Case_Statement_to_gnu (Node_Id gnat_node)
   /* Now emit a definition of the label the cases branch to, if any.  */
   if (may_fallthru)
     add_stmt (build1 (LABEL_EXPR, void_type_node, gnu_label));
-  gnu_result
-    = build3 (SWITCH_EXPR, gnu_type, gnu_expr, end_stmt_group (), NULL_TREE);
+  gnu_result = build2 (SWITCH_EXPR, gnu_type, gnu_expr, end_stmt_group ());
 
   return gnu_result;
 }
diff --git a/gcc/brig/ChangeLog b/gcc/brig/ChangeLog
index ba07ca39e36233e9dc5c2080d52350a5c5748fd3..3e8f44330daa3602b9a57ea037e835227f68f342 100644
--- a/gcc/brig/ChangeLog
+++ b/gcc/brig/ChangeLog
@@ -1,3 +1,9 @@
+2017-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* brigfrontend/brig-branch-inst-handler.cc
+	(brig_branch_inst_handler::operator): Build SWITCH_EXPR using build2
+	instead of build3.
+
 2017-11-17  Henry Linjamäki  <henry.linjamaki@parmance.com>
 
 	* brigfrontend/brig-util.cc: Fix sprintf format string type mismatch
diff --git a/gcc/brig/brigfrontend/brig-branch-inst-handler.cc b/gcc/brig/brigfrontend/brig-branch-inst-handler.cc
index 039f1853d4a30739374455860fc21da0e3213dc4..a660698c8a3d1bdd2db3e1bd3605496cc0675f23 100644
--- a/gcc/brig/brigfrontend/brig-branch-inst-handler.cc
+++ b/gcc/brig/brigfrontend/brig-branch-inst-handler.cc
@@ -167,8 +167,8 @@ brig_branch_inst_handler::operator () (const BrigBase *base)
       tree select = operands[0];
       tree cases = operands[1];
 
-      tree switch_expr = build3 (SWITCH_EXPR, TREE_TYPE (select), select,
-				 NULL_TREE, NULL_TREE);
+      tree switch_expr = build2 (SWITCH_EXPR, TREE_TYPE (select), select,
+				 NULL_TREE);
 
       tree default_case
 	= build_case_label (NULL_TREE, NULL_TREE,
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 087a1e7cfaf484875cb72e02fb0743586fd6b5a0..cb1cd308cea401d0daf93c80854eafe639898c56 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,8 @@
+2017-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* c-typeck.c (c_start_case): Build SWITCH_EXPR using build2 instead
+	of build3.
+
 2017-11-14 Boris Kolpackov  <boris@codesynthesis.com>
 
 	* Make-lang.in (c.install-plugin): Install backend import library.
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 7f85c6b216e0de8b5b408a167eb5fa146c70e556..a4d3d39c3d07b8477e1f23b5de07948f25a8c4b3 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -10330,7 +10330,7 @@ c_start_case (location_t switch_loc,
 
   /* Add this new SWITCH_EXPR to the stack.  */
   cs = XNEW (struct c_switch);
-  cs->switch_expr = build3 (SWITCH_EXPR, orig_type, exp, NULL_TREE, NULL_TREE);
+  cs->switch_expr = build2 (SWITCH_EXPR, orig_type, exp, NULL_TREE);
   SET_EXPR_LOCATION (cs->switch_expr, switch_loc);
   cs->orig_type = orig_type;
   cs->cases = splay_tree_new (case_compare, NULL, NULL);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0f91df7d7a7efa50a9bea8270cdf817ade4615d2..13fe545cd1c2ca7a18fcb30570839e2ef7d696d2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2017-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* cp-gimplify.c (genericize_switch_stmt): Build SWITCH_EXPR using
+	build2_loc instead of build3_loc.
+
 2017-11-27  Martin Sebor  <msebor@redhat.com>
 
 	PR c++/83058
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 734b15660b33bce2af6de71bfb5036c2bf63457f..f50aff739a2df3515d94ffa3d3696159245939ab 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -332,7 +332,7 @@ genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data)
   cp_walk_tree (&type, cp_genericize_r, data, NULL);
   *walk_subtrees = 0;
 
-  *stmt_p = build3_loc (stmt_locus, SWITCH_EXPR, type, cond, body, NULL_TREE);
+  *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
   finish_bc_block (stmt_p, bc_break, break_block);
 }
 
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 3278c5bfa600cdbe189787b62a04e6b670b61cc9..7ba781447f9cb80b469507e52657fde4e7251a83 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,11 @@
+2017-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* trans-decl.c (gfc_trans_entry_master_switch): Build SWITCH_EXPR
+	using fold_build2_loc instead of fold_build3_loc.
+	* trans-io.c (io_result): Likewise.
+	* trans-stmt.c (gfc_trans_integer_select, gfc_trans_character_select):
+	Likewise.
+
 2017-11-24  Jakub Jelinek  <jakub@redhat.com>
 
 	PR fortran/81304
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 5c248d06e57803186975ecb882794cd29cab5413..3231fb98e2d20ffcef9bb4a3c5ea8778e6f67a41 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -5758,8 +5758,7 @@ gfc_trans_entry_master_switch (gfc_entry_list * el)
   tmp = gfc_finish_block (&block);
   /* The first argument selects the entry point.  */
   val = DECL_ARGUMENTS (current_function_decl);
-  tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
-			 val, tmp, NULL_TREE);
+  tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, val, tmp);
   return tmp;
 }
 
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 9cd33b331e19d2b76faba4ae31ca5db13133dd95..764766d003fecc7ea9519c1e7cd69edd48b18fb0 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -1002,8 +1002,7 @@ io_result (stmtblock_t * block, tree var, gfc_st_label * err_label,
 			rc, build_int_cst (TREE_TYPE (rc),
 					   IOPARM_common_libreturn_mask));
 
-  tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
-			 rc, tmp, NULL_TREE);
+  tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, rc, tmp);
 
   gfc_add_expr_to_block (block, tmp);
 }
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 96ca21756742514d635bbe45678a917a05d10d47..df29b78e3f189ff275e413218ab79cb6beca5c37 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -2666,8 +2666,7 @@ gfc_trans_integer_select (gfc_code * code)
     }
 
   tmp = gfc_finish_block (&body);
-  tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
-			 se.expr, tmp, NULL_TREE);
+  tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, se.expr, tmp);
   gfc_add_expr_to_block (&block, tmp);
 
   tmp = build1_v (LABEL_EXPR, end_label);
@@ -2952,8 +2951,8 @@ gfc_trans_character_select (gfc_code *code)
 	  gfc_add_block_to_block (&block, &expr1se.post);
 
 	  tmp = gfc_finish_block (&body);
-	  tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
-				 case_num, tmp, NULL_TREE);
+	  tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
+				 case_num, tmp);
 	  gfc_add_expr_to_block (&block, tmp);
 
 	  tmp = build1_v (LABEL_EXPR, end_label);
@@ -3099,8 +3098,8 @@ gfc_trans_character_select (gfc_code *code)
   gfc_add_block_to_block (&block, &expr1se.post);
 
   tmp = gfc_finish_block (&body);
-  tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
-			 case_num, tmp, NULL_TREE);
+  tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
+			 case_num, tmp);
   gfc_add_expr_to_block (&block, tmp);
 
   tmp = build1_v (LABEL_EXPR, end_label);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 13dbbe0538d2faa9ce51f43e04930038eb9b11ca..8769505b313cefa61ef34c051d2c24338e078690 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2287,10 +2287,6 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
       tree default_case = NULL_TREE;
       gswitch *switch_stmt;
 
-      /* If someone can be bothered to fill in the labels, they can
-	 be bothered to null out the body too.  */
-      gcc_assert (!SWITCH_LABELS (switch_expr));
-
       /* Save old labels, get new ones from body, then restore the old
          labels.  Save all the things from the switch body to append after.  */
       saved_labels = gimplify_ctxp->case_labels;
@@ -2347,7 +2343,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
       labels.release ();
     }
   else
-    gcc_assert (SWITCH_LABELS (switch_expr));
+    gcc_unreachable ();
 
   return GS_ALL_DONE;
 }
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 947f49cd48bf55ce5ccf953340b71e46c0d05c2f..01af4678684ab862efa8c0f4e74e996ecc553cd6 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,8 @@
+2017-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* go-gcc.cc (Gcc_backend::switch_statement): Build SWITCH_EXPR using
+	build2_loc instead of build3_loc.
+
 2017-11-14  Than McIntosh  <thanm@google.com>
 
 	* go-gcc.cc (var_expression): Remove Varexpr_context parameter.
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index a50abdd856b8457b4ccbe4655f04b524fc1d2fbc..1b0190d954ba136f533ec594781ffa0c14848682 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -2289,8 +2289,8 @@ Gcc_backend::switch_statement(
   tree tv = value->get_tree();
   if (tv == error_mark_node)
     return this->error_statement();
-  tree t = build3_loc(switch_location.gcc_location(), SWITCH_EXPR,
-                      NULL_TREE, tv, stmt_list, NULL_TREE);
+  tree t = build2_loc(switch_location.gcc_location(), SWITCH_EXPR,
+                      NULL_TREE, tv, stmt_list);
   return this->make_statement(t);
 }
 
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index 35f210841163cb0df92977826105ac6094b26724..afa53791d798274941b2ab3f6024320bb11a1cf5 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -1,3 +1,8 @@
+2017-11-28  Jakub Jelinek  <jakub@redhat.com>
+
+	* jit-playback.c (add_switch): Build SWITCH_EXPR using build2 instead
+	of build3.  Formatting fixes.  Adjust funciton comment.
+
 2017-11-23  Tom de Vries  <tom@codesourcery.com>
 
 	* libgccjit.c (RETURN_NULL_IF_FAIL_NONNULL_NUMERIC_TYPE): Wrap in
diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c
index 95126c94393c0896234b3187e089cf118fa7660b..fe9fb2d8bc29cb2cb5adde978417401c029d41b9 100644
--- a/gcc/jit/jit-playback.c
+++ b/gcc/jit/jit-playback.c
@@ -1689,12 +1689,7 @@ add_case (tree *ptr_t_switch_body,
 
 /* Add a switch statement to the function's statement list.
 
-   My initial attempt at implementing this constructed a TREE_VEC
-   of the cases and set it as SWITCH_LABELS (switch_expr).  However,
-   gimplify.c:gimplify_switch_expr is set up to deal with SWITCH_BODY, and
-   doesn't have any logic for gimplifying SWITCH_LABELS.
-
-   Hence we create a switch body, and populate it with case labels, each
+   We create a switch body, and populate it with case labels, each
    followed by a goto to the desired block.  */
 
 void
@@ -1722,18 +1717,12 @@ add_switch (location *loc,
     {
       tree t_low_value = c->m_min_value->as_tree ();
       tree t_high_value = c->m_max_value->as_tree ();
-      add_case (&t_switch_body,
-		t_low_value,
-		t_high_value,
-		c->m_dest_block);
+      add_case (&t_switch_body, t_low_value, t_high_value, c->m_dest_block);
     }
   /* Default label. */
-  add_case (&t_switch_body,
-	    NULL_TREE, NULL_TREE,
-	    default_block);
+  add_case (&t_switch_body, NULL_TREE, NULL_TREE, default_block);
 
-  tree switch_stmt = build3 (SWITCH_EXPR, t_type, t_expr,
-			     t_switch_body, NULL_TREE);
+  tree switch_stmt = build2 (SWITCH_EXPR, t_type, t_expr, t_switch_body);
   if (loc)
     set_tree_location (switch_stmt, loc);
   add_stmt (switch_stmt);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index c9a3e6360e0337808549481eb86b7afd129d8b04..1cdec69314dec5bf99bc23f6bacab4d1dbce6ebe 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -2686,26 +2686,6 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
 	      dump_generic_node (pp, SWITCH_BODY (node), spc+4, flags,
 		                 true);
 	    }
-	  else
-	    {
-	      tree vec = SWITCH_LABELS (node);
-	      size_t i, n = TREE_VEC_LENGTH (vec);
-	      for (i = 0; i < n; ++i)
-		{
-		  tree elt = TREE_VEC_ELT (vec, i);
-		  newline_and_indent (pp, spc+4);
-		  if (elt)
-		    {
-		      dump_generic_node (pp, elt, spc+4, flags, false);
-		      pp_string (pp, " goto ");
-		      dump_generic_node (pp, CASE_LABEL (elt), spc+4,
-					 flags, true);
-		      pp_semicolon (pp);
-		    }
-		  else
-		    pp_string (pp, "case ???: goto ???;");
-		}
-	    }
 	  newline_and_indent (pp, spc+2);
 	  pp_right_brace (pp);
 	}
diff --git a/gcc/tree.c b/gcc/tree.c
index c328b1345c074e26e02f5b6fc2efa57f47fdcb80..da2db7ae9bf452c9ec9f213740ba2c75721c69ec 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -12351,11 +12351,7 @@ block_may_fallthru (const_tree block)
       return false;
 
     case SWITCH_EXPR:
-      /* If SWITCH_LABELS is set, this is lowered, and represents a
-	 branch to a selected label and hence can not fall through.
-	 Otherwise SWITCH_BODY is set, and the switch can fall
-	 through.  */
-      return SWITCH_LABELS (stmt) == NULL_TREE;
+      return true;
 
     case COND_EXPR:
       if (block_may_fallthru (COND_EXPR_THEN (stmt)))
diff --git a/gcc/tree.def b/gcc/tree.def
index 7523f5747bf4a2729e2b6b53889ddb1d33990598..9b6e06fba8c08c2919e56adddf1712e4c1c50207 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -943,10 +943,8 @@ DEFTREECODE (LOOP_EXPR, "loop_expr", tcc_statement, 1)
    Operand 0 is the expression used to perform the branch,
    Operand 1 is the body of the switch, which probably contains
      CASE_LABEL_EXPRs.  It may also be NULL, in which case operand 2
-     must not be NULL.
-   Operand 2 is either NULL_TREE or a TREE_VEC of the CASE_LABEL_EXPRs
-     of all the cases.  */
-DEFTREECODE (SWITCH_EXPR, "switch_expr", tcc_statement, 3)
+     must not be NULL.  */
+DEFTREECODE (SWITCH_EXPR, "switch_expr", tcc_statement, 2)
 
 /* Used to represent a case label.
 
diff --git a/gcc/tree.h b/gcc/tree.h
index c2cabfc752938097590c695987aaf54cdea983e1..68c5b2c4bd2520a2491f7a8a297ad5a709dd2785 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1172,12 +1172,9 @@ extern void protected_set_expr_location (tree, location_t);
 #define COMPOUND_LITERAL_EXPR_DECL(NODE)			\
   DECL_EXPR_DECL (COMPOUND_LITERAL_EXPR_DECL_EXPR (NODE))
 
-/* SWITCH_EXPR accessors. These give access to the condition, body and
-   original condition type (before any compiler conversions)
-   of the switch statement, respectively.  */
+/* SWITCH_EXPR accessors. These give access to the condition and body.  */
 #define SWITCH_COND(NODE)       TREE_OPERAND (SWITCH_EXPR_CHECK (NODE), 0)
 #define SWITCH_BODY(NODE)       TREE_OPERAND (SWITCH_EXPR_CHECK (NODE), 1)
-#define SWITCH_LABELS(NODE)     TREE_OPERAND (SWITCH_EXPR_CHECK (NODE), 2)
 
 /* CASE_LABEL_EXPR accessors. These give access to the high and low values
    of a case label, respectively.  */