// #target: macos-x64
module foo;

extern fn void* malloc(uint);

struct List
{
  int data;
  List* next;
}

fn List* passThroughList(List* l) {
  return l;
}

// Recursive data structure tests...

List* data;

fn void foo()
{
  static int foo = 0;            // Test static local variable
  foo += 1;                      // Increment static variable

  data = (List*)malloc(12);      // This is not a proper list allocation
}

List listNode3 = { 4, null          };
List listNode2 = { 3, &listNode3 };
List listNode0 = { 1, &listNode1 };
List listNode1 = { 2, &listNode2 };


List[10] listArray;

// Iterative insert fn
fn void insertIntoListTail(List **l, int data) {
  while (*l) l = &(*l).next;
  *l = (List*)malloc(List.sizeof);
  (*l).data = data;
  (*l).next = null;
}

// Recursive list search fn
fn List *findData(List *l, int data) {
  if (!l) return null;
  if (l.data == data) return l;
  return findData(l.next, data);
}

extern fn void foundIt();

// Driver fn...
fn void doListStuff() {
  List* myList = null;
  insertIntoListTail(&myList, 100);
  insertIntoListTail(&myList, 12);
  insertIntoListTail(&myList, 42);
  insertIntoListTail(&myList, 1123);
  insertIntoListTail(&myList, 1213);

  if (findData(myList, 75)) foundIt();
  if (findData(myList, 42)) foundIt();
  if (findData(myList, 700)) foundIt();
}


fn int floatcomptest(double *x, double *y, float *x1, float *y1) {
  return (int)(*x < *y || *x1 < *y1);
}

// Exposed a bug
fn void* memset_impl(void* dstpp, int c, uint len)
{
  iptr dstp = (iptr)dstpp;

  while (dstp % 4 != 0)
    {
      ((char*)dstp)[0] = (char)c;
      dstp += 1;
      len -= 1;
    }
  return dstpp;
}

// TEST problem with signed/unsigned versions of the same constants being shared
// incorrectly!
char* temp @private;
int remaining @private;
fn char* localmalloc(int size) @private {
  char* blah;

  if (size>remaining)
    {
      temp = (char*) malloc(32768);
      remaining = 32768;
      return temp;
    }
  return null;
}


struct PBVTest { double x; double y; int z; }

fn PBVTest testRetStruct(float x, double y, int z) {
  PBVTest t = { x, y, z };
  return t;
}
extern fn PBVTest testRetStruct2();  // external func no inlining


fn double callRetStruct(float x, double y, int z) {
  PBVTest t = testRetStruct2();
  return t.x+x+y+z;
}

extern fn int fp(int, char*);
char *ext;
fn void __bb_exit_func()
{
    fp(12, ext ? ext : "<none>");
}

extern fn int puts(char* s);

struct FunStructTest
{
	int test1;
	char* pointer;
	int[12] array;
}

struct SubStruct {
  short x, y;
}

struct Quad {
  int w;
  SubStruct ss;
  SubStruct *ssp;
  char c;
  int y;
}

Quad globalQuad = { 4, {1, 2}, null, 3, 156 };

alias FuncPtr = fn int(int);

fn uint ptrFunc(FuncPtr func, int x) {
  return func(x);
}

fn char ptrFunc2(FuncPtr[30] funcTab, int num) {
  return (char)funcTab[num]('b');
}

extern fn char smallArgs2(char w, char x, long zrrk, char y, char z);
extern fn int someFuncA();
fn char smallArgs(char w, char x, char y, char z) {
  someFuncA();
  return smallArgs2(w-1, x+1, y, z, w);
}

fn int f0(Quad q, int i) @private {              /* Pass Q by value */
  Quad r @noinit;
  if (i) r.ss = q.ss;
  q.ssp = &r.ss;
  q.w = q.y = q.c = 1;
  return q.ss.y + i + r.y - q.c;
}

fn int f1(Quad *q, int i) {             /* Pass Q by address */
  Quad r @noinit;
  if (i) r = *q;
  q.w = q.y = q.c = 1;
  return q.ss.y+i+r.y-q.c;
}


fn int badFunc(float val) {
  int result @noinit;
  if (val > 12.345) result = 4;
  return result;     /* Test use of undefined value */
}

extern fn int ef1(int *, char *, int *);

fn int func(int param, long param2) {
  int result = param;

  {{{{
      char c @noinit; int x @noinit;
      ef1(&result, &c, &x);
    }}}

    {   // c & X are duplicate names!
      char c; int x;
      ef1(&result, &c, &x);
    }

  }
  return result;
}


fn short funFunc(long x, char z) {
  return (short)(x+z);
}

fn uint castTest(int x) { return x; }

fn double testAdd(double x, float y) {
  return x+y+0.5;
}

fn int funcZ(int i, int j) {
  while (i != 20) i += 2;

  j += funcZ(2, i);
  return (i * 3 + j*2)*j;
}

fn int sumArray(int* array, int num) {
  int i @noinit;
  int result = 0;
  for (i = 0; i < num; ++i) result += array[i];
  return result;
}

fn int arrayParam(int* values) {
  return ef1((int*)(iptr)values[50], (char*)1, &values[50]);
}

fn int arrayToSum() {
  int[100] a @noinit;
  int i;
  for (i = 0; i < 100; ++i) a[i] = i*4;

  return a[a[0]]; //SumArray(A, 100);
}


extern fn int externFunc(long, uint*, short, char);

fn int main(int argc, char **argv)
{
	uint i @noinit;
	puts("Hello world!\n");

	externFunc(-1, null, (short)argc, 2);
	//func(argc, argc);

	for (i = 0; i < 10; i++) puts(argv[3]);
	return 0;
}

fn double mathFunc(double x, double y, double z,
                double aa, double bb, double cc, double dd,
                double ee, double ff, double gg, double hh,
                double aaa, double abb, double acc, double add,
                double aee, double aff) {
  return x + y + z + aa + bb + cc + dd + ee + ff + gg + hh
       + aaa + abb + acc + add + aee + aff;
}



fn void strcpy(char *s1, char *s2) {
  while (*s1++ = *s2++);
}

fn void strcat(char *s1, char *s2) {
  while (*s1++);
  s1--;
  while (*s1++ = *s2++);
}

fn int strcmp(char *s1, char *s2) {
  while (*s1++ == *s2++);
  if (*s1 == 0) {
    if (*s2 == 0) {
      return 0;
    } else {
      return -1;
    }
  } else {
    if (*s2 == 0) {
      return 1;
    } else {
      return (*(--s1) - *(--s2));
    }
  }
}

/* #expect: foo.ll

%.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] }
%List = type { i32, ptr }
%Quad = type { i32, %SubStruct, ptr, i8, i32 }
%SubStruct = type { i16, i16 }
%PBVTest = type { double, double, i32 }

@"$ct.foo.List" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 16, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
@"$ct.foo.PBVTest" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8
@"$ct.foo.FunStructTest" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 64, i64 0, i64 3, [0 x i64] zeroinitializer }, align 8
@"$ct.foo.SubStruct" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 4, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
@"$ct.foo.Quad" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 5, [0 x i64] zeroinitializer }, align 8
@foo.data = local_unnamed_addr global ptr null, align 8
@foo.listNode3 = global %List { i32 4, ptr null }, align 8
@foo.listNode2 = global %List { i32 3, ptr @foo.listNode3 }, align 8
@foo.listNode0 = local_unnamed_addr global %List { i32 1, ptr @foo.listNode1 }, align 8
@foo.listNode1 = global %List { i32 2, ptr @foo.listNode2 }, align 8
@foo.listArray = local_unnamed_addr global [10 x %List] zeroinitializer, align 16
@foo.temp = internal unnamed_addr global ptr null, align 8
@foo.remaining = internal unnamed_addr global i32 0, align 4
@foo.ext = local_unnamed_addr global ptr null, align 8
@foo.globalQuad = local_unnamed_addr global %Quad { i32 4, %SubStruct { i16 1, i16 2 }, ptr null, i8 3, i32 156 }, align 8
@foo.foo.10 = internal unnamed_addr global i32 0, align 4
@.str = private unnamed_addr constant [7 x i8] c"<none>\00", align 1
@.str.11 = private unnamed_addr constant [14 x i8] c"Hello world!\0A\00", align 1

declare ptr @malloc(i32) #0

define ptr @foo.passThroughList(ptr %0) #0 {
entry:
  ret ptr %0
}

define void @foo.foo() #0 {
entry:
  %0 = load i32, ptr @foo.foo.10, align 4
  %add = add i32 %0, 1
  store i32 %add, ptr @foo.foo.10, align 4
  %1 = call ptr @malloc(i32 12)
  store ptr %1, ptr @foo.data, align 8
  ret void
}

define void @foo.insertIntoListTail(ptr %0, i32 %1) #0 {
entry:
  %l = alloca ptr, align 8
  store ptr %0, ptr %l, align 8
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %2 = load ptr, ptr %l, align 8
  %3 = load ptr, ptr %2, align 8
  %i2b = icmp ne ptr %3, null
  br i1 %i2b, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  %4 = load ptr, ptr %l, align 8
  %5 = load ptr, ptr %4, align 8
  %ptradd = getelementptr inbounds i8, ptr %5, i64 8
  store ptr %ptradd, ptr %l, align 8
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  %6 = call ptr @malloc(i32 16)
  %7 = load ptr, ptr %l, align 8
  store ptr %6, ptr %7, align 8
  %8 = load ptr, ptr %l, align 8
  %9 = load ptr, ptr %8, align 8
  store i32 %1, ptr %9, align 8
  %10 = load ptr, ptr %l, align 8
  %11 = load ptr, ptr %10, align 8
  %ptradd1 = getelementptr inbounds i8, ptr %11, i64 8
  store ptr null, ptr %ptradd1, align 8
  ret void
}

define ptr @foo.findData(ptr %0, i32 %1) #0 {
entry:
  %i2nb = icmp eq ptr %0, null
  br i1 %i2nb, label %if.then, label %if.exit

if.then:                                          ; preds = %entry
  ret ptr null

if.exit:                                          ; preds = %entry
  %2 = load i32, ptr %0, align 8
  %eq = icmp eq i32 %2, %1
  br i1 %eq, label %if.then1, label %if.exit2

if.then1:                                         ; preds = %if.exit
  ret ptr %0

if.exit2:                                         ; preds = %if.exit
  %ptradd = getelementptr inbounds i8, ptr %0, i64 8
  %3 = load ptr, ptr %ptradd, align 8
  %4 = call ptr @foo.findData(ptr %3, i32 %1)
  ret ptr %4
}

declare void @foundIt() #0

define void @foo.doListStuff() #0 {
entry:
  %myList = alloca ptr, align 8
  store ptr null, ptr %myList, align 8
  call void @foo.insertIntoListTail(ptr %myList, i32 100)
  call void @foo.insertIntoListTail(ptr %myList, i32 12)
  call void @foo.insertIntoListTail(ptr %myList, i32 42)
  call void @foo.insertIntoListTail(ptr %myList, i32 1123)
  call void @foo.insertIntoListTail(ptr %myList, i32 1213)
  %0 = load ptr, ptr %myList, align 8
  %1 = call ptr @foo.findData(ptr %0, i32 75)
  %i2b = icmp ne ptr %1, null
  br i1 %i2b, label %if.then, label %if.exit

if.then:                                          ; preds = %entry
  call void @foundIt()
  br label %if.exit

if.exit:                                          ; preds = %if.then, %entry
  %2 = load ptr, ptr %myList, align 8
  %3 = call ptr @foo.findData(ptr %2, i32 42)
  %i2b1 = icmp ne ptr %3, null
  br i1 %i2b1, label %if.then2, label %if.exit3

if.then2:                                         ; preds = %if.exit
  call void @foundIt()
  br label %if.exit3

if.exit3:                                         ; preds = %if.then2, %if.exit
  %4 = load ptr, ptr %myList, align 8
  %5 = call ptr @foo.findData(ptr %4, i32 700)
  %i2b4 = icmp ne ptr %5, null
  br i1 %i2b4, label %if.then5, label %if.exit6

if.then5:                                         ; preds = %if.exit3
  call void @foundIt()
  br label %if.exit6

if.exit6:                                         ; preds = %if.then5, %if.exit3
  ret void
}

define i32 @foo.floatcomptest(ptr %0, ptr %1, ptr %2, ptr %3) #0 {
entry:
  %4 = load double, ptr %0, align 8
  %5 = load double, ptr %1, align 8
  %lt = fcmp olt double %4, %5
  br i1 %lt, label %or.phi, label %or.rhs

or.rhs:                                           ; preds = %entry
  %6 = load float, ptr %2, align 4
  %7 = load float, ptr %3, align 4
  %lt1 = fcmp olt float %6, %7
  br label %or.phi

or.phi:                                           ; preds = %or.rhs, %entry
  %val = phi i1 [ true, %entry ], [ %lt1, %or.rhs ]
  %zext = zext i1 %val to i32
  ret i32 %zext
}

define ptr @foo.memset_impl(ptr %0, i32 %1, i32 %2) #0 {
entry:
  %len = alloca i32, align 4
  %dstp = alloca i64, align 8
  store i32 %2, ptr %len, align 4
  %ptrxi = ptrtoint ptr %0 to i64
  store i64 %ptrxi, ptr %dstp, align 8
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %3 = load i64, ptr %dstp, align 8
  %smod = srem i64 %3, 4
  %neq = icmp ne i64 %smod, 0
  br i1 %neq, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  %trunc = trunc i32 %1 to i8
  %4 = load i64, ptr %dstp, align 8
  %intptr = inttoptr i64 %4 to ptr
  store i8 %trunc, ptr %intptr, align 1
  %5 = load i64, ptr %dstp, align 8
  %add = add i64 %5, 1
  store i64 %add, ptr %dstp, align 8
  %6 = load i32, ptr %len, align 4
  %sub = sub i32 %6, 1
  store i32 %sub, ptr %len, align 4
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  ret ptr %0
}

define internal ptr @foo.localmalloc(i32 %0) #0 {
entry:
  %blah = alloca ptr, align 8
  store ptr null, ptr %blah, align 8
  %1 = load i32, ptr @foo.remaining, align 4
  %gt = icmp sgt i32 %0, %1
  br i1 %gt, label %if.then, label %if.exit

if.then:                                          ; preds = %entry
  %2 = call ptr @malloc(i32 32768)
  store ptr %2, ptr @foo.temp, align 8
  store i32 32768, ptr @foo.remaining, align 4
  %3 = load ptr, ptr @foo.temp, align 8
  ret ptr %3

if.exit:                                          ; preds = %entry
  ret ptr null
}

define void @foo.testRetStruct(ptr noalias sret(%PBVTest) align 8 %0, float %1, double %2, i32 %3) #0 {
entry:
  %t = alloca %PBVTest, align 8
  %fpfpext = fpext float %1 to double
  store double %fpfpext, ptr %t, align 8
  %ptradd = getelementptr inbounds i8, ptr %t, i64 8
  store double %2, ptr %ptradd, align 8
  %ptradd1 = getelementptr inbounds i8, ptr %t, i64 16
  store i32 %3, ptr %ptradd1, align 8
  call void @llvm.memcpy.p0.p0.i32(ptr align 8 %0, ptr align 8 %t, i32 24, i1 false)
  ret void
}

declare void @testRetStruct2(ptr noalias sret(%PBVTest) align 8) #0

define double @foo.callRetStruct(float %0, double %1, i32 %2) #0 {
entry:
  %t = alloca %PBVTest, align 8
  call void @testRetStruct2(ptr sret(%PBVTest) align 8 %t)
  %3 = load double, ptr %t, align 8
  %fpfpext = fpext float %0 to double
  %fadd = fadd double %3, %fpfpext
  %fadd1 = fadd double %fadd, %1
  %sifp = sitofp i32 %2 to double
  %fadd2 = fadd double %fadd1, %sifp
  ret double %fadd2
}

declare i32 @fp(i32, ptr) #0

define void @foo.__bb_exit_func() #0 {
entry:
  %0 = load ptr, ptr @foo.ext, align 8
  %i2b = icmp ne ptr %0, null
  br i1 %i2b, label %cond.lhs, label %cond.rhs

cond.lhs:                                         ; preds = %entry
  %1 = load ptr, ptr @foo.ext, align 8
  br label %cond.phi

cond.rhs:                                         ; preds = %entry
  br label %cond.phi

cond.phi:                                         ; preds = %cond.rhs, %cond.lhs
  %val = phi ptr [ %1, %cond.lhs ], [ @.str, %cond.rhs ]
  %2 = call i32 @fp(i32 12, ptr %val)
  ret void
}

declare i32 @puts(ptr) #0

define i32 @foo.ptrFunc(ptr %0, i32 %1) #0 {
entry:
  %2 = call i32 %0(i32 %1)
  ret i32 %2
}

define zeroext i8 @foo.ptrFunc2(ptr byval([30 x ptr]) align 8 %0, i32 %1) #0 {
entry:
  %sext = sext i32 %1 to i64
  %ptroffset = getelementptr inbounds [8 x i8], ptr %0, i64 %sext
  %2 = load ptr, ptr %ptroffset, align 8
  %3 = call i32 %2(i32 98)
  %trunc = trunc i32 %3 to i8
  ret i8 %trunc
}

declare zeroext i8 @smallArgs2(i8 zeroext, i8 zeroext, i64, i8 zeroext, i8 zeroext) #0

declare i32 @someFuncA() #0

define zeroext i8 @foo.smallArgs(i8 zeroext %0, i8 zeroext %1, i8 zeroext %2, i8 zeroext %3) #0 {
entry:
  %4 = call i32 @someFuncA()
  %zext = zext i8 %0 to i32
  %sub = sub i32 %zext, 1
  %trunc = trunc i32 %sub to i8
  %zext1 = zext i8 %1 to i32
  %add = add i32 %zext1, 1
  %trunc2 = trunc i32 %add to i8
  %zext3 = zext i8 %2 to i64
  %5 = call i8 @smallArgs2(i8 zeroext %trunc, i8 zeroext %trunc2, i64 %zext3, i8 zeroext %3, i8 zeroext %0)
  ret i8 %5
}

define internal i32 @foo.f0(ptr byval(%Quad) align 8 %0, i32 %1) #0 {
entry:
  %r = alloca %Quad, align 8
  %i2b = icmp ne i32 %1, 0
  br i1 %i2b, label %if.then, label %if.exit

if.then:                                          ; preds = %entry
  %ptradd = getelementptr inbounds i8, ptr %0, i64 4
  %ptradd1 = getelementptr inbounds i8, ptr %r, i64 4
  call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd1, ptr align 4 %ptradd, i32 4, i1 false)
  br label %if.exit

if.exit:                                          ; preds = %if.then, %entry
  %ptradd2 = getelementptr inbounds i8, ptr %r, i64 4
  %ptradd3 = getelementptr inbounds i8, ptr %0, i64 8
  store ptr %ptradd2, ptr %ptradd3, align 8
  %ptradd4 = getelementptr inbounds i8, ptr %0, i64 16
  store i8 1, ptr %ptradd4, align 8
  %ptradd5 = getelementptr inbounds i8, ptr %0, i64 20
  store i32 1, ptr %ptradd5, align 4
  store i32 1, ptr %0, align 8
  %ptradd6 = getelementptr inbounds i8, ptr %0, i64 4
  %ptradd7 = getelementptr inbounds i8, ptr %ptradd6, i64 2
  %2 = load i16, ptr %ptradd7, align 2
  %sext = sext i16 %2 to i32
  %add = add i32 %sext, %1
  %ptradd8 = getelementptr inbounds i8, ptr %r, i64 20
  %3 = load i32, ptr %ptradd8, align 4
  %add9 = add i32 %add, %3
  %ptradd10 = getelementptr inbounds i8, ptr %0, i64 16
  %4 = load i8, ptr %ptradd10, align 8
  %zext = zext i8 %4 to i32
  %sub = sub i32 %add9, %zext
  ret i32 %sub
}

define i32 @foo.f1(ptr %0, i32 %1) #0 {
entry:
  %r = alloca %Quad, align 8
  %i2b = icmp ne i32 %1, 0
  br i1 %i2b, label %if.then, label %if.exit

if.then:                                          ; preds = %entry
  call void @llvm.memcpy.p0.p0.i32(ptr align 8 %r, ptr align 8 %0, i32 24, i1 false)
  br label %if.exit

if.exit:                                          ; preds = %if.then, %entry
  %ptradd = getelementptr inbounds i8, ptr %0, i64 16
  store i8 1, ptr %ptradd, align 8
  %ptradd1 = getelementptr inbounds i8, ptr %0, i64 20
  store i32 1, ptr %ptradd1, align 4
  store i32 1, ptr %0, align 8
  %ptradd2 = getelementptr inbounds i8, ptr %0, i64 4
  %ptradd3 = getelementptr inbounds i8, ptr %ptradd2, i64 2
  %2 = load i16, ptr %ptradd3, align 2
  %sext = sext i16 %2 to i32
  %add = add i32 %sext, %1
  %ptradd4 = getelementptr inbounds i8, ptr %r, i64 20
  %3 = load i32, ptr %ptradd4, align 4
  %add5 = add i32 %add, %3
  %ptradd6 = getelementptr inbounds i8, ptr %0, i64 16
  %4 = load i8, ptr %ptradd6, align 8
  %zext = zext i8 %4 to i32
  %sub = sub i32 %add5, %zext
  ret i32 %sub
}

define i32 @foo.badFunc(float %0) #0 {
entry:
  %result = alloca i32, align 4
  %fpfpext = fpext float %0 to double
  %gt = fcmp ogt double %fpfpext, 1.234500e+01
  br i1 %gt, label %if.then, label %if.exit

if.then:                                          ; preds = %entry
  store i32 4, ptr %result, align 4
  br label %if.exit

if.exit:                                          ; preds = %if.then, %entry
  %1 = load i32, ptr %result, align 4
  ret i32 %1
}

declare i32 @ef1(ptr, ptr, ptr) #0

define i32 @foo.func(i32 %0, i64 %1) #0 {
entry:
  %result = alloca i32, align 4
  %c = alloca i8, align 1
  %x = alloca i32, align 4
  %c1 = alloca i8, align 1
  %x2 = alloca i32, align 4
  store i32 %0, ptr %result, align 4
  %2 = call i32 @ef1(ptr %result, ptr %c, ptr %x)
  store i8 0, ptr %c1, align 1
  store i32 0, ptr %x2, align 4
  %3 = call i32 @ef1(ptr %result, ptr %c1, ptr %x2)
  %4 = load i32, ptr %result, align 4
  ret i32 %4
}

define signext i16 @foo.funFunc(i64 %0, i8 zeroext %1) #0 {
entry:
  %zext = zext i8 %1 to i64
  %add = add i64 %0, %zext
  %trunc = trunc i64 %add to i16
  ret i16 %trunc
}

define i32 @foo.castTest(i32 %0) #0 {
entry:
  ret i32 %0
}

define double @foo.testAdd(double %0, float %1) #0 {
entry:
  %fpfpext = fpext float %1 to double
  %fadd = fadd double %0, %fpfpext
  %fadd1 = fadd double %fadd, 5.000000e-01
  ret double %fadd1
}

define i32 @foo.funcZ(i32 %0, i32 %1) #0 {
entry:
  %i = alloca i32, align 4
  %j = alloca i32, align 4
  store i32 %0, ptr %i, align 4
  store i32 %1, ptr %j, align 4
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %2 = load i32, ptr %i, align 4
  %neq = icmp ne i32 %2, 20
  br i1 %neq, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  %3 = load i32, ptr %i, align 4
  %add = add i32 %3, 2
  store i32 %add, ptr %i, align 4
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  %4 = load i32, ptr %j, align 4
  %5 = load i32, ptr %i, align 4
  %6 = call i32 @foo.funcZ(i32 2, i32 %5)
  %add1 = add i32 %4, %6
  store i32 %add1, ptr %j, align 4
  %7 = load i32, ptr %i, align 4
  %mul = mul i32 %7, 3
  %8 = load i32, ptr %j, align 4
  %mul2 = mul i32 %8, 2
  %add3 = add i32 %mul, %mul2
  %9 = load i32, ptr %j, align 4
  %mul4 = mul i32 %add3, %9
  ret i32 %mul4
}

define i32 @foo.sumArray(ptr %0, i32 %1) #0 {
entry:
  %i = alloca i32, align 4
  %result = alloca i32, align 4
  store i32 0, ptr %result, align 4
  store i32 0, ptr %i, align 4
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %2 = load i32, ptr %i, align 4
  %lt = icmp slt i32 %2, %1
  br i1 %lt, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  %3 = load i32, ptr %result, align 4
  %4 = load i32, ptr %i, align 4
  %sext = sext i32 %4 to i64
  %ptroffset = getelementptr inbounds [4 x i8], ptr %0, i64 %sext
  %5 = load i32, ptr %ptroffset, align 4
  %add = add i32 %3, %5
  store i32 %add, ptr %result, align 4
  %6 = load i32, ptr %i, align 4
  %add1 = add i32 %6, 1
  store i32 %add1, ptr %i, align 4
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  %7 = load i32, ptr %result, align 4
  ret i32 %7
}

define i32 @foo.arrayParam(ptr %0) #0 {
entry:
  %ptradd = getelementptr inbounds i8, ptr %0, i64 200
  %1 = load i32, ptr %ptradd, align 4
  %sext = sext i32 %1 to i64
  %intptr = inttoptr i64 %sext to ptr
  %ptradd1 = getelementptr inbounds i8, ptr %0, i64 200
  %2 = call i32 @ef1(ptr %intptr, ptr inttoptr (i64 1 to ptr), ptr %ptradd1)
  ret i32 %2
}

define i32 @foo.arrayToSum() #0 {
entry:
  %a = alloca [100 x i32], align 16
  %i = alloca i32, align 4
  store i32 0, ptr %i, align 4
  store i32 0, ptr %i, align 4
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %0 = load i32, ptr %i, align 4
  %lt = icmp slt i32 %0, 100
  br i1 %lt, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  %1 = load i32, ptr %i, align 4
  %mul = mul i32 %1, 4
  %2 = load i32, ptr %i, align 4
  %sext = sext i32 %2 to i64
  %ptroffset = getelementptr inbounds [4 x i8], ptr %a, i64 %sext
  store i32 %mul, ptr %ptroffset, align 4
  %3 = load i32, ptr %i, align 4
  %add = add i32 %3, 1
  store i32 %add, ptr %i, align 4
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  %4 = load i32, ptr %a, align 4
  %sext1 = sext i32 %4 to i64
  %ptroffset2 = getelementptr inbounds [4 x i8], ptr %a, i64 %sext1
  %5 = load i32, ptr %ptroffset2, align 4
  ret i32 %5
}

; Function Attrs:
declare i32 @externFunc(i64, ptr, i16 signext, i8 zeroext) #0

; Function Attrs:
define i32 @main(i32 %0, ptr %1) #0 {
entry:
  %i = alloca i32, align 4
  %2 = call i32 @puts(ptr @.str.11)
  %trunc = trunc i32 %0 to i16
  %3 = call i32 @externFunc(i64 -1, ptr null, i16 signext %trunc, i8 zeroext 2)
  store i32 0, ptr %i, align 4
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %4 = load i32, ptr %i, align 4
  %gt = icmp ugt i32 10, %4
  br i1 %gt, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  %ptradd = getelementptr inbounds i8, ptr %1, i64 24
  %5 = load ptr, ptr %ptradd, align 8
  %6 = call i32 @puts(ptr %5)
  %7 = load i32, ptr %i, align 4
  %add = add i32 %7, 1
  store i32 %add, ptr %i, align 4
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  ret i32 0
}

define double @foo.mathFunc(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, double %8, double %9, double %10, double %11, double %12, double %13, double %14, double %15, double %16) #0 {
entry:
  %fadd = fadd double %0, %1
  %fadd1 = fadd double %fadd, %2
  %fadd2 = fadd double %fadd1, %3
  %fadd3 = fadd double %fadd2, %4
  %fadd4 = fadd double %fadd3, %5
  %fadd5 = fadd double %fadd4, %6
  %fadd6 = fadd double %fadd5, %7
  %fadd7 = fadd double %fadd6, %8
  %fadd8 = fadd double %fadd7, %9
  %fadd9 = fadd double %fadd8, %10
  %fadd10 = fadd double %fadd9, %11
  %fadd11 = fadd double %fadd10, %12
  %fadd12 = fadd double %fadd11, %13
  %fadd13 = fadd double %fadd12, %14
  %fadd14 = fadd double %fadd13, %15
  %fadd15 = fadd double %fadd14, %16
  ret double %fadd15
}

define void @foo.strcpy(ptr %0, ptr %1) #0 {
entry:
  %s1 = alloca ptr, align 8
  %s2 = alloca ptr, align 8
  store ptr %0, ptr %s1, align 8
  store ptr %1, ptr %s2, align 8
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %2 = load ptr, ptr %s2, align 8
  %ptradd_any = getelementptr i8, ptr %2, i64 1
  store ptr %ptradd_any, ptr %s2, align 8
  %3 = load ptr, ptr %s1, align 8
  %ptradd_any1 = getelementptr i8, ptr %3, i64 1
  store ptr %ptradd_any1, ptr %s1, align 8
  %4 = load i8, ptr %2, align 1
  store i8 %4, ptr %3, align 1
  %i2b = icmp ne i8 %4, 0
  br i1 %i2b, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  ret void
}

; Function Attrs: nounwind uwtable
define void @foo.strcat(ptr %0, ptr %1) #0 {
entry:
  %s1 = alloca ptr, align 8
  %s2 = alloca ptr, align 8
  store ptr %0, ptr %s1, align 8
  store ptr %1, ptr %s2, align 8
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %2 = load ptr, ptr %s1, align 8
  %ptradd_any = getelementptr i8, ptr %2, i64 1
  store ptr %ptradd_any, ptr %s1, align 8
  %3 = load i8, ptr %2, align 1
  %i2b = icmp ne i8 %3, 0
  br i1 %i2b, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  %4 = load ptr, ptr %s1, align 8
  %ptradd_any1 = getelementptr i8, ptr %4, i64 -1
  store ptr %ptradd_any1, ptr %s1, align 8
  br label %loop.cond2

loop.cond2:                                       ; preds = %loop.body6, %loop.exit
  %5 = load ptr, ptr %s2, align 8
  %ptradd_any3 = getelementptr i8, ptr %5, i64 1
  store ptr %ptradd_any3, ptr %s2, align 8
  %6 = load ptr, ptr %s1, align 8
  %ptradd_any4 = getelementptr i8, ptr %6, i64 1
  store ptr %ptradd_any4, ptr %s1, align 8
  %7 = load i8, ptr %5, align 1
  store i8 %7, ptr %6, align 1
  %i2b5 = icmp ne i8 %7, 0
  br i1 %i2b5, label %loop.body6, label %loop.exit7

loop.body6:                                       ; preds = %loop.cond2
  br label %loop.cond2

loop.exit7:                                       ; preds = %loop.cond2
  ret void
}

; Function Attrs: nounwind uwtable
define i32 @foo.strcmp(ptr %0, ptr %1) #0 {
entry:
  %s1 = alloca ptr, align 8
  %s2 = alloca ptr, align 8
  store ptr %0, ptr %s1, align 8
  store ptr %1, ptr %s2, align 8
  br label %loop.cond

loop.cond:                                        ; preds = %loop.body, %entry
  %2 = load ptr, ptr %s1, align 8
  %ptradd_any = getelementptr i8, ptr %2, i64 1
  store ptr %ptradd_any, ptr %s1, align 8
  %3 = load i8, ptr %2, align 1
  %4 = load ptr, ptr %s2, align 8
  %ptradd_any1 = getelementptr i8, ptr %4, i64 1
  store ptr %ptradd_any1, ptr %s2, align 8
  %5 = load i8, ptr %4, align 1
  %eq = icmp eq i8 %3, %5
  br i1 %eq, label %loop.body, label %loop.exit

loop.body:                                        ; preds = %loop.cond
  br label %loop.cond

loop.exit:                                        ; preds = %loop.cond
  %6 = load ptr, ptr %s1, align 8
  %7 = load i8, ptr %6, align 1
  %zext = zext i8 %7 to i32
  %eq2 = icmp eq i32 0, %zext
  br i1 %eq2, label %if.then, label %if.else6

if.then:                                          ; preds = %loop.exit
  %8 = load ptr, ptr %s2, align 8
  %9 = load i8, ptr %8, align 1
  %zext3 = zext i8 %9 to i32
  %eq4 = icmp eq i32 0, %zext3
  br i1 %eq4, label %if.then5, label %if.else

if.then5:                                         ; preds = %if.then
  ret i32 0

if.else:                                          ; preds = %if.then
  ret i32 -1

if.else6:                                         ; preds = %loop.exit
  %10 = load ptr, ptr %s2, align 8
  %11 = load i8, ptr %10, align 1
  %zext7 = zext i8 %11 to i32
  %eq8 = icmp eq i32 0, %zext7
  br i1 %eq8, label %if.then9, label %if.else10

if.then9:                                         ; preds = %if.else6
  ret i32 1

if.else10:                                        ; preds = %if.else6
  %12 = load ptr, ptr %s1, align 8
  %ptradd_any11 = getelementptr i8, ptr %12, i64 -1
  store ptr %ptradd_any11, ptr %s1, align 8
  %13 = load i8, ptr %ptradd_any11, align 1
  %zext12 = zext i8 %13 to i32
  %14 = load ptr, ptr %s2, align 8
  %ptradd_any13 = getelementptr i8, ptr %14, i64 -1
  store ptr %ptradd_any13, ptr %s2, align 8
  %15 = load i8, ptr %ptradd_any13, align 1
  %zext14 = zext i8 %15 to i32
  %sub = sub i32 %zext12, %zext14
  ret i32 %sub
}
