radeonsi: generate an explicit switch instruction over vertex streams
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Tue, 29 Nov 2016 15:25:21 +0000 (16:25 +0100)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Mon, 12 Dec 2016 08:04:49 +0000 (09:04 +0100)
SimplifyCFG generates a switch instruction anyway when all four streams
are present, but is simultaneously not smart enough to eliminate some
redundant jumps that it generates.

The generated assembly is still a bit silly, probably because the
control flow annotation doesn't know how to handle a switch with uniform
condition.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/radeonsi/si_shader.c

index 31a0b3047c1b04a641406e346a87b7d133c46f70..469e0c1cc3df1a864c30de98d748646bacde6c8b 100644 (file)
@@ -6407,8 +6407,14 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
                }
        }
 
+       LLVMBasicBlockRef end_bb;
+       LLVMValueRef switch_inst;
+
+       end_bb = LLVMAppendBasicBlockInContext(gallivm->context, ctx.main_fn, "end");
+       switch_inst = LLVMBuildSwitch(builder, stream_id, end_bb, 4);
+
        for (int stream = 0; stream < 4; stream++) {
-               struct lp_build_if_state if_ctx_stream;
+               LLVMBasicBlockRef bb;
 
                if (!gsinfo->num_stream_output_components[stream])
                        continue;
@@ -6416,12 +6422,9 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
                if (stream > 0 && !gs_selector->so.num_outputs)
                        continue;
 
-               LLVMValueRef is_stream =
-                       LLVMBuildICmp(builder, LLVMIntEQ,
-                                     stream_id,
-                                     lp_build_const_int32(gallivm, stream), "");
-
-               lp_build_if(&if_ctx_stream, gallivm, is_stream);
+               bb = LLVMInsertBasicBlockInContext(gallivm->context, end_bb, "out");
+               LLVMAddCase(switch_inst, lp_build_const_int32(gallivm, stream), bb);
+               LLVMPositionBuilderAtEnd(builder, bb);
 
                /* Fetch vertex data from GSVS ring */
                for (i = 0; i < gsinfo->num_outputs; ++i) {
@@ -6455,9 +6458,11 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
                if (stream == 0)
                        si_llvm_export_vs(bld_base, outputs, gsinfo->num_outputs);
 
-               lp_build_endif(&if_ctx_stream);
+               LLVMBuildBr(builder, end_bb);
        }
 
+       LLVMPositionBuilderAtEnd(builder, end_bb);
+
        LLVMBuildRetVoid(gallivm->builder);
 
        /* Dump LLVM IR before any optimization passes */