diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index fed5802..76cfe48 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -2293,6 +2293,47 @@ pp_c_expression (c_pretty_printer *pp, tree e)
       pp_c_expression (pp, C_MAYBE_CONST_EXPR_EXPR (e));
       break;
 
+    CASE_CCMP_ANDIF:
+    CASE_CCMP_ORIF:
+      {
+	enum tree_code ncode, icode;
+	ncode = get_code_from_ccompare_expr (&icode, TREE_CODE (e));
+	pp_c_left_paren (pp);
+	pp_c_expression (pp, TREE_OPERAND (e, 2));
+        if (icode == BIT_AND_EXPR)
+	  pp_string (pp, " ?&& ");
+        else
+	  pp_string (pp, " ?|| ");
+	pp_c_expression (pp, TREE_OPERAND (e, 0));
+	switch (ncode)
+	  {
+	  case NE_EXPR:
+	    pp_string (pp, " != ");
+	    break;
+	  case EQ_EXPR:
+	    pp_string (pp, " == ");
+	    break;
+	  case LT_EXPR:
+	    pp_string (pp, " < ");
+	    break;
+	  case LE_EXPR:
+	    pp_string (pp, " <= ");
+	    break;
+	  case GT_EXPR:
+	    pp_string (pp, " > ");
+	    break;
+	  case GE_EXPR:
+	    pp_string (pp, " >= ");
+	    break;
+	  default:
+	    pp_unsupported_tree (pp, e);
+	    break;
+	  }
+	pp_c_expression (pp, TREE_OPERAND (e, 1));
+	pp_c_right_paren (pp);
+      }
+      break;
+
     default:
       pp_unsupported_tree (pp, e);
       break;
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index a7d9170..02cc830 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2747,7 +2747,7 @@ expand_debug_expr (tree exp)
 	  break;
 	}
       break;
-
+    case tcc_ccomparison:
     ternary:
       op2 = expand_debug_expr (TREE_OPERAND (exp, 2));
       if (!op2)
@@ -3306,6 +3306,11 @@ expand_debug_expr (tree exp)
     case TRUTH_AND_EXPR:
       return simplify_gen_binary (AND, mode, op0, op1);
 
+    CASE_CCMP_ANDIF:
+    CASE_CCMP_ORIF:
+      /* TBD.  */
+      return NULL_RTX;
+
     case BIT_IOR_EXPR:
     case TRUTH_OR_EXPR:
       return simplify_gen_binary (IOR, mode, op0, op1);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 440169a..ca12bcf 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2572,6 +2572,25 @@ dump_expr (tree t, int flags)
       pp_cxx_right_paren (cxx_pp);
       break;
 
+    CASE_CCMP_ANDIF:
+    CASE_CCMP_ORIF:
+      {
+	enum tree_code ncode, icode;
+	ncode = get_code_from_ccompare_expr (&icode, TREE_CODE (t));
+	pp_cxx_left_paren (cxx_pp);
+	dump_expr (TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS);
+        if (icode == BIT_AND_EXPR)
+	  pp_string (cxx_pp, " ?&& ");
+        else
+	  pp_string (cxx_pp, " ?|| ");
+	dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+	pp_space (cxx_pp);
+	pp_string (cxx_pp, operator_name_info [(int) ncode].name);
+	pp_space (cxx_pp);
+	dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
+	pp_cxx_right_paren (cxx_pp);
+      }
+      break;
       /*  This list is incomplete, but should suffice for now.
 	  It is very important that `sorry' does not call
 	  `report_error_function'.  That could cause an infinite loop.  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3bc09b9..54b5c72 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7272,6 +7272,45 @@ cxx_eval_logical_expression (const constexpr_call *call, tree t,
   return r;
 }
 
+/* Subroutine of cxx_eval_constant_expression.
+   Evaluate a conditional compare expression T in the context
+   of a given constexpr CALL.  BAILOUT_VALUE is the value for
+   early return.  CONTINUE_VALUE is used here purely for
+   sanity check purposes.  */
+
+static tree
+cxx_eval_ccmp_expression (const constexpr_call *call, tree t,
+			  tree bailout_value, tree continue_value,
+			  bool allow_non_constant, bool addr,
+			  bool *non_constant_p, bool *overflow_p)
+{
+  tree r;
+  tree orig_lhs = TREE_OPERAND (t, 0);
+  tree orig_rhs = TREE_OPERAND (t, 1);
+  tree op0, op1;
+  tree op2 = cxx_eval_constant_expression (call, TREE_OPERAND (t, 2),
+					   allow_non_constant, addr,
+					   non_constant_p, overflow_p);
+  VERIFY_CONSTANT (op2);
+  if (tree_int_cst_equal (op2, bailout_value))
+    return op2;
+  gcc_assert (tree_int_cst_equal (op2, continue_value));
+
+  op0 = cxx_eval_constant_expression (call, orig_lhs,
+				      allow_non_constant, addr,
+				      non_constant_p, overflow_p);
+  VERIFY_CONSTANT (op0);
+  op1 = cxx_eval_constant_expression (call, orig_rhs,
+				      allow_non_constant, addr,
+				      non_constant_p, overflow_p);
+  VERIFY_CONSTANT (op1);
+  if (op0 == orig_lhs && op1 == orig_rhs)
+    return t;
+  r = fold_build3 (TREE_CODE (t), TREE_TYPE (t), op0, op1, op2);
+  VERIFY_CONSTANT (r);
+  return r;
+}
+
 /* REF is a COMPONENT_REF designating a particular field.  V is a vector of
    CONSTRUCTOR elements to initialize (part of) an object containing that
    field.  Return a pointer to the constructor_elt corresponding to the
@@ -8074,6 +8113,20 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
 				       non_constant_p, overflow_p);
       break;
 
+    CASE_CCMP_ANDIF:
+      r = cxx_eval_ccmp_expression (call, t, boolean_false_node,
+				    boolean_false_node,
+				    allow_non_constant, addr,
+				    non_constant_p, overflow_p);
+      break;
+
+    CASE_CCMP_ORIF:
+      r = cxx_eval_ccmp_expression (call, t, boolean_true_node,
+				    boolean_false_node,
+				    allow_non_constant, addr,
+				    non_constant_p, overflow_p);
+      break;
+
     case ARRAY_REF:
       r = cxx_eval_array_reference (call, t, allow_non_constant, addr,
 				    non_constant_p, overflow_p);
@@ -8687,6 +8740,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case GE_EXPR:
     case EQ_EXPR:
     case NE_EXPR:
+    compare:
       /* -- a relational or equality operator where at least
             one of the operands is a pointer.  */
       if (TYPE_PTR_P (TREE_OPERAND (t, 0))
@@ -8941,6 +8995,29 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       return false;
 
     default:
+      if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_ccomparison)
+	{
+	  /* If the third operand is a constant, look at the compare between
+	     the first and second operand.  */
+	  tree op;
+	  enum tree_code icode;
+	  get_code_from_ccompare_expr (&icode, TREE_CODE (t));
+	  if (icode == BIT_AND_EXPR)
+	    tmp = boolean_true_node;
+	  else
+	    tmp = boolean_false_node;
+
+	  op = TREE_OPERAND (t, 2);
+	  if (!potential_constant_expression_1 (op, rval, flags))
+	    return false;
+	  if (!processing_template_decl)
+	    op = cxx_eval_outermost_constant_expr (op, true);
+
+	  if (tree_int_cst_equal (op, tmp))
+	    goto compare;
+	  else
+	    return true;
+	}
       if (objc_is_property_ref (t))
 	return false;
 
diff --git a/gcc/expr.c b/gcc/expr.c
index bbe0401..611787d 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7195,6 +7195,7 @@ safe_from_p (const_rtx x, tree exp, int top_p)
 
     case tcc_binary:
     case tcc_comparison:
+    case tcc_ccomparison:
       if (!safe_from_p (x, TREE_OPERAND (exp, 1), 0))
 	return 0;
       /* Fall through.  */
@@ -7967,6 +7968,30 @@ expand_cond_expr_using_cmove (tree treeop0 ATTRIBUTE_UNUSED,
   return NULL_RTX;
 }
 
+#ifdef HAVE_conditional_compare
+/* Expand conditional compare OPS to AND/IOR epxoresstion.  */
+static rtx
+expand_ccmp_to_bitop (sepops ops, rtx target, enum machine_mode tmode,
+		      enum expand_modifier modifier)
+{
+  tree cmp, bit_op;
+  enum tree_code ncode;
+  location_t loc = ops->location;
+  enum tree_code code = ops->code;
+  tree treeop0, treeop1, treeop2;
+  treeop0 = ops->op0;
+  treeop1 = ops->op1;
+  treeop2 = ops->op2;
+
+  code = get_code_from_ccompare_expr (&ncode, code);
+  cmp = fold_build2_loc (loc, code, TREE_TYPE (treeop2),
+			 treeop0, treeop1);
+  bit_op = fold_build2_loc (loc, ncode, TREE_TYPE (treeop2),
+			    treeop2, cmp);
+  return expand_expr (bit_op, target, tmode, modifier);
+}
+#endif
+
 rtx
 expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 		    enum expand_modifier modifier)
@@ -8840,6 +8865,12 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 	temp = REDUCE_BIT_FIELD (temp);
       return temp;
 
+#ifdef HAVE_conditional_compare
+    CASE_CCMP_ANDIF:
+    CASE_CCMP_ORIF:
+      return expand_ccmp_to_bitop (ops, target, tmode, modifier);
+#endif
+
       /* Could determine the answer when only additive constants differ.  Also,
 	 the addition of one can be handled by changing the condition.  */
     case LT_EXPR:
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 6506ae7..fa46e96 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8640,6 +8640,41 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type,
   if ((tem = fold_truth_andor_1 (loc, code, type, arg0, arg1)) != 0)
     return tem;
 
+#ifdef HAVE_conditional_compare
+  /*  Generate conditional compare for SHORT_CIRCUIT.  */
+  if (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
+    {
+      /* Convert TRUTH_[AND|OR]IF_EXPR to CONDITIONAL_COMPARE_EXPR.  */
+      enum tree_code code0 = TREE_CODE (arg0);
+      enum tree_code code1 = TREE_CODE (arg1);
+
+      if ((TREE_CODE_CLASS (code1) == tcc_comparison)
+	  && (TREE_CODE_CLASS (code0) == tcc_comparison)
+          && simple_operand_p_2 (arg1)
+	  && simple_operand_p_2 (arg0))
+	{
+	  enum tree_code ncode = generate_ccompare_code (code, code1);
+	  if ((ncode != MAX_TREE_CODES)
+	      && (TREE_CODE (TREE_TYPE (TREE_OPERAND (arg1, 0)))
+		  !=  COMPLEX_TYPE))
+	    {
+	      tem = fold_build3_loc (loc, ncode, type,
+				     TREE_OPERAND (arg1, 0),
+				     TREE_OPERAND (arg1, 1), arg0);
+	      if (tem)
+		return tem;
+	    }
+	}
+#if 0
+      /* TBD: handle case: [AND|OR]-IF (CCMP1, CCMP2).  */
+      else if ((TREE_CODE_CLASS (code1) == tcc_ccomparison)
+		&& (simple_operand_p_2 (TREE_OPERAND (arg1, 2)))
+		&& simple_operand_p_2 (TREE_OPERAND (arg0, 1)))
+	{
+	}
+#endif
+    }
+#endif
   if (LOGICAL_OP_NON_SHORT_CIRCUIT
       && (code == TRUTH_AND_EXPR
           || code == TRUTH_ANDIF_EXPR
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 1d40680..e5d2403 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -388,6 +388,33 @@ dump_binary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
     }
 }
 
+/* Helper for dump_gimple_assign.  Print the conditional compare RHS of the
+   assignment GS.  BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.  */
+
+static void
+dump_ccomparison_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+  enum tree_code code, ncode, icode;
+  code = gimple_assign_rhs_code (gs);
+  ncode = get_code_from_ccompare_expr (&icode, code);
+  dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false);
+  pp_space (buffer);
+  if (icode == BIT_AND_EXPR)
+    pp_string (buffer, "?&&");
+  else
+    pp_string (buffer, "?||");
+  pp_space (buffer);
+  dump_generic_node (buffer, gimple_assign_rhs1 (gs), spc, flags, false);
+  pp_space (buffer);
+  pp_string (buffer, op_symbol_code (ncode));
+  pp_space (buffer);
+  dump_generic_node (buffer, gimple_assign_rhs2 (gs), spc, flags, false);
+  pp_space (buffer);
+  pp_character (buffer, ':');
+  pp_space (buffer);
+  dump_generic_node (buffer, gimple_assign_rhs3 (gs), spc, flags, false);
+}
+
 /* Helper for dump_gimple_assign.  Print the ternary RHS of the
    assignment GS.  BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1.  */
 
@@ -522,6 +549,9 @@ dump_gimple_assign (pretty_printer *buffer, gimple gs, int spc, int flags)
         dump_unary_rhs (buffer, gs, spc, flags);
       else if (gimple_num_ops (gs) == 3)
         dump_binary_rhs (buffer, gs, spc, flags);
+      else if (TREE_CODE_CLASS (gimple_assign_rhs_code (gs))
+	       == tcc_ccomparison)
+	dump_ccomparison_rhs (buffer, gs, spc, flags);
       else if (gimple_num_ops (gs) == 4)
         dump_ternary_rhs (buffer, gs, spc, flags);
       else
diff --git a/gcc/gimple.c b/gcc/gimple.c
index f507419..486e2f1 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -2525,6 +2525,7 @@ get_gimple_rhs_num_ops (enum tree_code code)
       || (SYM) == VEC_COND_EXPR						    \
       || (SYM) == VEC_PERM_EXPR                                             \
       || (SYM) == FMA_EXPR) ? GIMPLE_TERNARY_RHS			    \
+   : (TYPE) == tcc_ccomparison ? GIMPLE_TERNARY_RHS			    \
    : ((SYM) == CONSTRUCTOR						    \
       || (SYM) == OBJ_TYPE_REF						    \
       || (SYM) == ASSERT_EXPR						    \
@@ -2898,6 +2899,7 @@ recalculate_side_effects (tree t)
       /* Fall through.  */
 
     case tcc_comparison:  /* a comparison expression */
+    case tcc_ccomparison:  /* a conditional comparison expression.  */
     case tcc_unary:       /* a unary arithmetic expression */
     case tcc_binary:      /* a binary arithmetic expression */
     case tcc_reference:   /* a reference */
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 4d39d53..e1784af 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -3054,6 +3054,13 @@ gimple_boolify (tree expr)
 	    TREE_TYPE (expr) = boolean_type_node;
 	  return expr;
 	}
+      if (CCOMPARISON_CLASS_P (expr))
+	{
+	  /* There expressions always prduce boolean results.  */
+	  TREE_TYPE (expr) = boolean_type_node;
+	  TREE_OPERAND (expr, 2) = gimple_boolify (TREE_OPERAND (expr, 2));
+	  return expr;
+	}
       /* Other expressions that get here must have boolean values, but
 	 might need to be converted to the appropriate mode.  */
       if (TREE_CODE (type) == BOOLEAN_TYPE)
@@ -6756,6 +6763,7 @@ goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
     {
     case tcc_binary:
     case tcc_comparison:
+    case tcc_ccomparison:
       saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
 				     lhs_var);
     case tcc_unary:
@@ -7784,6 +7792,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 		break;
 	      }
 
+	    case tcc_ccomparison:
 	    expr_3:
 	      {
 		enum gimplify_status r0, r1, r2;
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index ee72f7f..886f09c 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -5280,7 +5280,7 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
 {
   basic_block bb;
   int regno, sregno, prev_sregno, dregno, restore_regno;
-  rtx set, prev_set, prev_insn;
+  rtx set = NULL_RTX, prev_set, prev_insn;
   bool change_p, done_p;
 
   change_p = ! bitmap_empty_p (remove_pseudos);
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 029c3a2..7f76e83 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -690,6 +690,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
 
     case tcc_expression:
     case tcc_comparison:
+    case tcc_ccomparison:
     case tcc_unary:
     case tcc_binary:
     case tcc_reference:
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index af8685c..20d39de 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3182,12 +3182,10 @@ verify_gimple_call (gimple stmt)
 
   return false;
 }
-
-/* Verifies the gimple comparison with the result type TYPE and
-   the operands OP0 and OP1.  */
+/* Verifies the gimple comparison with the operands OP0 and OP1.  */
 
 static bool
-verify_gimple_comparison (tree type, tree op0, tree op1)
+verify_gimple_comparison_operands (tree op0, tree op1)
 {
   tree op0_type = TREE_TYPE (op0);
   tree op1_type = TREE_TYPE (op1);
@@ -3215,6 +3213,20 @@ verify_gimple_comparison (tree type, tree op0, tree op1)
       debug_generic_expr (op1_type);
       return true;
     }
+  return false;
+}
+
+/* Verifies the gimple comparison with the result type TYPE and
+   the operands OP0 and OP1.  */
+
+static bool
+verify_gimple_comparison (tree type, tree op0, tree op1)
+{
+  tree op0_type = TREE_TYPE (op0);
+  tree op1_type = TREE_TYPE (op1);
+
+  if (verify_gimple_comparison_operands (op0, op1))
+    return true;
 
   /* The resulting type of a comparison may be an effective boolean type.  */
   if (INTEGRAL_TYPE_P (type)
@@ -3842,6 +3854,18 @@ verify_gimple_assign_ternary (gimple stmt)
       /* FIXME.  */
       return false;
 
+    CASE_CCMP_ANDIF:
+    CASE_CCMP_ORIF:
+      if (!useless_type_conversion_p (lhs_type, rhs3_type))
+	{
+	  error ("type mismatch in conditinal compare expression");
+	  debug_generic_stmt (lhs_type);
+	  debug_generic_stmt (rhs3_type);
+	  return true;
+	}
+
+      return verify_gimple_comparison_operands (rhs1, rhs2);
+
     default:
       gcc_unreachable ();
     }
diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c
index 12a2be7..ef4ab15 100644
--- a/gcc/tree-dump.c
+++ b/gcc/tree-dump.c
@@ -339,6 +339,12 @@ dequeue_and_dump (dump_info_p di)
 	  dump_child ("op 1", TREE_OPERAND (t, 1));
 	  break;
 
+	case tcc_ccomparison:
+	  dump_child ("op 0", TREE_OPERAND (t, 0));
+	  dump_child ("op 1", TREE_OPERAND (t, 1));
+	  dump_child ("op 2", TREE_OPERAND (t, 2));
+	  break;
+
 	case tcc_expression:
 	case tcc_reference:
 	case tcc_statement:
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 00e3198..ef47f00 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3505,6 +3505,8 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
     case GE_EXPR:
     case EQ_EXPR:
     case NE_EXPR:
+    CASE_CCMP_ANDIF:
+    CASE_CCMP_ORIF:
     case ORDERED_EXPR:
     case UNORDERED_EXPR:
 
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index f00ac4c..a7802ee 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1523,6 +1523,25 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
 	}
       break;
 
+    CASE_CCMP_ANDIF:
+    CASE_CCMP_ORIF:
+      {
+	enum tree_code ncode, icode;
+	ncode = get_code_from_ccompare_expr (&icode, code);
+	dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
+	if (icode == BIT_AND_EXPR)
+	  pp_string (buffer, " ?&& ");
+	else
+	  pp_string (buffer, " ?|| ");
+	dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+	pp_space (buffer);
+	pp_string (buffer, op_symbol_code (ncode));
+	pp_space (buffer);
+	dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+	pp_string (buffer, " : ");
+	dump_generic_node (buffer, TREE_OPERAND (node, 2), spc, flags, false);
+      }
+      break;
     case BIND_EXPR:
       pp_left_brace (buffer);
       if (!(flags & TDF_SLIM))
@@ -2597,10 +2616,12 @@ op_code_prio (enum tree_code code)
 
     case TRUTH_OR_EXPR:
     case TRUTH_ORIF_EXPR:
+    CASE_CCMP_ORIF:
       return 4;
 
     case TRUTH_AND_EXPR:
     case TRUTH_ANDIF_EXPR:
+    CASE_CCMP_ANDIF:
       return 5;
 
     case BIT_IOR_EXPR:
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 9d6f9ef..e3bf8ab 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -2186,6 +2186,11 @@ get_val_for (tree x, tree base)
       return fold_build2 (gimple_assign_rhs_code (stmt),
 			  gimple_expr_type (stmt), rhs1, rhs2);
     }
+  else if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_ccomparison)
+    {
+      /* TBD.  */
+      return chrec_dont_know;
+    }
   else
     gcc_unreachable ();
 }
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 0915080..19839f2 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -851,6 +851,7 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
     case WIDEN_MULT_PLUS_EXPR:
     case WIDEN_MULT_MINUS_EXPR:
     case FMA_EXPR:
+    do_ternary:
       {
 	get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
 	get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
@@ -870,6 +871,8 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
 	goto do_unary;
       if (codeclass == tcc_binary || codeclass == tcc_comparison)
 	goto do_binary;
+      if (codeclass == tcc_ccomparison)
+	goto do_ternary;
       if (codeclass == tcc_constant || codeclass == tcc_type)
 	return;
     }
diff --git a/gcc/tree.c b/gcc/tree.c
index a1c0dea..cc6987a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -310,6 +310,7 @@ tree_node_structure_for_code (enum tree_code code)
       return TS_TYPE_NON_COMMON;
     case tcc_reference:
     case tcc_comparison:
+    case tcc_ccomparison:
     case tcc_unary:
     case tcc_binary:
     case tcc_expression:
@@ -657,6 +658,7 @@ tree_code_size (enum tree_code code)
     case tcc_expression:  /* an expression */
     case tcc_statement:   /* an expression with side effects */
     case tcc_comparison:  /* a comparison expression */
+    case tcc_ccomparison:  /* a conditional comparison expression.  */
     case tcc_unary:       /* a unary arithmetic expression */
     case tcc_binary:      /* a binary arithmetic expression */
       return (sizeof (struct tree_exp)
@@ -775,6 +777,7 @@ record_node_allocation_statistics (enum tree_code code ATTRIBUTE_UNUSED,
 
     case tcc_expression:  /* an expression */
     case tcc_comparison:  /* a comparison expression */
+    case tcc_ccomparison:  /* a conditional comparison expression.  */
     case tcc_unary:  /* a unary arithmetic expression */
     case tcc_binary:  /* a binary arithmetic expression */
       kind = e_kind;
@@ -3149,6 +3152,7 @@ contains_placeholder_p (const_tree exp)
     case tcc_unary:
     case tcc_binary:
     case tcc_comparison:
+    case tcc_ccomparison:
     case tcc_expression:
       switch (code)
 	{
@@ -3370,6 +3374,7 @@ find_placeholder_in_expr (tree exp, vec<tree> *refs)
       case tcc_unary:
       case tcc_binary:
       case tcc_comparison:
+      case tcc_ccomparison:
       case tcc_reference:
 	for (i = 0; i < TREE_CODE_LENGTH (code); i++)
 	  FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs);
@@ -3459,6 +3464,7 @@ substitute_in_expr (tree exp, tree f, tree r)
       case tcc_unary:
       case tcc_binary:
       case tcc_comparison:
+      case tcc_ccomparison:
       case tcc_reference:
 	switch (TREE_CODE_LENGTH (code))
 	  {
@@ -3639,6 +3645,7 @@ substitute_placeholder_in_expr (tree exp, tree obj)
       case tcc_unary:
       case tcc_binary:
       case tcc_comparison:
+      case tcc_ccomparison:
       case tcc_expression:
       case tcc_reference:
       case tcc_statement:
@@ -3853,6 +3860,7 @@ stabilize_reference_1 (tree e)
     case tcc_type:
     case tcc_declaration:
     case tcc_comparison:
+    case tcc_ccomparison:
     case tcc_statement:
     case tcc_expression:
     case tcc_reference:
@@ -4106,6 +4114,7 @@ build2_stat (enum tree_code code, tree tt, tree arg0, tree arg1 MEM_STAT_DECL)
   /* Expressions without side effects may be constant if their
      arguments are as well.  */
   constant = (TREE_CODE_CLASS (code) == tcc_comparison
+	      || TREE_CODE_CLASS (code) == tcc_ccomparison
 	      || TREE_CODE_CLASS (code) == tcc_binary);
   read_only = 1;
   side_effects = TREE_SIDE_EFFECTS (t);
@@ -7077,6 +7086,7 @@ simple_cst_equal (const_tree t1, const_tree t2)
     case tcc_unary:
     case tcc_binary:
     case tcc_comparison:
+    case tcc_ccomparison:
     case tcc_expression:
     case tcc_reference:
     case tcc_statement:
@@ -12063,4 +12073,57 @@ contains_bitfld_component_ref_p (const_tree ref)
   return false;
 }
 
+/* Separte conditional compare code CODE to two codes.
+   ICODE will be BIT_AND_EXPR or BIT_IOR_EXPR.
+   It returns the compare expr code beween subop1 and subop2.  */
+enum tree_code get_code_from_ccompare_expr (enum tree_code *icode,
+					    enum tree_code code)
+{
+  enum tree_code ncode;
+  int offset = TRUTH_ANDIF_LT_EXPR - LT_EXPR;
+  switch (code)
+    {
+    CASE_CCMP_ORIF:
+      offset += offset;
+      ncode = (enum tree_code) (code - offset);
+      *icode = BIT_IOR_EXPR;
+      break;
+    CASE_CCMP_ANDIF:
+      ncode = (enum tree_code) (code - offset);
+      *icode = BIT_AND_EXPR;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  return ncode;
+}
+
+/*  Generate conditional compare code from CODE and CMPCODE.
+    For TRUTH_ANDIF_EXPR or BIT_AND_EXPR, it returns TRUTH_ANDIF_CMP_EXPR;
+    For TRUTH_ORIF_EXPR or BIT_IOR_EXPR, it returns TRUTH_ORIF_CMP_EXPR.  */
+enum tree_code generate_ccompare_code (enum tree_code code,
+				       enum tree_code cmpcode)
+{
+  enum tree_code ncode;
+  int offset;
+
+  /*  TBD: Maybe extend to all compare.  */
+  if (cmpcode < LT_EXPR || cmpcode > NE_EXPR)
+    return MAX_TREE_CODES;
+
+  offset = TRUTH_ANDIF_LT_EXPR - LT_EXPR;
+  if (code == TRUTH_ANDIF_EXPR
+      || code == BIT_AND_EXPR)
+    {
+      ncode = (enum tree_code) (cmpcode + offset);
+    }
+  else
+    {
+      gcc_assert (code == TRUTH_ORIF_EXPR
+		  || code == BIT_IOR_EXPR);
+      ncode = (enum tree_code) (cmpcode + offset + offset);
+    }
+  return ncode;
+}
+
 #include "gt-tree.h"
diff --git a/gcc/tree.def b/gcc/tree.def
index da30074..2f9b941 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -736,13 +736,28 @@ DEFTREECODE (TRUTH_NOT_EXPR, "truth_not_expr", tcc_expression, 1)
    and the value is either the type used by the language for booleans
    or an integer vector type of the same size and with the same number
    of elements as the comparison operands.  True for a vector of
-   comparison results has all bits set while false is equal to zero.  */
+   comparison results has all bits set while false is equal to zero.
+
+   The ordering of the following codes is optimized for convertion.
+   Keep them in a consecutive group.  */
 DEFTREECODE (LT_EXPR, "lt_expr", tcc_comparison, 2)
 DEFTREECODE (LE_EXPR, "le_expr", tcc_comparison, 2)
 DEFTREECODE (GT_EXPR, "gt_expr", tcc_comparison, 2)
 DEFTREECODE (GE_EXPR, "ge_expr", tcc_comparison, 2)
 DEFTREECODE (EQ_EXPR, "eq_expr", tcc_comparison, 2)
 DEFTREECODE (NE_EXPR, "ne_expr", tcc_comparison, 2)
+DEFTREECODE (TRUTH_ANDIF_LT_EXPR, "truth_andif_lt_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ANDIF_LE_EXPR, "truth_andif_le_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ANDIF_GT_EXPR, "truth_andif_gt_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ANDIF_GE_EXPR, "truth_andif_ge_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ANDIF_EQ_EXPR, "truth_andif_eq_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ANDIF_NE_EXPR, "truth_andif_ne_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ORIF_LT_EXPR, "truth_orif_lt_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ORIF_LE_EXPR, "truth_orif_le_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ORIF_GT_EXPR, "truth_orif_gt_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ORIF_GE_EXPR, "truth_orif_ge_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ORIF_EQ_EXPR, "truth_orif_eq_expr", tcc_ccomparison, 3)
+DEFTREECODE (TRUTH_ORIF_NE_EXPR, "truth_orif_ne_expr", tcc_ccomparison, 3)
 
 /* Additional relational operators for floating point unordered.  */
 DEFTREECODE (UNORDERED_EXPR, "unordered_expr", tcc_comparison, 2)
diff --git a/gcc/tree.h b/gcc/tree.h
index 94f112f..74635e1 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -123,6 +123,7 @@ enum tree_code_class {
   tcc_declaration, /* A declaration (also serving as variable refs).  */
   tcc_reference,   /* A reference to storage.  */
   tcc_comparison,  /* A comparison expression.  */
+  tcc_ccomparison, /* A conditionalised comparison expression.  */
   tcc_unary,       /* A unary arithmetic expression.  */
   tcc_binary,      /* A binary arithmetic expression.  */
   tcc_statement,   /* A statement expression, which have side effects
@@ -190,6 +191,11 @@ extern const enum tree_code_class tree_code_type[];
 #define COMPARISON_CLASS_P(CODE)\
 	(TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_comparison)
 
+/* Nonzero if CODE represents a conditional comparison.  */
+
+#define CCOMPARISON_CLASS_P(CODE)\
+	(TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_ccomparison)
+
 /* Nonzero if CODE represents a unary arithmetic expression.  */
 
 #define UNARY_CLASS_P(CODE)\
@@ -6375,6 +6381,26 @@ extern bool is_tm_ending_fndecl (tree);
 extern void record_tm_replacement (tree, tree);
 extern void tm_malloc_replacement (tree);
 
+#define CASE_CCMP_ANDIF                                         \
+  case TRUTH_ANDIF_LT_EXPR:                                     \
+  case TRUTH_ANDIF_LE_EXPR:                                     \
+  case TRUTH_ANDIF_GT_EXPR:                                     \
+  case TRUTH_ANDIF_GE_EXPR:                                     \
+  case TRUTH_ANDIF_EQ_EXPR:                                     \
+  case TRUTH_ANDIF_NE_EXPR
+
+#define CASE_CCMP_ORIF                                          \
+  case TRUTH_ORIF_LT_EXPR:                                      \
+  case TRUTH_ORIF_LE_EXPR:                                      \
+  case TRUTH_ORIF_GT_EXPR:                                      \
+  case TRUTH_ORIF_GE_EXPR:                                      \
+  case TRUTH_ORIF_EQ_EXPR:                                      \
+  case TRUTH_ORIF_NE_EXPR
+
+extern enum tree_code get_code_from_ccompare_expr (enum tree_code *icode,
+						   enum tree_code code);
+enum tree_code generate_ccompare_code (enum tree_code code,
+				       enum tree_code cmpcode);
 static inline bool
 is_tm_safe_or_pure (const_tree x)
 {
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 45e9ada..8756c1e 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -12669,3 +12669,14 @@
 (include "sync.md")
 ;; Fixed-point patterns
 (include "arm-fixed.md")
+
+;; This is a dummy for test only.
+(define_expand "conditional_compare"
+  [(set (match_operand:SI 0 "s_register_operand" "")
+	(match_operator:SI 1 "expandable_comparison_operator"
+	 [(match_operand:SI 2 "s_register_operand" "")
+	  (match_operand:SI 3 "reg_or_int_operand" "")]))]
+  "TARGET_32BIT"
+  "{DONE;}"
+)
+
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 84515ae..2cbe4fb 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -17771,6 +17771,14 @@
   [(set_attr "type" "other")
    (set_attr "length" "3")])
 
+;; A dummy pattern for test only.
+(define_expand "conditional_compare"
+  [(parallel [(match_operand 0 "memory_operand" "=m")
+              (match_operand 1 "register_operand" "r")
+              (match_operand:DI 2 "register_operand" "=&r")])]
+  "TARGET_64BIT"
+{
+})
 (include "mmx.md")
 (include "sse.md")
 (include "sync.md")
