glsl: add lowering passes for carry/borrow

Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
Reviewed-by: Matt Turner <mattst88@gmail.com>
This commit is contained in:
Ilia Mirkin
2014-04-28 23:13:08 -04:00
parent f64bfb2e39
commit 31b92aa2fc
2 changed files with 60 additions and 0 deletions

View File

@@ -38,6 +38,8 @@
#define INT_DIV_TO_MUL_RCP 0x40 #define INT_DIV_TO_MUL_RCP 0x40
#define BITFIELD_INSERT_TO_BFM_BFI 0x80 #define BITFIELD_INSERT_TO_BFM_BFI 0x80
#define LDEXP_TO_ARITH 0x100 #define LDEXP_TO_ARITH 0x100
#define CARRY_TO_ARITH 0x200
#define BORROW_TO_ARITH 0x400
/** /**
* \see class lower_packing_builtins_visitor * \see class lower_packing_builtins_visitor

View File

@@ -39,6 +39,8 @@
* - MOD_TO_FRACT * - MOD_TO_FRACT
* - LDEXP_TO_ARITH * - LDEXP_TO_ARITH
* - BITFIELD_INSERT_TO_BFM_BFI * - BITFIELD_INSERT_TO_BFM_BFI
* - CARRY_TO_ARITH
* - BORROW_TO_ARITH
* *
* SUB_TO_ADD_NEG: * SUB_TO_ADD_NEG:
* --------------- * ---------------
@@ -94,6 +96,14 @@
* Many GPUs implement the bitfieldInsert() built-in from ARB_gpu_shader_5 * Many GPUs implement the bitfieldInsert() built-in from ARB_gpu_shader_5
* with a pair of instructions. * with a pair of instructions.
* *
* CARRY_TO_ARITH:
* ---------------
* Converts ir_carry into (x + y) < x.
*
* BORROW_TO_ARITH:
* ----------------
* Converts ir_borrow into (x < y).
*
*/ */
#include "main/core.h" /* for M_LOG2E */ #include "main/core.h" /* for M_LOG2E */
@@ -127,6 +137,8 @@ private:
void log_to_log2(ir_expression *); void log_to_log2(ir_expression *);
void bitfield_insert_to_bfm_bfi(ir_expression *); void bitfield_insert_to_bfm_bfi(ir_expression *);
void ldexp_to_arith(ir_expression *); void ldexp_to_arith(ir_expression *);
void carry_to_arith(ir_expression *);
void borrow_to_arith(ir_expression *);
}; };
} /* anonymous namespace */ } /* anonymous namespace */
@@ -436,6 +448,42 @@ lower_instructions_visitor::ldexp_to_arith(ir_expression *ir)
this->progress = true; this->progress = true;
} }
void
lower_instructions_visitor::carry_to_arith(ir_expression *ir)
{
/* Translates
* ir_binop_carry x y
* into
* sum = ir_binop_add x y
* bcarry = ir_binop_less sum x
* carry = ir_unop_b2i bcarry
*/
ir_rvalue *x_clone = ir->operands[0]->clone(ir, NULL);
ir->operation = ir_unop_i2u;
ir->operands[0] = b2i(less(add(ir->operands[0], ir->operands[1]), x_clone));
ir->operands[1] = NULL;
this->progress = true;
}
void
lower_instructions_visitor::borrow_to_arith(ir_expression *ir)
{
/* Translates
* ir_binop_borrow x y
* into
* bcarry = ir_binop_less x y
* carry = ir_unop_b2i bcarry
*/
ir->operation = ir_unop_i2u;
ir->operands[0] = b2i(less(ir->operands[0], ir->operands[1]));
ir->operands[1] = NULL;
this->progress = true;
}
ir_visitor_status ir_visitor_status
lower_instructions_visitor::visit_leave(ir_expression *ir) lower_instructions_visitor::visit_leave(ir_expression *ir)
{ {
@@ -482,6 +530,16 @@ lower_instructions_visitor::visit_leave(ir_expression *ir)
ldexp_to_arith(ir); ldexp_to_arith(ir);
break; break;
case ir_binop_carry:
if (lowering(CARRY_TO_ARITH))
carry_to_arith(ir);
break;
case ir_binop_borrow:
if (lowering(BORROW_TO_ARITH))
borrow_to_arith(ir);
break;
default: default:
return visit_continue; return visit_continue;
} }