mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-27 13:30:05 +00:00
Some of these are feature tests, not regression tests.
This directory needs to be reorganized and some of the tests need changes to make them executable. Also comments would help... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2865 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
975f6d4f44
commit
a7a1c7e971
28
test/CodeGen/Generic/badlive.ll
Normal file
28
test/CodeGen/Generic/badlive.ll
Normal file
@ -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
|
44
test/CodeGen/Generic/constindices.ll
Normal file
44
test/CodeGen/Generic/constindices.ll
Normal file
@ -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
|
33
test/CodeGen/Generic/fwdtwice.ll
Normal file
33
test/CodeGen/Generic/fwdtwice.ll
Normal file
@ -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
|
||||
|
48
test/CodeGen/Generic/negintconst.ll
Normal file
48
test/CodeGen/Generic/negintconst.ll
Normal file
@ -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
|
30
test/CodeGen/Generic/sched.ll
Normal file
30
test/CodeGen/Generic/sched.ll
Normal file
@ -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
|
155
test/CodeGen/Generic/select.ll
Normal file
155
test/CodeGen/Generic/select.ll
Normal file
@ -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
|
52
test/CodeGen/Generic/spillccr.ll
Normal file
52
test/CodeGen/Generic/spillccr.ll
Normal file
@ -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)
|
||||
|
74
test/LLC/badfuncptr.c
Normal file
74
test/LLC/badfuncptr.c
Normal file
@ -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;
|
||||
}
|
28
test/LLC/badlive.ll
Normal file
28
test/LLC/badlive.ll
Normal file
@ -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
|
156
test/LLC/callargs.c
Normal file
156
test/LLC/callargs.c
Normal file
@ -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;
|
||||
}
|
84
test/LLC/casts.c
Normal file
84
test/LLC/casts.c
Normal file
@ -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;
|
||||
}
|
44
test/LLC/constindices.ll
Normal file
44
test/LLC/constindices.ll
Normal file
@ -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
|
33
test/LLC/fwdtwice.ll
Normal file
33
test/LLC/fwdtwice.ll
Normal file
@ -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
|
||||
|
48
test/LLC/negintconst.ll
Normal file
48
test/LLC/negintconst.ll
Normal file
@ -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
|
41
test/LLC/poisson.c
Normal file
41
test/LLC/poisson.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
30
test/LLC/sched.ll
Normal file
30
test/LLC/sched.ll
Normal file
@ -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
|
155
test/LLC/select.ll
Normal file
155
test/LLC/select.ll
Normal file
@ -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
|
52
test/LLC/spillccr.ll
Normal file
52
test/LLC/spillccr.ll
Normal file
@ -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)
|
||||
|
44
test/LLC/testtrace.c
Normal file
44
test/LLC/testtrace.c
Normal file
@ -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;
|
||||
}
|
29
test/LLC/varargs.c
Normal file
29
test/LLC/varargs.c
Normal file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user