Skip to content
  1. Mar 12, 2004
  2. Mar 08, 2004
    • Chris Lattner's avatar
      Initial support for edge profiling · 721264ae
      Chris Lattner authored
      llvm-svn: 12225
      721264ae
    • Chris Lattner's avatar
      Split utility functions out of BlockProfiling.cpp · dae48f93
      Chris Lattner authored
      llvm-svn: 12224
      dae48f93
    • Chris Lattner's avatar
      finegrainify namespacification · d91e6767
      Chris Lattner authored
      llvm-svn: 12221
      d91e6767
    • Chris Lattner's avatar
      Implement ArgumentPromotion/aggregate-promote.ll · fe6f2e3e
      Chris Lattner authored
      This allows pointers to aggregate objects, whose elements are only read, to
      be promoted and passed in by element instead of by reference.  This can
      enable a LOT of subsequent optimizations in the caller function.
      
      It's worth pointing out that this stuff happens a LOT of C++ programs, because
      objects in templates are generally passed around by reference.  When these
      templates are instantiated on small aggregate or scalar types, however, it is
      more efficient to pass them in by value than by reference.
      
      This transformation triggers most on C++ codes (e.g. 334 times on eon), but
      does happen on C codes as well.  For example, on mesa it triggers 72 times,
      and on gcc it triggers 35 times.  this is amazingly good considering that
      we are using 'basicaa' so far.
      
      llvm-svn: 12202
      fe6f2e3e
  3. Mar 07, 2004
  4. Mar 03, 2004
  5. Mar 02, 2004
  6. Mar 01, 2004
  7. Feb 29, 2004
  8. Feb 28, 2004
  9. Feb 27, 2004
  10. Feb 26, 2004
    • Chris Lattner's avatar
      Since LLVM uses structure type equivalence, it isn't useful to keep around · 79636d7c
      Chris Lattner authored
      multiple type names for the same structural type.  Make DTE eliminate all
      but one of the type names
      
      llvm-svn: 11879
      79636d7c
    • Chris Lattner's avatar
      turn things like: · 21e941fb
      Chris Lattner authored
         if (X == 0 || X == 2)
      
      ...where the comparisons and branches are in different blocks... into a switch
      instruction.  This comes up a lot in various programs, and works well with
      the switch/switch merging code I checked earlier.  For example, this testcase:
      
      int switchtest(int C) {
        return C == 0 ? f(123) :
               C == 1 ? f(3123) :
               C == 4 ? f(312) :
               C == 5 ? f(1234): f(444);
      }
      
      is converted into this:
              switch int %C, label %cond_false.3 [
                       int 0, label %cond_true.0
                       int 1, label %cond_true.1
                       int 4, label %cond_true.2
                       int 5, label %cond_true.3
              ]
      
      instead of a whole bunch of conditional branches.
      
      Admittedly the code is ugly, and incomplete.  To be complete, we need to add
      br -> switch merging and switch -> br merging.  For example, this testcase:
      
      struct foo { int Q, R, Z; };
      #define A (X->Q+X->R * 123)
      int test(struct foo *X) {
        return A  == 123 ? X1() :
              A == 12321 ? X2():
              (A == 111 || A == 222) ? X3() :
              A == 875 ? X4() : X5();
      }
      
      Gets compiled to this:
              switch int %tmp.7, label %cond_false.2 [
                       int 123, label %cond_true.0
                       int 12321, label %cond_true.1
                       int 111, label %cond_true.2
                       int 222, label %cond_true.2
              ]
      ...
      cond_false.2:           ; preds = %entry
              %tmp.52 = seteq int %tmp.7, 875         ; <bool> [#uses=1]
              br bool %tmp.52, label %cond_true.3, label %cond_false.3
      
      where the branch could be folded into the switch.
      
      This kind of thing occurs *ALL OF THE TIME*, especially in programs like
      176.gcc, which is a horrible mess of code.  It contains stuff like *shudder*:
      
      #define SWITCH_TAKES_ARG(CHAR) \
        (   (CHAR) == 'D' \
         || (CHAR) == 'U' \
         || (CHAR) == 'o' \
         || (CHAR) == 'e' \
         || (CHAR) == 'u' \
         || (CHAR) == 'I' \
         || (CHAR) == 'm' \
         || (CHAR) == 'L' \
         || (CHAR) == 'A' \
         || (CHAR) == 'h' \
         || (CHAR) == 'z')
      
      and
      
      #define CONST_OK_FOR_LETTER_P(VALUE, C)                 \
        ((C) == 'I' ? SMALL_INTVAL (VALUE)                    \
         : (C) == 'J' ? SMALL_INTVAL (-(VALUE))               \
         : (C) == 'K' ? (unsigned)(VALUE) < 32                \
         : (C) == 'L' ? ((VALUE) & 0xffff) == 0               \
         : (C) == 'M' ? integer_ok_for_set (VALUE)            \
         : (C) == 'N' ? (VALUE) < 0                           \
         : (C) == 'O' ? (VALUE) == 0                          \
         : (C) == 'P' ? (VALUE) >= 0                          \
         : 0)
      
      and
      
      #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)                     \
      {                                                               \
        if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 1))) \
          (X) = gen_rtx (PLUS, SImode, XEXP (X, 0),                   \
                         copy_to_mode_reg (SImode, XEXP (X, 1)));     \
        if (GET_CODE (X) == PLUS && CONSTANT_ADDRESS_P (XEXP (X, 0))) \
          (X) = gen_rtx (PLUS, SImode, XEXP (X, 1),                   \
                         copy_to_mode_reg (SImode, XEXP (X, 0)));     \
        if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == MULT)   \
          (X) = gen_rtx (PLUS, SImode, XEXP (X, 1),                   \
                         force_operand (XEXP (X, 0), 0));             \
        if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == MULT)   \
          (X) = gen_rtx (PLUS, SImode, XEXP (X, 0),                   \
                         force_operand (XEXP (X, 1), 0));             \
        if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == PLUS)   \
          (X) = gen_rtx (PLUS, Pmode, force_operand (XEXP (X, 0), NULL_RTX),\
                         XEXP (X, 1));                                \
        if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == PLUS)   \
          (X) = gen_rtx (PLUS, Pmode, XEXP (X, 0),                    \
                         force_operand (XEXP (X, 1), NULL_RTX));      \
        if (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST       \
                 || GET_CODE (X) == LABEL_REF)                        \
          (X) = legitimize_address (flag_pic, X, 0, 0);               \
        if (memory_address_p (MODE, X))                               \
          goto WIN; }
      
      and others.  These macros get used multiple times of course.  These are such
      lovely candidates for macros, aren't they?  :)
      
      This code also nicely handles LLVM constructs that look like this:
      
        if (isa<CastInst>(I))
         ...
        else if (isa<BranchInst>(I))
         ...
        else if (isa<SetCondInst>(I))
         ...
        else if (isa<UnwindInst>(I))
         ...
        else if (isa<VAArgInst>(I))
         ...
      
      where the isa can obviously be a dyn_cast as well.  Switch instructions are a
      good thing.
      
      llvm-svn: 11870
      21e941fb
  11. Feb 25, 2004
    • Chris Lattner's avatar
      My faith in programmers has been found to be totally misplaced. One would · 8d1da1ab
      Chris Lattner authored
      assume that if they don't intend to write to a global variable, that they
      would mark it as constant.  However, there are people that don't understand
      that the compiler can do nice things for them if they give it the information
      it needs.
      
      This pass looks for blatently obvious globals that are only ever read from.
      Though it uses a trivially simple "alias analysis" of sorts, it is still able
      to do amazing things to important benchmarks.  253.perlbmk, for example,
      contains several ***GIANT*** function pointer tables that are not marked
      constant and should be.  Marking them constant allows the optimizer to turn
      a whole bunch of indirect calls into direct calls.  Note that only a link-time
      optimizer can do this transformation, but perlbmk does have several strings
      and other minor globals that can be marked constant by this pass when run
      from GCCAS.
      
      176.gcc has a ton of strings and large tables that are marked constant, both
      at compile time (38 of them) and at link time (48 more).  Other benchmarks
      give similar results, though it seems like big ones have disproportionally
      more than small ones.
      
      This pass is extremely quick and does good things.  I'm going to enable it
      in gccas & gccld.  Not bad for 50 SLOC.
      
      llvm-svn: 11836
      8d1da1ab
    • Chris Lattner's avatar
      Fix incorrect debug code · 9c6833c5
      Chris Lattner authored
      llvm-svn: 11821
      9c6833c5
  12. Feb 24, 2004
  13. Feb 23, 2004
Loading