X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FREADME.txt;h=341c5c1ff472f9f683fbc87384b4a44b9b0a2bc1;hb=0a0e68a7eac0513505aff3079e2d5d6864e51895;hp=812f6fdbe59b89bd8c7cf91af6a7d1867fe98cb1;hpb=ffb08f569b7e5568865388431797652ae5533a29;p=oota-llvm.git diff --git a/lib/Target/README.txt b/lib/Target/README.txt index 812f6fdbe59..341c5c1ff47 100644 --- a/lib/Target/README.txt +++ b/lib/Target/README.txt @@ -1552,3 +1552,172 @@ This could be eliminated by doing the strlen once in bb8, saving code size and improving perf on the bb8->9->10 path. //===---------------------------------------------------------------------===// + +I see an interesting fully redundant call to strlen left in 186.crafty:InputMove +which looks like: + %movetext11 = getelementptr [128 x i8]* %movetext, i32 0, i32 0 + + +bb62: ; preds = %bb55, %bb53 + %promote.0 = phi i32 [ %169, %bb55 ], [ 0, %bb53 ] + %171 = call i32 @strlen(i8* %movetext11) nounwind readonly align 1 + %172 = add i32 %171, -1 ; [#uses=1] + %173 = getelementptr [128 x i8]* %movetext, i32 0, i32 %172 + +... no stores ... + br i1 %or.cond, label %bb65, label %bb72 + +bb65: ; preds = %bb62 + store i8 0, i8* %173, align 1 + br label %bb72 + +bb72: ; preds = %bb65, %bb62 + %trank.1 = phi i32 [ %176, %bb65 ], [ -1, %bb62 ] + %177 = call i32 @strlen(i8* %movetext11) nounwind readonly align 1 + +Note that on the bb62->bb72 path, that the %177 strlen call is partially +redundant with the %171 call. At worst, we could shove the %177 strlen call +up into the bb65 block moving it out of the bb62->bb72 path. However, note +that bb65 stores to the string, zeroing out the last byte. This means that on +that path the value of %177 is actually just %171-1. A sub is cheaper than a +strlen! + +This pattern repeats several times, basically doing: + + A = strlen(P); + P[A-1] = 0; + B = strlen(P); + where it is "obvious" that B = A-1. + +//===---------------------------------------------------------------------===// + +186.crafty contains this interesting pattern: + +%77 = call i8* @strstr(i8* getelementptr ([6 x i8]* @"\01LC5", i32 0, i32 0), + i8* %30) +%phitmp648 = icmp eq i8* %77, getelementptr ([6 x i8]* @"\01LC5", i32 0, i32 0) +br i1 %phitmp648, label %bb70, label %bb76 + +bb70: ; preds = %OptionMatch.exit91, %bb69 + %78 = call i32 @strlen(i8* %30) nounwind readonly align 1 ; [#uses=1] + +This is basically: + cststr = "abcdef"; + if (strstr(cststr, P) == cststr) { + x = strlen(P); + ... + +The strstr call would be significantly cheaper written as: + +cststr = "abcdef"; +if (memcmp(P, str, strlen(P))) + x = strlen(P); + +This is memcmp+strlen instead of strstr. This also makes the strlen fully +redundant. + +//===---------------------------------------------------------------------===// + +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( + i8* getelementptr ([10 x i8]* @out.4543, i32 0, i32 0), + i8* getelementptr ([7 x i8]* @"\01LC28700", i32 0, i32 0), i32 7, i32 1) +%101 = call@printf(i8* ... @out.4543, i32 0, i32 0)) nounwind + +It is basically doing: + + memcpy(globalarray, "string"); + printf(..., globalarray); + +Anyway, by knowing that printf just reads the memory and forward substituting +the string directly into the printf, this eliminates reads from globalarray. +Since this pattern occurs frequently in crafty (due to the "DisplayTime" and +other similar functions) there are many stores to "out". Once all the printfs +stop using "out", all that is left is the memcpy's into it. This should allow +globalopt to remove the "stored only" global. + +//===---------------------------------------------------------------------===// + +This code: + +define inreg i32 @foo(i8* inreg %p) nounwind { + %tmp0 = load i8* %p + %tmp1 = ashr i8 %tmp0, 5 + %tmp2 = sext i8 %tmp1 to i32 + ret i32 %tmp2 +} + +could be dagcombine'd to a sign-extending load with a shift. +For example, on x86 this currently gets this: + + movb (%eax), %al + sarb $5, %al + movsbl %al, %eax + +while it could get this: + + movsbl (%eax), %eax + sarl $5, %eax + +//===---------------------------------------------------------------------===// + +GCC PR31029: + +int test(int x) { return 1-x == x; } // --> return false +int test2(int x) { return 2-x == x; } // --> return x == 1 ? + +Always foldable for odd constants, what is the rule for even? + +//===---------------------------------------------------------------------===// + +PR 3381: GEP to field of size 0 inside a struct could be turned into GEP +for next field in struct (which is at same address). + +For example: store of float into { {{}}, float } could be turned into a store to +the float directly. + +//===---------------------------------------------------------------------===// + +#include +double foo(double a) { return sin(a); } + +This compiles into this on x86-64 Linux: +foo: + subq $8, %rsp + call sin + addq $8, %rsp + ret +vs: + +foo: + jmp sin + +//===---------------------------------------------------------------------===// + +Instcombine should replace the load with a constant in: + + static const char x[4] = {'a', 'b', 'c', 'd'}; + + unsigned int y(void) { + return *(unsigned int *)x; + } + +It currently only does this transformation when the size of the constant +is the same as the size of the integer (so, try x[5]) and the last byte +is a null (making it a C string). There's no need for these restrictions. + +//===---------------------------------------------------------------------===// +