summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler/glsl/builtin_functions.cpp8
-rw-r--r--src/compiler/glsl/builtin_functions.h6
-rw-r--r--src/compiler/glsl/builtin_int64.h672
-rw-r--r--src/compiler/glsl/glcpp/glcpp-parse.y2
-rw-r--r--src/compiler/glsl/int64.glsl77
5 files changed, 763 insertions, 2 deletions
diff --git a/src/compiler/glsl/builtin_functions.cpp b/src/compiler/glsl/builtin_functions.cpp
index f64ab6a5f33..6d9ff4b504c 100644
--- a/src/compiler/glsl/builtin_functions.cpp
+++ b/src/compiler/glsl/builtin_functions.cpp
@@ -3099,10 +3099,18 @@ builtin_builder::create_builtins()
add_function("allInvocationsARB", _vote(ir_unop_vote_all), NULL);
add_function("allInvocationsEqualARB", _vote(ir_unop_vote_eq), NULL);
+ add_function("__builtin_idiv64",
+ generate_ir::idiv64(mem_ctx, integer_functions_supported),
+ NULL);
+
add_function("__builtin_sign64",
generate_ir::sign64(mem_ctx, integer_functions_supported),
NULL);
+ add_function("__builtin_udiv64",
+ generate_ir::udiv64(mem_ctx, integer_functions_supported),
+ NULL);
+
add_function("__builtin_umul64",
generate_ir::umul64(mem_ctx, integer_functions_supported),
NULL);
diff --git a/src/compiler/glsl/builtin_functions.h b/src/compiler/glsl/builtin_functions.h
index c66f523f692..ac1a8ccd1eb 100644
--- a/src/compiler/glsl/builtin_functions.h
+++ b/src/compiler/glsl/builtin_functions.h
@@ -46,6 +46,12 @@ _mesa_glsl_release_builtin_functions(void);
namespace generate_ir {
ir_function_signature *
+udiv64(void *mem_ctx, builtin_available_predicate avail);
+
+ir_function_signature *
+idiv64(void *mem_ctx, builtin_available_predicate avail);
+
+ir_function_signature *
umul64(void *mem_ctx, builtin_available_predicate avail);
ir_function_signature *
diff --git a/src/compiler/glsl/builtin_int64.h b/src/compiler/glsl/builtin_int64.h
index c12565d14c7..5eaa4a8eac9 100644
--- a/src/compiler/glsl/builtin_int64.h
+++ b/src/compiler/glsl/builtin_int64.h
@@ -54,3 +54,675 @@ sign64(void *mem_ctx, builtin_available_predicate avail)
sig->replace_parameters(&sig_parameters);
return sig;
}
+ir_function_signature *
+udivmod64(void *mem_ctx, builtin_available_predicate avail)
+{
+ ir_function_signature *const sig =
+ new(mem_ctx) ir_function_signature(glsl_type::uvec4_type, avail);
+ ir_factory body(&sig->body, mem_ctx);
+ sig->is_defined = true;
+
+ exec_list sig_parameters;
+
+ ir_variable *const r000C = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_function_in);
+ sig_parameters.push_tail(r000C);
+ ir_variable *const r000D = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_function_in);
+ sig_parameters.push_tail(r000D);
+ ir_variable *const r000E = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+ body.emit(r000E);
+ ir_variable *const r000F = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto);
+ body.emit(r000F);
+ ir_variable *const r0010 = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto);
+ body.emit(r0010);
+ ir_variable *const r0011 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto);
+ body.emit(r0011);
+ body.emit(assign(r0011, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03));
+
+ ir_expression *const r0012 = expr(ir_unop_find_msb, swizzle_y(r000D));
+ body.emit(assign(r0010, add(r0012, body.constant(int(32))), 0x01));
+
+ /* IF CONDITION */
+ ir_expression *const r0014 = equal(swizzle_y(r000D), body.constant(0u));
+ ir_expression *const r0015 = gequal(swizzle_y(r000C), swizzle_x(r000D));
+ ir_expression *const r0016 = logic_and(r0014, r0015);
+ ir_if *f0013 = new(mem_ctx) ir_if(operand(r0016).val);
+ exec_list *const f0013_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0013->then_instructions;
+
+ ir_variable *const r0017 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+ body.emit(r0017);
+ ir_variable *const r0018 = body.make_temp(glsl_type::int_type, "findMSB_retval");
+ body.emit(assign(r0018, expr(ir_unop_find_msb, swizzle_x(r000D)), 0x01));
+
+ body.emit(assign(r0010, r0018, 0x01));
+
+ body.emit(assign(r0017, body.constant(int(31)), 0x01));
+
+ /* LOOP BEGIN */
+ ir_loop *f0019 = new(mem_ctx) ir_loop();
+ exec_list *const f0019_parent_instructions = body.instructions;
+
+ body.instructions = &f0019->body_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r001B = less(r0017, body.constant(int(1)));
+ ir_if *f001A = new(mem_ctx) ir_if(operand(r001B).val);
+ exec_list *const f001A_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f001A->then_instructions;
+
+ body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+ body.instructions = f001A_parent_instructions;
+ body.emit(f001A);
+
+ /* END IF */
+
+ /* IF CONDITION */
+ ir_expression *const r001D = sub(body.constant(int(31)), r0017);
+ ir_expression *const r001E = lequal(r0018, r001D);
+ ir_expression *const r001F = lshift(swizzle_x(r000D), r0017);
+ ir_expression *const r0020 = lequal(r001F, swizzle_y(r000C));
+ ir_expression *const r0021 = logic_and(r001E, r0020);
+ ir_if *f001C = new(mem_ctx) ir_if(operand(r0021).val);
+ exec_list *const f001C_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f001C->then_instructions;
+
+ ir_expression *const r0022 = lshift(swizzle_x(r000D), r0017);
+ body.emit(assign(r000C, sub(swizzle_y(r000C), r0022), 0x02));
+
+ ir_expression *const r0023 = lshift(body.constant(1u), r0017);
+ body.emit(assign(r0011, bit_or(swizzle_y(r0011), r0023), 0x02));
+
+
+ body.instructions = f001C_parent_instructions;
+ body.emit(f001C);
+
+ /* END IF */
+
+ body.emit(assign(r0017, add(r0017, body.constant(int(-1))), 0x01));
+
+ /* LOOP END */
+
+ body.instructions = f0019_parent_instructions;
+ body.emit(f0019);
+
+ /* IF CONDITION */
+ ir_expression *const r0025 = lequal(swizzle_x(r000D), swizzle_y(r000C));
+ ir_if *f0024 = new(mem_ctx) ir_if(operand(r0025).val);
+ exec_list *const f0024_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0024->then_instructions;
+
+ body.emit(assign(r000C, sub(swizzle_y(r000C), swizzle_x(r000D)), 0x02));
+
+ body.emit(assign(r0011, bit_or(swizzle_y(r0011), body.constant(1u)), 0x02));
+
+
+ body.instructions = f0024_parent_instructions;
+ body.emit(f0024);
+
+ /* END IF */
+
+
+ body.instructions = f0013_parent_instructions;
+ body.emit(f0013);
+
+ /* END IF */
+
+ ir_variable *const r0026 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval");
+ body.emit(assign(r0026, expr(ir_unop_pack_uint_2x32, r000D), 0x01));
+
+ body.emit(assign(r000F, expr(ir_unop_pack_uint_2x32, r000C), 0x01));
+
+ body.emit(assign(r000E, body.constant(int(31)), 0x01));
+
+ /* LOOP BEGIN */
+ ir_loop *f0027 = new(mem_ctx) ir_loop();
+ exec_list *const f0027_parent_instructions = body.instructions;
+
+ body.instructions = &f0027->body_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r0029 = less(r000E, body.constant(int(1)));
+ ir_if *f0028 = new(mem_ctx) ir_if(operand(r0029).val);
+ exec_list *const f0028_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0028->then_instructions;
+
+ body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+ body.instructions = f0028_parent_instructions;
+ body.emit(f0028);
+
+ /* END IF */
+
+ /* IF CONDITION */
+ ir_expression *const r002B = sub(body.constant(int(63)), r000E);
+ ir_expression *const r002C = lequal(r0010, r002B);
+ ir_expression *const r002D = lshift(r0026, r000E);
+ ir_expression *const r002E = lequal(r002D, r000F);
+ ir_expression *const r002F = logic_and(r002C, r002E);
+ ir_if *f002A = new(mem_ctx) ir_if(operand(r002F).val);
+ exec_list *const f002A_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f002A->then_instructions;
+
+ ir_expression *const r0030 = lshift(r0026, r000E);
+ body.emit(assign(r000F, sub(r000F, r0030), 0x01));
+
+ ir_expression *const r0031 = lshift(body.constant(1u), r000E);
+ body.emit(assign(r0011, bit_or(swizzle_x(r0011), r0031), 0x01));
+
+
+ body.instructions = f002A_parent_instructions;
+ body.emit(f002A);
+
+ /* END IF */
+
+ body.emit(assign(r000E, add(r000E, body.constant(int(-1))), 0x01));
+
+ /* LOOP END */
+
+ body.instructions = f0027_parent_instructions;
+ body.emit(f0027);
+
+ /* IF CONDITION */
+ ir_expression *const r0033 = lequal(r0026, r000F);
+ ir_if *f0032 = new(mem_ctx) ir_if(operand(r0033).val);
+ exec_list *const f0032_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0032->then_instructions;
+
+ body.emit(assign(r000F, sub(r000F, r0026), 0x01));
+
+ body.emit(assign(r0011, bit_or(swizzle_x(r0011), body.constant(1u)), 0x01));
+
+
+ body.instructions = f0032_parent_instructions;
+ body.emit(f0032);
+
+ /* END IF */
+
+ ir_variable *const r0034 = body.make_temp(glsl_type::uvec4_type, "vec_ctor");
+ body.emit(assign(r0034, r0011, 0x03));
+
+ body.emit(assign(r0034, expr(ir_unop_unpack_uint_2x32, r000F), 0x0c));
+
+ body.emit(ret(r0034));
+
+ sig->replace_parameters(&sig_parameters);
+ return sig;
+}
+ir_function_signature *
+udiv64(void *mem_ctx, builtin_available_predicate avail)
+{
+ ir_function_signature *const sig =
+ new(mem_ctx) ir_function_signature(glsl_type::uvec2_type, avail);
+ ir_factory body(&sig->body, mem_ctx);
+ sig->is_defined = true;
+
+ exec_list sig_parameters;
+
+ ir_variable *const r0035 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_function_in);
+ sig_parameters.push_tail(r0035);
+ ir_variable *const r0036 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_function_in);
+ sig_parameters.push_tail(r0036);
+ ir_variable *const r0037 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_auto);
+ body.emit(r0037);
+ body.emit(assign(r0037, r0035, 0x03));
+
+ ir_variable *const r0038 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+ body.emit(r0038);
+ ir_variable *const r0039 = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto);
+ body.emit(r0039);
+ ir_variable *const r003A = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto);
+ body.emit(r003A);
+ ir_variable *const r003B = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto);
+ body.emit(r003B);
+ body.emit(assign(r003B, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03));
+
+ ir_expression *const r003C = expr(ir_unop_find_msb, swizzle_y(r0036));
+ body.emit(assign(r003A, add(r003C, body.constant(int(32))), 0x01));
+
+ /* IF CONDITION */
+ ir_expression *const r003E = equal(swizzle_y(r0036), body.constant(0u));
+ ir_expression *const r003F = gequal(swizzle_y(r0035), swizzle_x(r0036));
+ ir_expression *const r0040 = logic_and(r003E, r003F);
+ ir_if *f003D = new(mem_ctx) ir_if(operand(r0040).val);
+ exec_list *const f003D_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f003D->then_instructions;
+
+ ir_variable *const r0041 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+ body.emit(r0041);
+ ir_variable *const r0042 = body.make_temp(glsl_type::int_type, "findMSB_retval");
+ body.emit(assign(r0042, expr(ir_unop_find_msb, swizzle_x(r0036)), 0x01));
+
+ body.emit(assign(r003A, r0042, 0x01));
+
+ body.emit(assign(r0041, body.constant(int(31)), 0x01));
+
+ /* LOOP BEGIN */
+ ir_loop *f0043 = new(mem_ctx) ir_loop();
+ exec_list *const f0043_parent_instructions = body.instructions;
+
+ body.instructions = &f0043->body_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r0045 = less(r0041, body.constant(int(1)));
+ ir_if *f0044 = new(mem_ctx) ir_if(operand(r0045).val);
+ exec_list *const f0044_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0044->then_instructions;
+
+ body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+ body.instructions = f0044_parent_instructions;
+ body.emit(f0044);
+
+ /* END IF */
+
+ /* IF CONDITION */
+ ir_expression *const r0047 = sub(body.constant(int(31)), r0041);
+ ir_expression *const r0048 = lequal(r0042, r0047);
+ ir_expression *const r0049 = lshift(swizzle_x(r0036), r0041);
+ ir_expression *const r004A = lequal(r0049, swizzle_y(r0037));
+ ir_expression *const r004B = logic_and(r0048, r004A);
+ ir_if *f0046 = new(mem_ctx) ir_if(operand(r004B).val);
+ exec_list *const f0046_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0046->then_instructions;
+
+ ir_expression *const r004C = lshift(swizzle_x(r0036), r0041);
+ body.emit(assign(r0037, sub(swizzle_y(r0037), r004C), 0x02));
+
+ ir_expression *const r004D = lshift(body.constant(1u), r0041);
+ body.emit(assign(r003B, bit_or(swizzle_y(r003B), r004D), 0x02));
+
+
+ body.instructions = f0046_parent_instructions;
+ body.emit(f0046);
+
+ /* END IF */
+
+ body.emit(assign(r0041, add(r0041, body.constant(int(-1))), 0x01));
+
+ /* LOOP END */
+
+ body.instructions = f0043_parent_instructions;
+ body.emit(f0043);
+
+ /* IF CONDITION */
+ ir_expression *const r004F = lequal(swizzle_x(r0036), swizzle_y(r0037));
+ ir_if *f004E = new(mem_ctx) ir_if(operand(r004F).val);
+ exec_list *const f004E_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f004E->then_instructions;
+
+ body.emit(assign(r0037, sub(swizzle_y(r0037), swizzle_x(r0036)), 0x02));
+
+ body.emit(assign(r003B, bit_or(swizzle_y(r003B), body.constant(1u)), 0x02));
+
+
+ body.instructions = f004E_parent_instructions;
+ body.emit(f004E);
+
+ /* END IF */
+
+
+ body.instructions = f003D_parent_instructions;
+ body.emit(f003D);
+
+ /* END IF */
+
+ ir_variable *const r0050 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval");
+ body.emit(assign(r0050, expr(ir_unop_pack_uint_2x32, r0036), 0x01));
+
+ body.emit(assign(r0039, expr(ir_unop_pack_uint_2x32, r0037), 0x01));
+
+ body.emit(assign(r0038, body.constant(int(31)), 0x01));
+
+ /* LOOP BEGIN */
+ ir_loop *f0051 = new(mem_ctx) ir_loop();
+ exec_list *const f0051_parent_instructions = body.instructions;
+
+ body.instructions = &f0051->body_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r0053 = less(r0038, body.constant(int(1)));
+ ir_if *f0052 = new(mem_ctx) ir_if(operand(r0053).val);
+ exec_list *const f0052_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0052->then_instructions;
+
+ body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+ body.instructions = f0052_parent_instructions;
+ body.emit(f0052);
+
+ /* END IF */
+
+ /* IF CONDITION */
+ ir_expression *const r0055 = sub(body.constant(int(63)), r0038);
+ ir_expression *const r0056 = lequal(r003A, r0055);
+ ir_expression *const r0057 = lshift(r0050, r0038);
+ ir_expression *const r0058 = lequal(r0057, r0039);
+ ir_expression *const r0059 = logic_and(r0056, r0058);
+ ir_if *f0054 = new(mem_ctx) ir_if(operand(r0059).val);
+ exec_list *const f0054_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0054->then_instructions;
+
+ ir_expression *const r005A = lshift(r0050, r0038);
+ body.emit(assign(r0039, sub(r0039, r005A), 0x01));
+
+ ir_expression *const r005B = lshift(body.constant(1u), r0038);
+ body.emit(assign(r003B, bit_or(swizzle_x(r003B), r005B), 0x01));
+
+
+ body.instructions = f0054_parent_instructions;
+ body.emit(f0054);
+
+ /* END IF */
+
+ body.emit(assign(r0038, add(r0038, body.constant(int(-1))), 0x01));
+
+ /* LOOP END */
+
+ body.instructions = f0051_parent_instructions;
+ body.emit(f0051);
+
+ /* IF CONDITION */
+ ir_expression *const r005D = lequal(r0050, r0039);
+ ir_if *f005C = new(mem_ctx) ir_if(operand(r005D).val);
+ exec_list *const f005C_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f005C->then_instructions;
+
+ body.emit(assign(r0039, sub(r0039, r0050), 0x01));
+
+ body.emit(assign(r003B, bit_or(swizzle_x(r003B), body.constant(1u)), 0x01));
+
+
+ body.instructions = f005C_parent_instructions;
+ body.emit(f005C);
+
+ /* END IF */
+
+ body.emit(ret(r003B));
+
+ sig->replace_parameters(&sig_parameters);
+ return sig;
+}
+ir_function_signature *
+idiv64(void *mem_ctx, builtin_available_predicate avail)
+{
+ ir_function_signature *const sig =
+ new(mem_ctx) ir_function_signature(glsl_type::ivec2_type, avail);
+ ir_factory body(&sig->body, mem_ctx);
+ sig->is_defined = true;
+
+ exec_list sig_parameters;
+
+ ir_variable *const r005E = new(mem_ctx) ir_variable(glsl_type::ivec2_type, "_n", ir_var_function_in);
+ sig_parameters.push_tail(r005E);
+ ir_variable *const r005F = new(mem_ctx) ir_variable(glsl_type::ivec2_type, "_d", ir_var_function_in);
+ sig_parameters.push_tail(r005F);
+ ir_variable *const r0060 = new(mem_ctx) ir_variable(glsl_type::bool_type, "negate", ir_var_auto);
+ body.emit(r0060);
+ ir_expression *const r0061 = less(swizzle_y(r005E), body.constant(int(0)));
+ ir_expression *const r0062 = less(swizzle_y(r005F), body.constant(int(0)));
+ body.emit(assign(r0060, nequal(r0061, r0062), 0x01));
+
+ ir_variable *const r0063 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_auto);
+ body.emit(r0063);
+ ir_expression *const r0064 = expr(ir_unop_pack_int_2x32, r005E);
+ ir_expression *const r0065 = expr(ir_unop_abs, r0064);
+ ir_expression *const r0066 = expr(ir_unop_i642u64, r0065);
+ body.emit(assign(r0063, expr(ir_unop_unpack_uint_2x32, r0066), 0x03));
+
+ ir_variable *const r0067 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_auto);
+ body.emit(r0067);
+ ir_expression *const r0068 = expr(ir_unop_pack_int_2x32, r005F);
+ ir_expression *const r0069 = expr(ir_unop_abs, r0068);
+ ir_expression *const r006A = expr(ir_unop_i642u64, r0069);
+ body.emit(assign(r0067, expr(ir_unop_unpack_uint_2x32, r006A), 0x03));
+
+ ir_variable *const r006B = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+ body.emit(r006B);
+ ir_variable *const r006C = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto);
+ body.emit(r006C);
+ ir_variable *const r006D = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto);
+ body.emit(r006D);
+ ir_variable *const r006E = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto);
+ body.emit(r006E);
+ body.emit(assign(r006E, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03));
+
+ ir_expression *const r006F = expr(ir_unop_find_msb, swizzle_y(r0067));
+ body.emit(assign(r006D, add(r006F, body.constant(int(32))), 0x01));
+
+ /* IF CONDITION */
+ ir_expression *const r0071 = equal(swizzle_y(r0067), body.constant(0u));
+ ir_expression *const r0072 = gequal(swizzle_y(r0063), swizzle_x(r0067));
+ ir_expression *const r0073 = logic_and(r0071, r0072);
+ ir_if *f0070 = new(mem_ctx) ir_if(operand(r0073).val);
+ exec_list *const f0070_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0070->then_instructions;
+
+ ir_variable *const r0074 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+ body.emit(r0074);
+ ir_variable *const r0075 = body.make_temp(glsl_type::int_type, "findMSB_retval");
+ body.emit(assign(r0075, expr(ir_unop_find_msb, swizzle_x(r0067)), 0x01));
+
+ body.emit(assign(r006D, r0075, 0x01));
+
+ body.emit(assign(r0074, body.constant(int(31)), 0x01));
+
+ /* LOOP BEGIN */
+ ir_loop *f0076 = new(mem_ctx) ir_loop();
+ exec_list *const f0076_parent_instructions = body.instructions;
+
+ body.instructions = &f0076->body_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r0078 = less(r0074, body.constant(int(1)));
+ ir_if *f0077 = new(mem_ctx) ir_if(operand(r0078).val);
+ exec_list *const f0077_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0077->then_instructions;
+
+ body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+ body.instructions = f0077_parent_instructions;
+ body.emit(f0077);
+
+ /* END IF */
+
+ /* IF CONDITION */
+ ir_expression *const r007A = sub(body.constant(int(31)), r0074);
+ ir_expression *const r007B = lequal(r0075, r007A);
+ ir_expression *const r007C = lshift(swizzle_x(r0067), r0074);
+ ir_expression *const r007D = lequal(r007C, swizzle_y(r0063));
+ ir_expression *const r007E = logic_and(r007B, r007D);
+ ir_if *f0079 = new(mem_ctx) ir_if(operand(r007E).val);
+ exec_list *const f0079_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0079->then_instructions;
+
+ ir_expression *const r007F = lshift(swizzle_x(r0067), r0074);
+ body.emit(assign(r0063, sub(swizzle_y(r0063), r007F), 0x02));
+
+ ir_expression *const r0080 = lshift(body.constant(1u), r0074);
+ body.emit(assign(r006E, bit_or(swizzle_y(r006E), r0080), 0x02));
+
+
+ body.instructions = f0079_parent_instructions;
+ body.emit(f0079);
+
+ /* END IF */
+
+ body.emit(assign(r0074, add(r0074, body.constant(int(-1))), 0x01));
+
+ /* LOOP END */
+
+ body.instructions = f0076_parent_instructions;
+ body.emit(f0076);
+
+ /* IF CONDITION */
+ ir_expression *const r0082 = lequal(swizzle_x(r0067), swizzle_y(r0063));
+ ir_if *f0081 = new(mem_ctx) ir_if(operand(r0082).val);
+ exec_list *const f0081_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0081->then_instructions;
+
+ body.emit(assign(r0063, sub(swizzle_y(r0063), swizzle_x(r0067)), 0x02));
+
+ body.emit(assign(r006E, bit_or(swizzle_y(r006E), body.constant(1u)), 0x02));
+
+
+ body.instructions = f0081_parent_instructions;
+ body.emit(f0081);
+
+ /* END IF */
+
+
+ body.instructions = f0070_parent_instructions;
+ body.emit(f0070);
+
+ /* END IF */
+
+ ir_variable *const r0083 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval");
+ body.emit(assign(r0083, expr(ir_unop_pack_uint_2x32, r0067), 0x01));
+
+ body.emit(assign(r006C, expr(ir_unop_pack_uint_2x32, r0063), 0x01));
+
+ body.emit(assign(r006B, body.constant(int(31)), 0x01));
+
+ /* LOOP BEGIN */
+ ir_loop *f0084 = new(mem_ctx) ir_loop();
+ exec_list *const f0084_parent_instructions = body.instructions;
+
+ body.instructions = &f0084->body_instructions;
+
+ /* IF CONDITION */
+ ir_expression *const r0086 = less(r006B, body.constant(int(1)));
+ ir_if *f0085 = new(mem_ctx) ir_if(operand(r0086).val);
+ exec_list *const f0085_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0085->then_instructions;
+
+ body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+ body.instructions = f0085_parent_instructions;
+ body.emit(f0085);
+
+ /* END IF */
+
+ /* IF CONDITION */
+ ir_expression *const r0088 = sub(body.constant(int(63)), r006B);
+ ir_expression *const r0089 = lequal(r006D, r0088);
+ ir_expression *const r008A = lshift(r0083, r006B);
+ ir_expression *const r008B = lequal(r008A, r006C);
+ ir_expression *const r008C = logic_and(r0089, r008B);
+ ir_if *f0087 = new(mem_ctx) ir_if(operand(r008C).val);
+ exec_list *const f0087_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0087->then_instructions;
+
+ ir_expression *const r008D = lshift(r0083, r006B);
+ body.emit(assign(r006C, sub(r006C, r008D), 0x01));
+
+ ir_expression *const r008E = lshift(body.constant(1u), r006B);
+ body.emit(assign(r006E, bit_or(swizzle_x(r006E), r008E), 0x01));
+
+
+ body.instructions = f0087_parent_instructions;
+ body.emit(f0087);
+
+ /* END IF */
+
+ body.emit(assign(r006B, add(r006B, body.constant(int(-1))), 0x01));
+
+ /* LOOP END */
+
+ body.instructions = f0084_parent_instructions;
+ body.emit(f0084);
+
+ /* IF CONDITION */
+ ir_expression *const r0090 = lequal(r0083, r006C);
+ ir_if *f008F = new(mem_ctx) ir_if(operand(r0090).val);
+ exec_list *const f008F_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f008F->then_instructions;
+
+ body.emit(assign(r006C, sub(r006C, r0083), 0x01));
+
+ body.emit(assign(r006E, bit_or(swizzle_x(r006E), body.constant(1u)), 0x01));
+
+
+ body.instructions = f008F_parent_instructions;
+ body.emit(f008F);
+
+ /* END IF */
+
+ ir_variable *const r0091 = body.make_temp(glsl_type::ivec2_type, "conditional_tmp");
+ /* IF CONDITION */
+ ir_if *f0092 = new(mem_ctx) ir_if(operand(r0060).val);
+ exec_list *const f0092_parent_instructions = body.instructions;
+
+ /* THEN INSTRUCTIONS */
+ body.instructions = &f0092->then_instructions;
+
+ ir_expression *const r0093 = expr(ir_unop_pack_uint_2x32, r006E);
+ ir_expression *const r0094 = expr(ir_unop_u642i64, r0093);
+ ir_expression *const r0095 = neg(r0094);
+ body.emit(assign(r0091, expr(ir_unop_unpack_int_2x32, r0095), 0x03));
+
+
+ /* ELSE INSTRUCTIONS */
+ body.instructions = &f0092->else_instructions;
+
+ body.emit(assign(r0091, expr(ir_unop_u2i, r006E), 0x03));
+
+
+ body.instructions = f0092_parent_instructions;
+ body.emit(f0092);
+
+ /* END IF */
+
+ body.emit(ret(r0091));
+
+ sig->replace_parameters(&sig_parameters);
+ return sig;
+}
diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y
index 39a7a89258f..d801cf8a9d7 100644
--- a/src/compiler/glsl/glcpp/glcpp-parse.y
+++ b/src/compiler/glsl/glcpp/glcpp-parse.y
@@ -2345,6 +2345,8 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
if (parser->extension_list->MESA_shader_integer_functions) {
add_builtin_define(parser, "__have_builtin_builtin_sign64", 1);
add_builtin_define(parser, "__have_builtin_builtin_umul64", 1);
+ add_builtin_define(parser, "__have_builtin_builtin_udiv64", 1);
+ add_builtin_define(parser, "__have_builtin_builtin_idiv64", 1);
}
}
diff --git a/src/compiler/glsl/int64.glsl b/src/compiler/glsl/int64.glsl
index a2bec011e3e..84e80ee349b 100644
--- a/src/compiler/glsl/int64.glsl
+++ b/src/compiler/glsl/int64.glsl
@@ -4,8 +4,9 @@
*
* Using version 1.40+ prevents built-in variables from being included.
*/
-#version 140
-#extension GL_MESA_shader_integer_functions: require
+#version 400
+#extension GL_ARB_gpu_shader_int64: require
+#extension GL_ARB_shading_language_420pack: require
uvec2
umul64(uvec2 a, uvec2 b)
@@ -28,3 +29,75 @@ sign64(ivec2 a)
return result;
}
+
+uvec4
+udivmod64(uvec2 n, uvec2 d)
+{
+ uvec2 quot = uvec2(0U, 0U);
+ int log2_denom = findMSB(d.y) + 32;
+
+ /* If the upper 32 bits of denom are non-zero, it is impossible for shifts
+ * greater than 32 bits to occur. If the upper 32 bits of the numerator
+ * are zero, it is impossible for (denom << [63, 32]) <= numer unless
+ * denom == 0.
+ */
+ if (d.y == 0 && n.y >= d.x) {
+ log2_denom = findMSB(d.x);
+
+ /* Since the upper 32 bits of denom are zero, log2_denom <= 31 and we
+ * don't have to compare log2_denom inside the loop as is done in the
+ * general case (below).
+ */
+ for (int i = 31; i >= 1; i--) {
+ if (log2_denom <= 31 - i && (d.x << i) <= n.y) {
+ n.y -= d.x << i;
+ quot.y |= 1U << i;
+ }
+ }
+
+ /* log2_denom is always <= 31, so manually peel the last loop
+ * iteration.
+ */
+ if (d.x <= n.y) {
+ n.y -= d.x;
+ quot.y |= 1U;
+ }
+ }
+
+ uint64_t d64 = packUint2x32(d);
+ uint64_t n64 = packUint2x32(n);
+ for (int i = 31; i >= 1; i--) {
+ if (log2_denom <= 63 - i && (d64 << i) <= n64) {
+ n64 -= d64 << i;
+ quot.x |= 1U << i;
+ }
+ }
+
+ /* log2_denom is always <= 63, so manually peel the last loop
+ * iteration.
+ */
+ if (d64 <= n64) {
+ n64 -= d64;
+ quot.x |= 1U;
+ }
+
+ return uvec4(quot, unpackUint2x32(n64));
+}
+
+uvec2
+udiv64(uvec2 n, uvec2 d)
+{
+ return udivmod64(n, d).xy;
+}
+
+ivec2
+idiv64(ivec2 _n, ivec2 _d)
+{
+ const bool negate = (_n.y < 0) != (_d.y < 0);
+ uvec2 n = unpackUint2x32(uint64_t(abs(packInt2x32(_n))));
+ uvec2 d = unpackUint2x32(uint64_t(abs(packInt2x32(_d))));
+
+ uvec2 quot = udivmod64(n, d).xy;
+
+ return negate ? unpackInt2x32(-int64_t(packUint2x32(quot))) : ivec2(quot);
+}