Deleted Added
full compact
builtins.c (117404) builtins.c (122190)
1/* Expand builtin functions.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free

--- 1330 unchanged lines hidden (view full) ---

1339 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1340 else
1341#endif
1342 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1343
1344 OK_DEFER_POP;
1345
1346 /* Return the address of the result block. */
1/* Expand builtin functions.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free

--- 1330 unchanged lines hidden (view full) ---

1339 emit_stack_restore (SAVE_NONLOCAL, old_stack_level, NULL_RTX);
1340 else
1341#endif
1342 emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
1343
1344 OK_DEFER_POP;
1345
1346 /* Return the address of the result block. */
1347 return copy_addr_to_reg (XEXP (result, 0));
1347 result = copy_addr_to_reg (XEXP (result, 0));
1348#ifdef POINTERS_EXTEND_UNSIGNED
1349 if (GET_MODE (result) != ptr_mode)
1350 result = convert_memory_address (ptr_mode, result);
1351#endif
1352 return result;
1348}
1349
1350/* Perform an untyped return. */
1351
1352static void
1353expand_builtin_return (result)
1354 rtx result;
1355{

--- 987 unchanged lines hidden (view full) ---

2343 result = expand_builtin_memset (exp, const0_rtx, VOIDmode);
2344
2345 /* Always restore the original arguments. */
2346 TREE_OPERAND (exp, 1) = arglist;
2347
2348 return result;
2349}
2350
1353}
1354
1355/* Perform an untyped return. */
1356
1357static void
1358expand_builtin_return (result)
1359 rtx result;
1360{

--- 987 unchanged lines hidden (view full) ---

2348 result = expand_builtin_memset (exp, const0_rtx, VOIDmode);
2349
2350 /* Always restore the original arguments. */
2351 TREE_OPERAND (exp, 1) = arglist;
2352
2353 return result;
2354}
2355
2351/* Expand expression EXP, which is a call to the memcmp or the strcmp builtin.
2356/* Expand expression EXP, which is a call to the memcmp built-in function.
2352 ARGLIST is the argument list for this call. Return 0 if we failed and the
2353 caller should emit a normal call, otherwise try to get the result in
2354 TARGET, if convenient (and in mode MODE, if that's convenient). */
2355
2356static rtx
2357expand_builtin_memcmp (exp, arglist, target, mode)
2358 tree exp ATTRIBUTE_UNUSED;
2359 tree arglist;

--- 120 unchanged lines hidden (view full) ---

2480
2481static rtx
2482expand_builtin_strcmp (exp, target, mode)
2483 tree exp;
2484 rtx target;
2485 enum machine_mode mode;
2486{
2487 tree arglist = TREE_OPERAND (exp, 1);
2357 ARGLIST is the argument list for this call. Return 0 if we failed and the
2358 caller should emit a normal call, otherwise try to get the result in
2359 TARGET, if convenient (and in mode MODE, if that's convenient). */
2360
2361static rtx
2362expand_builtin_memcmp (exp, arglist, target, mode)
2363 tree exp ATTRIBUTE_UNUSED;
2364 tree arglist;

--- 120 unchanged lines hidden (view full) ---

2485
2486static rtx
2487expand_builtin_strcmp (exp, target, mode)
2488 tree exp;
2489 rtx target;
2490 enum machine_mode mode;
2491{
2492 tree arglist = TREE_OPERAND (exp, 1);
2488 tree arg1, arg2, len, len2, fn;
2493 tree arg1, arg2;
2489 const char *p1, *p2;
2490
2491 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2492 return 0;
2493
2494 arg1 = TREE_VALUE (arglist);
2495 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2496

--- 19 unchanged lines hidden (view full) ---

2516 tree ind2 =
2517 fold (build1 (CONVERT_EXPR, integer_type_node,
2518 build1 (INDIRECT_REF, cst_uchar_node,
2519 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2520 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2521 return expand_expr (result, target, mode, EXPAND_NORMAL);
2522 }
2523
2494 const char *p1, *p2;
2495
2496 if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, VOID_TYPE))
2497 return 0;
2498
2499 arg1 = TREE_VALUE (arglist);
2500 arg2 = TREE_VALUE (TREE_CHAIN (arglist));
2501

--- 19 unchanged lines hidden (view full) ---

2521 tree ind2 =
2522 fold (build1 (CONVERT_EXPR, integer_type_node,
2523 build1 (INDIRECT_REF, cst_uchar_node,
2524 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2525 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2526 return expand_expr (result, target, mode, EXPAND_NORMAL);
2527 }
2528
2524 len = c_strlen (arg1);
2525 len2 = c_strlen (arg2);
2529#ifdef HAVE_cmpstrsi
2530 if (HAVE_cmpstrsi)
2531 {
2532 tree len, len1, len2;
2533 rtx arg1_rtx, arg2_rtx, arg3_rtx;
2534 rtx result, insn;
2526
2535
2527 if (len)
2528 len = size_binop (PLUS_EXPR, ssize_int (1), len);
2536 int arg1_align
2537 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2538 int arg2_align
2539 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2540 enum machine_mode insn_mode
2541 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
2529
2542
2530 if (len2)
2531 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
2543 len1 = c_strlen (arg1);
2544 len2 = c_strlen (arg2);
2532
2545
2533 /* If we don't have a constant length for the first, use the length
2534 of the second, if we know it. We don't require a constant for
2535 this case; some cost analysis could be done if both are available
2536 but neither is constant. For now, assume they're equally cheap
2537 unless one has side effects.
2546 if (len1)
2547 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
2548 if (len2)
2549 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
2538
2550
2539 If both strings have constant lengths, use the smaller. This
2540 could arise if optimization results in strcpy being called with
2541 two fixed strings, or if the code was machine-generated. We should
2542 add some code to the `memcmp' handler below to deal with such
2543 situations, someday. */
2551 /* If we don't have a constant length for the first, use the length
2552 of the second, if we know it. We don't require a constant for
2553 this case; some cost analysis could be done if both are available
2554 but neither is constant. For now, assume they're equally cheap
2555 unless one has side effects. If both strings have constant lengths,
2556 use the smaller. */
2544
2557
2545 if (!len || TREE_CODE (len) != INTEGER_CST)
2546 {
2547 if (len2 && !TREE_SIDE_EFFECTS (len2))
2558 if (!len1)
2548 len = len2;
2559 len = len2;
2549 else if (len == 0)
2560 else if (!len2)
2561 len = len1;
2562 else if (TREE_SIDE_EFFECTS (len1))
2563 len = len2;
2564 else if (TREE_SIDE_EFFECTS (len2))
2565 len = len1;
2566 else if (TREE_CODE (len1) != INTEGER_CST)
2567 len = len2;
2568 else if (TREE_CODE (len2) != INTEGER_CST)
2569 len = len1;
2570 else if (tree_int_cst_lt (len1, len2))
2571 len = len1;
2572 else
2573 len = len2;
2574
2575 /* If both arguments have side effects, we cannot optimize. */
2576 if (!len || TREE_SIDE_EFFECTS (len))
2550 return 0;
2577 return 0;
2551 }
2552 else if (len2 && TREE_CODE (len2) == INTEGER_CST
2553 && tree_int_cst_lt (len2, len))
2554 len = len2;
2555
2578
2556 /* If both arguments have side effects, we cannot optimize. */
2557 if (TREE_SIDE_EFFECTS (len))
2558 return 0;
2579 /* If we don't have POINTER_TYPE, call the function. */
2580 if (arg1_align == 0 || arg2_align == 0)
2581 return 0;
2559
2582
2560 fn = built_in_decls[BUILT_IN_MEMCMP];
2561 if (!fn)
2562 return 0;
2583 /* Make a place to write the result of the instruction. */
2584 result = target;
2585 if (! (result != 0
2586 && GET_CODE (result) == REG
2587 && GET_MODE (result) == insn_mode
2588 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2589 result = gen_reg_rtx (insn_mode);
2563
2590
2564 arglist = build_tree_list (NULL_TREE, len);
2565 arglist = tree_cons (NULL_TREE, arg2, arglist);
2566 arglist = tree_cons (NULL_TREE, arg1, arglist);
2567 return expand_expr (build_function_call_expr (fn, arglist),
2568 target, mode, EXPAND_NORMAL);
2591 arg1_rtx = get_memory_rtx (arg1);
2592 arg2_rtx = get_memory_rtx (arg2);
2593 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2594 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
2595 GEN_INT (MIN (arg1_align, arg2_align)));
2596 if (!insn)
2597 return 0;
2598
2599 emit_insn (insn);
2600
2601 /* Return the value in the proper mode for this function. */
2602 mode = TYPE_MODE (TREE_TYPE (exp));
2603 if (GET_MODE (result) == mode)
2604 return result;
2605 if (target == 0)
2606 return convert_to_mode (mode, result, 0);
2607 convert_move (target, result, 0);
2608 return target;
2609 }
2610#endif
2611 return 0;
2569}
2570
2571/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
2572 if we failed the caller should emit a normal call, otherwise try to get
2573 the result in TARGET, if convenient. */
2574
2575static rtx
2576expand_builtin_strncmp (exp, target, mode)
2577 tree exp;
2578 rtx target;
2579 enum machine_mode mode;
2580{
2581 tree arglist = TREE_OPERAND (exp, 1);
2612}
2613
2614/* Expand expression EXP, which is a call to the strncmp builtin. Return 0
2615 if we failed the caller should emit a normal call, otherwise try to get
2616 the result in TARGET, if convenient. */
2617
2618static rtx
2619expand_builtin_strncmp (exp, target, mode)
2620 tree exp;
2621 rtx target;
2622 enum machine_mode mode;
2623{
2624 tree arglist = TREE_OPERAND (exp, 1);
2582 tree fn, newarglist, len = 0;
2583 tree arg1, arg2, arg3;
2584 const char *p1, *p2;
2585
2586 if (!validate_arglist (arglist,
2587 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2588 return 0;
2589
2590 arg1 = TREE_VALUE (arglist);

--- 37 unchanged lines hidden (view full) ---

2628 fold (build1 (CONVERT_EXPR, integer_type_node,
2629 build1 (INDIRECT_REF, cst_uchar_node,
2630 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2631 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2632 return expand_expr (result, target, mode, EXPAND_NORMAL);
2633 }
2634
2635 /* If c_strlen can determine an expression for one of the string
2625 tree arg1, arg2, arg3;
2626 const char *p1, *p2;
2627
2628 if (!validate_arglist (arglist,
2629 POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE))
2630 return 0;
2631
2632 arg1 = TREE_VALUE (arglist);

--- 37 unchanged lines hidden (view full) ---

2670 fold (build1 (CONVERT_EXPR, integer_type_node,
2671 build1 (INDIRECT_REF, cst_uchar_node,
2672 build1 (NOP_EXPR, cst_uchar_ptr_node, arg2))));
2673 tree result = fold (build (MINUS_EXPR, integer_type_node, ind1, ind2));
2674 return expand_expr (result, target, mode, EXPAND_NORMAL);
2675 }
2676
2677 /* If c_strlen can determine an expression for one of the string
2636 lengths, and it doesn't have side effects, then call
2637 expand_builtin_memcmp() using length MIN(strlen(string)+1, arg3). */
2678 lengths, and it doesn't have side effects, then emit cmpstrsi
2679 using length MIN(strlen(string)+1, arg3). */
2680#ifdef HAVE_cmpstrsi
2681 if (HAVE_cmpstrsi)
2682 {
2683 tree len, len1, len2;
2684 rtx arg1_rtx, arg2_rtx, arg3_rtx;
2685 rtx result, insn;
2638
2686
2639 /* Perhaps one of the strings is really constant, if so prefer
2640 that constant length over the other string's length. */
2641 if (p1)
2642 len = c_strlen (arg1);
2643 else if (p2)
2644 len = c_strlen (arg2);
2687 int arg1_align
2688 = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2689 int arg2_align
2690 = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
2691 enum machine_mode insn_mode
2692 = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
2645
2693
2646 /* If we still don't have a len, try either string arg as long
2647 as they don't have side effects. */
2648 if (!len && !TREE_SIDE_EFFECTS (arg1))
2649 len = c_strlen (arg1);
2650 if (!len && !TREE_SIDE_EFFECTS (arg2))
2651 len = c_strlen (arg2);
2652 /* If we still don't have a length, punt. */
2653 if (!len)
2654 return 0;
2694 len1 = c_strlen (arg1);
2695 len2 = c_strlen (arg2);
2655
2696
2656 fn = built_in_decls[BUILT_IN_MEMCMP];
2657 if (!fn)
2658 return 0;
2697 if (len1)
2698 len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
2699 if (len2)
2700 len2 = size_binop (PLUS_EXPR, ssize_int (1), len2);
2659
2701
2660 /* Add one to the string length. */
2661 len = fold (size_binop (PLUS_EXPR, len, ssize_int (1)));
2702 /* If we don't have a constant length for the first, use the length
2703 of the second, if we know it. We don't require a constant for
2704 this case; some cost analysis could be done if both are available
2705 but neither is constant. For now, assume they're equally cheap,
2706 unless one has side effects. If both strings have constant lengths,
2707 use the smaller. */
2662
2708
2663 /* The actual new length parameter is MIN(len,arg3). */
2664 len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
2709 if (!len1)
2710 len = len2;
2711 else if (!len2)
2712 len = len1;
2713 else if (TREE_SIDE_EFFECTS (len1))
2714 len = len2;
2715 else if (TREE_SIDE_EFFECTS (len2))
2716 len = len1;
2717 else if (TREE_CODE (len1) != INTEGER_CST)
2718 len = len2;
2719 else if (TREE_CODE (len2) != INTEGER_CST)
2720 len = len1;
2721 else if (tree_int_cst_lt (len1, len2))
2722 len = len1;
2723 else
2724 len = len2;
2665
2725
2666 newarglist = build_tree_list (NULL_TREE, len);
2667 newarglist = tree_cons (NULL_TREE, arg2, newarglist);
2668 newarglist = tree_cons (NULL_TREE, arg1, newarglist);
2669 return expand_expr (build_function_call_expr (fn, newarglist),
2670 target, mode, EXPAND_NORMAL);
2726 /* If both arguments have side effects, we cannot optimize. */
2727 if (!len || TREE_SIDE_EFFECTS (len))
2728 return 0;
2729
2730 /* The actual new length parameter is MIN(len,arg3). */
2731 len = fold (build (MIN_EXPR, TREE_TYPE (len), len, arg3));
2732
2733 /* If we don't have POINTER_TYPE, call the function. */
2734 if (arg1_align == 0 || arg2_align == 0)
2735 return 0;
2736
2737 /* Make a place to write the result of the instruction. */
2738 result = target;
2739 if (! (result != 0
2740 && GET_CODE (result) == REG
2741 && GET_MODE (result) == insn_mode
2742 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
2743 result = gen_reg_rtx (insn_mode);
2744
2745 arg1_rtx = get_memory_rtx (arg1);
2746 arg2_rtx = get_memory_rtx (arg2);
2747 arg3_rtx = expand_expr (len, NULL_RTX, VOIDmode, 0);
2748 insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, arg3_rtx,
2749 GEN_INT (MIN (arg1_align, arg2_align)));
2750 if (!insn)
2751 return 0;
2752
2753 emit_insn (insn);
2754
2755 /* Return the value in the proper mode for this function. */
2756 mode = TYPE_MODE (TREE_TYPE (exp));
2757 if (GET_MODE (result) == mode)
2758 return result;
2759 if (target == 0)
2760 return convert_to_mode (mode, result, 0);
2761 convert_move (target, result, 0);
2762 return target;
2763 }
2764#endif
2765 return 0;
2671}
2672
2673/* Expand expression EXP, which is a call to the strcat builtin.
2674 Return 0 if we failed the caller should emit a normal call,
2675 otherwise try to get the result in TARGET, if convenient. */
2676
2677static rtx
2678expand_builtin_strcat (arglist, target, mode)

--- 1653 unchanged lines hidden ---
2766}
2767
2768/* Expand expression EXP, which is a call to the strcat builtin.
2769 Return 0 if we failed the caller should emit a normal call,
2770 otherwise try to get the result in TARGET, if convenient. */
2771
2772static rtx
2773expand_builtin_strcat (arglist, target, mode)

--- 1653 unchanged lines hidden ---