- rtx tmp, tmp1, tmp2, tmp3, jump;
- rtx neq_label = gen_label_rtx ();
- rtx end_label = gen_label_rtx ();
- rtx sequence;
-
- start_sequence ();
-
- if (!REG_P (op2))
- {
- tmp = gen_reg_rtx (mode);
- emit_move_insn (tmp, copy_rtx (op2));
- }
- else
- tmp = op2;
-
- tmp1 = expand_simple_binop (mode, PLUS, tmp, constm1_rtx, NULL_RTX,
- 0, OPTAB_WIDEN);
- tmp2 = expand_simple_binop (mode, AND, tmp, tmp1, NULL_RTX,
- 0, OPTAB_WIDEN);
- do_compare_rtx_and_jump (tmp2, const0_rtx, NE, 0, mode, NULL_RTX,
- NULL_RTX, neq_label);
-
- /* Add branch probability to jump we just created. */
- jump = get_last_insn ();
- REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB,
- GEN_INT (REG_BR_PROB_BASE - prob),
- REG_NOTES (jump));
-
- tmp3 = expand_simple_binop (mode, AND, op1, tmp1, target,
- 0, OPTAB_WIDEN);
- if (tmp3 != target)
- emit_move_insn (copy_rtx (target), tmp3);
- emit_jump_insn (gen_jump (end_label));
- emit_barrier ();
-
- emit_label (neq_label);
- tmp1 = simplify_gen_binary (operation, mode, copy_rtx (op1), copy_rtx (tmp));
- tmp1 = force_operand (tmp1, target);
- if (tmp1 != target)
- emit_move_insn (target, tmp1);
+ tree stmt1, stmt2, stmt3, stmt4;
+ tree tmp1, tmp2, tmp3;
+ tree label_decl1 = create_artificial_label ();
+ tree label_decl2 = create_artificial_label ();
+ tree label_decl3 = create_artificial_label ();
+ tree label1, label2, label3;
+ tree bb1end, bb2end, bb3end;
+ basic_block bb, bb2, bb3, bb4;
+ tree optype = TREE_TYPE (operation);
+ edge e12, e13, e23, e24, e34;
+ block_stmt_iterator bsi;
+ tree result = create_tmp_var (optype, "PROF");
+
+ bb = bb_for_stmt (stmt);
+ bsi = bsi_for_stmt (stmt);
+
+ tmp1 = create_tmp_var (optype, "PROF");
+ tmp2 = create_tmp_var (optype, "PROF");
+ tmp3 = create_tmp_var (optype, "PROF");
+ stmt1 = build2 (MODIFY_EXPR, optype, tmp1, fold_convert (optype, op2));
+ stmt2 = build2 (MODIFY_EXPR, optype, tmp2,
+ build2 (PLUS_EXPR, optype, op2, integer_minus_one_node));
+ stmt3 = build2 (MODIFY_EXPR, optype, tmp3,
+ build2 (BIT_AND_EXPR, optype, tmp2, tmp1));
+ stmt4 = build3 (COND_EXPR, void_type_node,
+ build2 (NE_EXPR, boolean_type_node, tmp3, integer_zero_node),
+ build1 (GOTO_EXPR, void_type_node, label_decl2),
+ build1 (GOTO_EXPR, void_type_node, label_decl1));
+ bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
+ bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
+ bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
+ bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
+ bb1end = stmt4;
+
+ /* tmp2 == op2-1 inherited from previous block */
+ label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
+ stmt1 = build2 (MODIFY_EXPR, optype, result,
+ build2 (BIT_AND_EXPR, optype, op1, tmp2));
+ bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
+ bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
+ bb2end = stmt1;
+
+ label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
+ stmt1 = build2 (MODIFY_EXPR, optype, result,
+ build2 (TREE_CODE (operation), optype, op1, op2));
+ bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
+ bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
+ bb3end = stmt1;
+
+ label3 = build1 (LABEL_EXPR, void_type_node, label_decl3);
+ bsi_insert_before (&bsi, label3, BSI_SAME_STMT);
+
+ /* Fix CFG. */
+ /* Edge e23 connects bb2 to bb3, etc. */
+ e12 = split_block (bb, bb1end);
+ bb2 = e12->dest;
+ bb2->count = count;
+ e23 = split_block (bb2, bb2end);
+ bb3 = e23->dest;
+ bb3->count = all - count;
+ e34 = split_block (bb3, bb3end);
+ bb4 = e34->dest;
+ bb4->count = all;
+
+ e12->flags &= ~EDGE_FALLTHRU;
+ e12->flags |= EDGE_FALSE_VALUE;
+ e12->probability = prob;
+ e12->count = count;
+
+ e13 = make_edge (bb, bb3, EDGE_TRUE_VALUE);
+ e13->probability = REG_BR_PROB_BASE - prob;
+ e13->count = all - count;
+
+ remove_edge (e23);