X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FREADME.txt;h=6d42d812a00bf3753843531996f3021a0d60c792;hb=867fe8570f299a058f155f98646d85cabc27155b;hp=f4f767aa4d5f00ae8a762c18d3bc06038297aebe;hpb=8c47d3b73f43edcbca7434772d18b10079cc3810;p=oota-llvm.git diff --git a/lib/Target/README.txt b/lib/Target/README.txt index f4f767aa4d5..6d42d812a00 100644 --- a/lib/Target/README.txt +++ b/lib/Target/README.txt @@ -2,6 +2,38 @@ Target Independent Opportunities: //===---------------------------------------------------------------------===// +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. @@ -300,6 +332,14 @@ unsigned long reverse(unsigned v) { 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] @@ -898,17 +938,6 @@ The expression should optimize to something like //===---------------------------------------------------------------------===// -From GCC Bug 3756: -int -pn (int n) -{ - return (n >= 0 ? 1 : -1); -} -Should combine to (n >> 31) | 1. Currently not optimized with "clang --emit-llvm-bc | opt -std-compile-opts | llc". - -//===---------------------------------------------------------------------===// - void a(int variable) { if (variable == 4 || variable == 6) @@ -1311,12 +1340,6 @@ void foo (int a, struct T b) simplifylibcalls should do several optimizations for strspn/strcspn: -strcspn(x, "") -> strlen(x) -strcspn("", x) -> 0 -strspn("", x) -> 0 -strspn(x, "") -> strlen(x) -strspn(x, "a") -> strchr(x, 'a')-x - strcspn(x, "a") -> inlined loop for up to 3 letters (similarly for strspn): size_t __strcspn_c3 (__const char *__s, int __reject1, int __reject2, @@ -1439,33 +1462,6 @@ This pattern repeats several times, basically doing: //===---------------------------------------------------------------------===// -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,3 +1903,83 @@ of the ADD, and replacing the ADD with the ADDE, should give the desired result. (That said, we are doing a lot better than gcc on this testcase. :) ) //===---------------------------------------------------------------------===// + +Switch lowering generates less than ideal code for the following switch: +define void @a(i32 %x) nounwind { +entry: + switch i32 %x, label %if.end [ + i32 0, label %if.then + i32 1, label %if.then + i32 2, label %if.then + i32 3, label %if.then + i32 5, label %if.then + ] +if.then: + tail call void @foo() nounwind + ret void +if.end: + ret void +} +declare void @foo() + +Generated code on x86-64 (other platforms give similar results): +a: + cmpl $5, %edi + ja .LBB0_2 + movl %edi, %eax + movl $47, %ecx + btq %rax, %rcx + jb .LBB0_3 +.LBB0_2: + ret +.LBB0_3: + jmp foo # TAILCALL + +The movl+movl+btq+jb could be simplified to a cmpl+jne. + +Or, if we wanted to be really clever, we could simplify the whole thing to +something like the following, which eliminates a branch: + xorl $1, %edi + cmpl $4, %edi + ja .LBB0_2 + ret +.LBB0_2: + jmp foo # TAILCALL +//===---------------------------------------------------------------------===// +Given a branch where the two target blocks are identical ("ret i32 %b" in +both), simplifycfg will simplify them away. But not so for a switch statement: + +define i32 @f(i32 %a, i32 %b) nounwind readnone { +entry: + switch i32 %a, label %bb3 [ + i32 4, label %bb + i32 6, label %bb + ] + +bb: ; preds = %entry, %entry + ret i32 %b + +bb3: ; preds = %entry + ret i32 %b +} +//===---------------------------------------------------------------------===// + +clang -O3 fails to devirtualize this virtual inheritance case: (GCC PR45875) + +struct c1 {}; +struct c10 : c1{ + virtual void foo (); +}; +struct c11 : c10, c1{ + virtual void f6 (); +}; +struct c28 : virtual c11{ + void f6 (); +}; +void check_c28 () { + c28 obj; + c11 *ptr = &obj; + ptr->f6 (); +} + +//===---------------------------------------------------------------------===//