2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Lower floating point operations to function calls
9 * @author Sebastian Buchwald
16 #include "dbginfo_t.h"
22 #include "irnodeset.h"
25 #include "iropt_dbg.h"
26 #include "iroptimize.h"
28 #include "lower_softfloat.h"
34 /** The debug handle */
35 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
37 typedef void (*lower_softfloat_func)(ir_node *node);
39 static ir_type *binop_tp_d;
40 static ir_type *binop_tp_f;
41 static ir_type *cmp_tp_d;
42 static ir_type *cmp_tp_f;
43 static ir_type *unop_tp_d;
44 static ir_type *unop_tp_f;
45 static ir_type *unop_tp_d_f;
46 static ir_type *unop_tp_d_is;
47 static ir_type *unop_tp_d_iu;
48 static ir_type *unop_tp_d_ls;
49 static ir_type *unop_tp_d_lu;
50 static ir_type *unop_tp_f_d;
51 static ir_type *unop_tp_f_is;
52 static ir_type *unop_tp_f_iu;
53 static ir_type *unop_tp_f_ls;
54 static ir_type *unop_tp_f_lu;
55 static ir_type *unop_tp_is_d;
56 static ir_type *unop_tp_is_f;
57 static ir_type *unop_tp_iu_d;
58 static ir_type *unop_tp_iu_f;
59 static ir_type *unop_tp_ls_d;
60 static ir_type *unop_tp_ls_f;
61 static ir_type *unop_tp_lu_d;
62 static ir_type *unop_tp_lu_f;
64 /** A map from a method type to its lowered type. */
65 static pmap *lowered_type;
67 static ir_nodeset_t created_mux_nodes;
70 * @return The lowered (floating point) mode.
72 static ir_mode *get_lowered_mode(ir_mode *mode)
74 if (! mode_is_float(mode))
79 else if (mode == mode_D)
82 panic("Unsupported floating point type");
86 * Adapts the mode of the given node.
88 static void lower_mode(ir_node *n, void *env)
90 ir_op *op = get_irn_op(n);
91 lower_softfloat_func lower_func = (lower_softfloat_func) op->ops.generic;
92 ir_mode *mode = get_irn_mode(n);
96 if (lower_func != NULL) {
101 set_irn_mode(n, get_lowered_mode(mode));
105 * Wrapper for specific lower function.
107 static void lower_node(ir_node *n, void *env)
109 ir_op *op = get_irn_op(n);
110 lower_softfloat_func lower_func = (lower_softfloat_func) op->ops.generic;
114 if (lower_func != NULL)
119 * @return The type of the function replacing the given node.
121 static ir_type *get_softfloat_type(const ir_node *n)
123 unsigned opcode = get_irn_opcode(n);
124 ir_mode *mode = get_irn_mode(n);
125 ir_node *operand = get_irn_n(n, 0);
126 ir_mode *operand_mode = get_irn_mode(operand);
130 operand_mode = get_irn_mode(get_Div_left(n));
135 if (operand_mode == mode_F)
137 else if (operand_mode == mode_D)
141 if (operand_mode == mode_F)
143 else if (operand_mode == mode_D)
147 if (operand_mode == mode_D) {
150 else if (mode == mode_Is || mode == mode_Hs || mode == mode_Bs)
152 else if (mode == mode_Iu || mode == mode_Hu || mode == mode_Bu)
154 else if (mode == mode_Ls)
156 else if (mode == mode_Lu)
159 else if (operand_mode == mode_F) {
162 else if (mode == mode_Is || mode == mode_Hs || mode == mode_Bs)
164 else if (mode == mode_Iu || mode == mode_Hu || mode == mode_Bu)
166 else if (mode == mode_Ls)
168 else if (mode == mode_Lu)
171 else if (operand_mode == mode_Is || operand_mode == mode_Hs || operand_mode == mode_Bs) {
174 else if (mode == mode_F)
177 else if (operand_mode == mode_Iu || operand_mode == mode_Hu || operand_mode == mode_Bu) {
180 else if (mode == mode_F)
183 else if (operand_mode == mode_Ls) {
186 else if (mode == mode_F)
189 else if (operand_mode == mode_Lu) {
192 else if (mode == mode_F)
197 if (operand_mode == mode_F)
199 else if (operand_mode == mode_D)
205 assert(0 && "Could not determine a suitable type");
211 * @return A SymConst representing the function that replaces the given node.
213 static ir_node *create_softfloat_symconst(const ir_node *n, const char *name)
216 const char *first_param = "";
217 const char *second_param = "";
218 const char *result = "";
223 unsigned float_types = 0;
224 unsigned double_types = 0;
225 ir_graph *irg = get_irn_irg(n);
226 ir_type *method = get_softfloat_type(n);
228 n_params = get_method_n_params(method);
230 /* Parameter types. */
234 ir_type *param_type = get_method_param_type(method, 1);
235 ir_mode *mode = get_type_mode(param_type);
237 if (mode == mode_F) {
241 else if (mode == mode_D) {
245 else if (mode == mode_Iu || mode == mode_Is)
247 else if (mode == mode_Lu || mode == mode_Ls)
253 ir_type *param_type = get_method_param_type(method, 0);
254 ir_mode *mode = get_type_mode(param_type);
256 if (mode == mode_F) {
257 first_param = float_types > 0 ? "" : "sf";
260 else if (mode == mode_D) {
261 first_param = double_types > 0 ? "" : "df";
264 else if (mode == mode_Iu || mode == mode_Is)
266 else if (mode == mode_Lu || mode == mode_Ls)
279 mode = get_Div_resmode(n);
281 mode = get_irn_mode(n);
283 if (mode == mode_F) {
284 result = float_types > 0 ? "" : "sf";
287 else if (mode == mode_D) {
288 result = double_types > 0 ? "" : "df";
291 else if (mode == mode_Iu || mode == mode_Hu || mode == mode_Bu
292 || mode == mode_Is || mode == mode_Hs || mode == mode_Bs)
294 else if (mode == mode_Lu || mode == mode_Ls)
298 assert(float_types <= 3);
299 assert(double_types <= 3);
301 if (float_types + double_types > 1)
302 snprintf(buf, sizeof(buf), "__%s%s%s%s%u", name, first_param, second_param, result, float_types + double_types);
304 snprintf(buf, sizeof(buf), "__%s%s%s%s", name, first_param, second_param, result);
306 id = new_id_from_str(buf);
307 ent = create_compilerlib_entity(id, method);
310 return new_r_SymConst(irg, mode_P_code, sym, symconst_addr_ent);
314 * Transforms an Add into the appropriate soft float function.
316 static void lower_Add(ir_node *n)
319 ir_node *block = get_nodes_block(n);
320 ir_node *call_result = NULL;
321 dbg_info *dbgi = get_irn_dbg_info(n);
322 ir_graph *irg = get_irn_irg(n);
323 ir_node *left = get_Add_left(n);
324 ir_node *right = get_Add_right(n);
325 ir_mode *mode = get_irn_mode(n);
327 if (! mode_is_float(mode))
330 symconst = create_softfloat_symconst(n, "add");
333 ir_node *call_results;
334 ir_node *in[2] = {left, right};
335 ir_node *nomem = get_irg_no_mem(irg);
336 ir_type *type = get_softfloat_type(n);
337 ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
339 call = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
340 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
341 call_result = new_r_Proj(call_results, res_mode, 0);
343 exchange(n, call_result);
347 * @return The lowered (floating point) type.
349 static ir_type *lower_type(ir_type *tp)
351 ir_mode *mode = get_type_mode(tp);
352 ir_mode *lowered_mode = get_lowered_mode(mode);
354 return get_type_for_mode(lowered_mode);
358 * @return The lowered method type.
360 static ir_type *lower_method_type(ir_type *mtp)
367 res = pmap_get(ir_type, lowered_type, mtp);
371 n_param = get_method_n_params(mtp);
372 n_res = get_method_n_ress(mtp);
374 res = new_type_method(n_param, n_res);
376 /* set param types and result types */
377 for (i = 0; i < n_param; ++i) {
378 ir_type *ptp = get_method_param_type(mtp, i);
379 ir_mode *pmode = get_type_mode(ptp);
381 if (pmode != NULL && mode_is_float(pmode)) {
382 ptp = lower_type(ptp);
385 set_method_param_type(res, i, ptp);
387 for (i = 0; i < n_res; ++i) {
388 ir_type *rtp = get_method_res_type(mtp, i);
389 ir_mode *rmode = get_type_mode(rtp);
391 if (rmode != NULL && mode_is_float(rmode)) {
392 rtp = lower_type(rtp);
395 set_method_res_type(res, i, rtp);
398 set_method_variadicity(res, get_method_variadicity(mtp));
399 set_method_calling_convention(res, get_method_calling_convention(mtp));
400 set_method_additional_properties(res, get_method_additional_properties(mtp));
402 set_higher_type(res, mtp);
404 pmap_insert(lowered_type, mtp, res);
409 * Adapts the method type of a Call.
411 static void lower_Call(ir_node *node)
413 ir_type *tp = get_Call_type(node);
416 bool need_lower = false;
420 n_params = get_method_n_params(tp);
422 for (p = 0; p < n_params; ++p) {
423 ir_type *ptp = get_method_param_type(tp, p);
424 ir_mode *pmode = get_type_mode(ptp);
429 if (mode_is_float(pmode)) {
435 n_res = get_method_n_ress(tp);
437 for (i = 0; i < n_res; ++i) {
438 ir_type *rtp = get_method_res_type(tp, i);
439 ir_mode *rmode = get_type_mode(rtp);
444 if (mode_is_float(rmode)) {
453 tp = lower_method_type(tp);
454 set_Call_type(node, tp);
458 * Transforms a Cmp into the appropriate soft float function.
460 static void lower_Cmp(ir_node *n)
462 ir_node *symconst = NULL;
463 ir_node *block = get_nodes_block(n);
464 ir_node *call_result = NULL;
465 dbg_info *dbgi = get_irn_dbg_info(n);
466 ir_graph *irg = get_irn_irg(n);
467 ir_node *left = get_Cmp_left(n);
468 ir_relation relation = get_Cmp_relation(n);
469 ir_mode *op_mode = get_irn_mode(left);
470 ir_node *right = get_Cmp_right(n);
471 ir_node *symconst2 = NULL;
472 ir_node *zero = new_rd_Const(dbgi, irg, get_mode_null(mode_Is));
474 if (! mode_is_float(op_mode))
478 case ir_relation_false:
481 case ir_relation_equal:
482 symconst = create_softfloat_symconst(n, "eq");
484 case ir_relation_less:
485 symconst = create_softfloat_symconst(n, "lt");
487 case ir_relation_greater:
488 symconst = create_softfloat_symconst(n, "gt");
490 case ir_relation_unordered:
491 symconst = create_softfloat_symconst(n, "unord");
492 relation = ir_relation_less_greater;
494 case ir_relation_less_equal:
495 symconst = create_softfloat_symconst(n, "le");
497 case ir_relation_greater_equal:
498 symconst = create_softfloat_symconst(n, "ge");
500 case ir_relation_less_greater:
501 symconst = create_softfloat_symconst(n, "unord");
502 symconst2 = create_softfloat_symconst(n, "ne");
504 case ir_relation_less_equal_greater:
505 symconst = create_softfloat_symconst(n, "unord");
506 relation = ir_relation_equal;
508 case ir_relation_unordered_equal:
509 symconst = create_softfloat_symconst(n, "unord");
510 relation = ir_relation_less_greater;
511 symconst2 = create_softfloat_symconst(n, "ne");
513 case ir_relation_unordered_less:
514 symconst = create_softfloat_symconst(n, "ge");
515 relation = ir_relation_less;
517 case ir_relation_unordered_less_equal:
518 symconst = create_softfloat_symconst(n, "gt");
519 relation = ir_relation_less_equal;
521 case ir_relation_unordered_greater:
522 symconst = create_softfloat_symconst(n, "le");
523 relation = ir_relation_greater;
525 case ir_relation_unordered_greater_equal:
526 symconst = create_softfloat_symconst(n, "lt");
527 relation = ir_relation_greater_equal;
529 case ir_relation_unordered_less_greater:
530 symconst = create_softfloat_symconst(n, "eq");
531 relation = ir_relation_less_greater;
533 case ir_relation_true:
538 if (call_result == NULL) {
540 ir_node *call_results;
541 ir_node *in[2] = {left, right};
542 ir_node *nomem = get_irg_no_mem(irg);
543 ir_type *type = get_softfloat_type(n);
545 call = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
546 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
547 call_result = new_r_Proj(call_results, mode_Is, 0);
550 ir_node *cmp = new_r_Cmp(block, call_result, zero, relation);
552 /* We need two calls into the softfloat library */
553 if (symconst2 != NULL) {
555 ir_node *call_results;
557 arch_allow_ifconv_func allow_ifconv = be_get_backend_param()->allow_ifconv;
558 ir_node *in[2] = {left, right};
559 ir_node *nomem = get_irg_no_mem(irg);
560 ir_type *type = get_softfloat_type(n);
562 call = new_rd_Call(dbgi, block, nomem, symconst2, 2, in, type);
563 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
564 call_result = new_r_Proj(call_results, mode_Is, 0);
565 relation = get_Cmp_relation(n);
567 mux = new_rd_Mux(dbgi, block, cmp, call_result, zero, mode_Is);
569 if (! allow_ifconv(cmp, call_result, zero))
570 ir_nodeset_insert(&created_mux_nodes, mux);
572 cmp = new_r_Cmp(block, mux, zero, relation);
578 static const tarval_mode_info hex_output = {
585 * Adapts floating point constants.
587 static void lower_Const(ir_node *n)
589 ir_mode *mode = get_irn_mode(n);
590 if (!mode_is_float(mode))
593 ir_mode *lowered_mode = get_lowered_mode(mode);
594 set_irn_mode(n, lowered_mode);
596 set_tarval_mode_output_option(mode, &hex_output);
598 tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
600 size_t len = strlen(buf);
601 ir_tarval *tv = new_tarval_from_str(buf, len, lowered_mode);
602 set_Const_tarval(n, tv);
606 * Transforms a Conv into the appropriate soft float function.
608 static void lower_Conv(ir_node *n)
611 ir_node *block = get_nodes_block(n);
612 ir_node *call_result = NULL;
613 dbg_info *dbgi = get_irn_dbg_info(n);
614 ir_graph *irg = get_irn_irg(n);
615 ir_node *op = get_Conv_op(n);
616 ir_mode *mode = get_irn_mode(n);
617 ir_mode *op_mode = get_irn_mode(op);
619 if (! mode_is_float(mode) && ! mode_is_float(op_mode))
622 /* Remove unnecessary Convs. */
623 if (op_mode == mode) {
627 else if (op_mode == mode_Hs || op_mode == mode_Bs) {
629 op = new_rd_Conv(dbgi, block, op, op_mode);
631 else if (op_mode == mode_Hu || op_mode == mode_Bu) {
633 op = new_rd_Conv(dbgi, block, op, op_mode);
636 if (mode_is_float(op_mode) && mode_is_float(mode)) {
637 if (get_mode_size_bits(op_mode) > get_mode_size_bits(mode))
638 symconst = create_softfloat_symconst(n, "trunc");
640 symconst = create_softfloat_symconst(n, "extend");
642 else if (mode_is_float(op_mode)) {
643 if (mode_is_signed(mode))
644 symconst = create_softfloat_symconst(n, "fix");
646 symconst = create_softfloat_symconst(n, "fixuns");
649 if (mode_is_signed(op_mode))
650 symconst = create_softfloat_symconst(n, "float");
652 symconst = create_softfloat_symconst(n, "floatun");
656 ir_node *call_results;
657 ir_node *in[1] = {op};
658 ir_node *nomem = get_irg_no_mem(irg);
659 ir_type *type = get_softfloat_type(n);
660 ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
662 call = new_rd_Call(dbgi, block, nomem, symconst, 1, in, type);
663 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
664 call_result = new_r_Proj(call_results, res_mode, 0);
666 /* Check whether we need a Conv for the result. */
667 if (res_mode != mode)
668 call_result = new_rd_Conv(dbgi, block, call_result, mode);
670 exchange(n, call_result);
674 * Transforms a Div into the appropriate soft float function.
676 static void lower_Div(ir_node *n)
679 ir_node *block = get_nodes_block(n);
680 ir_node *call_result = NULL;
681 dbg_info *dbgi = get_irn_dbg_info(n);
682 ir_graph *irg = get_irn_irg(n);
683 ir_node *left = get_Div_left(n);
684 ir_mode *mode = get_Div_resmode(n);
685 ir_node *right = get_Div_right(n);
687 if (! mode_is_float(mode))
690 symconst = create_softfloat_symconst(n, "div");
693 ir_node *call_results;
694 ir_node *in[2] = {left, right};
695 ir_node *nomem = get_irg_no_mem(irg);
696 ir_type *type = get_softfloat_type(n);
697 ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
699 call = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
700 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
701 call_result = new_r_Proj(call_results, res_mode, 0);
703 set_irn_pinned(call, get_irn_pinned(n));
705 foreach_out_edge_safe(n, edge) {
706 ir_node *proj = get_edge_src_irn(edge);
710 switch (get_Proj_proj(proj)) {
712 set_Proj_pred(proj, call);
713 set_Proj_proj(proj, pn_Call_M);
715 case pn_Div_X_regular:
716 set_Proj_pred(proj, call);
717 set_Proj_proj(proj, pn_Call_X_regular);
719 case pn_Div_X_except:
720 set_Proj_pred(proj, call);
721 set_Proj_proj(proj, pn_Call_X_except);
724 exchange(proj, call_result);
727 assert(0 && "unexpected Proj number");
734 * Adapts the resmode of a Div.
736 static void lower_Div_mode(ir_node *n)
738 ir_mode *res_mode = get_Div_resmode(n);
739 ir_mode *lowered_res_mode = get_lowered_mode(res_mode);
740 ir_mode *mode = get_irn_mode(n);
741 ir_mode *lowered_mode = get_lowered_mode(mode);
743 set_irn_mode(n, lowered_mode);
744 set_Div_resmode(n, lowered_res_mode);
748 * Adapts the ls_mode of a Load.
750 static void lower_Load(ir_node *n)
752 ir_mode *ls_mode = get_Load_mode(n);
753 ir_mode *lowered_ls_mode = get_lowered_mode(ls_mode);
754 ir_mode *mode = get_irn_mode(n);
755 ir_mode *lowered_mode = get_lowered_mode(mode);
757 set_irn_mode(n, lowered_mode);
758 set_Load_mode(n, lowered_ls_mode);
762 * Transforms a Minus into the appropriate soft float function.
764 static void lower_Minus(ir_node *n)
767 ir_node *block = get_nodes_block(n);
768 ir_node *call_result = NULL;
769 dbg_info *dbgi = get_irn_dbg_info(n);
770 ir_graph *irg = get_irn_irg(n);
771 ir_mode *mode = get_irn_mode(n);
772 ir_node *op = get_Minus_op(n);
774 if (! mode_is_float(mode))
777 symconst = create_softfloat_symconst(n, "neg");
780 ir_node *call_results;
781 ir_node *in[1] = {op};
782 ir_node *nomem = get_irg_no_mem(irg);
783 ir_type *type = get_softfloat_type(n);
784 ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
786 call = new_rd_Call(dbgi, block, nomem, symconst, 1, in, type);
787 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
788 call_result = new_r_Proj(call_results, res_mode, 0);
790 exchange(n, call_result);
794 * Transforms a Mul into the appropriate soft float function.
796 static void lower_Mul(ir_node *n)
799 ir_node *block = get_nodes_block(n);
800 ir_node *call_result = NULL;
801 dbg_info *dbgi = get_irn_dbg_info(n);
802 ir_graph *irg = get_irn_irg(n);
803 ir_node *left = get_Mul_left(n);
804 ir_mode *mode = get_irn_mode(n);
805 ir_node *right = get_Mul_right(n);
807 if (! mode_is_float(mode))
810 symconst = create_softfloat_symconst(n, "mul");
813 ir_node *call_results;
814 ir_node *in[2] = {left, right};
815 ir_node *nomem = get_irg_no_mem(irg);
816 ir_type *type = get_softfloat_type(n);
817 ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
819 call = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
820 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
821 call_result = new_r_Proj(call_results, res_mode, 0);
823 exchange(n, call_result);
827 * Transforms a Sub into the appropriate soft float function.
829 static void lower_Sub(ir_node *n)
832 ir_node *block = get_nodes_block(n);
833 ir_node *call_result = NULL;
834 dbg_info *dbgi = get_irn_dbg_info(n);
835 ir_graph *irg = get_irn_irg(n);
836 ir_node *left = get_Sub_left(n);
837 ir_mode *mode = get_irn_mode(n);
838 ir_node *right = get_Sub_right(n);
840 if (! mode_is_float(mode))
843 symconst = create_softfloat_symconst(n, "sub");
846 ir_node *call_results;
847 ir_node *in[2] = {left, right};
848 ir_node *nomem = get_irg_no_mem(irg);
849 ir_type *type = get_softfloat_type(n);
850 ir_mode *res_mode = get_type_mode(get_method_res_type(type, 0));
852 call = new_rd_Call(dbgi, block, nomem, symconst, 2, in, type);
853 call_results = new_r_Proj(call, mode_T, pn_Call_T_result);
854 call_result = new_r_Proj(call_results, res_mode, 0);
856 exchange(n, call_result);
860 * Enter a lowering function into an ir_op.
862 static void ir_register_softloat_lower_function(ir_op *op, lower_softfloat_func func)
864 op->ops.generic = (op_func)func;
868 * Initializes softfloat lowering.
870 static void ir_prepare_softfloat_lowering(void)
872 FIRM_DBG_REGISTER(dbg, "firm.lower.softfloat");
875 lowered_type = pmap_create();
878 binop_tp_d = new_type_method(2, 1);
879 set_method_param_type(binop_tp_d, 0, get_type_for_mode(mode_D));
880 set_method_param_type(binop_tp_d, 1, get_type_for_mode(mode_D));
881 set_method_res_type(binop_tp_d, 0, get_type_for_mode(mode_D));
885 binop_tp_f = new_type_method(2, 1);
886 set_method_param_type(binop_tp_f, 0, get_type_for_mode(mode_F));
887 set_method_param_type(binop_tp_f, 1, get_type_for_mode(mode_F));
888 set_method_res_type(binop_tp_f, 0, get_type_for_mode(mode_F));
892 cmp_tp_d = new_type_method(2, 1);
893 set_method_param_type(cmp_tp_d, 0, get_type_for_mode(mode_D));
894 set_method_param_type(cmp_tp_d, 1, get_type_for_mode(mode_D));
895 set_method_res_type(cmp_tp_d, 0, get_type_for_mode(mode_Is));
899 cmp_tp_f = new_type_method(2, 1);
900 set_method_param_type(cmp_tp_f, 0, get_type_for_mode(mode_F));
901 set_method_param_type(cmp_tp_f, 1, get_type_for_mode(mode_F));
902 set_method_res_type(cmp_tp_f, 0, get_type_for_mode(mode_Is));
906 unop_tp_d = new_type_method(1, 1);
907 set_method_param_type(unop_tp_d, 0, get_type_for_mode(mode_D));
908 set_method_res_type(unop_tp_d, 0, get_type_for_mode(mode_D));
912 unop_tp_f = new_type_method(1, 1);
913 set_method_param_type(unop_tp_f, 0, get_type_for_mode(mode_F));
914 set_method_res_type(unop_tp_f, 0, get_type_for_mode(mode_F));
918 unop_tp_d_f = new_type_method(1, 1);
919 set_method_param_type(unop_tp_d_f, 0, get_type_for_mode(mode_D));
920 set_method_res_type(unop_tp_d_f, 0, get_type_for_mode(mode_F));
923 if (! unop_tp_d_is) {
924 unop_tp_d_is = new_type_method(1, 1);
925 set_method_param_type(unop_tp_d_is, 0, get_type_for_mode(mode_D));
926 set_method_res_type(unop_tp_d_is, 0, get_type_for_mode(mode_Is));
929 if (! unop_tp_d_iu) {
930 unop_tp_d_iu = new_type_method(1, 1);
931 set_method_param_type(unop_tp_d_iu, 0, get_type_for_mode(mode_D));
932 set_method_res_type(unop_tp_d_iu, 0, get_type_for_mode(mode_Iu));
935 if (! unop_tp_d_ls) {
936 unop_tp_d_ls = new_type_method(1, 1);
937 set_method_param_type(unop_tp_d_ls, 0, get_type_for_mode(mode_D));
938 set_method_res_type(unop_tp_d_ls, 0, get_type_for_mode(mode_Ls));
941 if (! unop_tp_d_lu) {
942 unop_tp_d_lu = new_type_method(1, 1);
943 set_method_param_type(unop_tp_d_lu, 0, get_type_for_mode(mode_D));
944 set_method_res_type(unop_tp_d_lu, 0, get_type_for_mode(mode_Lu));
948 unop_tp_f_d = new_type_method(1, 1);
949 set_method_param_type(unop_tp_f_d, 0, get_type_for_mode(mode_F));
950 set_method_res_type(unop_tp_f_d, 0, get_type_for_mode(mode_D));
953 if (! unop_tp_f_is) {
954 unop_tp_f_is = new_type_method(1, 1);
955 set_method_param_type(unop_tp_f_is, 0, get_type_for_mode(mode_F));
956 set_method_res_type(unop_tp_f_is, 0, get_type_for_mode(mode_Is));
959 if (! unop_tp_f_iu) {
960 unop_tp_f_iu = new_type_method(1, 1);
961 set_method_param_type(unop_tp_f_iu, 0, get_type_for_mode(mode_F));
962 set_method_res_type(unop_tp_f_iu, 0, get_type_for_mode(mode_Iu));
965 if (! unop_tp_f_ls) {
966 unop_tp_f_ls = new_type_method(1, 1);
967 set_method_param_type(unop_tp_f_ls, 0, get_type_for_mode(mode_F));
968 set_method_res_type(unop_tp_f_ls, 0, get_type_for_mode(mode_Ls));
971 if (! unop_tp_f_lu) {
972 unop_tp_f_lu = new_type_method(1, 1);
973 set_method_param_type(unop_tp_f_lu, 0, get_type_for_mode(mode_F));
974 set_method_res_type(unop_tp_f_lu, 0, get_type_for_mode(mode_Lu));
977 if (! unop_tp_is_d) {
978 unop_tp_is_d = new_type_method(1, 1);
979 set_method_param_type(unop_tp_is_d, 0, get_type_for_mode(mode_Is));
980 set_method_res_type(unop_tp_is_d, 0, get_type_for_mode(mode_D));
983 if (! unop_tp_is_f) {
984 unop_tp_is_f = new_type_method(1, 1);
985 set_method_param_type(unop_tp_is_f, 0, get_type_for_mode(mode_Is));
986 set_method_res_type(unop_tp_is_f, 0, get_type_for_mode(mode_F));
989 if (! unop_tp_iu_d) {
990 unop_tp_iu_d = new_type_method(1, 1);
991 set_method_param_type(unop_tp_iu_d, 0, get_type_for_mode(mode_Iu));
992 set_method_res_type(unop_tp_iu_d, 0, get_type_for_mode(mode_D));
995 if (! unop_tp_iu_f) {
996 unop_tp_iu_f = new_type_method(1, 1);
997 set_method_param_type(unop_tp_iu_f, 0, get_type_for_mode(mode_Iu));
998 set_method_res_type(unop_tp_iu_f, 0, get_type_for_mode(mode_F));
1001 if (! unop_tp_ls_d) {
1002 unop_tp_ls_d = new_type_method(1, 1);
1003 set_method_param_type(unop_tp_ls_d, 0, get_type_for_mode(mode_Ls));
1004 set_method_res_type(unop_tp_ls_d, 0, get_type_for_mode(mode_D));
1007 if (! unop_tp_ls_f) {
1008 unop_tp_ls_f = new_type_method(1, 1);
1009 set_method_param_type(unop_tp_ls_f, 0, get_type_for_mode(mode_Ls));
1010 set_method_res_type(unop_tp_ls_f, 0, get_type_for_mode(mode_F));
1013 if (! unop_tp_lu_d) {
1014 unop_tp_lu_d = new_type_method(1, 1);
1015 set_method_param_type(unop_tp_lu_d, 0, get_type_for_mode(mode_Lu));
1016 set_method_res_type(unop_tp_lu_d, 0, get_type_for_mode(mode_D));
1019 if (! unop_tp_lu_f) {
1020 unop_tp_lu_f = new_type_method(1, 1);
1021 set_method_param_type(unop_tp_lu_f, 0, get_type_for_mode(mode_Lu));
1022 set_method_res_type(unop_tp_lu_f, 0, get_type_for_mode(mode_F));
1027 * Callback to lower only the Mux nodes we created.
1029 static int lower_mux_cb(ir_node *mux)
1031 return ir_nodeset_contains(&created_mux_nodes, mux);
1034 void lower_floating_point(void)
1037 size_t n_irgs = get_irp_n_irgs();
1039 FIRM_DBG_REGISTER(dbg, "firm.lower.softfloat");
1041 ir_prepare_softfloat_lowering();
1043 ir_clear_opcodes_generic_func();
1044 ir_register_softloat_lower_function(op_Add, lower_Add);
1045 ir_register_softloat_lower_function(op_Cmp, lower_Cmp);
1046 ir_register_softloat_lower_function(op_Conv, lower_Conv);
1047 ir_register_softloat_lower_function(op_Div, lower_Div);
1048 ir_register_softloat_lower_function(op_Minus, lower_Minus);
1049 ir_register_softloat_lower_function(op_Mul, lower_Mul);
1050 ir_register_softloat_lower_function(op_Sub, lower_Sub);
1052 for (i = 0; i < n_irgs; ++i) {
1053 ir_graph *irg = get_irp_irg(i);
1055 ir_nodeset_init(&created_mux_nodes);
1059 irg_walk_graph(irg, NULL, lower_node, NULL);
1061 if (ir_nodeset_size(&created_mux_nodes) > 0)
1062 lower_mux(irg, lower_mux_cb);
1064 ir_nodeset_destroy(&created_mux_nodes);
1067 ir_clear_opcodes_generic_func();
1068 ir_register_softloat_lower_function(op_Call, lower_Call);
1069 ir_register_softloat_lower_function(op_Const, lower_Const);
1070 ir_register_softloat_lower_function(op_Div, lower_Div_mode);
1071 ir_register_softloat_lower_function(op_Load, lower_Load);
1073 for (i = 0; i < n_irgs; ++i) {
1074 ir_graph *irg = get_irp_irg(i);
1075 ir_entity *ent = get_irg_entity(irg);
1076 ir_type *mtp = get_entity_type(ent);
1077 ir_type *lowered_mtp = lower_method_type(mtp);
1078 ir_type *frame_tp = get_irg_frame_type(irg);
1082 if (lowered_mtp != mtp)
1083 set_entity_type(ent, lowered_mtp);
1085 irg_walk_graph(irg, NULL, lower_mode, NULL);
1087 /* fixup parameter entities */
1088 n_members = get_compound_n_members(frame_tp);
1089 for (i = 0; i < n_members; ++i) {
1090 ir_entity *member = get_compound_member(frame_tp, i);
1091 ir_type *type = get_entity_type(member);
1092 if (is_Primitive_type(type)) {
1093 ir_type *lowered = lower_type(type);
1094 set_entity_type(member, lowered);