glsl: Make most ir_instruction::as_subclass() functions non-virtual.
authorMatt Turner <mattst88@gmail.com>
Sat, 31 May 2014 02:26:30 +0000 (19:26 -0700)
committerMatt Turner <mattst88@gmail.com>
Wed, 4 Jun 2014 00:58:34 +0000 (17:58 -0700)
There are several common ways to check whether an object is a particular
subclass: dynamic_cast<>, the as_subclass() pattern, or explicit enum
tags.  We originally used the virtual as_subclass methods, but later
added enum tags as they are much nicer for debugging.

Since we have the enum tags, we don't necessarily need to use virtual
functions to implement the as_subclass() methods.  We can just check the
tag and return the pointer or NULL.

This saves 18 entries in the vtable, and instead of two pointer
dereferences per as_subclass() call most are only three inline
instructions.

Compile time of sam3/112.frag (the longest compile in a recent shader-db
run) is reduced by 5% from 348 to 329 ms (n=500).

perf stat of this workload shows:
   24.14% reduction in iTLB-loads:       285,543 -> 216,606
   42.55% reduction in iTLB-load-misses:  18,785 ->  10,792

Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com>
src/glsl/ir.h

index 585c31c2db6f6f2c17a2143913660ac4d4af09dc..2afafe4b5c7c4e6ecabc174181ba0b7baf17f258 100644 (file)
@@ -117,24 +117,58 @@ public:
     * Additional downcast functions will be added as needed.
     */
    /*@{*/
-   virtual class ir_variable *          as_variable()         { return NULL; }
-   virtual class ir_function *          as_function()         { return NULL; }
-   virtual class ir_dereference *       as_dereference()      { return NULL; }
-   virtual class ir_dereference_array *        as_dereference_array() { return NULL; }
-   virtual class ir_dereference_variable *as_dereference_variable() { return NULL; }
-   virtual class ir_dereference_record *as_dereference_record() { return NULL; }
-   virtual class ir_expression *        as_expression()       { return NULL; }
-   virtual class ir_rvalue *            as_rvalue()           { return NULL; }
-   virtual class ir_loop *              as_loop()             { return NULL; }
-   virtual class ir_assignment *        as_assignment()       { return NULL; }
-   virtual class ir_call *              as_call()             { return NULL; }
-   virtual class ir_return *            as_return()           { return NULL; }
-   virtual class ir_if *                as_if()               { return NULL; }
-   virtual class ir_swizzle *           as_swizzle()          { return NULL; }
-   virtual class ir_texture *           as_texture()          { return NULL; }
-   virtual class ir_constant *          as_constant()         { return NULL; }
-   virtual class ir_discard *           as_discard()          { return NULL; }
-   virtual class ir_jump *              as_jump()             { return NULL; }
+   class ir_rvalue *as_rvalue()
+   {
+      if (ir_type == ir_type_dereference_array ||
+          ir_type == ir_type_dereference_record ||
+          ir_type == ir_type_dereference_variable ||
+          ir_type == ir_type_constant ||
+          ir_type == ir_type_expression ||
+          ir_type == ir_type_swizzle ||
+          ir_type == ir_type_texture)
+         return (class ir_rvalue *) this;
+      return NULL;
+   }
+
+   class ir_dereference *as_dereference()
+   {
+      if (ir_type == ir_type_dereference_array ||
+          ir_type == ir_type_dereference_record ||
+          ir_type == ir_type_dereference_variable)
+         return (class ir_dereference *) this;
+      return NULL;
+   }
+
+   class ir_jump *as_jump()
+   {
+      if (ir_type == ir_type_loop_jump ||
+          ir_type == ir_type_return ||
+          ir_type == ir_type_discard)
+         return (class ir_jump *) this;
+      return NULL;
+   }
+
+   #define AS_CHILD(TYPE) \
+   class ir_##TYPE * as_##TYPE() \
+   { \
+      return ir_type == ir_type_##TYPE ? (ir_##TYPE *) this : NULL; \
+   }
+   AS_CHILD(variable)
+   AS_CHILD(function)
+   AS_CHILD(dereference_array)
+   AS_CHILD(dereference_variable)
+   AS_CHILD(dereference_record)
+   AS_CHILD(expression)
+   AS_CHILD(loop)
+   AS_CHILD(assignment)
+   AS_CHILD(call)
+   AS_CHILD(return)
+   AS_CHILD(if)
+   AS_CHILD(swizzle)
+   AS_CHILD(texture)
+   AS_CHILD(constant)
+   AS_CHILD(discard)
+   #undef AS_CHILD
    /*@}*/
 
    /**
@@ -179,11 +213,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_rvalue * as_rvalue()
-   {
-      return this;
-   }
-
    ir_rvalue *as_rvalue_to_saturate();
 
    virtual bool is_lvalue() const
@@ -384,11 +413,6 @@ public:
 
    virtual ir_variable *clone(void *mem_ctx, struct hash_table *ht) const;
 
-   virtual ir_variable *as_variable()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -919,11 +943,6 @@ public:
 
    virtual ir_function *clone(void *mem_ctx, struct hash_table *ht) const;
 
-   virtual ir_function *as_function()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -992,11 +1011,6 @@ public:
 
    virtual ir_if *clone(void *mem_ctx, struct hash_table *ht) const;
 
-   virtual ir_if *as_if()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -1028,11 +1042,6 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual ir_loop *as_loop()
-   {
-      return this;
-   }
-
    /** List of ir_instruction that make up the body of the loop. */
    exec_list body_instructions;
 };
@@ -1063,11 +1072,6 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual ir_assignment * as_assignment()
-   {
-      return this;
-   }
-
    /**
     * Get a whole variable written by an assignment
     *
@@ -1431,11 +1435,6 @@ public:
     */
    ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1, ir_rvalue *op2);
 
-   virtual ir_expression *as_expression()
-   {
-      return this;
-   }
-
    virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
 
    virtual ir_expression *clone(void *mem_ctx, struct hash_table *ht) const;
@@ -1526,11 +1525,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_call *as_call()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);
@@ -1583,12 +1577,6 @@ protected:
       : ir_instruction(t)
    {
    }
-
-public:
-   virtual ir_jump *as_jump()
-   {
-      return this;
-   }
 };
 
 class ir_return : public ir_jump {
@@ -1605,11 +1593,6 @@ public:
 
    virtual ir_return *clone(void *mem_ctx, struct hash_table *) const;
 
-   virtual ir_return *as_return()
-   {
-      return this;
-   }
-
    ir_rvalue *get_value() const
    {
       return value;
@@ -1696,11 +1679,6 @@ public:
 
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
-   virtual ir_discard *as_discard()
-   {
-      return this;
-   }
-
    ir_rvalue *condition;
 };
 /*@}*/
@@ -1766,11 +1744,6 @@ public:
       v->visit(this);
    }
 
-   virtual ir_texture *as_texture()
-   {
-      return this;
-   }
-
    virtual ir_visitor_status accept(ir_hierarchical_visitor *);
 
    virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
@@ -1862,11 +1835,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_swizzle *as_swizzle()
-   {
-      return this;
-   }
-
    /**
     * Construct an ir_swizzle from the textual representation.  Can fail.
     */
@@ -1908,11 +1876,6 @@ class ir_dereference : public ir_rvalue {
 public:
    virtual ir_dereference *clone(void *mem_ctx, struct hash_table *) const = 0;
 
-   virtual ir_dereference *as_dereference()
-   {
-      return this;
-   }
-
    bool is_lvalue() const;
 
    /**
@@ -1937,11 +1900,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_dereference_variable *as_dereference_variable()
-   {
-      return this;
-   }
-
    virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
 
    /**
@@ -1988,11 +1946,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_dereference_array *as_dereference_array()
-   {
-      return this;
-   }
-
    virtual bool equals(ir_instruction *ir, enum ir_node_type ignore = ir_type_unset);
 
    /**
@@ -2029,11 +1982,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_dereference_record *as_dereference_record()
-   {
-      return this;
-   }
-
    /**
     * Get the variable that is ultimately referenced by an r-value
     */
@@ -2099,11 +2047,6 @@ public:
 
    virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL);
 
-   virtual ir_constant *as_constant()
-   {
-      return this;
-   }
-
    virtual void accept(ir_visitor *v)
    {
       v->visit(this);