glsl: Add "built-in" functions to do 64%64 => 64 modulus
authorIan Romanick <ian.d.romanick@intel.com>
Tue, 18 Oct 2016 23:46:35 +0000 (16:46 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 20 Jan 2017 23:41:23 +0000 (15:41 -0800)
These functions are directly available in shaders.  A #define is added
to detect the presence.  This allows these functions to be tested using
piglit regardless of whether the driver uses them for lowering.  The
GLSL spec says that functions and macros beginning with __ are reserved
for use by the implementation... hey, that's us!

v2: Use function inlining.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/compiler/glsl/builtin_functions.cpp
src/compiler/glsl/builtin_functions.h
src/compiler/glsl/builtin_int64.h
src/compiler/glsl/glcpp/glcpp-parse.y
src/compiler/glsl/int64.glsl

index 6d9ff4b504c75bc9666edda63f91a8442467055b..4a6c5afd65c9e6ed7499168066b563b2f3aa6dc1 100644 (file)
@@ -3103,6 +3103,10 @@ builtin_builder::create_builtins()
                 generate_ir::idiv64(mem_ctx, integer_functions_supported),
                 NULL);
 
+   add_function("__builtin_imod64",
+                generate_ir::imod64(mem_ctx, integer_functions_supported),
+                NULL);
+
    add_function("__builtin_sign64",
                 generate_ir::sign64(mem_ctx, integer_functions_supported),
                 NULL);
@@ -3111,6 +3115,10 @@ builtin_builder::create_builtins()
                 generate_ir::udiv64(mem_ctx, integer_functions_supported),
                 NULL);
 
+   add_function("__builtin_umod64",
+                generate_ir::umod64(mem_ctx, integer_functions_supported),
+                NULL);
+
    add_function("__builtin_umul64",
                 generate_ir::umul64(mem_ctx, integer_functions_supported),
                 NULL);
index ac1a8ccd1eb2a06aecbdd1abfddd236f6b1bd82b..7ae211b48aa070e0da781ad38e699b919754d188 100644 (file)
@@ -51,6 +51,12 @@ udiv64(void *mem_ctx, builtin_available_predicate avail);
 ir_function_signature *
 idiv64(void *mem_ctx, builtin_available_predicate avail);
 
+ir_function_signature *
+umod64(void *mem_ctx, builtin_available_predicate avail);
+
+ir_function_signature *
+imod64(void *mem_ctx, builtin_available_predicate avail);
+
 ir_function_signature *
 umul64(void *mem_ctx, builtin_available_predicate avail);
 
index 5eaa4a8eac96b6827e927940db5158a943f4f22a..c3577afdee880804560c44971ca79f8bba123634 100644 (file)
@@ -726,3 +726,477 @@ idiv64(void *mem_ctx, builtin_available_predicate avail)
    sig->replace_parameters(&sig_parameters);
    return sig;
 }
+ir_function_signature *
+umod64(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 r0096 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_function_in);
+   sig_parameters.push_tail(r0096);
+   ir_variable *const r0097 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_function_in);
+   sig_parameters.push_tail(r0097);
+   ir_variable *const r0098 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_auto);
+   body.emit(r0098);
+   body.emit(assign(r0098, r0096, 0x03));
+
+   ir_variable *const r0099 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+   body.emit(r0099);
+   ir_variable *const r009A = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto);
+   body.emit(r009A);
+   ir_variable *const r009B = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto);
+   body.emit(r009B);
+   ir_variable *const r009C = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto);
+   body.emit(r009C);
+   body.emit(assign(r009C, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03));
+
+   ir_expression *const r009D = expr(ir_unop_find_msb, swizzle_y(r0097));
+   body.emit(assign(r009B, add(r009D, body.constant(int(32))), 0x01));
+
+   /* IF CONDITION */
+   ir_expression *const r009F = equal(swizzle_y(r0097), body.constant(0u));
+   ir_expression *const r00A0 = gequal(swizzle_y(r0096), swizzle_x(r0097));
+   ir_expression *const r00A1 = logic_and(r009F, r00A0);
+   ir_if *f009E = new(mem_ctx) ir_if(operand(r00A1).val);
+   exec_list *const f009E_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f009E->then_instructions;
+
+      ir_variable *const r00A2 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+      body.emit(r00A2);
+      ir_variable *const r00A3 = body.make_temp(glsl_type::int_type, "findMSB_retval");
+      body.emit(assign(r00A3, expr(ir_unop_find_msb, swizzle_x(r0097)), 0x01));
+
+      body.emit(assign(r009B, r00A3, 0x01));
+
+      body.emit(assign(r00A2, body.constant(int(31)), 0x01));
+
+      /* LOOP BEGIN */
+      ir_loop *f00A4 = new(mem_ctx) ir_loop();
+      exec_list *const f00A4_parent_instructions = body.instructions;
+
+         body.instructions = &f00A4->body_instructions;
+
+         /* IF CONDITION */
+         ir_expression *const r00A6 = less(r00A2, body.constant(int(1)));
+         ir_if *f00A5 = new(mem_ctx) ir_if(operand(r00A6).val);
+         exec_list *const f00A5_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f00A5->then_instructions;
+
+            body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+         body.instructions = f00A5_parent_instructions;
+         body.emit(f00A5);
+
+         /* END IF */
+
+         /* IF CONDITION */
+         ir_expression *const r00A8 = sub(body.constant(int(31)), r00A2);
+         ir_expression *const r00A9 = lequal(r00A3, r00A8);
+         ir_expression *const r00AA = lshift(swizzle_x(r0097), r00A2);
+         ir_expression *const r00AB = lequal(r00AA, swizzle_y(r0098));
+         ir_expression *const r00AC = logic_and(r00A9, r00AB);
+         ir_if *f00A7 = new(mem_ctx) ir_if(operand(r00AC).val);
+         exec_list *const f00A7_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f00A7->then_instructions;
+
+            ir_expression *const r00AD = lshift(swizzle_x(r0097), r00A2);
+            body.emit(assign(r0098, sub(swizzle_y(r0098), r00AD), 0x02));
+
+            ir_expression *const r00AE = lshift(body.constant(1u), r00A2);
+            body.emit(assign(r009C, bit_or(swizzle_y(r009C), r00AE), 0x02));
+
+
+         body.instructions = f00A7_parent_instructions;
+         body.emit(f00A7);
+
+         /* END IF */
+
+         body.emit(assign(r00A2, add(r00A2, body.constant(int(-1))), 0x01));
+
+      /* LOOP END */
+
+      body.instructions = f00A4_parent_instructions;
+      body.emit(f00A4);
+
+      /* IF CONDITION */
+      ir_expression *const r00B0 = lequal(swizzle_x(r0097), swizzle_y(r0098));
+      ir_if *f00AF = new(mem_ctx) ir_if(operand(r00B0).val);
+      exec_list *const f00AF_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f00AF->then_instructions;
+
+         body.emit(assign(r0098, sub(swizzle_y(r0098), swizzle_x(r0097)), 0x02));
+
+         body.emit(assign(r009C, bit_or(swizzle_y(r009C), body.constant(1u)), 0x02));
+
+
+      body.instructions = f00AF_parent_instructions;
+      body.emit(f00AF);
+
+      /* END IF */
+
+
+   body.instructions = f009E_parent_instructions;
+   body.emit(f009E);
+
+   /* END IF */
+
+   ir_variable *const r00B1 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval");
+   body.emit(assign(r00B1, expr(ir_unop_pack_uint_2x32, r0097), 0x01));
+
+   body.emit(assign(r009A, expr(ir_unop_pack_uint_2x32, r0098), 0x01));
+
+   body.emit(assign(r0099, body.constant(int(31)), 0x01));
+
+   /* LOOP BEGIN */
+   ir_loop *f00B2 = new(mem_ctx) ir_loop();
+   exec_list *const f00B2_parent_instructions = body.instructions;
+
+      body.instructions = &f00B2->body_instructions;
+
+      /* IF CONDITION */
+      ir_expression *const r00B4 = less(r0099, body.constant(int(1)));
+      ir_if *f00B3 = new(mem_ctx) ir_if(operand(r00B4).val);
+      exec_list *const f00B3_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f00B3->then_instructions;
+
+         body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+      body.instructions = f00B3_parent_instructions;
+      body.emit(f00B3);
+
+      /* END IF */
+
+      /* IF CONDITION */
+      ir_expression *const r00B6 = sub(body.constant(int(63)), r0099);
+      ir_expression *const r00B7 = lequal(r009B, r00B6);
+      ir_expression *const r00B8 = lshift(r00B1, r0099);
+      ir_expression *const r00B9 = lequal(r00B8, r009A);
+      ir_expression *const r00BA = logic_and(r00B7, r00B9);
+      ir_if *f00B5 = new(mem_ctx) ir_if(operand(r00BA).val);
+      exec_list *const f00B5_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f00B5->then_instructions;
+
+         ir_expression *const r00BB = lshift(r00B1, r0099);
+         body.emit(assign(r009A, sub(r009A, r00BB), 0x01));
+
+         ir_expression *const r00BC = lshift(body.constant(1u), r0099);
+         body.emit(assign(r009C, bit_or(swizzle_x(r009C), r00BC), 0x01));
+
+
+      body.instructions = f00B5_parent_instructions;
+      body.emit(f00B5);
+
+      /* END IF */
+
+      body.emit(assign(r0099, add(r0099, body.constant(int(-1))), 0x01));
+
+   /* LOOP END */
+
+   body.instructions = f00B2_parent_instructions;
+   body.emit(f00B2);
+
+   /* IF CONDITION */
+   ir_expression *const r00BE = lequal(r00B1, r009A);
+   ir_if *f00BD = new(mem_ctx) ir_if(operand(r00BE).val);
+   exec_list *const f00BD_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f00BD->then_instructions;
+
+      body.emit(assign(r009A, sub(r009A, r00B1), 0x01));
+
+      body.emit(assign(r009C, bit_or(swizzle_x(r009C), body.constant(1u)), 0x01));
+
+
+   body.instructions = f00BD_parent_instructions;
+   body.emit(f00BD);
+
+   /* END IF */
+
+   ir_variable *const r00BF = body.make_temp(glsl_type::uvec4_type, "vec_ctor");
+   body.emit(assign(r00BF, r009C, 0x03));
+
+   body.emit(assign(r00BF, expr(ir_unop_unpack_uint_2x32, r009A), 0x0c));
+
+   ir_swizzle *const r00C0 = swizzle(r00BF, MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W, SWIZZLE_X, SWIZZLE_X), 2);
+   body.emit(ret(r00C0));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
+ir_function_signature *
+imod64(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 r00C1 = new(mem_ctx) ir_variable(glsl_type::ivec2_type, "_n", ir_var_function_in);
+   sig_parameters.push_tail(r00C1);
+   ir_variable *const r00C2 = new(mem_ctx) ir_variable(glsl_type::ivec2_type, "_d", ir_var_function_in);
+   sig_parameters.push_tail(r00C2);
+   ir_variable *const r00C3 = new(mem_ctx) ir_variable(glsl_type::bool_type, "negate", ir_var_auto);
+   body.emit(r00C3);
+   ir_expression *const r00C4 = less(swizzle_y(r00C1), body.constant(int(0)));
+   ir_expression *const r00C5 = less(swizzle_y(r00C2), body.constant(int(0)));
+   body.emit(assign(r00C3, nequal(r00C4, r00C5), 0x01));
+
+   ir_variable *const r00C6 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "n", ir_var_auto);
+   body.emit(r00C6);
+   ir_expression *const r00C7 = expr(ir_unop_pack_int_2x32, r00C1);
+   ir_expression *const r00C8 = expr(ir_unop_abs, r00C7);
+   ir_expression *const r00C9 = expr(ir_unop_i642u64, r00C8);
+   body.emit(assign(r00C6, expr(ir_unop_unpack_uint_2x32, r00C9), 0x03));
+
+   ir_variable *const r00CA = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "d", ir_var_auto);
+   body.emit(r00CA);
+   ir_expression *const r00CB = expr(ir_unop_pack_int_2x32, r00C2);
+   ir_expression *const r00CC = expr(ir_unop_abs, r00CB);
+   ir_expression *const r00CD = expr(ir_unop_i642u64, r00CC);
+   body.emit(assign(r00CA, expr(ir_unop_unpack_uint_2x32, r00CD), 0x03));
+
+   ir_variable *const r00CE = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+   body.emit(r00CE);
+   ir_variable *const r00CF = new(mem_ctx) ir_variable(glsl_type::uint64_t_type, "n64", ir_var_auto);
+   body.emit(r00CF);
+   ir_variable *const r00D0 = new(mem_ctx) ir_variable(glsl_type::int_type, "log2_denom", ir_var_auto);
+   body.emit(r00D0);
+   ir_variable *const r00D1 = new(mem_ctx) ir_variable(glsl_type::uvec2_type, "quot", ir_var_auto);
+   body.emit(r00D1);
+   body.emit(assign(r00D1, ir_constant::zero(mem_ctx, glsl_type::uvec2_type), 0x03));
+
+   ir_expression *const r00D2 = expr(ir_unop_find_msb, swizzle_y(r00CA));
+   body.emit(assign(r00D0, add(r00D2, body.constant(int(32))), 0x01));
+
+   /* IF CONDITION */
+   ir_expression *const r00D4 = equal(swizzle_y(r00CA), body.constant(0u));
+   ir_expression *const r00D5 = gequal(swizzle_y(r00C6), swizzle_x(r00CA));
+   ir_expression *const r00D6 = logic_and(r00D4, r00D5);
+   ir_if *f00D3 = new(mem_ctx) ir_if(operand(r00D6).val);
+   exec_list *const f00D3_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f00D3->then_instructions;
+
+      ir_variable *const r00D7 = new(mem_ctx) ir_variable(glsl_type::int_type, "i", ir_var_auto);
+      body.emit(r00D7);
+      ir_variable *const r00D8 = body.make_temp(glsl_type::int_type, "findMSB_retval");
+      body.emit(assign(r00D8, expr(ir_unop_find_msb, swizzle_x(r00CA)), 0x01));
+
+      body.emit(assign(r00D0, r00D8, 0x01));
+
+      body.emit(assign(r00D7, body.constant(int(31)), 0x01));
+
+      /* LOOP BEGIN */
+      ir_loop *f00D9 = new(mem_ctx) ir_loop();
+      exec_list *const f00D9_parent_instructions = body.instructions;
+
+         body.instructions = &f00D9->body_instructions;
+
+         /* IF CONDITION */
+         ir_expression *const r00DB = less(r00D7, body.constant(int(1)));
+         ir_if *f00DA = new(mem_ctx) ir_if(operand(r00DB).val);
+         exec_list *const f00DA_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f00DA->then_instructions;
+
+            body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+         body.instructions = f00DA_parent_instructions;
+         body.emit(f00DA);
+
+         /* END IF */
+
+         /* IF CONDITION */
+         ir_expression *const r00DD = sub(body.constant(int(31)), r00D7);
+         ir_expression *const r00DE = lequal(r00D8, r00DD);
+         ir_expression *const r00DF = lshift(swizzle_x(r00CA), r00D7);
+         ir_expression *const r00E0 = lequal(r00DF, swizzle_y(r00C6));
+         ir_expression *const r00E1 = logic_and(r00DE, r00E0);
+         ir_if *f00DC = new(mem_ctx) ir_if(operand(r00E1).val);
+         exec_list *const f00DC_parent_instructions = body.instructions;
+
+            /* THEN INSTRUCTIONS */
+            body.instructions = &f00DC->then_instructions;
+
+            ir_expression *const r00E2 = lshift(swizzle_x(r00CA), r00D7);
+            body.emit(assign(r00C6, sub(swizzle_y(r00C6), r00E2), 0x02));
+
+            ir_expression *const r00E3 = lshift(body.constant(1u), r00D7);
+            body.emit(assign(r00D1, bit_or(swizzle_y(r00D1), r00E3), 0x02));
+
+
+         body.instructions = f00DC_parent_instructions;
+         body.emit(f00DC);
+
+         /* END IF */
+
+         body.emit(assign(r00D7, add(r00D7, body.constant(int(-1))), 0x01));
+
+      /* LOOP END */
+
+      body.instructions = f00D9_parent_instructions;
+      body.emit(f00D9);
+
+      /* IF CONDITION */
+      ir_expression *const r00E5 = lequal(swizzle_x(r00CA), swizzle_y(r00C6));
+      ir_if *f00E4 = new(mem_ctx) ir_if(operand(r00E5).val);
+      exec_list *const f00E4_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f00E4->then_instructions;
+
+         body.emit(assign(r00C6, sub(swizzle_y(r00C6), swizzle_x(r00CA)), 0x02));
+
+         body.emit(assign(r00D1, bit_or(swizzle_y(r00D1), body.constant(1u)), 0x02));
+
+
+      body.instructions = f00E4_parent_instructions;
+      body.emit(f00E4);
+
+      /* END IF */
+
+
+   body.instructions = f00D3_parent_instructions;
+   body.emit(f00D3);
+
+   /* END IF */
+
+   ir_variable *const r00E6 = body.make_temp(glsl_type::uint64_t_type, "packUint2x32_retval");
+   body.emit(assign(r00E6, expr(ir_unop_pack_uint_2x32, r00CA), 0x01));
+
+   body.emit(assign(r00CF, expr(ir_unop_pack_uint_2x32, r00C6), 0x01));
+
+   body.emit(assign(r00CE, body.constant(int(31)), 0x01));
+
+   /* LOOP BEGIN */
+   ir_loop *f00E7 = new(mem_ctx) ir_loop();
+   exec_list *const f00E7_parent_instructions = body.instructions;
+
+      body.instructions = &f00E7->body_instructions;
+
+      /* IF CONDITION */
+      ir_expression *const r00E9 = less(r00CE, body.constant(int(1)));
+      ir_if *f00E8 = new(mem_ctx) ir_if(operand(r00E9).val);
+      exec_list *const f00E8_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f00E8->then_instructions;
+
+         body.emit(new(mem_ctx) ir_loop_jump(ir_loop_jump::jump_break));
+
+
+      body.instructions = f00E8_parent_instructions;
+      body.emit(f00E8);
+
+      /* END IF */
+
+      /* IF CONDITION */
+      ir_expression *const r00EB = sub(body.constant(int(63)), r00CE);
+      ir_expression *const r00EC = lequal(r00D0, r00EB);
+      ir_expression *const r00ED = lshift(r00E6, r00CE);
+      ir_expression *const r00EE = lequal(r00ED, r00CF);
+      ir_expression *const r00EF = logic_and(r00EC, r00EE);
+      ir_if *f00EA = new(mem_ctx) ir_if(operand(r00EF).val);
+      exec_list *const f00EA_parent_instructions = body.instructions;
+
+         /* THEN INSTRUCTIONS */
+         body.instructions = &f00EA->then_instructions;
+
+         ir_expression *const r00F0 = lshift(r00E6, r00CE);
+         body.emit(assign(r00CF, sub(r00CF, r00F0), 0x01));
+
+         ir_expression *const r00F1 = lshift(body.constant(1u), r00CE);
+         body.emit(assign(r00D1, bit_or(swizzle_x(r00D1), r00F1), 0x01));
+
+
+      body.instructions = f00EA_parent_instructions;
+      body.emit(f00EA);
+
+      /* END IF */
+
+      body.emit(assign(r00CE, add(r00CE, body.constant(int(-1))), 0x01));
+
+   /* LOOP END */
+
+   body.instructions = f00E7_parent_instructions;
+   body.emit(f00E7);
+
+   /* IF CONDITION */
+   ir_expression *const r00F3 = lequal(r00E6, r00CF);
+   ir_if *f00F2 = new(mem_ctx) ir_if(operand(r00F3).val);
+   exec_list *const f00F2_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f00F2->then_instructions;
+
+      body.emit(assign(r00CF, sub(r00CF, r00E6), 0x01));
+
+      body.emit(assign(r00D1, bit_or(swizzle_x(r00D1), body.constant(1u)), 0x01));
+
+
+   body.instructions = f00F2_parent_instructions;
+   body.emit(f00F2);
+
+   /* END IF */
+
+   ir_variable *const r00F4 = body.make_temp(glsl_type::uvec4_type, "vec_ctor");
+   body.emit(assign(r00F4, r00D1, 0x03));
+
+   body.emit(assign(r00F4, expr(ir_unop_unpack_uint_2x32, r00CF), 0x0c));
+
+   ir_variable *const r00F5 = body.make_temp(glsl_type::ivec2_type, "conditional_tmp");
+   /* IF CONDITION */
+   ir_if *f00F6 = new(mem_ctx) ir_if(operand(r00C3).val);
+   exec_list *const f00F6_parent_instructions = body.instructions;
+
+      /* THEN INSTRUCTIONS */
+      body.instructions = &f00F6->then_instructions;
+
+      ir_swizzle *const r00F7 = swizzle(r00F4, MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X, SWIZZLE_X), 2);
+      ir_expression *const r00F8 = expr(ir_unop_pack_uint_2x32, r00F7);
+      ir_expression *const r00F9 = expr(ir_unop_u642i64, r00F8);
+      ir_expression *const r00FA = neg(r00F9);
+      body.emit(assign(r00F5, expr(ir_unop_unpack_int_2x32, r00FA), 0x03));
+
+
+      /* ELSE INSTRUCTIONS */
+      body.instructions = &f00F6->else_instructions;
+
+      ir_swizzle *const r00FB = swizzle(r00F4, MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_Y, SWIZZLE_X, SWIZZLE_X), 2);
+      body.emit(assign(r00F5, expr(ir_unop_u2i, r00FB), 0x03));
+
+
+   body.instructions = f00F6_parent_instructions;
+   body.emit(f00F6);
+
+   /* END IF */
+
+   body.emit(ret(r00F5));
+
+   sig->replace_parameters(&sig_parameters);
+   return sig;
+}
index d801cf8a9d74096cf94ff17675e2c4a907b788cc..e113253061f6a2ff71344ece3840db61446e87d5 100644 (file)
@@ -2346,7 +2346,9 @@ _glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t versio
          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_umod64", 1);
          add_builtin_define(parser, "__have_builtin_builtin_idiv64", 1);
+         add_builtin_define(parser, "__have_builtin_builtin_imod64", 1);
       }
    }
 
index 84e80ee349b1af2f7e8db314602ccace797a7fe9..b1036e379c9f5daf818548b775130d9896ff01dd 100644 (file)
@@ -101,3 +101,21 @@ idiv64(ivec2 _n, ivec2 _d)
 
    return negate ? unpackInt2x32(-int64_t(packUint2x32(quot))) : ivec2(quot);
 }
+
+uvec2
+umod64(uvec2 n, uvec2 d)
+{
+   return udivmod64(n, d).zw;
+}
+
+ivec2
+imod64(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 rem = udivmod64(n, d).zy;
+
+   return negate ? unpackInt2x32(-int64_t(packUint2x32(rem))) : ivec2(rem);
+}