forgot these 2 files in my last committ
authorMatthias Braun <matze@braunis.de>
Fri, 31 Aug 2007 14:53:11 +0000 (14:53 +0000)
committerMatthias Braun <matze@braunis.de>
Fri, 31 Aug 2007 14:53:11 +0000 (14:53 +0000)
[r15644]

ir/be/ia32/ia32_address_mode.c [new file with mode: 0644]
ir/be/ia32/ia32_address_mode.h [new file with mode: 0644]

diff --git a/ir/be/ia32/ia32_address_mode.c b/ir/be/ia32/ia32_address_mode.c
new file mode 100644 (file)
index 0000000..72f204a
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/**
+ * @file
+ * @brief       This file contains functions for matching firm graphs for
+ *              nodes that can be used as addressmode for x86 commands
+ * @author      Matthias Braun
+ * @version     $Id: ia32_transform.c 15462 2007-08-03 16:50:59Z matze $
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ia32_address_mode.h"
+
+#include "irtypes.h"
+#include "irnode_t.h"
+#include "irprintf.h"
+#include "error.h"
+#include "iredges_t.h"
+
+#include "../benode_t.h"
+
+#undef AGGRESSIVE_AM
+
+static int is_immediate_2(const ir_node *node, int *symconsts)
+{
+       ir_node *left;
+       ir_node *right;
+
+       switch(get_irn_opcode(node)) {
+       case iro_Const:
+               if(!tarval_is_long(get_Const_tarval(node))) {
+#ifdef DEBUG_libfirm
+                       ir_fprintf(stderr, "Optimisation warning tarval of %+F is not a "
+                                  "long.");
+#endif
+                       return 0;
+               }
+               return 1;
+       case iro_SymConst:
+               if(get_SymConst_kind(node) != symconst_addr_ent)
+                       return 0;
+               (*symconsts)++;
+               if(*symconsts > 1)
+                       return 0;
+
+               return 1;
+       case iro_Add:
+       case iro_Sub:
+               left  = get_binop_left(node);
+               right = get_binop_right(node);
+               if(!is_immediate_2(left, symconsts))
+                       return 0;
+               if(!is_immediate_2(right, symconsts))
+                       return 0;
+
+               return 1;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int is_immediate(ia32_address_t *addr, const ir_node *node)
+{
+       int symconsts = 0;
+       if(addr->symconst_ent != NULL)
+               symconsts = 1;
+
+       return is_immediate_2(node, &symconsts);
+}
+
+static void eat_immediate(ia32_address_t *addr, ir_node *node, int negate)
+{
+       tarval  *tv;
+       ir_node *left;
+       ir_node *right;
+
+       switch(get_irn_opcode(node)) {
+       case iro_Const:
+               tv = get_Const_tarval(node);
+               if(negate) {
+                       addr->offset -= get_tarval_long(tv);
+               } else {
+                       addr->offset += get_tarval_long(tv);
+               }
+               break;
+       case iro_SymConst:
+               if(addr->symconst_ent != NULL) {
+                       panic("Internal error: more than 1 symconst in address "
+                             "calculation");
+               }
+               addr->symconst_ent  = get_SymConst_entity(node);
+               addr->symconst_sign = negate;
+               break;
+       case iro_Add:
+               left  = get_Add_left(node);
+               right = get_Add_right(node);
+               eat_immediate(addr, left, negate);
+               eat_immediate(addr, right, negate);
+               break;
+       case iro_Sub:
+               left  = get_Sub_left(node);
+               right = get_Sub_right(node);
+               eat_immediate(addr, left, negate);
+               eat_immediate(addr, right, !negate);
+               break;
+       default:
+               panic("Internal error in immediate address calculation");
+       }
+}
+
+static ir_node *eat_immediates(ia32_address_t *addr, ir_node *node, int force)
+{
+       if(is_Add(node)) {
+               ir_node *left  = get_Add_left(node);
+               ir_node *right = get_Add_right(node);
+
+#if 0
+#ifndef AGGRESSIVE_AM
+               if(!force && get_irn_n_edges(node) > 1)
+                       return node;
+#else
+               (void) force;
+#endif
+#endif
+
+               if(is_immediate(addr, left)) {
+                       eat_immediate(addr, left, 0);
+                       return eat_immediates(addr, right, 0);
+               }
+               if(is_immediate(addr, right)) {
+                       eat_immediate(addr, right, 0);
+                       return eat_immediates(addr, left, 0);
+               }
+       } else if(is_Sub(node)) {
+               ir_node *left  = get_Sub_left(node);
+               ir_node *right = get_Sub_right(node);
+
+#if 0
+#ifndef AGGRESSIVE_AM
+               if(!force && get_irn_n_edges(node) > 1)
+                       return node;
+#endif
+#endif
+
+               if(is_immediate(addr, right)) {
+                       eat_immediate(addr, right, 1);
+                       return eat_immediates(addr, left, 0);
+               }
+       }
+
+       return node;
+}
+
+static int eat_shl(ia32_address_t *addr, ir_node *node)
+{
+       ir_node *right = get_Shl_right(node);
+       tarval  *tv;
+       long     val;
+
+       /* we can only eat a shl if we don't have a scale or index set */
+       if(addr->scale != 0 || addr->index != NULL)
+               return 0;
+
+       /* we can use shl with 1, 2 or 3 shift */
+       if(!is_Const(right))
+               return 0;
+       tv = get_Const_tarval(right);
+       if(!tarval_is_long(tv))
+               return 0;
+       val = get_tarval_long(tv);
+       if(val < 0 || val > 3)
+               return 0;
+       if(val == 0) {
+               ir_fprintf(stderr, "Optimisation warning: unoptimized Shl(,0) found\n");
+       }
+
+#ifndef AGGRESSIVE_AM
+       if(get_irn_n_edges(node) > 1)
+               return 0;
+#endif
+
+       addr->scale = val;
+       addr->index = eat_immediates(addr, get_Shl_left(node), 0);
+       return 1;
+}
+
+void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force)
+{
+       int      res = 0;
+       ir_node *eat_imms;
+
+       if(is_immediate(addr, node)) {
+               eat_immediate(addr, node, 0);
+               return;
+       }
+
+#ifndef AGGRESSIVE_AM
+       if(!force && get_irn_n_edges(node) > 1) {
+               addr->base = node;
+               return;
+       }
+#endif
+
+       eat_imms = eat_immediates(addr, node, force);
+       if(eat_imms != node) {
+               res  = 1;
+               node = eat_imms;
+#ifndef AGGRESSIVE_AM
+               if(get_irn_n_edges(node) > 1) {
+                       addr->base = node;
+                       return;
+               }
+#endif
+       }
+
+       /* starting point Add, Sub or Shl, FrameAddr */
+       if(is_Shl(node)) {
+               if(eat_shl(addr, node))
+                       return;
+       } else if(is_immediate(addr, node)) {
+               eat_immediate(addr, node, 0);
+               return;
+       } else if(be_is_FrameAddr(node)) {
+               assert(addr->base == NULL);
+               assert(addr->frame_entity == NULL);
+               addr->base         = be_get_FrameAddr_frame(node);
+               addr->use_frame    = 1;
+               addr->frame_entity = be_get_FrameAddr_entity(node);
+               return;
+       } else if(is_Add(node)) {
+               ir_node *left  = get_Add_left(node);
+               ir_node *right = get_Add_right(node);
+               assert(force || !is_immediate(addr, left));
+               assert(force || !is_immediate(addr, right));
+
+               if(is_Shl(left) && eat_shl(addr, left)) {
+                       left = NULL;
+               } else if(is_Shl(right) && eat_shl(addr, right)) {
+                       right = NULL;
+               }
+               if(left != NULL && be_is_FrameAddr(left)) {
+                       assert(addr->base == NULL);
+                       assert(addr->frame_entity == NULL);
+                       addr->base         = be_get_FrameAddr_frame(left);
+                       addr->use_frame    = 1;
+                       addr->frame_entity = be_get_FrameAddr_entity(left);
+                       left               = NULL;
+               } else if(right != NULL && be_is_FrameAddr(right)) {
+                       assert(addr->base == NULL);
+                       assert(addr->frame_entity == NULL);
+                       addr->base         = be_get_FrameAddr_frame(right);
+                       addr->use_frame    = 1;
+                       addr->frame_entity = be_get_FrameAddr_entity(right);
+                       right              = NULL;
+               }
+
+               if(left != NULL) {
+                       if(addr->base != NULL) {
+                               assert(addr->index == NULL && addr->scale == 0);
+                               assert(right == NULL);
+                               addr->index = left;
+                       } else {
+                               addr->base = left;
+                       }
+               }
+               if(right != NULL) {
+                       if(addr->base == NULL) {
+                               addr->base = right;
+                       } else {
+                               assert(addr->index == NULL && addr->scale == 0);
+                               addr->index = right;
+                       }
+               }
+               return;
+       }
+
+       addr->base = node;
+}
+
+
+typedef struct mark_evn_t mark_evn_t;
+struct mark_evn_t {
+       bitset_t *non_address_nodes;
+};
+
+
+static void mark_non_address_nodes(mark_evn_t *env, ir_node *node)
+{
+       bitset_set(env->non_address_nodes, get_irn_idx(node));
+
+       if(is_Load(node)) {
+               ir_node *ptr = get_Load_ptr(node);
+               ir_node *mem = get_Load_mem(node);
+
+               mark_non_address_nodes(env, mem);
+               (void) ptr;
+       } else if(is_Store(node)) {
+               ir_node *val = get_Store_value(node);
+               ir_node *ptr = get_Store_ptr(node);
+               ir_node *mem = get_Store_mem(node);
+
+               mark_non_address_nodes(env, val);
+               mark_non_address_nodes(env, mem);
+               (void) ptr;
+       } else {
+               int i;
+               int arity = get_irn_arity(node);
+
+               for(i = 0; i < arity; ++i) {
+                       ir_node *in = get_irn_n(node, i);
+                       mark_non_address_nodes(env, in);
+               }
+       }
+}
diff --git a/ir/be/ia32/ia32_address_mode.h b/ir/be/ia32/ia32_address_mode.h
new file mode 100644 (file)
index 0000000..59cd30c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/**
+ * @file
+ * @brief       This file contains functions for matching firm graphs for
+ *              nodes that can be used as addressmode for x86 commands
+ * @author      Matthias Braun
+ * @version     $Id: ia32_transform.c 15462 2007-08-03 16:50:59Z matze $
+ */
+#ifndef IA32_ADDRESS_MODE_H
+#define IA32_ADDRESS_MODE_H
+
+#include "irtypes.h"
+
+typedef struct ia32_address_t ia32_address_t;
+struct ia32_address_t {
+    ir_node   *base;
+    ir_node   *index;
+       ir_node   *mem;
+    int        offset;
+    int        scale;
+    ir_entity *symconst_ent;
+    int        use_frame;
+    ir_entity *frame_entity;
+    int        symconst_sign;
+};
+
+void ia32_create_address_mode(ia32_address_t *addr, ir_node *node, int force);
+
+#endif