+ else
+ real_one = build_real (type, dconst1);
+
+ stmt1 = gimple_build_assign_with_ops (RDIV_EXPR,
+ var, real_one, gimple_assign_rhs2 (stmt));
+ name = make_ssa_name (var, stmt1);
+ gimple_assign_set_lhs (stmt1, name);
+
+ stmt2 = gimple_build_assign_with_ops (MULT_EXPR, lhs, name,
+ gimple_assign_rhs1 (stmt));
+
+ /* Replace division stmt with reciprocal and multiply stmts.
+ The multiply stmt is not invariant, so update iterator
+ and avoid rescanning. */
+ gsi = *bsi;
+ gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+ gsi_replace (&gsi, stmt2, true);
+
+ /* Continue processing with invariant reciprocal statement. */
+ return stmt1;
+}
+
+/* Check if the pattern at *BSI is a bittest of the form
+ (A >> B) & 1 != 0 and in this case rewrite it to A & (1 << B) != 0. */
+
+static gimple
+rewrite_bittest (gimple_stmt_iterator *bsi)
+{
+ gimple stmt, use_stmt, stmt1, stmt2;
+ tree lhs, var, name, t, a, b;
+ use_operand_p use;
+
+ stmt = gsi_stmt (*bsi);
+ lhs = gimple_assign_lhs (stmt);
+
+ /* Verify that the single use of lhs is a comparison against zero. */
+ if (TREE_CODE (lhs) != SSA_NAME
+ || !single_imm_use (lhs, &use, &use_stmt)
+ || gimple_code (use_stmt) != GIMPLE_COND)
+ return stmt;
+ if (gimple_cond_lhs (use_stmt) != lhs
+ || (gimple_cond_code (use_stmt) != NE_EXPR
+ && gimple_cond_code (use_stmt) != EQ_EXPR)
+ || !integer_zerop (gimple_cond_rhs (use_stmt)))
+ return stmt;
+
+ /* Get at the operands of the shift. The rhs is TMP1 & 1. */
+ stmt1 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
+ if (gimple_code (stmt1) != GIMPLE_ASSIGN)
+ return stmt;
+
+ /* There is a conversion in between possibly inserted by fold. */
+ if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt1)))
+ {
+ t = gimple_assign_rhs1 (stmt1);
+ if (TREE_CODE (t) != SSA_NAME
+ || !has_single_use (t))
+ return stmt;
+ stmt1 = SSA_NAME_DEF_STMT (t);
+ if (gimple_code (stmt1) != GIMPLE_ASSIGN)
+ return stmt;
+ }
+
+ /* Verify that B is loop invariant but A is not. Verify that with
+ all the stmt walking we are still in the same loop. */
+ if (gimple_assign_rhs_code (stmt1) != RSHIFT_EXPR
+ || loop_containing_stmt (stmt1) != loop_containing_stmt (stmt))
+ return stmt;
+
+ a = gimple_assign_rhs1 (stmt1);
+ b = gimple_assign_rhs2 (stmt1);
+
+ if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
+ && outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
+ {
+ gimple_stmt_iterator rsi;
+
+ /* 1 << B */
+ var = create_tmp_var (TREE_TYPE (a), "shifttmp");
+ add_referenced_var (var);
+ t = fold_build2 (LSHIFT_EXPR, TREE_TYPE (a),
+ build_int_cst (TREE_TYPE (a), 1), b);
+ stmt1 = gimple_build_assign (var, t);
+ name = make_ssa_name (var, stmt1);
+ gimple_assign_set_lhs (stmt1, name);
+
+ /* A & (1 << B) */
+ t = fold_build2 (BIT_AND_EXPR, TREE_TYPE (a), a, name);
+ stmt2 = gimple_build_assign (var, t);
+ name = make_ssa_name (var, stmt2);
+ gimple_assign_set_lhs (stmt2, name);
+
+ /* Replace the SSA_NAME we compare against zero. Adjust
+ the type of zero accordingly. */
+ SET_USE (use, name);
+ gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
+
+ /* Don't use gsi_replace here, none of the new assignments sets
+ the variable originally set in stmt. Move bsi to stmt1, and
+ then remove the original stmt, so that we get a chance to
+ retain debug info for it. */
+ rsi = *bsi;
+ gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+ gsi_insert_before (&rsi, stmt2, GSI_SAME_STMT);
+ gsi_remove (&rsi, true);
+
+ return stmt1;
+ }
+
+ return stmt;