https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85980

            Bug ID: 85980
           Summary: suboptimal code for strncmp for powerpc64
           Product: gcc
           Version: 8.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

As discussed in https://gcc.gnu.org/ml/gcc-patches/2018-05/msg01514.html, for
the following test case and the powerpc64le target, GCC emits the code below:

int f (__SIZE_TYPE__ i)
{
  return __builtin_strncmp ("1234", "123", i < 3 ? i : 3);
}

f:
.LFB0:
        .cfi_startproc
.LCF0:
0:      addis 2,12,.TOC.-.LCF0@ha
        addi 2,2,.TOC.-.LCF0@l
        .localentry     f,.-f
        mflr 0
        cmpldi 7,3,3
        li 5,3
        std 0,16(1)
        stdu 1,-32(1)
        .cfi_def_cfa_offset 32
        .cfi_offset 65, 16
        bgt 7,.L5
        cmpdi 7,3,4                  << unnecessary
        mr 5,3                       << 
        ble 7,.L5                    <<
        li 5,4                       <<
.L5:
        addis 4,2,.LC1@toc@ha
        addis 3,2,.LC0@toc@ha
        addi 4,4,.LC1@toc@l
        addi 3,3,.LC0@toc@l
        bl strncmp
        nop
        addi 1,1,32
        .cfi_def_cfa_offset 0
        ld 0,16(1)
        mtlr 0
        .cfi_restore 65
        blr

The comparison and the subsequent branch are helpful when strncmp is expanded
inline but do not benefit the library version of strncmp and only bloat and
slow down the caller.  (The origins of the code are tracked down in
https://gcc.gnu.org/ml/gcc-patches/2018-05/msg01406.html).  The following
simple patch is enough to improve the generated code:

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 841c1ef..5b9085b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4708,12 +4708,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx
target,
       return target;
     }

-  /* Expand the library call ourselves using a stabilized argument
-     list to avoid re-evaluating the function's arguments twice.  */
-  tree fn = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
-  gcc_assert (TREE_CODE (fn) == CALL_EXPR);
-  CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp);
-  return expand_call (fn, target, target == const0_rtx);
+  return expand_call (exp, target, target == const0_rtx);
 }

 /* Expand a call to __builtin_saveregs, generating the result in TARGET,

Reply via email to