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 --- |