From 630fa2688634365c03edf2a189cf9225899fbcc5 Mon Sep 17 00:00:00 2001 From: James Benton Date: Thu, 19 Apr 2012 13:02:57 +0100 Subject: [PATCH] gallivm: llvm c-style for loops, allows us to create loops with conditions on entry, rather than condition check on loop --- src/gallium/auxiliary/gallivm/lp_bld_flow.c | 67 +++++++++++++++++++++ src/gallium/auxiliary/gallivm/lp_bld_flow.h | 27 +++++++++ 2 files changed, 94 insertions(+) diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.c b/src/gallium/auxiliary/gallivm/lp_bld_flow.c index a9c9c7af10c..d2b3713ed2d 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_flow.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.c @@ -265,6 +265,73 @@ lp_build_loop_end(struct lp_build_loop_state *state, lp_build_loop_end_cond(state, end, step, LLVMIntNE); } +/** + * Creates a c-style for loop, + * contrasts lp_build_loop as this checks condition on entry + * e.g. for(i = start; i cmp_op end; i += step) + * \param state the for loop state, initialized here + * \param gallivm the gallivm state + * \param start starting value of iterator + * \param cmp_op comparison operator used for comparing current value with end value + * \param end value used to compare against iterator + * \param step value added to iterator at end of each loop + */ +void +lp_build_for_loop_begin(struct lp_build_for_loop_state *state, + struct gallivm_state *gallivm, + LLVMValueRef start, + LLVMIntPredicate cmp_op, + LLVMValueRef end, + LLVMValueRef step) +{ + LLVMBuilderRef builder = gallivm->builder; + + assert(LLVMTypeOf(start) == LLVMTypeOf(end)); + assert(LLVMTypeOf(start) == LLVMTypeOf(step)); + + state->begin = lp_build_insert_new_block(gallivm, "loop_begin"); + state->step = step; + state->counter_var = lp_build_alloca(gallivm, LLVMTypeOf(start), "loop_counter"); + state->gallivm = gallivm; + state->cond = cmp_op; + state->end = end; + + LLVMBuildStore(builder, start, state->counter_var); + LLVMBuildBr(builder, state->begin); + + LLVMPositionBuilderAtEnd(builder, state->begin); + state->counter = LLVMBuildLoad(builder, state->counter_var, ""); + + state->body = lp_build_insert_new_block(gallivm, "loop_body"); + LLVMPositionBuilderAtEnd(builder, state->body); +} + +/** + * End the for loop. + */ +void +lp_build_for_loop_end(struct lp_build_for_loop_state *state) +{ + LLVMValueRef next, cond; + LLVMBuilderRef builder = state->gallivm->builder; + + next = LLVMBuildAdd(builder, state->counter, state->step, ""); + LLVMBuildStore(builder, next, state->counter_var); + LLVMBuildBr(builder, state->begin); + + state->exit = lp_build_insert_new_block(state->gallivm, "loop_exit"); + + /* + * We build the comparison for the begin block here, + * if we build it earlier the output llvm ir is not human readable + * as the code produced is not in the standard begin -> body -> end order. + */ + LLVMPositionBuilderAtEnd(builder, state->begin); + cond = LLVMBuildICmp(builder, state->cond, state->counter, state->end, ""); + LLVMBuildCondBr(builder, cond, state->body, state->exit); + + LLVMPositionBuilderAtEnd(builder, state->exit); +} /* diff --git a/src/gallium/auxiliary/gallivm/lp_bld_flow.h b/src/gallium/auxiliary/gallivm/lp_bld_flow.h index 3cd5a9f42a5..0da849bfe0c 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_flow.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_flow.h @@ -131,6 +131,33 @@ lp_build_loop_end_cond(struct lp_build_loop_state *state, LLVMIntPredicate cond); +/** + * Implementation of simple C-style for loops + */ +struct lp_build_for_loop_state +{ + LLVMBasicBlockRef begin; + LLVMBasicBlockRef body; + LLVMBasicBlockRef exit; + LLVMValueRef counter_var; + LLVMValueRef counter; + LLVMValueRef step; + LLVMIntPredicate cond; + LLVMValueRef end; + struct gallivm_state *gallivm; +}; + +void +lp_build_for_loop_begin(struct lp_build_for_loop_state *state, + struct gallivm_state *gallivm, + LLVMValueRef start, + LLVMIntPredicate llvm_cond, + LLVMValueRef end, + LLVMValueRef step); + +void +lp_build_for_loop_end(struct lp_build_for_loop_state *state); + /** * if/else/endif. -- 2.30.2