//===---------------------------------------------------------------------===//
-Make the PPC branch selector target independant
+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;
+}
//===---------------------------------------------------------------------===//
Consider:
int test() {
- long long input[8] = {1,1,1,1,1,1,1,1};
+ long long input[8] = {1,0,1,0,1,0,1,0};
foo(input);
}
//===---------------------------------------------------------------------===//
+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
//===---------------------------------------------------------------------===//
-void a(int variable)
-{
- if (variable == 4 || variable == 6)
- bar();
-}
-This should optimize to "if ((variable | 2) == 6)". Currently not
-optimized with "clang -emit-llvm-bc | opt -std-compile-opts | llc".
-
-//===---------------------------------------------------------------------===//
-
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;}
//===---------------------------------------------------------------------===//
-int a(int x) {return (x & 8) == 0 ? -1 : -9;}
-Should combine to (x | -9) ^ 8. Currently not optimized with "clang
--emit-llvm-bc | opt -std-compile-opts".
-
-//===---------------------------------------------------------------------===//
-
-int a(int x) {return (x & 8) == 0 ? -9 : -1;}
-Should combine to x | -9. 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".
actually a conditional increment: loadpre18.c loadpre19.c
+//===---------------------------------------------------------------------===//
+
+[LOAD PRE / STORE SINKING / SPEC HACK]
+
+This is a chunk of code from 456.hmmer:
+
+int f(int M, int *mc, int *mpp, int *tpmm, int *ip, int *tpim, int *dpp,
+ int *tpdm, int xmb, int *bp, int *ms) {
+ int k, sc;
+ for (k = 1; k <= M; k++) {
+ mc[k] = mpp[k-1] + tpmm[k-1];
+ if ((sc = ip[k-1] + tpim[k-1]) > mc[k]) mc[k] = sc;
+ if ((sc = dpp[k-1] + tpdm[k-1]) > mc[k]) mc[k] = sc;
+ if ((sc = xmb + bp[k]) > mc[k]) mc[k] = sc;
+ mc[k] += ms[k];
+ }
+}
+
+It is very profitable for this benchmark to turn the conditional stores to mc[k]
+into a conditional move (select instr in IR) and allow the final store to do the
+store. See GCC PR27313 for more details. Note that this is valid to xform even
+with the new C++ memory model, since mc[k] is previously loaded and later
+stored.
//===---------------------------------------------------------------------===//
This is interesting for a couple reasons. First, in this:
- %3073 = call i8* @strcpy(i8* %3072, i8* %3071) nounwind
- %strlen = call i32 @strlen(i8* %3072)
-
-The strlen could be replaced with: %strlen = sub %3072, %3073, because the
-strcpy call returns a pointer to the end of the string. Based on that, the
-endptr GEP just becomes equal to 3073, which eliminates a strlen call and GEP.
-
-Second, the memcpy+strlen strlen can be replaced with:
+The memcpy+strlen strlen can be replaced with:
%3074 = call i32 @strlen([5 x i8]* @"\01LC42") nounwind readonly
//===---------------------------------------------------------------------===//
-186.crafty also contains this code:
-
-%1906 = call i32 @strlen(i8* getelementptr ([32 x i8]* @pgn_event, i32 0,i32 0))
-%1907 = getelementptr [32 x i8]* @pgn_event, i32 0, i32 %1906
-%1908 = call i8* @strcpy(i8* %1907, i8* %1905) nounwind align 1
-%1909 = call i32 @strlen(i8* getelementptr ([32 x i8]* @pgn_event, i32 0,i32 0))
-%1910 = getelementptr [32 x i8]* @pgn_event, i32 0, i32 %1909
-
-The last strlen is computable as 1908-@pgn_event, which means 1910=1908.
-
-//===---------------------------------------------------------------------===//
-
186.crafty has this interesting pattern with the "out.4543" variable:
call void @llvm.memcpy.i32(
//===---------------------------------------------------------------------===//
-Missed instcombine transformation:
-void b();
-void a(int x) { if (((1<<x)&8)==0) b(); }
-
-The shift should be optimized out. Testcase derived from gcc.
-
-//===---------------------------------------------------------------------===//
-
Missed instcombine or reassociate transformation:
int a(int a, int b) { return (a==12)&(b>47)&(b<58); }
//===---------------------------------------------------------------------===//
Missed instcombine transformation:
-define i32 @a(i32 %x) nounwind readnone {
-entry:
- %rem = srem i32 %x, 32
- %shl = shl i32 1, %rem
- ret i32 %shl
-}
-The srem can be transformed to an and because if x is negative, the shift is
-undefined. Testcase derived from gcc.
+ %382 = srem i32 %tmp14.i, 64 ; [#uses=1]
+ %383 = zext i32 %382 to i64 ; [#uses=1]
+ %384 = shl i64 %381, %383 ; [#uses=1]
+ %385 = icmp slt i32 %tmp14.i, 64 ; [#uses=1]
+
+The srem can be transformed to an and because if %tmp14.i is negative, the
+shift is undefined. Testcase derived from 403.gcc.
//===---------------------------------------------------------------------===//
-Missed instcombine/dagcombine transformation:
-define i32 @a(i32 %x, i32 %y) nounwind readnone {
-entry:
- %mul = mul i32 %y, -8
- %sub = sub i32 %x, %mul
- ret i32 %sub
-}
+This is a range comparison on a divided result (from 403.gcc):
+
+ %1337 = sdiv i32 %1336, 8 ; [#uses=1]
+ %.off.i208 = add i32 %1336, 7 ; [#uses=1]
+ %1338 = icmp ult i32 %.off.i208, 15 ; [#uses=1]
+
+We already catch this (removing the sdiv) if there isn't an add, we should
+handle the 'add' as well. This is a common idiom with it's builtin_alloca code.
+C testcase:
-Should compile to something like x+y*8, but currently compiles to an
-inefficient result. Testcase derived from gcc.
+int a(int x) { return (unsigned)(x/16+7) < 15; }
+
+Another similar case involves truncations on 64-bit targets:
+
+ %361 = sdiv i64 %.046, 8 ; [#uses=1]
+ %362 = trunc i64 %361 to i32 ; [#uses=2]
+...
+ %367 = icmp eq i32 %362, 0 ; [#uses=1]
//===---------------------------------------------------------------------===//
//===---------------------------------------------------------------------===//
+This code (from GCC PR28685):
+
+int test(int a, int b) {
+ int lt = a < b;
+ int eq = a == b;
+ if (lt)
+ return 1;
+ return eq;
+}
+
+Is compiled to:
+
+define i32 @test(i32 %a, i32 %b) nounwind readnone ssp {
+entry:
+ %cmp = icmp slt i32 %a, %b
+ br i1 %cmp, label %return, label %if.end
+
+if.end: ; preds = %entry
+ %cmp5 = icmp eq i32 %a, %b
+ %conv6 = zext i1 %cmp5 to i32
+ ret i32 %conv6
+
+return: ; preds = %entry
+ ret i32 1
+}
+
+it could be:
+
+define i32 @test__(i32 %a, i32 %b) nounwind readnone ssp {
+entry:
+ %0 = icmp sle i32 %a, %b
+ %retval = zext i1 %0 to i32
+ ret i32 %retval
+}
+
+//===---------------------------------------------------------------------===//
+
+This compare could fold to false:
+
+define i1 @g(i32 a) nounwind readnone {
+ %add = shl i32 %a, 1
+ %mul = shl i32 %a, 1
+ %cmp = icmp ugt i32 %add, %mul
+ ret i1 %cmp
+}
+
+//===---------------------------------------------------------------------===//