Skip to content
README.txt 71.4 KiB
Newer Older
Chris Lattner's avatar
Chris Lattner committed
Target Independent Opportunities:

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
With the recent changes to make the implicit def/use set explicit in
machineinstrs, we should change the target descriptions for 'call' instructions
so that the .td files don't list all the call-clobbered registers as implicit
defs.  Instead, these should be added by the code generator (e.g. on the dag).

This has a number of uses:

1. PPC32/64 and X86 32/64 can avoid having multiple copies of call instructions
   for their different impdef sets.
2. Targets with multiple calling convs (e.g. x86) which have different clobber
   sets don't need copies of call instructions.
3. 'Interprocedural register allocation' can be done to reduce the clobber sets
   of calls.

//===---------------------------------------------------------------------===//

We should recognized various "overflow detection" idioms and translate them into
llvm.uadd.with.overflow and similar intrinsics.  Here is a multiply idiom:

unsigned int mul(unsigned int a,unsigned int b) {
 if ((unsigned long long)a*b>0xffffffff)
   exit(0);
  return a*b;
}

The legalization code for mul-with-overflow needs to be made more robust before
this can be implemented though.

Nate Begeman's avatar
Nate Begeman committed
//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

Get the C front-end to expand hypot(x,y) -> llvm.sqrt(x*x+y*y) when errno and
precision don't matter (ffastmath).  Misc/mandel will like this. :)  This isn't
safe in general, even on darwin.  See the libm implementation of hypot for
examples (which special case when x/y are exactly zero to get signed zeros etc
right).
Chris Lattner's avatar
Chris Lattner committed

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
On targets with expensive 64-bit multiply, we could LSR this:

for (i = ...; ++i) {
   x = 1ULL << i;

into:
 long long tmp = 1;
 for (i = ...; ++i, tmp+=tmp)
   x = tmp;

This would be a win on ppc32, but not x86 or ppc64.

Chris Lattner's avatar
Chris Lattner committed
//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

Shrink: (setlt (loadi32 P), 0) -> (setlt (loadi8 Phi), 0)

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

Reassociate should turn things like:

int factorial(int X) {
 return X*X*X*X*X*X*X*X;
}

into llvm.powi calls, allowing the code generator to produce balanced
multiplication trees.

First, the intrinsic needs to be extended to support integers, and second the
code generator needs to be enhanced to lower these to multiplication trees.
Chris Lattner's avatar
Chris Lattner committed

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
Interesting? testcase for add/shift/mul reassoc:

int bar(int x, int y) {
  return x*x*x+y+x*x*x*x*x*y*y*y*y;
}
int foo(int z, int n) {
  return bar(z, n) + bar(2*z, 2*n);
}

This is blocked on not handling X*X*X -> powi(X, 3) (see note above).  The issue
is that we end up getting t = 2*X  s = t*t   and don't turn this into 4*X*X,
which is the same number of multiplies and is canonical, because the 2*X has
multiple uses.  Here's a simple example:

define i32 @test15(i32 %X1) {
  %B = mul i32 %X1, 47   ; X1*47
  %C = mul i32 %B, %B
  ret i32 %C
}


//===---------------------------------------------------------------------===//

Reassociate should handle the example in GCC PR16157:

extern int a0, a1, a2, a3, a4; extern int b0, b1, b2, b3, b4; 
void f () {  /* this can be optimized to four additions... */ 
        b4 = a4 + a3 + a2 + a1 + a0; 
        b3 = a3 + a2 + a1 + a0; 
        b2 = a2 + a1 + a0; 
        b1 = a1 + a0; 
} 

This requires reassociating to forms of expressions that are already available,
something that reassoc doesn't think about yet.
Chris Lattner's avatar
Chris Lattner committed

//===---------------------------------------------------------------------===//

This function: (derived from GCC PR19988)
double foo(double x, double y) {
  return ((x + 0.1234 * y) * (x + -0.1234 * y));
}

compiles to:
_foo:
	movapd	%xmm1, %xmm2
	mulsd	LCPI1_1(%rip), %xmm1
	mulsd	LCPI1_0(%rip), %xmm2
	addsd	%xmm0, %xmm1
	addsd	%xmm0, %xmm2
	movapd	%xmm1, %xmm0
	mulsd	%xmm2, %xmm0
	ret

Reassociate should be able to turn it into:
Chris Lattner's avatar
Chris Lattner committed

double foo(double x, double y) {
  return ((x + 0.1234 * y) * (x - 0.1234 * y));
}

Which allows the multiply by constant to be CSE'd, producing:

_foo:
	mulsd	LCPI1_0(%rip), %xmm1
	movapd	%xmm1, %xmm2
	addsd	%xmm0, %xmm2
	subsd	%xmm1, %xmm0
	mulsd	%xmm2, %xmm0
	ret

This doesn't need -ffast-math support at all.  This is particularly bad because
the llvm-gcc frontend is canonicalizing the later into the former, but clang
doesn't have this problem.

Chris Lattner's avatar
Chris Lattner committed
//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
These two functions should generate the same code on big-endian systems:

int g(int *j,int *l)  {  return memcmp(j,l,4);  }
int h(int *j, int *l) {  return *j - *l; }

this could be done in SelectionDAGISel.cpp, along with other special cases,
for 1,2,4,8 bytes.

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
It would be nice to revert this patch:
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20060213/031986.html

And teach the dag combiner enough to simplify the code expanded before 
legalize.  It seems plausible that this knowledge would let it simplify other
stuff too.

Chris Lattner's avatar
Chris Lattner committed
//===---------------------------------------------------------------------===//

Reid Spencer's avatar
Reid Spencer committed
For vector types, TargetData.cpp::getTypeInfo() returns alignment that is equal
to the type size. It works but can be overly conservative as the alignment of
Reid Spencer's avatar
Reid Spencer committed
specific vector types are target dependent.
Chris Lattner's avatar
Chris Lattner committed

//===---------------------------------------------------------------------===//

We should produce an unaligned load from code like this:
Chris Lattner's avatar
Chris Lattner committed

v4sf example(float *P) {
  return (v4sf){P[0], P[1], P[2], P[3] };
}

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
Add support for conditional increments, and other related patterns.  Instead
of:

	movl 136(%esp), %eax
	cmpl $0, %eax
	je LBB16_2	#cond_next
LBB16_1:	#cond_true
	incl _foo
LBB16_2:	#cond_next

emit:
	movl	_foo, %eax
	cmpl	$1, %edi
	sbbl	$-1, %eax
	movl	%eax, _foo

//===---------------------------------------------------------------------===//

Combine: a = sin(x), b = cos(x) into a,b = sincos(x).

Expand these to calls of sin/cos and stores:
      double sincos(double x, double *sin, double *cos);
      float sincosf(float x, float *sin, float *cos);
      long double sincosl(long double x, long double *sin, long double *cos);

Doing so could allow SROA of the destination pointers.  See also:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17687

This is now easily doable with MRVs.  We could even make an intrinsic for this
if anyone cared enough about sincos.

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

quantum_sigma_x in 462.libquantum contains the following loop:

      for(i=0; i<reg->size; i++)
	{
	  /* Flip the target bit of each basis state */
	  reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
	} 

Where MAX_UNSIGNED/state is a 64-bit int.  On a 32-bit platform it would be just
so cool to turn it into something like:

   long long Res = ((MAX_UNSIGNED) 1 << target);
   if (target < 32) {
     for(i=0; i<reg->size; i++)
       reg->node[i].state ^= Res & 0xFFFFFFFFULL;
   } else {
     for(i=0; i<reg->size; i++)
       reg->node[i].state ^= Res & 0xFFFFFFFF00000000ULL
   }
   
... which would only do one 32-bit XOR per loop iteration instead of two.

It would also be nice to recognize the reg->size doesn't alias reg->node[i], but
this requires TBAA.
Chris Lattner's avatar
Chris Lattner committed

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
This isn't recognized as bswap by instcombine (yes, it really is bswap):
Chris Lattner's avatar
Chris Lattner committed

unsigned long reverse(unsigned v) {
    unsigned t;
    t = v ^ ((v << 16) | (v >> 16));
    t &= ~0xff0000;
    v = (v << 24) | (v >> 8);
    return v ^ (t >> 8);
}

Chris Lattner's avatar
Chris Lattner committed
//===---------------------------------------------------------------------===//

[LOOP DELETION]

We don't delete this output free loop, because trip count analysis doesn't
realize that it is finite (if it were infinite, it would be undefined).  Not
having this blocks Loop Idiom from matching strlen and friends.  

void foo(char *C) {
  int x = 0;
  while (*C)
    ++x,++C;
}

//===---------------------------------------------------------------------===//

These idioms should be recognized as popcount (see PR1488):

unsigned countbits_slow(unsigned v) {
  unsigned c;
  for (c = 0; v; v >>= 1)
    c += v & 1;
  return c;
}
unsigned countbits_fast(unsigned v){
  unsigned c;
  for (c = 0; v; c++)
    v &= v - 1; // clear the least significant bit set
  return c;
}

BITBOARD = unsigned long long
int PopCnt(register BITBOARD a) {
  register int c=0;
  while(a) {
    c++;
    a &= a - 1;
  }
  return c;
}
unsigned int popcount(unsigned int input) {
  unsigned int count = 0;
  for (unsigned int i =  0; i < 4 * 8; i++)
    count += (input >> i) & i;
  return count;
}

This should be recognized as CLZ:  rdar://8459039

unsigned clz_a(unsigned a) {
  int i;
  for (i=0;i<32;i++)
    if (a & (1<<(31-i)))
      return i;
  return 32;
}

This sort of thing should be added to the loop idiom pass.
//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
These should turn into single 16-bit (unaligned?) loads on little/big endian
processors.

unsigned short read_16_le(const unsigned char *adr) {
  return adr[0] | (adr[1] << 8);
}
unsigned short read_16_be(const unsigned char *adr) {
  return (adr[0] << 8) | adr[1];
}

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

Reid Spencer's avatar
Reid Spencer committed
-instcombine should handle this transform:
Reid Spencer's avatar
Reid Spencer committed
   icmp pred (sdiv X / C1 ), C2
Reid Spencer's avatar
Reid Spencer committed
when X, C1, and C2 are unsigned.  Similarly for udiv and signed operands. 

Currently InstCombine avoids this transform but will do it when the signs of
the operands and the sign of the divide match. See the FIXME in 
InstructionCombining.cpp in the visitSetCondInst method after the switch case 
for Instruction::UDiv (around line 4447) for more details.

The SingleSource/Benchmarks/Shootout-C++/hash and hash2 tests have examples of
this construct. 
Chris Lattner's avatar
Chris Lattner committed

//===---------------------------------------------------------------------===//

[LOOP OPTIMIZATION]

SingleSource/Benchmarks/Misc/dt.c shows several interesting optimization
opportunities in its double_array_divs_variable function: it needs loop
interchange, memory promotion (which LICM already does), vectorization and
variable trip count loop unrolling (since it has a constant trip count). ICC
apparently produces this very nice code with -ffast-math:

..B1.70:                        # Preds ..B1.70 ..B1.69
       mulpd     %xmm0, %xmm1                                  #108.2
       mulpd     %xmm0, %xmm1                                  #108.2
       mulpd     %xmm0, %xmm1                                  #108.2
       mulpd     %xmm0, %xmm1                                  #108.2
       addl      $8, %edx                                      #
       cmpl      $131072, %edx                                 #108.2
       jb        ..B1.70       # Prob 99%                      #108.2

It would be better to count down to zero, but this is a lot better than what we
do.

//===---------------------------------------------------------------------===//

Consider:

typedef unsigned U32;
typedef unsigned long long U64;
int test (U32 *inst, U64 *regs) {
    U64 effective_addr2;
    U32 temp = *inst;
    int r1 = (temp >> 20) & 0xf;
    int b2 = (temp >> 16) & 0xf;
    effective_addr2 = temp & 0xfff;
    if (b2) effective_addr2 += regs[b2];
    b2 = (temp >> 12) & 0xf;
    if (b2) effective_addr2 += regs[b2];
    effective_addr2 &= regs[4];
     if ((effective_addr2 & 3) == 0)
        return 1;
    return 0;
}

Note that only the low 2 bits of effective_addr2 are used.  On 32-bit systems,
we don't eliminate the computation of the top half of effective_addr2 because
we don't have whole-function selection dags.  On x86, this means we use one
extra register for the function when effective_addr2 is declared as U64 than
when it is declared U32.

Chris Lattner's avatar
Chris Lattner committed
PHI Slicing could be extended to do this.

//===---------------------------------------------------------------------===//

Tail call elim should be more aggressive, checking to see if the call is
followed by an uncond branch to an exit block.

; This testcase is due to tail-duplication not wanting to copy the return
; instruction into the terminating blocks because there was other code
; optimized out of the function after the taildup happened.
Chris Lattner's avatar
Chris Lattner committed
; RUN: llvm-as < %s | opt -tailcallelim | llvm-dis | not grep call
Chris Lattner's avatar
Chris Lattner committed
define i32 @t4(i32 %a) {
Chris Lattner's avatar
Chris Lattner committed
	%tmp.1 = and i32 %a, 1		; <i32> [#uses=1]
	%tmp.2 = icmp ne i32 %tmp.1, 0		; <i1> [#uses=1]
	br i1 %tmp.2, label %then.0, label %else.0

then.0:		; preds = %entry
	%tmp.5 = add i32 %a, -1		; <i32> [#uses=1]
	%tmp.3 = call i32 @t4( i32 %tmp.5 )		; <i32> [#uses=1]
	br label %return

else.0:		; preds = %entry
	%tmp.7 = icmp ne i32 %a, 0		; <i1> [#uses=1]
	br i1 %tmp.7, label %then.1, label %return

then.1:		; preds = %else.0
	%tmp.11 = add i32 %a, -2		; <i32> [#uses=1]
	%tmp.9 = call i32 @t4( i32 %tmp.11 )		; <i32> [#uses=1]
	br label %return

return:		; preds = %then.1, %else.0, %then.0
	%result.0 = phi i32 [ 0, %else.0 ], [ %tmp.3, %then.0 ],
Chris Lattner's avatar
Chris Lattner committed
	ret i32 %result.0
Chris Lattner's avatar
Chris Lattner committed

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
Tail recursion elimination should handle:

int pow2m1(int n) {
 if (n == 0)
   return 0;
 return 2 * pow2m1 (n - 1) + 1;
}

Also, multiplies can be turned into SHL's, so they should be handled as if
they were associative.  "return foo() << 1" can be tail recursion eliminated.

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
Argument promotion should promote arguments for recursive functions, like 
this:

Chris Lattner's avatar
Chris Lattner committed
; RUN: llvm-as < %s | opt -argpromotion | llvm-dis | grep x.val
Chris Lattner's avatar
Chris Lattner committed

Chris Lattner's avatar
Chris Lattner committed
define internal i32 @foo(i32* %x) {
Chris Lattner's avatar
Chris Lattner committed
entry:
Chris Lattner's avatar
Chris Lattner committed
	%tmp = load i32* %x		; <i32> [#uses=0]
	%tmp.foo = call i32 @foo( i32* %x )		; <i32> [#uses=1]
	ret i32 %tmp.foo
Chris Lattner's avatar
Chris Lattner committed
}

Chris Lattner's avatar
Chris Lattner committed
define i32 @bar(i32* %x) {
Chris Lattner's avatar
Chris Lattner committed
entry:
Chris Lattner's avatar
Chris Lattner committed
	%tmp3 = call i32 @foo( i32* %x )		; <i32> [#uses=1]
	ret i32 %tmp3
Chris Lattner's avatar
Chris Lattner committed
}

Chris Lattner's avatar
Chris Lattner committed
//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
We should investigate an instruction sinking pass.  Consider this silly
example in pic mode:

#include <assert.h>
void foo(int x) {
  assert(x);
  //...
}

we compile this to:
_foo:
	subl	$28, %esp
	call	"L1$pb"
"L1$pb":
	popl	%eax
	cmpl	$0, 32(%esp)
	je	LBB1_2	# cond_true
LBB1_1:	# return
	# ...
	addl	$28, %esp
	ret
LBB1_2:	# cond_true
...

The PIC base computation (call+popl) is only used on one path through the 
code, but is currently always computed in the entry block.  It would be 
better to sink the picbase computation down into the block for the 
assertion, as it is the only one that uses it.  This happens for a lot of 
code with early outs.
Chris Lattner's avatar
Chris Lattner committed

Chris Lattner's avatar
Chris Lattner committed
Another example is loads of arguments, which are usually emitted into the 
entry block on targets like x86.  If not used in all paths through a 
function, they should be sunk into the ones that do.

Chris Lattner's avatar
Chris Lattner committed
In this case, whole-function-isel would also handle this.
Chris Lattner's avatar
Chris Lattner committed

Chris Lattner's avatar
Chris Lattner committed
//===---------------------------------------------------------------------===//

Investigate lowering of sparse switch statements into perfect hash tables:
http://burtleburtle.net/bob/hash/perfect.html

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

We should turn things like "load+fabs+store" and "load+fneg+store" into the
corresponding integer operations.  On a yonah, this loop:

double a[256];
Chris Lattner's avatar
Chris Lattner committed
void foo() {
  int i, b;
  for (b = 0; b < 10000000; b++)
  for (i = 0; i < 256; i++)
    a[i] = -a[i];
}
Chris Lattner's avatar
Chris Lattner committed

is twice as slow as this loop:

long long a[256];
Chris Lattner's avatar
Chris Lattner committed
void foo() {
  int i, b;
  for (b = 0; b < 10000000; b++)
  for (i = 0; i < 256; i++)
    a[i] ^= (1ULL << 63);
}
Chris Lattner's avatar
Chris Lattner committed

and I suspect other processors are similar.  On X86 in particular this is a
big win because doing this with integers allows the use of read/modify/write
instructions.

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

DAG Combiner should try to combine small loads into larger loads when 
profitable.  For example, we compile this C++ example:

struct THotKey { short Key; bool Control; bool Shift; bool Alt; };
extern THotKey m_HotKey;
THotKey GetHotKey () { return m_HotKey; }

into (-m64 -O3 -fno-exceptions -static -fomit-frame-pointer):

__Z9GetHotKeyv:                         ## @_Z9GetHotKeyv
	movq	_m_HotKey@GOTPCREL(%rip), %rax
	movzwl	(%rax), %ecx
	movzbl	2(%rax), %edx
	shlq	$16, %rdx
	orq	%rcx, %rdx
	movzbl	3(%rax), %ecx
	shlq	$24, %rcx
	orq	%rdx, %rcx
	movzbl	4(%rax), %eax
	shlq	$32, %rax
	orq	%rcx, %rax
	ret
Chris Lattner's avatar
Chris Lattner committed

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

Nate Begeman's avatar
Nate Begeman committed
We should add an FRINT node to the DAG to model targets that have legal
implementations of ceil/floor/rint.

//===---------------------------------------------------------------------===//

Consider:

int test() {
  long long input[8] = {1,0,1,0,1,0,1,0};
Chris Lattner's avatar
Chris Lattner committed
Clang compiles this into:
Chris Lattner's avatar
Chris Lattner committed
  call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 64, i32 16, i1 false)
  %0 = getelementptr [8 x i64]* %input, i64 0, i64 0
  store i64 1, i64* %0, align 16
  %1 = getelementptr [8 x i64]* %input, i64 0, i64 2
  store i64 1, i64* %1, align 16
  %2 = getelementptr [8 x i64]* %input, i64 0, i64 4
  store i64 1, i64* %2, align 16
  %3 = getelementptr [8 x i64]* %input, i64 0, i64 6
  store i64 1, i64* %3, align 16
Chris Lattner's avatar
Chris Lattner committed
Which gets codegen'd into:

	pxor	%xmm0, %xmm0
	movaps	%xmm0, -16(%rbp)
	movaps	%xmm0, -32(%rbp)
	movaps	%xmm0, -48(%rbp)
	movaps	%xmm0, -64(%rbp)
	movq	$1, -64(%rbp)
	movq	$1, -48(%rbp)
	movq	$1, -32(%rbp)
	movq	$1, -16(%rbp)

It would be better to have 4 movq's of 0 instead of the movaps's.

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

http://llvm.org/PR717:

The following code should compile into "ret int undef". Instead, LLVM
produces "ret int 0":

int f() {
  int x = 4;
  int y;
  if (x == 3) y = 0;
  return y;
}

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

The loop unroller should partially unroll loops (instead of peeling them)
when code growth isn't too bad and when an unroll count allows simplification
of some code within the loop.  One trivial example is:

#include <stdio.h>
int main() {
    int nRet = 17;
    int nLoop;
    for ( nLoop = 0; nLoop < 1000; nLoop++ ) {
        if ( nLoop & 1 )
            nRet += 2;
        else
            nRet -= 1;
    }
    return nRet;
}

Unrolling by 2 would eliminate the '&1' in both copies, leading to a net
reduction in code size.  The resultant code would then also be suitable for
exit value computation.

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

We miss a bunch of rotate opportunities on various targets, including ppc, x86,
etc.  On X86, we miss a bunch of 'rotate by variable' cases because the rotate
matching code in dag combine doesn't look through truncates aggressively 
enough.  Here are some testcases reduces from GCC PR17886:

unsigned long long f5(unsigned long long x, unsigned long long y) {
  return (x << 8) | ((y >> 48) & 0xffull);
}
unsigned long long f6(unsigned long long x, unsigned long long y, int z) {
  switch(z) {
  case 1:
    return (x << 8) | ((y >> 48) & 0xffull);
  case 2:
    return (x << 16) | ((y >> 40) & 0xffffull);
  case 3:
    return (x << 24) | ((y >> 32) & 0xffffffull);
  case 4:
    return (x << 32) | ((y >> 24) & 0xffffffffull);
  default:
    return (x << 40) | ((y >> 16) & 0xffffffffffull);
  }
}

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

This (and similar related idioms):

unsigned int foo(unsigned char i) {
  return i | (i<<8) | (i<<16) | (i<<24);
} 

compiles into:

define i32 @foo(i8 zeroext %i) nounwind readnone ssp noredzone {
entry:
  %conv = zext i8 %i to i32
  %shl = shl i32 %conv, 8
  %shl5 = shl i32 %conv, 16
  %shl9 = shl i32 %conv, 24
  %or = or i32 %shl9, %conv
  %or6 = or i32 %or, %shl5
  %or10 = or i32 %or6, %shl
  ret i32 %or10
}

it would be better as:

unsigned int bar(unsigned char i) {
  unsigned int j=i | (i << 8); 
  return j | (j<<16);
}

aka:

define i32 @bar(i8 zeroext %i) nounwind readnone ssp noredzone {
entry:
  %conv = zext i8 %i to i32
  %shl = shl i32 %conv, 8
  %or = or i32 %shl, %conv
  %shl5 = shl i32 %or, 16
  %or6 = or i32 %shl5, %or
  ret i32 %or6
}

or even i*0x01010101, depending on the speed of the multiplier.  The best way to
handle this is to canonicalize it to a multiply in IR and have codegen handle
lowering multiplies to shifts on cpus where shifts are faster.

//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
We do a number of simplifications in simplify libcalls to strength reduce
standard library functions, but we don't currently merge them together.  For
example, it is useful to merge memcpy(a,b,strlen(b)) -> strcpy.  This can only
be done safely if "b" isn't modified between the strlen and memcpy of course.

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

We compile this program: (from GCC PR11680)
http://gcc.gnu.org/bugzilla/attachment.cgi?id=4487

Into code that runs the same speed in fast/slow modes, but both modes run 2x
slower than when compile with GCC (either 4.0 or 4.2):

$ llvm-g++ perf.cpp -O3 -fno-exceptions
$ time ./a.out fast
1.821u 0.003s 0:01.82 100.0%	0+0k 0+0io 0pf+0w

$ g++ perf.cpp -O3 -fno-exceptions
$ time ./a.out fast
0.821u 0.001s 0:00.82 100.0%	0+0k 0+0io 0pf+0w

It looks like we are making the same inlining decisions, so this may be raw
codegen badness or something else (haven't investigated).

//===---------------------------------------------------------------------===//

Divisibility by constant can be simplified (according to GCC PR12849) from
being a mulhi to being a mul lo (cheaper).  Testcase:

void bar(unsigned n) {
  if (n % 3 == 0)
    true();
}

This is equivalent to the following, where 2863311531 is the multiplicative
inverse of 3, and 1431655766 is ((2^32)-1)/3+1:
void bar(unsigned n) {
  if (n * 2863311531U < 1431655766U)
    true();
}

The same transformation can work with an even modulo with the addition of a
rotate: rotate the result of the multiply to the right by the number of bits
which need to be zero for the condition to be true, and shrink the compare RHS
by the same amount.  Unless the target supports rotates, though, that
transformation probably isn't worthwhile.

The transformation can also easily be made to work with non-zero equality
comparisons: just transform, for example, "n % 3 == 1" to "(n-1) % 3 == 0".

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed

Chris Lattner's avatar
Chris Lattner committed
Better mod/ref analysis for scanf would allow us to eliminate the vtable and a
bunch of other stuff from this example (see PR1604): 

#include <cstdio>
struct test {
    int val;
    virtual ~test() {}
};

int main() {
    test t;
    std::scanf("%d", &t.val);
    std::printf("%d\n", t.val);
}

//===---------------------------------------------------------------------===//

Nick Lewycky's avatar
Nick Lewycky committed
These functions perform the same computation, but produce different assembly.

define i8 @select(i8 %x) readnone nounwind {
  %A = icmp ult i8 %x, 250
  %B = select i1 %A, i8 0, i8 1
  ret i8 %B 
}

define i8 @addshr(i8 %x) readnone nounwind {
  %A = zext i8 %x to i9
  %B = add i9 %A, 6       ;; 256 - 250 == 6
  %C = lshr i9 %B, 8
  %D = trunc i9 %C to i8
  ret i8 %D
}

//===---------------------------------------------------------------------===//

From gcc bug 24696:
int
f (unsigned long a, unsigned long b, unsigned long c)
{
  return ((a & (c - 1)) != 0) || ((b & (c - 1)) != 0);
}
int
f (unsigned long a, unsigned long b, unsigned long c)
{
  return ((a & (c - 1)) != 0) | ((b & (c - 1)) != 0);
}
Both should combine to ((a|b) & (c-1)) != 0.  Currently not optimized with
"clang -emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

From GCC Bug 20192:
#define PMD_MASK    (~((1UL << 23) - 1))
void clear_pmd_range(unsigned long start, unsigned long end)
{
   if (!(start & ~PMD_MASK) && !(end & ~PMD_MASK))
       f();
}
The expression should optimize to something like
"!((start|end)&~PMD_MASK). Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

unsigned int f(unsigned int i, unsigned int n) {++i; if (i == n) ++i; return
i;}
unsigned int f2(unsigned int i, unsigned int n) {++i; i += i == n; return i;}
These should combine to the same thing.  Currently, the first function
produces better code on X86.

//===---------------------------------------------------------------------===//

From GCC Bug 15784:
#define abs(x) x>0?x:-x
int f(int x, int y)
{
 return (abs(x)) >= 0;
}
This should optimize to x == INT_MIN. (With -fwrapv.)  Currently not
optimized with "clang -emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

From GCC Bug 14753:
void
rotate_cst (unsigned int a)
{
 a = (a << 10) | (a >> 22);
 if (a == 123)
   bar ();
}
void
minus_cst (unsigned int a)
{
 unsigned int tem;

 tem = 20 - a;
 if (tem == 5)
   bar ();
}
void
mask_gt (unsigned int a)
{
 /* This is equivalent to a > 15.  */
 if ((a & ~7) > 8)
   bar ();
}
void
rshift_gt (unsigned int a)
{
 /* This is equivalent to a > 23.  */
 if ((a >> 2) > 5)
   bar ();
}
All should simplify to a single comparison.  All of these are
currently not optimized with "clang -emit-llvm-bc | opt
-std-compile-opts".

//===---------------------------------------------------------------------===//

From GCC Bug 32605:
int c(int* x) {return (char*)x+2 == (char*)x;}
Should combine to 0.  Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts" (although llc can optimize it).

//===---------------------------------------------------------------------===//

int a(unsigned b) {return ((b << 31) | (b << 30)) >> 31;}
Should be combined to  "((b >> 1) | b) & 1".  Currently not optimized
with "clang -emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

unsigned a(unsigned x, unsigned y) { return x | (y & 1) | (y & 2);}
Should combine to "x | (y & 3)".  Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

int a(int a, int b, int c) {return (~a & c) | ((c|a) & b);}
Should fold to "(~a & c) | (a & b)".  Currently not optimized with
"clang -emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

int a(int a,int b) {return (~(a|b))|a;}
Should fold to "a|~b".  Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

int a(int a, int b) {return (a&&b) || (a&&!b);}
Should fold to "a".  Currently not optimized with "clang -emit-llvm-bc
| opt -std-compile-opts".

//===---------------------------------------------------------------------===//

int a(int a, int b, int c) {return (a&&b) || (!a&&c);}
Should fold to "a ? b : c", or at least something sane.  Currently not
optimized with "clang -emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

int a(int a, int b, int c) {return (a&&b) || (a&&c) || (a&&b&&c);}
Should fold to a && (b || c).  Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

int a(int x) {return x | ((x & 8) ^ 8);}
Should combine to x | 8.  Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

int a(int x) {return x ^ ((x & 8) ^ 8);}
Should also combine to x | 8.  Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

int a(int x) {return ((x | -9) ^ 8) & x;}
Should combine to x & -9.  Currently not optimized with "clang
-emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

unsigned a(unsigned a) {return a * 0x11111111 >> 28 & 1;}
Should combine to "a * 0x88888888 >> 31".  Currently not optimized
with "clang -emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

unsigned a(char* x) {if ((*x & 32) == 0) return b();}
There's an unnecessary zext in the generated code with "clang
-emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//

unsigned a(unsigned long long x) {return 40 * (x >> 1);}
Should combine to "20 * (((unsigned)x) & -2)".  Currently not
optimized with "clang -emit-llvm-bc | opt -std-compile-opts".

//===---------------------------------------------------------------------===//
Chris Lattner's avatar
Chris Lattner committed
This was noticed in the entryblock for grokdeclarator in 403.gcc:

        %tmp = icmp eq i32 %decl_context, 4          
        %decl_context_addr.0 = select i1 %tmp, i32 3, i32 %decl_context 
        %tmp1 = icmp eq i32 %decl_context_addr.0, 1 
        %decl_context_addr.1 = select i1 %tmp1, i32 0, i32 %decl_context_addr.0

tmp1 should be simplified to something like:
  (!tmp || decl_context == 1)

This allows recursive simplifications, tmp1 is used all over the place in
the function, e.g. by:

        %tmp23 = icmp eq i32 %decl_context_addr.1, 0            ; <i1> [#uses=1]
        %tmp24 = xor i1 %tmp1, true             ; <i1> [#uses=1]
        %or.cond8 = and i1 %tmp23, %tmp24               ; <i1> [#uses=1]

later.

Chris Lattner's avatar
Chris Lattner committed
//===---------------------------------------------------------------------===//

Chris Lattner's avatar
Chris Lattner committed
Store sinking: This code:

void f (int n, int *cond, int *res) {
    int i;
    *res = 0;
    for (i = 0; i < n; i++)
        if (*cond)
            *res ^= 234; /* (*) */
}

On this function GVN hoists the fully redundant value of *res, but nothing
moves the store out.  This gives us this code:

bb:		; preds = %bb2, %entry