diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/CodeGen/Generic/badlive.ll | 28 | ||||
-rw-r--r-- | test/CodeGen/Generic/constindices.ll | 44 | ||||
-rw-r--r-- | test/CodeGen/Generic/fwdtwice.ll | 33 | ||||
-rw-r--r-- | test/CodeGen/Generic/negintconst.ll | 48 | ||||
-rw-r--r-- | test/CodeGen/Generic/sched.ll | 30 | ||||
-rw-r--r-- | test/CodeGen/Generic/select.ll | 155 | ||||
-rw-r--r-- | test/CodeGen/Generic/spillccr.ll | 52 | ||||
-rw-r--r-- | test/LLC/badfuncptr.c | 74 | ||||
-rw-r--r-- | test/LLC/badlive.ll | 28 | ||||
-rw-r--r-- | test/LLC/callargs.c | 156 | ||||
-rw-r--r-- | test/LLC/casts.c | 84 | ||||
-rw-r--r-- | test/LLC/constindices.ll | 44 | ||||
-rw-r--r-- | test/LLC/fwdtwice.ll | 33 | ||||
-rw-r--r-- | test/LLC/negintconst.ll | 48 | ||||
-rw-r--r-- | test/LLC/poisson.c | 41 | ||||
-rw-r--r-- | test/LLC/sched.ll | 30 | ||||
-rw-r--r-- | test/LLC/select.ll | 155 | ||||
-rw-r--r-- | test/LLC/spillccr.ll | 52 | ||||
-rw-r--r-- | test/LLC/testtrace.c | 44 | ||||
-rw-r--r-- | test/LLC/varargs.c | 29 |
20 files changed, 1208 insertions, 0 deletions
diff --git a/test/CodeGen/Generic/badlive.ll b/test/CodeGen/Generic/badlive.ll new file mode 100644 index 0000000..f9c74d2 --- /dev/null +++ b/test/CodeGen/Generic/badlive.ll @@ -0,0 +1,28 @@ +implementation + +int "main"() +begin +bb0: + %reg109 = malloc int, uint 100 + br label %bb2 + +bb2: + %cann-indvar1 = phi int [ 0, %bb0 ], [ %add1-indvar1, %bb2 ] + %reg127 = mul int %cann-indvar1, 2 + %add1-indvar1 = add int %cann-indvar1, 1 + store int 999, int * %reg109, uint 0 + %cond1015 = setle int 1, 99 + %reg128 = add int %reg127, 2 + br bool %cond1015, label %bb2, label %bb4 + +bb4: ;[#uses=3] + %cann-indvar = phi uint [ %add1-indvar, %bb4 ], [ 0, %bb2 ] + %add1-indvar = add uint %cann-indvar, 1 ; <uint> [#uses=1] + store int 333, int * %reg109, uint 0 + %reg131 = add uint %add1-indvar, 3 ; <int> [#uses=1] + %cond1017 = setle uint %reg131, 99 ; <bool> [#uses=1] + br bool %cond1017, label %bb4, label %bb5 + +bb5: + ret int 0 +end diff --git a/test/CodeGen/Generic/constindices.ll b/test/CodeGen/Generic/constindices.ll new file mode 100644 index 0000000..0b8ef91 --- /dev/null +++ b/test/CodeGen/Generic/constindices.ll @@ -0,0 +1,44 @@ +; Test that a sequence of constant indices are folded correctly +; into the equivalent offset at compile-time. + +%MixedA = type { float, [15 x int], sbyte, float } + +%MixedB = type { float, %MixedA, float } + +%fmtArg = internal global [44 x sbyte] c"sqrt(2) = %g\0Aexp(1) = %g\0Api = %g\0Afive = %g\0A\00"; <[44 x sbyte]*> [#uses=1] + +implementation + +declare int "printf"(sbyte*, ...) + +int "main"() +begin + %ScalarA = alloca %MixedA + %ScalarB = alloca %MixedB + %ArrayA = alloca %MixedA, uint 4 + %ArrayB = alloca %MixedB, uint 3 + + store float 1.4142, %MixedA* %ScalarA, uint 0, ubyte 0 + store float 2.7183, %MixedB* %ScalarB, uint 0, ubyte 1, ubyte 0 + + %fptrA = getelementptr %MixedA* %ArrayA, uint 1, ubyte 0 + %fptrB = getelementptr %MixedB* %ArrayB, uint 2, ubyte 1, ubyte 0 + + store float 3.1415, float* %fptrA + store float 5.0, float* %fptrB + + %sqrtTwo = load %MixedA* %ScalarA, uint 0, ubyte 0 + %exp = load %MixedB* %ScalarB, uint 0, ubyte 1, ubyte 0 + %pi = load %MixedA* %ArrayA, uint 1, ubyte 0 + %five = load %MixedB* %ArrayB, uint 2, ubyte 1, ubyte 0 + + %dsqrtTwo = cast float %sqrtTwo to double + %dexp = cast float %exp to double + %dpi = cast float %pi to double + %dfive = cast float %five to double + + %castFmt = getelementptr [44 x sbyte]* %fmtArg, uint 0, uint 0 + call int (sbyte*, ...)* %printf(sbyte* %castFmt, double %dsqrtTwo, double %dexp, double %dpi, double %dfive) + + ret int 0 +end diff --git a/test/CodeGen/Generic/fwdtwice.ll b/test/CodeGen/Generic/fwdtwice.ll new file mode 100644 index 0000000..44c7258 --- /dev/null +++ b/test/CodeGen/Generic/fwdtwice.ll @@ -0,0 +1,33 @@ +;; +;; Test the sequence: +;; cast -> setle 0, %cast -> br %cond +;; This sequence should cause the cast value to be forwarded twice, +;; i.e., cast is forwarded to the setle and teh setle is forwarded +;; to the branch. +;; register argument of the "branch-on-register" instruction, i.e., +;; +;; This produces the bogus output instruction: +;; brlez <NULL VALUE>, .L_SumArray_bb3. +;; This came from %bb1 of sumarrray.ll generated from sumarray.c. + + +;;;; ****************************************************** +implementation +;;;; ****************************************************** + +int "SumArray"(int %Num) +begin +bb0: ;[#uses=3] + br label %Top +Top: + %Num = alloca int ; <int *> [#uses=2] + store int %Num, int * %Num + %reg108 = load int * %Num ; <int> [#uses=2] + %cast1006 = cast int %reg108 to uint ; <uint> [#uses=1] + %cond1001 = setle uint %cast1006, 0 ; <bool> [#uses=1] + br bool %cond1001, label %bb6, label %Top + +bb6: + ret int 42 +end + diff --git a/test/CodeGen/Generic/negintconst.ll b/test/CodeGen/Generic/negintconst.ll new file mode 100644 index 0000000..9e671b0 --- /dev/null +++ b/test/CodeGen/Generic/negintconst.ll @@ -0,0 +1,48 @@ +; Test that a negative constant smaller than 64 bits (e.g., int) +; is correctly implemented with sign-extension. +; In particular, the current code generated is: +; +; main: +; .L_main_LL_0: +; save %o6, -224, %o6 +; setx .G_fmtArg_1, %o1, %o0 +; setuw 1, %o1 ! i = 1 +; setuw 4294967295, %o3 ! THE BUG: 0x00000000ffffffff +; setsw 0, %i0 +; add %i6, 1999, %o2 ! fval +; add %o1, %g0, %o1 +; add %o0, 0, %o0 +; mulx %o1, %o3, %o1 ! ERROR: 0xffffffff; should be -1 +; add %o1, 3, %o1 ! ERROR: 0x100000002; should be 0x2 +; mulx %o1, 12, %o3 ! +; add %o2, %o3, %o3 ! produces bad address! +; call printf +; nop +; jmpl %i7+8, %g0 +; restore %g0, 0, %g0 +; +; llc produces: +; ioff = 2 fval = 0xffffffff7fffec90 &fval[2] = 0xb7fffeca8 +; instead of: +; ioff = 2 fval = 0xffffffff7fffec90 &fval[2] = 0xffffffff7fffeca8 +; + +%Results = type { float, float, float } + +%fmtArg = internal global [39 x sbyte] c"ioff = %u\09fval = 0x%p\09&fval[2] = 0x%p\0A\00"; <[39 x sbyte]*> [#uses=1] + +implementation + +declare int "printf"(sbyte*, ...) + +int "main"() +begin + %fval = alloca %Results, uint 4 + %i = add uint 1, 0 ; i = 1 + %iscale = mul uint %i, 4294967295 ; i*-1 = -1 + %ioff = add uint %iscale, 3 ; 3+(-i) = 2 + %fptr = getelementptr %Results* %fval, uint %ioff ; &fval[2] + %castFmt = getelementptr [39 x sbyte]* %fmtArg, uint 0, uint 0 + call int (sbyte*, ...)* %printf(sbyte* %castFmt, uint %ioff, %Results* %fval, %Results* %fptr) + ret int 0 +end diff --git a/test/CodeGen/Generic/sched.ll b/test/CodeGen/Generic/sched.ll new file mode 100644 index 0000000..b8de02d --- /dev/null +++ b/test/CodeGen/Generic/sched.ll @@ -0,0 +1,30 @@ +implementation +declare int "printf"(sbyte*, int, float) + + +int "testissue"(int %i, float %x, float %y) +begin +bb1: + %x1 = mul float %x, %y ;; x1 + %y1 = mul float %y, 0.75 ;; y1 + %z1 = add float %x1, %y1 ;; z1 = x1 + y1 + + %x2 = mul float %x, 0.5 ;; x2 + %y2 = mul float %y, 0.9 ;; y2 + %z2 = add float %x2, %y2 ;; z2 = x2 + y2 + + %z3 = add float %z1, %z2 ;; z3 = z1 + z2 + + %i1 = shl int %i, ubyte 3 ;; i1 + %j1 = add int %i, 7 ;; j1 + %m1 = add int %i1, %j1 ;; k1 = i1 + j1 +;; %m1 = div int %k1, 99 ;; m1 = k1 / 99 + + %b = setle int %m1, 6 ;; (m1 <= 6)? + br bool %b, label %bb1, label %bb2 + +bb2: + %Msg = cast ulong 0 to sbyte * + call int %printf(sbyte* %Msg, int %m1, float %z3) + ret int 0 +end diff --git a/test/CodeGen/Generic/select.ll b/test/CodeGen/Generic/select.ll new file mode 100644 index 0000000..973bc7e --- /dev/null +++ b/test/CodeGen/Generic/select.ll @@ -0,0 +1,155 @@ +%AConst = constant int 123 + +implementation + +; Test setting values of different constants in registers. +; +void "testConsts"(int %N, float %X) +begin +; <label>:0 + %a = add int %N, 1 ; 1 should be put in immed field + %a2= add int %N, 12345678 ; constant has to be loaded + %b = add short 4, 3 ; one of the operands shd be immed + %c = add float %X, 0.0 ; will this be optimzzed? + %d = add float %X, 3.1415 ; constant has to be loaded + %f = add uint 4294967295, 10 ; result shd be 9 (not in immed fld) + %g = add ushort 20, 65535 ; result shd be 19 (65536 in immed fld) + %g = add ushort 65535, 30 ; result shd be 29 (not in immed fld) + %h = add ubyte 40, 255 ; result shd be 39 (255 in immed fld) + %h = add ubyte 255, 50 ; result shd be 49 (not in immed fld) + + ret void +end + +; A SetCC whose result is used should produce instructions to +; compute the boolean value in a register. One whose result +; is unused will only generate the condition code but not +; the boolean result. +; +void "unusedBool"(int * %x, int * %y) +begin +; <label>:0 ; [#uses=0] + seteq int * %x, %y ; <bool>:0 [#uses=1] + not bool %0 ; <bool>:1 [#uses=0] + setne int * %x, %y ; <bool>:2 [#uses=0] + ret void +end + +; A constant argument to a Phi produces a Cast instruction in the +; corresponding predecessor basic block. This checks a few things: +; -- phi arguments coming from the bottom of the same basic block +; (they should not be forward substituted in the machine code!) +; -- code generation for casts of various types +; -- use of immediate fields for integral constants of different sizes +; -- branch on a constant condition +; +void "mergeConstants"(int * %x, int * %y) +begin +; <label>:0 + br label %Top +Top: + phi int [ 0, %0 ], [ 1, %Top ], [ 524288, %Next ] + phi float [ 0.0, %0 ], [ 1.0, %Top ], [ 2.0, %Next ] + phi double [ 0.5, %0 ], [ 1.5, %Top ], [ 2.5, %Next ] + phi bool [ true, %0 ], [ false,%Top ], [ true, %Next ] + br bool true, label %Top, label %Next +Next: + br label %Top +end + + + +; A constant argument to a cast used only once should be forward substituted +; and loaded where needed, which happens is: +; -- User of cast has no immediate field +; -- User of cast has immediate field but constant is too large to fit +; or constant is not resolved until later (e.g., global address) +; -- User of cast uses it as a call arg. or return value so it is an implicit +; use but has to be loaded into a virtual register so that the reg. +; allocator can allocate the appropriate phys. reg. for it +; +int* "castconst"(float) +begin +; <label>:0 + %castbig = cast ulong 99999999 to int + %castsmall = cast ulong 1 to int + %usebig = add int %castbig, %castsmall + + %castglob = cast int* %AConst to long* + %dummyl = load long* %castglob + + %castnull = cast ulong 0 to int* + ret int* %castnull +end + + + +; Test branch-on-comparison-with-zero, in two ways: +; 1. can be folded +; 2. cannot be folded because result of comparison is used twice +; +void "testbool"(int, int) ; Def %0, %1 + const int 0 ; Def 2 + const int -4 ; Def 3 +begin +; <label>:0 + br label %Top +Top: + add int %0, %1 ; Def 4 + sub int %4, %3 ; Def 5 + setle int %5, %2 ; Def 0 - bool plane + br bool %0, label %retlbl, label %loop + +loop: + add int %0, %1 ; Def 6 + sub int %4, %3 ; Def 7 + setle int %7, %2 ; Def 1 - bool + not bool %1 ; Def 2 - bool. first use of bool %1 + br bool %1, label %loop, label %Top ; second use of bool %1 + +retlbl: + ret void +end + + +; Test branch on floating point comparison +; +void "testfloatbool"(float %x, float %y) ; Def %0, %1 - float +begin +; <label>:0 + br label %Top +Top: + %p = add float %x, %y ; Def 2 - float + %z = sub float %x, %y ; Def 3 - float + %b = setle float %p, %z ; Def 0 - bool + %c = not bool %b ; Def 1 - bool + br bool %b, label %Top, label %goon +goon: + ret void +end + + +; Test cases where an LLVM instruction requires no machine +; instructions (e.g., cast int* to long). But there are 2 cases: +; 1. If the result register has only a single use and the use is in the +; same basic block, the operand will be copy-propagated during +; instruction selection. +; 2. If the result register has multiple uses or is in a different +; basic block, it cannot (or will not) be copy propagated during +; instruction selection. It will generate a +; copy instruction (add-with-0), but this copy should get coalesced +; away by the register allocator. +; +int "checkForward"(int %N, int* %A) +begin + +bb2: ;;<label> + %reg114 = shl int %N, ubyte 2 ;; + %cast115 = cast int %reg114 to int* ;; reg114 will be propagated + %reg116 = add int* %A, %cast115 ;; + %reg118 = load int* %reg116 ;; + %cast117 = cast int %reg118 to long ;; reg118 will be copied 'cos + %reg159 = add long 1234567, %cast117 ;; cast117 has 2 uses, here + %reg160 = add long 7654321, %cast117 ;; and here. + ret void +end diff --git a/test/CodeGen/Generic/spillccr.ll b/test/CodeGen/Generic/spillccr.ll new file mode 100644 index 0000000..d34ea3f --- /dev/null +++ b/test/CodeGen/Generic/spillccr.ll @@ -0,0 +1,52 @@ +; July 6, 2002 -- LLC Regression test +; This test case checks if the integer CC register %xcc (or %ccr) +; is correctly spilled. The code fragment came from function +; MakeGraph in Olden-mst. +; The original code made all comparisons with 0, so that the %xcc +; register is not needed for the branch in the first basic block. +; Replace 0 with 1 in the first comparson so that the +; branch-on-register instruction cannot be used directly, i.e., +; the %xcc register is needed for the first branch. +; + %Graph = type %struct.graph_st* + %Hash = type %struct.hash* + %HashEntry = type %struct.hash_entry* + %Vertex = type %struct.vert_st* + %struct.graph_st = type { [1 x %Vertex] } + %struct.hash = type { %HashEntry*, int (uint)*, int } + %struct.hash_entry = type { uint, sbyte*, %HashEntry } + %struct.vert_st = type { int, %Vertex, %Hash } +%HashRange = internal uninitialized global int ; <int*> [#uses=1] +%.LC0 = internal global [13 x sbyte] c"Make phase 2\00" ; <[13 x sbyte]*> [#uses=1] +%.LC1 = internal global [13 x sbyte] c"Make phase 3\00" ; <[13 x sbyte]*> [#uses=1] +%.LC2 = internal global [13 x sbyte] c"Make phase 4\00" ; <[13 x sbyte]*> [#uses=1] +%.LC3 = internal global [15 x sbyte] c"Make returning\00" ; <[15 x sbyte]*> [#uses=1] + +implementation ; Functions: + +%Graph %MakeGraph(int %numvert, int %numproc) { +bb1: ;[#uses=1] + %reg111 = add int %numproc, -1 ; <int> [#uses=3] + %cond275 = setlt int %reg111, 1 ; <bool> [#uses=2] + %cond276 = setle int %reg111, 0 ; <bool> [#uses=1] + %cond277 = setge int %numvert, 0 ; <bool> [#uses=2] + %reg162 = add int %numvert, 3 ; <int> [#uses=2] + br bool %cond275, label %bb7, label %bb4 + +bb4: + br bool %cond276, label %bb7, label %bb5 + +bb5: + br bool %cond277, label %bb7, label %bb6 + +bb6: ;[#uses=2] + ret %Graph null + +bb7: ;[#uses=2] + ret %Graph null +} + +int %main(int argc, sbyte** argv) { +bb1: + %reg100 = call %struct.graph_st* (int, int)* %MakeGraph(1, 1) + diff --git a/test/LLC/badfuncptr.c b/test/LLC/badfuncptr.c new file mode 100644 index 0000000..8da7fbe --- /dev/null +++ b/test/LLC/badfuncptr.c @@ -0,0 +1,74 @@ +/* + * Program: llc + * + * Test Name: badfuncptr.c + * + * Test Problem: + * Indirect call via function pointer is mishandled in reg. alloc. + * The indirect call address was allocated the same register as the + * first outgoing argument, so it was overwritten before the call. + * + * Test Resolution: + * In PhyRegAlloc.cpp, mark the live range for the indirect call + * address as having a Call Interference. This has to be done + * as a special case since it may not be live after the call. + * + * Resolution Status: + * Fixed on 3/29/02 -- Adve. + */ +/* For copyright information, see olden_v1.0/COPYRIGHT */ + +#include <stdlib.h> +/* #include "hash.h" */ +/*--------*/ +/* hash.h */ +/*--------*/ +/* For copyright information, see olden_v1.0/COPYRIGHT */ + +#include "stdio.h" + +typedef struct hash_entry { + unsigned int key; + void *entry; + struct hash_entry *next; +} *HashEntry; + +typedef struct hash { + HashEntry *array; + int (*mapfunc)(unsigned int); + int size; +} *Hash; + +Hash MakeHash(int size, int (*map)(unsigned int)); +void *HashLookup(unsigned int key, Hash hash); +void HashInsert(void *entry,unsigned int key, Hash hash); +void HashDelete(unsigned int key, Hash hash); +/*--------*/ +/* END hash.h */ +/*--------*/ + +#define assert(num,a) if (!(a)) {printf("Assertion failure:%d in hash\n",num); exit(-1);} + +void *HashLookup(unsigned int key, Hash hash) +{ + int j; + HashEntry ent; + + j = (hash->mapfunc)(key); /* 14% miss in hash->mapfunc */ + assert(1,j>=0); + assert(2,j<hash->size); + for (ent = hash->array[j]; /* 17% miss in hash->array[j] */ /* adt_pf can't detect :( */ + ent && /* 47% miss in ent->key */ /* adt_pf can detect :) */ + ent->key!=key; + ent=ent->next); /* 8% miss in ent->next */ /* adt_pf can detect :) */ + if (ent) return ent->entry; + return NULL; +} + +/* essentially dummy main so testing does not fail */ +int +main() +{ + printf("&HashLookup = 0x%p\n", HashLookup); + return 0; +} diff --git a/test/LLC/badlive.ll b/test/LLC/badlive.ll new file mode 100644 index 0000000..f9c74d2 --- /dev/null +++ b/test/LLC/badlive.ll @@ -0,0 +1,28 @@ +implementation + +int "main"() +begin +bb0: + %reg109 = malloc int, uint 100 + br label %bb2 + +bb2: + %cann-indvar1 = phi int [ 0, %bb0 ], [ %add1-indvar1, %bb2 ] + %reg127 = mul int %cann-indvar1, 2 + %add1-indvar1 = add int %cann-indvar1, 1 + store int 999, int * %reg109, uint 0 + %cond1015 = setle int 1, 99 + %reg128 = add int %reg127, 2 + br bool %cond1015, label %bb2, label %bb4 + +bb4: ;[#uses=3] + %cann-indvar = phi uint [ %add1-indvar, %bb4 ], [ 0, %bb2 ] + %add1-indvar = add uint %cann-indvar, 1 ; <uint> [#uses=1] + store int 333, int * %reg109, uint 0 + %reg131 = add uint %add1-indvar, 3 ; <int> [#uses=1] + %cond1017 = setle uint %reg131, 99 ; <bool> [#uses=1] + br bool %cond1017, label %bb4, label %bb5 + +bb5: + ret int 0 +end diff --git a/test/LLC/callargs.c b/test/LLC/callargs.c new file mode 100644 index 0000000..1c31890 --- /dev/null +++ b/test/LLC/callargs.c @@ -0,0 +1,156 @@ +#include <stdio.h> +#include <stdarg.h> + + +#undef LLVM_CAN_PASS_STRUCTS_BY_VALUE +#ifdef LLVM_CAN_PASS_STRUCTS_BY_VALUE +typedef struct SmallStruct_struct { + char c1, c2, c3, c4; + int n; +} SmallStruct; + + +typedef struct BigStruct_struct { + char c1, c2, c3, c4; + double d1, d2; /* Note: d1 will need padding */ + int n; + struct BigStruct_struct* next; /* Note: next will need padding */ +} BigStruct; + + +SmallStruct +printStructArgs(SmallStruct s1, /* Could fit in reg */ + int a1, float a2, char a3, double a4, char* a5, + BigStruct s2, /* Must go on stack */ + int a6, float a7, char a8, double a9, char* a10, + SmallStruct s3, /* Probably no available regs */ + int a11, float a12, char a13, double a14, char* a15) +{ + SmallStruct result; + + printf("\nprintStructArgs with 13 arguments:\n"); + printf("\tArg 1 : %c %c %c %c %d\n", s1.c1, s1.c2, s1.c3, s1.c4, s1.n); + printf("\tArgs 2-6 : %d %f %c %lf %c\n", a1, a2, a3, a4, *a5); + printf("\tArg 7 : %c %c %c %c %lf %lf %d %p\n", + s2.c1, s2.c2, s2.c3, s2.c4, s2.d1, s2.d2, s2.n,s2.next); + printf("\tArg 8 : %c %c %c %c %d\n", s3.c1, s3.c2, s3.c3, s3.c4, s3.n); + printf("\tArgs 9-13 : %d %f %c %lf %c\n", a6, a7, a8, a9, *a10); + printf("\tArgs 14-18: %d %f %c %lf %c\n", a11, a12, a13, a14, *a15); + printf("\n"); + + result.c1 = s2.c1; + result.c2 = s2.c2; + result.c3 = s2.c3; + result.c4 = s2.c4; + result.n = s2.n; + + return result; +} +#endif /* LLVM_CAN_PASS_STRUCTS_BY_VALUE */ + +#undef LLC_SUPPORTS_VARARGS_FUNCTIONS +#ifdef LLC_SUPPORTS_VARARGS_FUNCTIONS +void +printVarArgs(int a1, ...) +{ + double a2, a7, a12; /* float is promoted to double! */ + int a3, a8, a13; /* char is promoted to int! */ + double a4, a9, a14; + char *a5, *a10, *a15; + int a6, a11; + + va_list ap; + va_start(ap, a1); + a2 = va_arg(ap, double); + a3 = va_arg(ap, int); + a4 = va_arg(ap, double); + a5 = va_arg(ap, char*); + + a6 = va_arg(ap, int); + a7 = va_arg(ap, double); + a8 = va_arg(ap, int); + a9 = va_arg(ap, double); + a10 = va_arg(ap, char*); + + a11 = va_arg(ap, int); + a12 = va_arg(ap, double); + a13 = va_arg(ap, int); + a14 = va_arg(ap, double); + a15 = va_arg(ap, char*); + + printf("\nprintVarArgs with 15 arguments:\n"); + printf("\tArgs 1-5 : %d %f %c %lf %c\n", a1, a2, a3, a4, *a5); + printf("\tArgs 6-10 : %d %f %c %lf %c\n", a6, a7, a8, a9, *a10); + printf("\tArgs 11-14: %d %f %c %lf %c\n", a11, a12, a13, a14, *a15); + printf("\n"); + return; +} +#endif /* LLC_SUPPORTS_VARARGS_FUNCTIONS */ + + +void +printArgsNoRet(int a1, float a2, char a3, double a4, char* a5, + int a6, float a7, char a8, double a9, char* a10, + int a11, float a12, char a13, double a14, char* a15) +{ + printf("\nprintArgsNoRet with 15 arguments:\n"); + printf("\tArgs 1-5 : %d %f %c %lf %c\n", a1, a2, a3, a4, *a5); + printf("\tArgs 6-10 : %d %f %c %lf %c\n", a6, a7, a8, a9, *a10); + printf("\tArgs 11-14: %d %f %c %lf %c\n", a11, a12, a13, a14, *a15); + printf("\n"); + return; +} + + +int +main(int argc, char** argv) +{ +#ifdef LLVM_CAN_PASS_STRUCTS_BY_VALUE + SmallStruct s1, s3, result; + BigStruct s2; +#endif /* LLVM_CAN_PASS_STRUCTS_BY_VALUE */ + + printArgsNoRet(1, 2.1, 'c', 4.1, "e", + 6, 7.1, 'h', 9.1, "j", + 11, 12.1, 'm', 14.1, "o"); + +#ifdef LLC_SUPPORTS_VARARGS_FUNCTIONS + printVarArgs(1, 2.2, 'c', 4.2, "e", + 6, 7.2, 'h', 9.2, "j", + 11, 12.2, 'm', 14.2, "o"); +#endif /* LLC_SUPPORTS_VARARGS_FUNCTIONS */ + +#ifdef LLVM_CAN_PASS_STRUCTS_BY_VALUE + s1.c1 = 'a'; + s1.c2 = 'b'; + s1.c3 = 'c'; + s1.c4 = 'd'; + s1.n = 111; + + s2.c1 = 'h'; + s2.c2 = 'i'; + s2.c3 = 'j'; + s2.c4 = 'k'; + s2.d1 = 1.1; + s2.d2 = 2.2; + s2.n = 222; + s2.next = &s2; + + s3.c1 = 'w'; + s3.c2 = 'x'; + s3.c3 = 'y'; + s3.c4 = 'z'; + s3.n = 333; + + result = printStructArgs(s1, + 1, 2.0, 'c', 4.0, "e", + s2, + 6, 7.0, 'h', 9.0, "j", + s3); + + printf("\nprintStructArgs returns:\n\t%c %c %c %c %d\n\n", + result.c1, result.c2, result.c3, result.c4, result.n); +#endif /* LLVM_CAN_PASS_STRUCTS_BY_VALUE */ + + return 0; +} diff --git a/test/LLC/casts.c b/test/LLC/casts.c new file mode 100644 index 0000000..bb45571 --- /dev/null +++ b/test/LLC/casts.c @@ -0,0 +1,84 @@ +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> + +int +main(int argc, char** argv) +{ + char c1; + short s1, ssf1, ssd1; + uint8_t ubs0; + int8_t bs0; + unsigned char ubc0, uc2; + unsigned short us2, usf1, usd1; + int ic3, is3, sif1, sid1; + uint uic4, uis4, uif1, uid1; + long slf1, sld1; + ulong ulf1, uld1; + float f1; + double d1; + + /* Test integer to integer conversions */ + + c1 = (char) (argc >= 2)? atoi(argv[1]) : 0xff64; /* 100 = 'd' */ + s1 = (short) (argc >= 3)? atoi(argv[2]) : -769; /* 0xf7ff = -769 */ + + ubc0 = (unsigned char) c1; /* 100 = 'd' */ + ubs0 = (uint8_t) s1; /* 0xff = 255 */ + bs0 = (int8_t) s1; /* 0xff = -1 */ + + uc2 = (unsigned char) c1; /* 100 = 'd' */ + us2 = (unsigned short) s1; /* 0xf7ff = 64767 */ + + ic3 = (int) c1; /* 100 = 'd' */ + is3 = (int) s1; /* 0xfffff7ff = -769 */ + + uic4 = (unsigned int) c1; /* 100 = 'd' */ + uis4 = (unsigned int) s1; /* 0xfffff7ff = 4294966527 */ + + printf("ubc0 = '%c'\n", ubc0); + printf("ubs0 = %u\n", ubs0); + printf("bs0 = %d\n", bs0); + printf("c1 = '%c'\n", c1); + printf("s1 = %d\n", s1); + printf("uc2 = '%c'\n", uc2); + printf("us2 = %u\n", us2); + printf("ic3 = '%c'\n", ic3); + printf("is3 = %d\n", is3); + printf("uic4 = '%c'\n", uic4); + printf("uis4 = %u\n", uis4); + + /* Test floating-point to integer conversions */ + f1 = (float) (argc >= 4)? atof(argv[3]) : 1.0; + d1 = (argc >= 5)? atof(argv[4]) : 2.0; + + usf1 = (unsigned short) f1; + usd1 = (unsigned short) d1; + uif1 = (unsigned int) f1; + uid1 = (unsigned int) d1; + ulf1 = (unsigned long) f1; + uld1 = (unsigned long) d1; + + ssf1 = (short) f1; + ssd1 = (short) d1; + sif1 = (int) f1; + sid1 = (int) d1; + slf1 = (long) f1; + sld1 = (long) d1; + + printf("usf1 = %u\n", usf1); + printf("usd1 = %u\n", usd1); + printf("uif1 = %u\n", uif1); + printf("uid1 = %u\n", uid1); + printf("ulf1 = %u\n", ulf1); + printf("uld1 = %u\n", uld1); + + printf("ssf1 = %d\n", ssf1); + printf("ssd1 = %d\n", ssd1); + printf("sif1 = %d\n", sif1); + printf("sid1 = %d\n", sid1); + printf("slf1 = %d\n", slf1); + printf("sld1 = %d\n", sld1); + + return 0; +} diff --git a/test/LLC/constindices.ll b/test/LLC/constindices.ll new file mode 100644 index 0000000..0b8ef91 --- /dev/null +++ b/test/LLC/constindices.ll @@ -0,0 +1,44 @@ +; Test that a sequence of constant indices are folded correctly +; into the equivalent offset at compile-time. + +%MixedA = type { float, [15 x int], sbyte, float } + +%MixedB = type { float, %MixedA, float } + +%fmtArg = internal global [44 x sbyte] c"sqrt(2) = %g\0Aexp(1) = %g\0Api = %g\0Afive = %g\0A\00"; <[44 x sbyte]*> [#uses=1] + +implementation + +declare int "printf"(sbyte*, ...) + +int "main"() +begin + %ScalarA = alloca %MixedA + %ScalarB = alloca %MixedB + %ArrayA = alloca %MixedA, uint 4 + %ArrayB = alloca %MixedB, uint 3 + + store float 1.4142, %MixedA* %ScalarA, uint 0, ubyte 0 + store float 2.7183, %MixedB* %ScalarB, uint 0, ubyte 1, ubyte 0 + + %fptrA = getelementptr %MixedA* %ArrayA, uint 1, ubyte 0 + %fptrB = getelementptr %MixedB* %ArrayB, uint 2, ubyte 1, ubyte 0 + + store float 3.1415, float* %fptrA + store float 5.0, float* %fptrB + + %sqrtTwo = load %MixedA* %ScalarA, uint 0, ubyte 0 + %exp = load %MixedB* %ScalarB, uint 0, ubyte 1, ubyte 0 + %pi = load %MixedA* %ArrayA, uint 1, ubyte 0 + %five = load %MixedB* %ArrayB, uint 2, ubyte 1, ubyte 0 + + %dsqrtTwo = cast float %sqrtTwo to double + %dexp = cast float %exp to double + %dpi = cast float %pi to double + %dfive = cast float %five to double + + %castFmt = getelementptr [44 x sbyte]* %fmtArg, uint 0, uint 0 + call int (sbyte*, ...)* %printf(sbyte* %castFmt, double %dsqrtTwo, double %dexp, double %dpi, double %dfive) + + ret int 0 +end diff --git a/test/LLC/fwdtwice.ll b/test/LLC/fwdtwice.ll new file mode 100644 index 0000000..44c7258 --- /dev/null +++ b/test/LLC/fwdtwice.ll @@ -0,0 +1,33 @@ +;; +;; Test the sequence: +;; cast -> setle 0, %cast -> br %cond +;; This sequence should cause the cast value to be forwarded twice, +;; i.e., cast is forwarded to the setle and teh setle is forwarded +;; to the branch. +;; register argument of the "branch-on-register" instruction, i.e., +;; +;; This produces the bogus output instruction: +;; brlez <NULL VALUE>, .L_SumArray_bb3. +;; This came from %bb1 of sumarrray.ll generated from sumarray.c. + + +;;;; ****************************************************** +implementation +;;;; ****************************************************** + +int "SumArray"(int %Num) +begin +bb0: ;[#uses=3] + br label %Top +Top: + %Num = alloca int ; <int *> [#uses=2] + store int %Num, int * %Num + %reg108 = load int * %Num ; <int> [#uses=2] + %cast1006 = cast int %reg108 to uint ; <uint> [#uses=1] + %cond1001 = setle uint %cast1006, 0 ; <bool> [#uses=1] + br bool %cond1001, label %bb6, label %Top + +bb6: + ret int 42 +end + diff --git a/test/LLC/negintconst.ll b/test/LLC/negintconst.ll new file mode 100644 index 0000000..9e671b0 --- /dev/null +++ b/test/LLC/negintconst.ll @@ -0,0 +1,48 @@ +; Test that a negative constant smaller than 64 bits (e.g., int) +; is correctly implemented with sign-extension. +; In particular, the current code generated is: +; +; main: +; .L_main_LL_0: +; save %o6, -224, %o6 +; setx .G_fmtArg_1, %o1, %o0 +; setuw 1, %o1 ! i = 1 +; setuw 4294967295, %o3 ! THE BUG: 0x00000000ffffffff +; setsw 0, %i0 +; add %i6, 1999, %o2 ! fval +; add %o1, %g0, %o1 +; add %o0, 0, %o0 +; mulx %o1, %o3, %o1 ! ERROR: 0xffffffff; should be -1 +; add %o1, 3, %o1 ! ERROR: 0x100000002; should be 0x2 +; mulx %o1, 12, %o3 ! +; add %o2, %o3, %o3 ! produces bad address! +; call printf +; nop +; jmpl %i7+8, %g0 +; restore %g0, 0, %g0 +; +; llc produces: +; ioff = 2 fval = 0xffffffff7fffec90 &fval[2] = 0xb7fffeca8 +; instead of: +; ioff = 2 fval = 0xffffffff7fffec90 &fval[2] = 0xffffffff7fffeca8 +; + +%Results = type { float, float, float } + +%fmtArg = internal global [39 x sbyte] c"ioff = %u\09fval = 0x%p\09&fval[2] = 0x%p\0A\00"; <[39 x sbyte]*> [#uses=1] + +implementation + +declare int "printf"(sbyte*, ...) + +int "main"() +begin + %fval = alloca %Results, uint 4 + %i = add uint 1, 0 ; i = 1 + %iscale = mul uint %i, 4294967295 ; i*-1 = -1 + %ioff = add uint %iscale, 3 ; 3+(-i) = 2 + %fptr = getelementptr %Results* %fval, uint %ioff ; &fval[2] + %castFmt = getelementptr [39 x sbyte]* %fmtArg, uint 0, uint 0 + call int (sbyte*, ...)* %printf(sbyte* %castFmt, uint %ioff, %Results* %fval, %Results* %fptr) + ret int 0 +end diff --git a/test/LLC/poisson.c b/test/LLC/poisson.c new file mode 100644 index 0000000..7d9289d --- /dev/null +++ b/test/LLC/poisson.c @@ -0,0 +1,41 @@ +/* For copyright information, see olden_v1.0/COPYRIGHT */ + +/********************************************************** + * poisson.c: handles math routines for health.c * + **********************************************************/ + +#include <stdio.h> +#include <math.h> + +/* From health.h */ +#define IA 16807 +#define IM 2147483647 +#define AM (1.0 / IM) +#define IQ 127773 +#define IR 2836 +#define MASK 123459876 + +float my_rand(long idum) +{ + long k; + float answer; + + idum ^= MASK; + k = idum / IQ; + idum = IA * (idum - k * IQ) - IR * k; + idum ^= MASK; + if (idum < 0) + idum += IM; + answer = AM * idum; + return answer; +} + +int +main(int argc, char** argv) +{ + printf("my_rand(%d) = %g\n", 2555540, my_rand(2555540)); + printf("my_rand(%d) = %g\n", 2427763, my_rand(2427763)); + return 0; +} + + diff --git a/test/LLC/sched.ll b/test/LLC/sched.ll new file mode 100644 index 0000000..b8de02d --- /dev/null +++ b/test/LLC/sched.ll @@ -0,0 +1,30 @@ +implementation +declare int "printf"(sbyte*, int, float) + + +int "testissue"(int %i, float %x, float %y) +begin +bb1: + %x1 = mul float %x, %y ;; x1 + %y1 = mul float %y, 0.75 ;; y1 + %z1 = add float %x1, %y1 ;; z1 = x1 + y1 + + %x2 = mul float %x, 0.5 ;; x2 + %y2 = mul float %y, 0.9 ;; y2 + %z2 = add float %x2, %y2 ;; z2 = x2 + y2 + + %z3 = add float %z1, %z2 ;; z3 = z1 + z2 + + %i1 = shl int %i, ubyte 3 ;; i1 + %j1 = add int %i, 7 ;; j1 + %m1 = add int %i1, %j1 ;; k1 = i1 + j1 +;; %m1 = div int %k1, 99 ;; m1 = k1 / 99 + + %b = setle int %m1, 6 ;; (m1 <= 6)? + br bool %b, label %bb1, label %bb2 + +bb2: + %Msg = cast ulong 0 to sbyte * + call int %printf(sbyte* %Msg, int %m1, float %z3) + ret int 0 +end diff --git a/test/LLC/select.ll b/test/LLC/select.ll new file mode 100644 index 0000000..973bc7e --- /dev/null +++ b/test/LLC/select.ll @@ -0,0 +1,155 @@ +%AConst = constant int 123 + +implementation + +; Test setting values of different constants in registers. +; +void "testConsts"(int %N, float %X) +begin +; <label>:0 + %a = add int %N, 1 ; 1 should be put in immed field + %a2= add int %N, 12345678 ; constant has to be loaded + %b = add short 4, 3 ; one of the operands shd be immed + %c = add float %X, 0.0 ; will this be optimzzed? + %d = add float %X, 3.1415 ; constant has to be loaded + %f = add uint 4294967295, 10 ; result shd be 9 (not in immed fld) + %g = add ushort 20, 65535 ; result shd be 19 (65536 in immed fld) + %g = add ushort 65535, 30 ; result shd be 29 (not in immed fld) + %h = add ubyte 40, 255 ; result shd be 39 (255 in immed fld) + %h = add ubyte 255, 50 ; result shd be 49 (not in immed fld) + + ret void +end + +; A SetCC whose result is used should produce instructions to +; compute the boolean value in a register. One whose result +; is unused will only generate the condition code but not +; the boolean result. +; +void "unusedBool"(int * %x, int * %y) +begin +; <label>:0 ; [#uses=0] + seteq int * %x, %y ; <bool>:0 [#uses=1] + not bool %0 ; <bool>:1 [#uses=0] + setne int * %x, %y ; <bool>:2 [#uses=0] + ret void +end + +; A constant argument to a Phi produces a Cast instruction in the +; corresponding predecessor basic block. This checks a few things: +; -- phi arguments coming from the bottom of the same basic block +; (they should not be forward substituted in the machine code!) +; -- code generation for casts of various types +; -- use of immediate fields for integral constants of different sizes +; -- branch on a constant condition +; +void "mergeConstants"(int * %x, int * %y) +begin +; <label>:0 + br label %Top +Top: + phi int [ 0, %0 ], [ 1, %Top ], [ 524288, %Next ] + phi float [ 0.0, %0 ], [ 1.0, %Top ], [ 2.0, %Next ] + phi double [ 0.5, %0 ], [ 1.5, %Top ], [ 2.5, %Next ] + phi bool [ true, %0 ], [ false,%Top ], [ true, %Next ] + br bool true, label %Top, label %Next +Next: + br label %Top +end + + + +; A constant argument to a cast used only once should be forward substituted +; and loaded where needed, which happens is: +; -- User of cast has no immediate field +; -- User of cast has immediate field but constant is too large to fit +; or constant is not resolved until later (e.g., global address) +; -- User of cast uses it as a call arg. or return value so it is an implicit +; use but has to be loaded into a virtual register so that the reg. +; allocator can allocate the appropriate phys. reg. for it +; +int* "castconst"(float) +begin +; <label>:0 + %castbig = cast ulong 99999999 to int + %castsmall = cast ulong 1 to int + %usebig = add int %castbig, %castsmall + + %castglob = cast int* %AConst to long* + %dummyl = load long* %castglob + + %castnull = cast ulong 0 to int* + ret int* %castnull +end + + + +; Test branch-on-comparison-with-zero, in two ways: +; 1. can be folded +; 2. cannot be folded because result of comparison is used twice +; +void "testbool"(int, int) ; Def %0, %1 + const int 0 ; Def 2 + const int -4 ; Def 3 +begin +; <label>:0 + br label %Top +Top: + add int %0, %1 ; Def 4 + sub int %4, %3 ; Def 5 + setle int %5, %2 ; Def 0 - bool plane + br bool %0, label %retlbl, label %loop + +loop: + add int %0, %1 ; Def 6 + sub int %4, %3 ; Def 7 + setle int %7, %2 ; Def 1 - bool + not bool %1 ; Def 2 - bool. first use of bool %1 + br bool %1, label %loop, label %Top ; second use of bool %1 + +retlbl: + ret void +end + + +; Test branch on floating point comparison +; +void "testfloatbool"(float %x, float %y) ; Def %0, %1 - float +begin +; <label>:0 + br label %Top +Top: + %p = add float %x, %y ; Def 2 - float + %z = sub float %x, %y ; Def 3 - float + %b = setle float %p, %z ; Def 0 - bool + %c = not bool %b ; Def 1 - bool + br bool %b, label %Top, label %goon +goon: + ret void +end + + +; Test cases where an LLVM instruction requires no machine +; instructions (e.g., cast int* to long). But there are 2 cases: +; 1. If the result register has only a single use and the use is in the +; same basic block, the operand will be copy-propagated during +; instruction selection. +; 2. If the result register has multiple uses or is in a different +; basic block, it cannot (or will not) be copy propagated during +; instruction selection. It will generate a +; copy instruction (add-with-0), but this copy should get coalesced +; away by the register allocator. +; +int "checkForward"(int %N, int* %A) +begin + +bb2: ;;<label> + %reg114 = shl int %N, ubyte 2 ;; + %cast115 = cast int %reg114 to int* ;; reg114 will be propagated + %reg116 = add int* %A, %cast115 ;; + %reg118 = load int* %reg116 ;; + %cast117 = cast int %reg118 to long ;; reg118 will be copied 'cos + %reg159 = add long 1234567, %cast117 ;; cast117 has 2 uses, here + %reg160 = add long 7654321, %cast117 ;; and here. + ret void +end diff --git a/test/LLC/spillccr.ll b/test/LLC/spillccr.ll new file mode 100644 index 0000000..d34ea3f --- /dev/null +++ b/test/LLC/spillccr.ll @@ -0,0 +1,52 @@ +; July 6, 2002 -- LLC Regression test +; This test case checks if the integer CC register %xcc (or %ccr) +; is correctly spilled. The code fragment came from function +; MakeGraph in Olden-mst. +; The original code made all comparisons with 0, so that the %xcc +; register is not needed for the branch in the first basic block. +; Replace 0 with 1 in the first comparson so that the +; branch-on-register instruction cannot be used directly, i.e., +; the %xcc register is needed for the first branch. +; + %Graph = type %struct.graph_st* + %Hash = type %struct.hash* + %HashEntry = type %struct.hash_entry* + %Vertex = type %struct.vert_st* + %struct.graph_st = type { [1 x %Vertex] } + %struct.hash = type { %HashEntry*, int (uint)*, int } + %struct.hash_entry = type { uint, sbyte*, %HashEntry } + %struct.vert_st = type { int, %Vertex, %Hash } +%HashRange = internal uninitialized global int ; <int*> [#uses=1] +%.LC0 = internal global [13 x sbyte] c"Make phase 2\00" ; <[13 x sbyte]*> [#uses=1] +%.LC1 = internal global [13 x sbyte] c"Make phase 3\00" ; <[13 x sbyte]*> [#uses=1] +%.LC2 = internal global [13 x sbyte] c"Make phase 4\00" ; <[13 x sbyte]*> [#uses=1] +%.LC3 = internal global [15 x sbyte] c"Make returning\00" ; <[15 x sbyte]*> [#uses=1] + +implementation ; Functions: + +%Graph %MakeGraph(int %numvert, int %numproc) { +bb1: ;[#uses=1] + %reg111 = add int %numproc, -1 ; <int> [#uses=3] + %cond275 = setlt int %reg111, 1 ; <bool> [#uses=2] + %cond276 = setle int %reg111, 0 ; <bool> [#uses=1] + %cond277 = setge int %numvert, 0 ; <bool> [#uses=2] + %reg162 = add int %numvert, 3 ; <int> [#uses=2] + br bool %cond275, label %bb7, label %bb4 + +bb4: + br bool %cond276, label %bb7, label %bb5 + +bb5: + br bool %cond277, label %bb7, label %bb6 + +bb6: ;[#uses=2] + ret %Graph null + +bb7: ;[#uses=2] + ret %Graph null +} + +int %main(int argc, sbyte** argv) { +bb1: + %reg100 = call %struct.graph_st* (int, int)* %MakeGraph(1, 1) + diff --git a/test/LLC/testtrace.c b/test/LLC/testtrace.c new file mode 100644 index 0000000..c7b3e8a --- /dev/null +++ b/test/LLC/testtrace.c @@ -0,0 +1,44 @@ +#include <stdio.h> + +/* + * Test routines for testing the tracing code. + */ + +struct DummyStruct { + struct DummyStruct* next; + int seqnum; +}; + +int +AddCounts(struct DummyStruct* S1, + struct DummyStruct* S2, + struct DummyStruct* S3, int noPrint) +{ + if (!noPrint) + printf("&S1 = %p\t&S2 = %p\t&S3 = %p\n", S1, S2, S3); + return S1->seqnum + S2->seqnum + S3->seqnum; +} + +void +testAllocaOrder(int noPrint) +{ + static int count = 0; + struct DummyStruct S1, S2, S3; + + S1.seqnum = ++count; + S2.seqnum = ++count; + S3.seqnum = ++count; + + printf("sum = %d\n", AddCounts(&S1, &S2, &S3, noPrint)); +} + +int +main(int argc, char** argv) +{ + unsigned int i, noPrint = 1; + if (argc > 1 && ! strcmp(argv[1], "-d")) + noPrint = 0; + for (i=0; i < 10; ++i) + testAllocaOrder(noPrint); + return 0; +} diff --git a/test/LLC/varargs.c b/test/LLC/varargs.c new file mode 100644 index 0000000..a267f03 --- /dev/null +++ b/test/LLC/varargs.c @@ -0,0 +1,29 @@ +#include <stdio.h> +#include <stdlib.h> + +#define A 16807.0 +#define M 2147483647.0 + +/* + * This function calls floor() which does not have a prototype. + * Test that the argument to floor is passed correctly. + */ +double +my_rand(double seed) +{ + double t = A*seed + 1; + double floor(); + + seed = t - (M * floor(t / M)); /* t%M if t > M; t otherwise */ + return seed; + +} /* end of random */ + + +int +main(int argc, char** argv) +{ + double seed = 123 * ((argc > 1)? atof(argv[1]) : 3.1415926); + printf("my_rand(%lf) = %lf\n", seed, my_rand(seed)); + return 0; +} |