mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Added fannkuch example.
This commit is contained in:
81
resources/examples/fannkuch-redux.c3
Normal file
81
resources/examples/fannkuch-redux.c3
Normal file
@@ -0,0 +1,81 @@
|
||||
module fannkuch;
|
||||
import std::mem;
|
||||
|
||||
macro int max(int a, int b)
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
func int fannkuchredux(int n)
|
||||
{
|
||||
int* perm = mem::alloc($sizeof(int), n);
|
||||
int* perm1 = mem::alloc($sizeof(int), n);
|
||||
int* count = mem::alloc($sizeof(int), n);
|
||||
int maxFlipsCount;
|
||||
int permCount;
|
||||
int checksum;
|
||||
|
||||
for (int i = 0; i < n; i++) perm1[i] = i;
|
||||
|
||||
int r = n;
|
||||
|
||||
while (1)
|
||||
{
|
||||
for (; r != 1; r--) count[r - 1] = r;
|
||||
|
||||
for (int i = 0; i < n; i++) perm[i] = perm1[i];
|
||||
|
||||
int flipsCount = 0;
|
||||
int k;
|
||||
|
||||
while (!((k = perm[0]) == 0))
|
||||
{
|
||||
int k2 = (k + 1) >> 1;
|
||||
for (int i = 0; i < k2; i++)
|
||||
{
|
||||
int temp = perm[i];
|
||||
perm[i] = perm[k - i];
|
||||
perm[k - i] = temp;
|
||||
}
|
||||
flipsCount++;
|
||||
}
|
||||
|
||||
maxFlipsCount = @max(maxFlipsCount, flipsCount);
|
||||
checksum += permCount % 2 == 0 ? flipsCount : -flipsCount;
|
||||
|
||||
/* Use incremental change to generate another permutation */
|
||||
while (1)
|
||||
{
|
||||
if (r == n)
|
||||
{
|
||||
printf("%d\n", checksum);
|
||||
return maxFlipsCount;
|
||||
}
|
||||
|
||||
int perm0 = perm1[0];
|
||||
int i = 0;
|
||||
while (i < r)
|
||||
{
|
||||
int j = i + 1;
|
||||
perm1[i] = perm1[j];
|
||||
i = j;
|
||||
}
|
||||
perm1[r] = perm0;
|
||||
count[r] = count[r] - 1;
|
||||
if (count[r] > 0) break;
|
||||
r++;
|
||||
}
|
||||
permCount++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern func int atoi(char *s);
|
||||
extern func int printf(char *s, ...);
|
||||
|
||||
func int main(int argc, char** argv)
|
||||
{
|
||||
int n = argc > 1 ? atoi(argv[1]) : 7;
|
||||
printf("Pfannkuchen(%d) = %d\n", n, fannkuchredux(n));
|
||||
return 0;
|
||||
}
|
||||
@@ -572,17 +572,41 @@ void gencontext_emit_while_stmt(GenContext *context, Ast *ast)
|
||||
// First, emit all inits.
|
||||
LLVMBasicBlockRef exit_block = llvm_basic_block_new(context, "while.exit");
|
||||
LLVMBasicBlockRef begin_block = llvm_basic_block_new(context, "while.begin");
|
||||
LLVMBasicBlockRef body_block = ast->while_stmt.body->compound_stmt.stmts ? llvm_basic_block_new(context,
|
||||
"while.body") : NULL;
|
||||
LLVMBasicBlockRef body_block = ast->while_stmt.body->compound_stmt.stmts ? llvm_basic_block_new(context, "while.body") : NULL;
|
||||
|
||||
ast->while_stmt.continue_block = begin_block;
|
||||
ast->while_stmt.break_block = exit_block;
|
||||
|
||||
Expr *cond = ast->while_stmt.cond;
|
||||
|
||||
bool is_infinite_loop = false;
|
||||
|
||||
// Is this while (false) or while (true)
|
||||
if (cond->expr_kind == EXPR_COND && vec_size(cond->cond_expr) == 1)
|
||||
{
|
||||
Expr *expr = cond->cond_expr[0];
|
||||
if (expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_BOOL)
|
||||
{
|
||||
is_infinite_loop = expr->const_expr.b;
|
||||
// This is a NOP
|
||||
if (!is_infinite_loop) return;
|
||||
assert(body_block);
|
||||
}
|
||||
}
|
||||
|
||||
DeferList defers = { 0, 0 };
|
||||
|
||||
// Emit cond
|
||||
llvm_emit_br(context, begin_block);
|
||||
|
||||
if (is_infinite_loop)
|
||||
{
|
||||
body_block = begin_block;
|
||||
goto EMIT_BODY;
|
||||
}
|
||||
|
||||
llvm_emit_block(context, begin_block);
|
||||
DeferList defers = { 0, 0 };
|
||||
Expr *cond = ast->while_stmt.cond;
|
||||
|
||||
if (cond->expr_kind == EXPR_SCOPED_EXPR)
|
||||
{
|
||||
defers = cond->expr_scope.defers;
|
||||
@@ -606,6 +630,7 @@ void gencontext_emit_while_stmt(GenContext *context, Ast *ast)
|
||||
llvm_emit_cond_br(context, &be_value, begin_block, exit_block);
|
||||
}
|
||||
|
||||
EMIT_BODY:
|
||||
if (body_block)
|
||||
{
|
||||
llvm_emit_block(context, body_block);
|
||||
|
||||
@@ -132,14 +132,8 @@ for.body:
|
||||
br label %while.begin
|
||||
|
||||
while.begin:
|
||||
br i1 true, label %while.body, label %while.exit
|
||||
|
||||
while.body:
|
||||
br label %for.exit
|
||||
|
||||
while.exit:
|
||||
br label %for.cond
|
||||
|
||||
for.exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ extern func int printf(char *fmt, ...);
|
||||
// #expect: foo.ll
|
||||
|
||||
define void @main()
|
||||
entry:
|
||||
%i = alloca [3 x i32], align 4
|
||||
%x = alloca %Foo, align 8
|
||||
%f = alloca i32, align 4
|
||||
@@ -69,13 +68,13 @@ entry:
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %8, i8* align 8 %9, i32 16, i1 false)
|
||||
br label %expr_block.exit
|
||||
|
||||
expr_block.exit:
|
||||
expr_block.exit: ; preds = %entry
|
||||
%10 = bitcast %FooIterator* %.iterator to i8*
|
||||
%11 = bitcast %FooIterator* %blockret to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %10, i8* align 8 %11, i32 16, i1 false)
|
||||
br label %for.cond
|
||||
|
||||
for.cond:
|
||||
for.cond: ; preds = %expr_block.exit
|
||||
store %FooIterator* %.iterator, %FooIterator** %it, align 8
|
||||
store i32* %f, i32** %value, align 8
|
||||
%12 = load %FooIterator*, %FooIterator** %it, align 8
|
||||
@@ -90,11 +89,11 @@ for.cond:
|
||||
%eq = icmp eq i64 %14, %19
|
||||
br i1 %eq, label %if.then, label %if.exit
|
||||
|
||||
if.then:
|
||||
if.then: ; preds = %for.cond
|
||||
store i8 0, i8* %blockret2, align 1
|
||||
br label %expr_block.exit3
|
||||
|
||||
if.exit:
|
||||
if.exit: ; preds = %for.cond
|
||||
%20 = load i32*, i32** %value, align 8
|
||||
%21 = load %FooIterator*, %FooIterator** %it, align 8
|
||||
%22 = getelementptr inbounds %FooIterator, %FooIterator* %21, i32 0, i32 1
|
||||
@@ -113,25 +112,19 @@ if.exit:
|
||||
store i8 1, i8* %blockret2, align 1
|
||||
br label %expr_block.exit3
|
||||
|
||||
expr_block.exit3:
|
||||
expr_block.exit3: ; preds = %if.exit, %if.then
|
||||
%29 = load i8, i8* %blockret2, align 1
|
||||
%30 = trunc i8 %29 to i1
|
||||
br i1 %30, label %for.body, label %for.exit
|
||||
|
||||
for.body:
|
||||
for.body: ; preds = %expr_block.exit3
|
||||
%31 = load i32, i32* %f, align 4
|
||||
%32 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i32 %31)
|
||||
br label %while.begin
|
||||
|
||||
while.begin:
|
||||
br i1 true, label %while.body, label %while.exit
|
||||
|
||||
while.body:
|
||||
while.begin: ; preds = %for.body
|
||||
br label %for.exit
|
||||
|
||||
while.exit:
|
||||
br label %for.cond
|
||||
|
||||
for.exit:
|
||||
for.exit: ; preds = %while.begin, %expr_block.exit3
|
||||
ret void
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user