Newer
Older
//===---------------------------------------------------------------------===//
We should recognize idioms for add-with-carry and turn it into the appropriate
intrinsics. This example:
unsigned add32carry(unsigned sum, unsigned x) {
unsigned z = sum + x;
if (sum + x < x)
z++;
return z;
}
Compiles to: clang t.c -S -o - -O3 -fomit-frame-pointer -m64 -mkernel
_add32carry: ## @add32carry
addl %esi, %edi
cmpl %esi, %edi
sbbl %eax, %eax
andl $1, %eax
addl %edi, %eax
ret
with clang, but to:
_add32carry:
leal (%rsi,%rdi), %eax
cmpl %esi, %eax
adcl $0, %eax
ret
with gcc.
//===---------------------------------------------------------------------===//
Dead argument elimination should be enhanced to handle cases when an argument is
dead to an externally visible function. Though the argument can't be removed
from the externally visible function, the caller doesn't need to pass it in.
For example in this testcase:
void foo(int X) __attribute__((noinline));
void foo(int X) { sideeffect(); }
void bar(int A) { foo(A+1); }
We compile bar to:
define void @bar(i32 %A) nounwind ssp {
%0 = add nsw i32 %A, 1 ; <i32> [#uses=1]
tail call void @foo(i32 %0) nounwind noinline ssp
ret void
}
The add is dead, we could pass in 'i32 undef' instead. This occurs for C++
templates etc, which usually have linkonce_odr/weak_odr linkage, not internal
linkage.
//===---------------------------------------------------------------------===//
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;
}
//===---------------------------------------------------------------------===//
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).
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//===---------------------------------------------------------------------===//
Solve this DAG isel folding deficiency:
int X, Y;
void fn1(void)
{
X = X | (Y << 3);
}
compiles to
fn1:
movl Y, %eax
shll $3, %eax
orl X, %eax
movl %eax, X
ret
The problem is the store's chain operand is not the load X but rather
a TokenFactor of the load X and load Y, which prevents the folding.
There are two ways to fix this:
1. The dag combiner can start using alias analysis to realize that y/x
don't alias, making the store to X not dependent on the load from Y.
2. The generated isel could be made smarter in the case it can't
disambiguate the pointers.
Number 1 is the preferred solution.
This has been "fixed" by a TableGen hack. But that is a short term workaround
which will be removed once the proper fix is made.
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
Shrink: (setlt (loadi32 P), 0) -> (setlt (loadi8 Phi), 0)
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
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);
}
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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.
//===---------------------------------------------------------------------===//
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
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.
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
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
//===---------------------------------------------------------------------===//
We should produce an unaligned load from code like this:
v4sf example(float *P) {
return (v4sf){P[0], P[1], P[2], P[3] };
}
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
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 isn't recognized as bswap by instcombine (yes, it really is bswap):
unsigned long reverse(unsigned v) {
unsigned t;
t = v ^ ((v << 16) | (v >> 16));
t &= ~0xff0000;
v = (v << 24) | (v >> 8);
return v ^ (t >> 8);
}
Neither is this (very standard idiom):
int f(int n)
{
return (((n) << 24) | (((n) & 0xff00) << 8)
| (((n) >> 8) & 0xff00) | ((n) >> 24));
}
//===---------------------------------------------------------------------===//
[LOOP RECOGNITION]
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
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 is a form of idiom recognition for loops, the same thing that could be
useful for recognizing memset/memcpy. This sort of thing should be added to the
loop idiom pass.
//===---------------------------------------------------------------------===//
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];
}
//===---------------------------------------------------------------------===//
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
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.
//===---------------------------------------------------------------------===//
LSR should know what GPR types a target has from TargetData. This code:
volatile short X, Y; // globals
void foo(int N) {
int i;
for (i = 0; i < N; i++) { X = i; Y = i*4; }
}
produces two near identical IV's (after promotion) on PPC/ARM:
LBB1_2:
ldr r3, LCPI1_0
ldr r3, [r3]
strh r2, [r3]
ldr r3, LCPI1_1
ldr r3, [r3]
strh r1, [r3]
add r1, r1, #4
add r2, r2, #1 <- [0,+,1]
sub r0, r0, #1 <- [0,-,1]
cmp r0, #0
bne LBB1_2
LSR should reuse the "+" IV for the exit test.
//===---------------------------------------------------------------------===//
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.
; RUN: llvm-as < %s | opt -tailcallelim | llvm-dis | not grep call
entry:
%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 ],
[ %tmp.9, %then.1 ]
}
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
Argument promotion should promote arguments for recursive functions, like
this:
; RUN: llvm-as < %s | opt -argpromotion | llvm-dis | grep x.val
%tmp = load i32* %x ; <i32> [#uses=0]
%tmp.foo = call i32 @foo( i32* %x ) ; <i32> [#uses=1]
ret i32 %tmp.foo
%tmp3 = call i32 @foo( i32* %x ) ; <i32> [#uses=1]
ret i32 %tmp3
//===---------------------------------------------------------------------===//
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
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.
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.
//===---------------------------------------------------------------------===//
Investigate lowering of sparse switch statements into perfect hash tables:
http://burtleburtle.net/bob/hash/perfect.html
//===---------------------------------------------------------------------===//
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];
void foo() {
int i, b;
for (b = 0; b < 10000000; b++)
for (i = 0; i < 256; i++)
a[i] = -a[i];
}
void foo() {
int i, b;
for (b = 0; b < 10000000; b++)
for (i = 0; i < 256; i++)
a[i] ^= (1ULL << 63);
}
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.
//===---------------------------------------------------------------------===//
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
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 (-O3 -fno-exceptions -static -fomit-frame-pointer):
__Z9GetHotKeyv:
pushl %esi
movl 8(%esp), %eax
movb _m_HotKey+3, %cl
movb _m_HotKey+4, %dl
movb _m_HotKey+2, %ch
movw _m_HotKey, %si
movw %si, (%eax)
movb %ch, 2(%eax)
movb %cl, 3(%eax)
movb %dl, 4(%eax)
popl %esi
ret $4
GCC produces:
__Z9GetHotKeyv:
movl _m_HotKey, %edx
movl 4(%esp), %eax
movl %edx, (%eax)
movzwl _m_HotKey+4, %edx
movw %dx, 4(%eax)
ret $4
The LLVM IR contains the needed alignment info, so we should be able to
merge the loads and stores into 4-byte loads:
%struct.THotKey = type { i16, i8, i8, i8 }
define void @_Z9GetHotKeyv(%struct.THotKey* sret %agg.result) nounwind {
...
%tmp2 = load i16* getelementptr (@m_HotKey, i32 0, i32 0), align 8
%tmp5 = load i8* getelementptr (@m_HotKey, i32 0, i32 1), align 2
%tmp8 = load i8* getelementptr (@m_HotKey, i32 0, i32 2), align 1
%tmp11 = load i8* getelementptr (@m_HotKey, i32 0, i32 3), align 2
Alternatively, we should use a small amount of base-offset alias analysis
to make it so the scheduler doesn't need to hold all the loads in regs at
once.
//===---------------------------------------------------------------------===//
We should add an FRINT node to the DAG to model targets that have legal
implementations of ceil/floor/rint.
//===---------------------------------------------------------------------===//
Consider:
int test() {
Benjamin Kramer
committed
long long input[8] = {1,0,1,0,1,0,1,0};
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
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.
//===---------------------------------------------------------------------===//
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;
}
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
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 f(unsigned long long x, int y) {
return (x << y) | (x >> 64-y);
}
unsigned f2(unsigned x, int y){
return (x << y) | (x >> 32-y);
}
unsigned long long f3(unsigned long long x){
int y = 9;
return (x << y) | (x >> 64-y);
}
unsigned f4(unsigned x){
int y = 10;
return (x << y) | (x >> 32-y);
}
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);
}
}
On X86-64, we only handle f2/f3/f4 right. On x86-32, a few of these
generate truly horrible code, instead of using shld and friends. On
ARM, we end up with calls to L___lshrdi3/L___ashldi3 in f, which is
badness. PPC64 misses f, f5 and f6. CellSPU aborts in isel.
//===---------------------------------------------------------------------===//
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
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.
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
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).
//===---------------------------------------------------------------------===//
We miss some instcombines for stuff like this:
void bar (void);
void foo (unsigned int a) {
/* This one is equivalent to a >= (3 << 2). */
if ((a >> 2) >= 3)
bar ();
}
A few other related ones are in GCC PR14753.
//===---------------------------------------------------------------------===//
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".
//===---------------------------------------------------------------------===//
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);
}
//===---------------------------------------------------------------------===//
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
}
//===---------------------------------------------------------------------===//
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
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)