mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-19 06:40:32 +01:00
Check for constant-valued while/do loop conditions.
Allows us to: 1. avoid generating constant-valued BRK test for while(1).. 2. discard entire loop for while(0). 3. detection infinite loops at compile-time.
This commit is contained in:
parent
c0a9f554be
commit
bd9615bbc5
1 changed files with 58 additions and 8 deletions
|
|
@ -1408,19 +1408,48 @@ _slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
|
|||
}
|
||||
|
||||
|
||||
static GLboolean
|
||||
_slang_is_constant_cond(const slang_operation *oper, GLboolean *value)
|
||||
{
|
||||
if (oper->type == slang_oper_literal_float ||
|
||||
oper->type == slang_oper_literal_int ||
|
||||
oper->type == slang_oper_literal_bool) {
|
||||
if (oper->literal[0])
|
||||
*value = GL_TRUE;
|
||||
else
|
||||
*value = GL_FALSE;
|
||||
return GL_TRUE;
|
||||
}
|
||||
else if (oper->type == slang_oper_expression &&
|
||||
oper->num_children == 1) {
|
||||
return _slang_is_constant_cond(&oper->children[0], value);
|
||||
}
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate loop code using high-level IR_LOOP instruction
|
||||
*/
|
||||
static slang_ir_node *
|
||||
_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
|
||||
{
|
||||
slang_ir_node *prevLoop;
|
||||
/*
|
||||
* LOOP:
|
||||
* BREAK if !expr (child[0])
|
||||
* body code (child[1])
|
||||
*/
|
||||
slang_ir_node *loop, *cond, *breakIf, *body;
|
||||
slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body;
|
||||
GLboolean isConst, constTrue;
|
||||
|
||||
/* Check if loop condition is a constant */
|
||||
isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
|
||||
|
||||
if (isConst && !constTrue) {
|
||||
/* loop is never executed! */
|
||||
return new_node0(IR_NOP);
|
||||
}
|
||||
|
||||
loop = new_loop(NULL);
|
||||
|
||||
|
|
@ -1429,10 +1458,23 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
A->CurLoop = loop;
|
||||
|
||||
cond = new_cond(_slang_gen_operation(A, &oper->children[0]));
|
||||
breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
|
||||
if (isConst && constTrue) {
|
||||
/* while(nonzero constant), no conditional break */
|
||||
breakIf = NULL;
|
||||
}
|
||||
else {
|
||||
breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
|
||||
}
|
||||
body = _slang_gen_operation(A, &oper->children[1]);
|
||||
loop->Children[0] = new_seq(breakIf, body);
|
||||
|
||||
/* Do infinite loop detection */
|
||||
if (loop->BranchNode == 0 && isConst && constTrue) {
|
||||
/* infinite loop detected */
|
||||
A->CurLoop = prevLoop; /* clean-up */
|
||||
RETURN_ERROR("Infinite loop detected!", 0);
|
||||
}
|
||||
|
||||
/* pop loop, restore prev */
|
||||
A->CurLoop = prevLoop;
|
||||
|
||||
|
|
@ -1446,13 +1488,16 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
static slang_ir_node *
|
||||
_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
|
||||
{
|
||||
slang_ir_node *prevLoop;
|
||||
/*
|
||||
* LOOP:
|
||||
* body code (child[0])
|
||||
* BREAK if !expr (child[1])
|
||||
*/
|
||||
slang_ir_node *loop, *cond, *breakIf, *body;
|
||||
slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body;
|
||||
GLboolean isConst, constTrue;
|
||||
|
||||
/* Check if loop condition is a constant */
|
||||
isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
|
||||
|
||||
loop = new_loop(NULL);
|
||||
|
||||
|
|
@ -1462,7 +1507,13 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
|
||||
body = _slang_gen_operation(A, &oper->children[0]);
|
||||
cond = new_cond(_slang_gen_operation(A, &oper->children[1]));
|
||||
breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
|
||||
if (isConst && constTrue) {
|
||||
/* while(nonzero constant), no conditional break */
|
||||
breakIf = NULL;
|
||||
}
|
||||
else {
|
||||
breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
|
||||
}
|
||||
loop->Children[0] = new_seq(body, breakIf);
|
||||
|
||||
/* pop loop, restore prev */
|
||||
|
|
@ -1478,7 +1529,6 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
static slang_ir_node *
|
||||
_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
|
||||
{
|
||||
slang_ir_node *prevLoop;
|
||||
/*
|
||||
* init (child[0])
|
||||
* LOOP:
|
||||
|
|
@ -1486,7 +1536,7 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
|
|||
* body code (child[3])
|
||||
* incr code (child[2]) // XXX continue here
|
||||
*/
|
||||
slang_ir_node *loop, *cond, *breakIf, *body, *init, *incr;
|
||||
slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr;
|
||||
|
||||
init = _slang_gen_operation(A, &oper->children[0]);
|
||||
loop = new_loop(NULL);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue