summaryrefslogtreecommitdiff
path: root/compiler_and_linker/FrontEnd/Optimizer/IroTransform.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/FrontEnd/Optimizer/IroTransform.c')
-rw-r--r--compiler_and_linker/FrontEnd/Optimizer/IroTransform.c2794
1 files changed, 2794 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Optimizer/IroTransform.c b/compiler_and_linker/FrontEnd/Optimizer/IroTransform.c
new file mode 100644
index 0000000..8a4af16
--- /dev/null
+++ b/compiler_and_linker/FrontEnd/Optimizer/IroTransform.c
@@ -0,0 +1,2794 @@
+#include "IroTransform.h"
+#include "compiler/CError.h"
+#include "compiler/CFunc.h"
+#include "compiler/CInt64.h"
+#include "compiler/CIRTransform.h"
+#include "compiler/CMachine.h"
+#include "compiler/CPrep.h"
+#include "compiler/CompilerTools.h"
+#include "IroDump.h"
+#include "IroLinearForm.h"
+#include "IroMalloc.h"
+#include "IroPointerAnalysis.h"
+#include "IROUseDef.h"
+#include "IroUtil.h"
+#include "IroVars.h"
+#include "compiler/enode.h"
+#include "compiler/types.h"
+
+ENodeType ExprType;
+ENode *IndirectRef;
+Boolean FirstTime;
+CInt64 OperandConst;
+Object *OperandObject;
+ENodeList *FirstAddend;
+ENodeList *LastAddend;
+static ENodeType AssignmentOp[MAXEXPR];
+static ENodeType ComplementaryOpLogical[MAXEXPR];
+static ENodeType ComplementaryOp[MAXEXPR];
+
+// forward decls
+static void DoDiadic(IROLinear *nd);
+
+static int GetTypeSize(Type *type) {
+ if (type->size == 1)
+ return 0;
+ if (type->size == 2)
+ return 1;
+ if (type->size == 4)
+ return 2;
+ if (type->size == 8)
+ return 3;
+ return -1;
+}
+
+void IRO_InitializeAssignmentOpArray(void) {
+ int i;
+
+ for (i = 0; i < MAXEXPR; i++)
+ AssignmentOp[i] = MAXEXPR;
+
+ AssignmentOp[EPOSTINC] = MAXEXPR;
+ AssignmentOp[EPOSTDEC] = MAXEXPR;
+ AssignmentOp[EPREINC] = MAXEXPR;
+ AssignmentOp[EPREDEC] = MAXEXPR;
+ AssignmentOp[EINDIRECT] = MAXEXPR;
+ AssignmentOp[EMONMIN] = MAXEXPR;
+ AssignmentOp[EBINNOT] = MAXEXPR;
+ AssignmentOp[ELOGNOT] = MAXEXPR;
+ AssignmentOp[EFORCELOAD] = MAXEXPR;
+ AssignmentOp[EMUL] = EMULASS;
+ AssignmentOp[EMULV] = MAXEXPR;
+ AssignmentOp[EDIV] = EDIVASS;
+ AssignmentOp[EMODULO] = EMODASS;
+ AssignmentOp[EADDV] = MAXEXPR;
+ AssignmentOp[ESUBV] = MAXEXPR;
+ AssignmentOp[EADD] = EADDASS;
+ AssignmentOp[ESUB] = ESUBASS;
+ AssignmentOp[ESHL] = ESHLASS;
+ AssignmentOp[ESHR] = ESHRASS;
+ AssignmentOp[ELESS] = MAXEXPR;
+ AssignmentOp[EGREATER] = MAXEXPR;
+ AssignmentOp[ELESSEQU] = MAXEXPR;
+ AssignmentOp[EGREATEREQU] = MAXEXPR;
+ AssignmentOp[EEQU] = MAXEXPR;
+ AssignmentOp[ENOTEQU] = MAXEXPR;
+ AssignmentOp[EAND] = EANDASS;
+ AssignmentOp[EXOR] = EXORASS;
+ AssignmentOp[EOR] = EORASS;
+ AssignmentOp[ELAND] = MAXEXPR;
+ AssignmentOp[ELOR] = MAXEXPR;
+ AssignmentOp[EASS] = MAXEXPR;
+ AssignmentOp[EMULASS] = MAXEXPR;
+ AssignmentOp[EDIVASS] = MAXEXPR;
+ AssignmentOp[EMODASS] = MAXEXPR;
+ AssignmentOp[EADDASS] = MAXEXPR;
+ AssignmentOp[ESUBASS] = MAXEXPR;
+ AssignmentOp[ESHLASS] = MAXEXPR;
+ AssignmentOp[ESHRASS] = MAXEXPR;
+ AssignmentOp[EANDASS] = MAXEXPR;
+ AssignmentOp[EXORASS] = MAXEXPR;
+ AssignmentOp[EORASS] = MAXEXPR;
+ AssignmentOp[ECOMMA] = MAXEXPR;
+ AssignmentOp[EPMODULO] = MAXEXPR;
+ AssignmentOp[EROTL] = MAXEXPR;
+ AssignmentOp[EROTR] = MAXEXPR;
+ AssignmentOp[EBCLR] = MAXEXPR;
+ AssignmentOp[EBTST] = MAXEXPR;
+ AssignmentOp[EBSET] = MAXEXPR;
+ AssignmentOp[ETYPCON] = MAXEXPR;
+ AssignmentOp[EBITFIELD] = MAXEXPR;
+ AssignmentOp[EINTCONST] = MAXEXPR;
+ AssignmentOp[EFLOATCONST] = MAXEXPR;
+ AssignmentOp[ESTRINGCONST] = MAXEXPR;
+ AssignmentOp[ECOND] = MAXEXPR;
+ AssignmentOp[EFUNCCALL] = MAXEXPR;
+ AssignmentOp[EFUNCCALLP] = MAXEXPR;
+ AssignmentOp[EOBJREF] = MAXEXPR;
+ AssignmentOp[EMFPOINTER] = MAXEXPR;
+ AssignmentOp[ENULLCHECK] = MAXEXPR;
+ AssignmentOp[EPRECOMP] = MAXEXPR;
+ AssignmentOp[ETEMP] = MAXEXPR;
+ AssignmentOp[EARGOBJ] = MAXEXPR;
+ AssignmentOp[ELOCOBJ] = MAXEXPR;
+ AssignmentOp[ELABEL] = MAXEXPR;
+ AssignmentOp[ESETCONST] = MAXEXPR;
+ AssignmentOp[ENEWEXCEPTION] = MAXEXPR;
+ AssignmentOp[ENEWEXCEPTIONARRAY] = MAXEXPR;
+ AssignmentOp[EOBJLIST] = MAXEXPR;
+ AssignmentOp[EMEMBER] = MAXEXPR;
+ AssignmentOp[ETEMPLDEP] = MAXEXPR;
+ AssignmentOp[EINSTRUCTION] = MAXEXPR;
+ AssignmentOp[EDEFINE] = MAXEXPR;
+ AssignmentOp[EREUSE] = MAXEXPR;
+ AssignmentOp[EASSBLK] = MAXEXPR;
+ AssignmentOp[EVECTOR128CONST] = MAXEXPR;
+ AssignmentOp[ECONDASS] = MAXEXPR;
+}
+
+void IRO_InitializeComplementaryOpArray(void) {
+ int i;
+
+ for (i = 0; i < MAXEXPR; i++)
+ ComplementaryOp[i] = MAXEXPR;
+
+ ComplementaryOp[EPOSTINC] = EPOSTDEC;
+ ComplementaryOp[EPOSTDEC] = EPOSTINC;
+ ComplementaryOp[EPREINC] = EPREDEC;
+ ComplementaryOp[EPREDEC] = EPREINC;
+ ComplementaryOp[EINDIRECT] = MAXEXPR;
+ ComplementaryOp[EMONMIN] = EMONMIN;
+ ComplementaryOp[EBINNOT] = EBINNOT;
+ ComplementaryOp[ELOGNOT] = ELOGNOT;
+ ComplementaryOp[EFORCELOAD] = MAXEXPR;
+ ComplementaryOp[EMUL] = EDIV;
+ ComplementaryOp[EMULV] = MAXEXPR;
+ ComplementaryOp[EDIV] = EMUL;
+ ComplementaryOp[EMODULO] = MAXEXPR;
+ ComplementaryOp[EADDV] = ESUBV;
+ ComplementaryOp[ESUBV] = EADDV;
+ ComplementaryOp[EADD] = ESUB;
+ ComplementaryOp[ESUB] = EADD;
+ ComplementaryOp[ESHL] = ESHR;
+ ComplementaryOp[ESHR] = ESHL;
+ ComplementaryOp[ELESS] = EGREATER;
+ ComplementaryOp[EGREATER] = ELESS;
+ ComplementaryOp[ELESSEQU] = EGREATEREQU;
+ ComplementaryOp[EGREATEREQU] = ELESSEQU;
+ ComplementaryOp[EEQU] = ENOTEQU;
+ ComplementaryOp[ENOTEQU] = EEQU;
+ ComplementaryOp[EAND] = EOR;
+ ComplementaryOp[EXOR] = MAXEXPR;
+ ComplementaryOp[EOR] = EAND;
+ ComplementaryOp[ELAND] = ELOR;
+ ComplementaryOp[ELOR] = ELAND;
+ ComplementaryOp[EASS] = MAXEXPR;
+ ComplementaryOp[EMULASS] = EDIVASS;
+ ComplementaryOp[EDIVASS] = EMULASS;
+ ComplementaryOp[EMODASS] = MAXEXPR;
+ ComplementaryOp[EADDASS] = ESUBASS;
+ ComplementaryOp[ESUBASS] = EADDASS;
+ ComplementaryOp[ESHLASS] = ESHRASS;
+ ComplementaryOp[ESHRASS] = ESHLASS;
+ ComplementaryOp[EANDASS] = EORASS;
+ ComplementaryOp[EXORASS] = MAXEXPR;
+ ComplementaryOp[EORASS] = EANDASS;
+ ComplementaryOp[ECOMMA] = MAXEXPR;
+ ComplementaryOp[EPMODULO] = MAXEXPR;
+ ComplementaryOp[EROTL] = EROTR;
+ ComplementaryOp[EROTR] = EROTL;
+ ComplementaryOp[EBCLR] = MAXEXPR;
+ ComplementaryOp[EBTST] = MAXEXPR;
+ ComplementaryOp[EBSET] = MAXEXPR;
+ ComplementaryOp[ETYPCON] = MAXEXPR;
+ ComplementaryOp[EBITFIELD] = MAXEXPR;
+ ComplementaryOp[EINTCONST] = MAXEXPR;
+ ComplementaryOp[EFLOATCONST] = MAXEXPR;
+ ComplementaryOp[ESTRINGCONST] = MAXEXPR;
+ ComplementaryOp[ECOND] = MAXEXPR;
+ ComplementaryOp[EFUNCCALL] = MAXEXPR;
+ ComplementaryOp[EFUNCCALLP] = MAXEXPR;
+ ComplementaryOp[EOBJREF] = MAXEXPR;
+ ComplementaryOp[EMFPOINTER] = MAXEXPR;
+ ComplementaryOp[ENULLCHECK] = MAXEXPR;
+ ComplementaryOp[EPRECOMP] = MAXEXPR;
+ ComplementaryOp[ETEMP] = MAXEXPR;
+ ComplementaryOp[EARGOBJ] = MAXEXPR;
+ ComplementaryOp[ELOCOBJ] = MAXEXPR;
+ ComplementaryOp[ELABEL] = MAXEXPR;
+ ComplementaryOp[ESETCONST] = MAXEXPR;
+ ComplementaryOp[ENEWEXCEPTION] = MAXEXPR;
+ ComplementaryOp[ENEWEXCEPTIONARRAY] = MAXEXPR;
+ ComplementaryOp[EOBJLIST] = MAXEXPR;
+ ComplementaryOp[EMEMBER] = MAXEXPR;
+ ComplementaryOp[ETEMPLDEP] = MAXEXPR;
+ ComplementaryOp[EINSTRUCTION] = MAXEXPR;
+ ComplementaryOp[EDEFINE] = MAXEXPR;
+ ComplementaryOp[EREUSE] = MAXEXPR;
+ ComplementaryOp[EASSBLK] = MAXEXPR;
+ ComplementaryOp[EVECTOR128CONST] = MAXEXPR;
+ ComplementaryOp[ECONDASS] = MAXEXPR;
+}
+
+void IRO_InitializeComplementaryOpLogicalArray(void) {
+ int i;
+
+ for (i = 0; i < MAXEXPR; i++)
+ ComplementaryOpLogical[i] = MAXEXPR;
+
+ ComplementaryOpLogical[EPOSTINC] = MAXEXPR;
+ ComplementaryOpLogical[EPOSTDEC] = MAXEXPR;
+ ComplementaryOpLogical[EPREINC] = MAXEXPR;
+ ComplementaryOpLogical[EPREDEC] = MAXEXPR;
+ ComplementaryOpLogical[EINDIRECT] = MAXEXPR;
+ ComplementaryOpLogical[EMONMIN] = MAXEXPR;
+ ComplementaryOpLogical[EBINNOT] = MAXEXPR;
+ ComplementaryOpLogical[ELOGNOT] = ELOGNOT;
+ ComplementaryOpLogical[EFORCELOAD] = MAXEXPR;
+ ComplementaryOpLogical[EMUL] = MAXEXPR;
+ ComplementaryOpLogical[EMULV] = MAXEXPR;
+ ComplementaryOpLogical[EDIV] = MAXEXPR;
+ ComplementaryOpLogical[EMODULO] = MAXEXPR;
+ ComplementaryOpLogical[EADDV] = MAXEXPR;
+ ComplementaryOpLogical[ESUBV] = MAXEXPR;
+ ComplementaryOpLogical[EADD] = MAXEXPR;
+ ComplementaryOpLogical[ESUB] = MAXEXPR;
+ ComplementaryOpLogical[ESHL] = MAXEXPR;
+ ComplementaryOpLogical[ESHR] = MAXEXPR;
+ ComplementaryOpLogical[ELESS] = EGREATEREQU;
+ ComplementaryOpLogical[EGREATER] = ELESSEQU;
+ ComplementaryOpLogical[ELESSEQU] = EGREATER;
+ ComplementaryOpLogical[EGREATEREQU] = ELESS;
+ ComplementaryOpLogical[EEQU] = ENOTEQU;
+ ComplementaryOpLogical[ENOTEQU] = EEQU;
+ ComplementaryOpLogical[EAND] = MAXEXPR;
+ ComplementaryOpLogical[EXOR] = MAXEXPR;
+ ComplementaryOpLogical[EOR] = MAXEXPR;
+ ComplementaryOpLogical[ELAND] = ELOR;
+ ComplementaryOpLogical[ELOR] = ELAND;
+ ComplementaryOpLogical[EASS] = MAXEXPR;
+ ComplementaryOpLogical[EMULASS] = MAXEXPR;
+ ComplementaryOpLogical[EDIVASS] = MAXEXPR;
+ ComplementaryOpLogical[EMODASS] = MAXEXPR;
+ ComplementaryOpLogical[EADDASS] = MAXEXPR;
+ ComplementaryOpLogical[ESUBASS] = MAXEXPR;
+ ComplementaryOpLogical[ESHLASS] = MAXEXPR;
+ ComplementaryOpLogical[ESHRASS] = MAXEXPR;
+ ComplementaryOpLogical[EANDASS] = MAXEXPR;
+ ComplementaryOpLogical[EXORASS] = MAXEXPR;
+ ComplementaryOpLogical[EORASS] = MAXEXPR;
+ ComplementaryOpLogical[ECOMMA] = MAXEXPR;
+ ComplementaryOpLogical[EPMODULO] = MAXEXPR;
+ ComplementaryOpLogical[EROTL] = MAXEXPR;
+ ComplementaryOpLogical[EROTR] = MAXEXPR;
+ ComplementaryOpLogical[EBCLR] = MAXEXPR;
+ ComplementaryOpLogical[EBTST] = MAXEXPR;
+ ComplementaryOpLogical[EBSET] = MAXEXPR;
+ ComplementaryOpLogical[ETYPCON] = MAXEXPR;
+ ComplementaryOpLogical[EBITFIELD] = MAXEXPR;
+ ComplementaryOpLogical[EINTCONST] = MAXEXPR;
+ ComplementaryOpLogical[EFLOATCONST] = MAXEXPR;
+ ComplementaryOpLogical[ESTRINGCONST] = MAXEXPR;
+ ComplementaryOpLogical[ECOND] = MAXEXPR;
+ ComplementaryOpLogical[EFUNCCALL] = MAXEXPR;
+ ComplementaryOpLogical[EFUNCCALLP] = MAXEXPR;
+ ComplementaryOpLogical[EOBJREF] = MAXEXPR;
+ ComplementaryOpLogical[EMFPOINTER] = MAXEXPR;
+ ComplementaryOpLogical[ENULLCHECK] = MAXEXPR;
+ ComplementaryOpLogical[EPRECOMP] = MAXEXPR;
+ ComplementaryOpLogical[ETEMP] = MAXEXPR;
+ ComplementaryOpLogical[EARGOBJ] = MAXEXPR;
+ ComplementaryOpLogical[ELOCOBJ] = MAXEXPR;
+ ComplementaryOpLogical[ELABEL] = MAXEXPR;
+ ComplementaryOpLogical[ESETCONST] = MAXEXPR;
+ ComplementaryOpLogical[ENEWEXCEPTION] = MAXEXPR;
+ ComplementaryOpLogical[ENEWEXCEPTIONARRAY] = MAXEXPR;
+ ComplementaryOpLogical[EOBJLIST] = MAXEXPR;
+ ComplementaryOpLogical[EMEMBER] = MAXEXPR;
+ ComplementaryOpLogical[ETEMPLDEP] = MAXEXPR;
+ ComplementaryOpLogical[EINSTRUCTION] = MAXEXPR;
+ ComplementaryOpLogical[EDEFINE] = MAXEXPR;
+ ComplementaryOpLogical[EREUSE] = MAXEXPR;
+ ComplementaryOpLogical[EASSBLK] = MAXEXPR;
+ ComplementaryOpLogical[EVECTOR128CONST] = MAXEXPR;
+ ComplementaryOpLogical[ECONDASS] = MAXEXPR;
+}
+
+static void DoTransformations(IROLinear *nd) {
+ IROLinear *nd2;
+ IROLinear *nd3;
+ IROLinear *nd4;
+ IROLinear *nd5;
+ Type *newtype;
+ SInt32 value;
+
+ if (nd->type == IROLinearOp2Arg) {
+ switch (nd->nodetype) {
+ case EASS:
+ nd2 = nd->u.diadic.right;
+ if (
+ nd2->type == IROLinearOp2Arg &&
+ AssignmentOp[nd2->nodetype] < MAXEXPR &&
+ IRO_TypesEqual(nd->rtype, nd2->rtype) &&
+ IRO_IsVariable(nd3 = nd->u.diadic.left) &&
+ !(nd3->flags & IROLF_BitfieldIndirect) &&
+ IRO_ExprsSame(nd3, nd2->u.diadic.left)
+ )
+ {
+ nd->nodetype = AssignmentOp[nd2->nodetype];
+ nd->u.diadic.right = nd2->u.diadic.right;
+ IRO_NopOut(nd2->u.diadic.left);
+ nd2->type = IROLinearNop;
+
+ nd3->flags |= IROLF_Used;
+ nd3->u.diadic.left->flags |= IROLF_Used;
+ }
+ break;
+
+ case EMUL:
+ if (
+ IS_TYPE_INT(nd->rtype) &&
+ IRO_IsPow2(nd->u.diadic.right, &value)
+ )
+ {
+ nd->nodetype = ESHL;
+ CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value);
+ }
+ break;
+
+ case EDIV:
+ if (
+ IS_TYPE_INT(nd->rtype) &&
+ IRO_IsPow2(nd->u.diadic.right, &value)
+ )
+ {
+ if (IRO_IsUnsignedType(nd->rtype)) {
+ nd->nodetype = ESHR;
+ CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value);
+ } else if (
+ !IRO_IsUnsignedType(nd->rtype) &&
+ TYPE_INTEGRAL(nd->rtype)->integral != IT_BOOL &&
+ nd->u.diadic.left->nodetype == ETYPCON &&
+ IS_TYPE_INT(nd->u.diadic.left->u.monadic->rtype) &&
+ IRO_IsUnsignedType(nd->u.diadic.left->u.monadic->rtype) &&
+ nd->u.diadic.left->u.monadic->rtype->size < nd->u.diadic.left->rtype->size
+ )
+ {
+ nd->nodetype = ESHR;
+ CInt64_SetLong(&nd->u.diadic.right->u.node->data.intval, value);
+ if (nd->flags & IROLF_Reffed) {
+ IROLinear *copy = IRO_NewLinear(IROLinearOp1Arg);
+ memcpy(copy, nd, sizeof(IROLinear));
+ copy->type = IROLinearOp1Arg;
+ copy->nodetype = ETYPCON;
+ copy->index = IRO_NumLinear++;
+ copy->rtype = nd->rtype;
+ IRO_PasteAfter(copy, copy, nd);
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, copy);
+ copy->u.monadic = nd;
+ nd->flags |= IROLF_Reffed;
+ }
+ nd->rtype = IRO_UnsignedType(nd->rtype);
+ newtype = IRO_UnsignedType(nd->u.diadic.right->rtype);
+ nd->u.diadic.right->u.node->rtype = newtype;
+ nd->u.diadic.right->rtype = newtype;
+ nd->u.diadic.left->rtype = IRO_UnsignedType(nd->u.diadic.left->rtype);
+ }
+ }
+ break;
+
+ case EMODULO:
+ if (
+ IS_TYPE_INT(nd->rtype) &&
+ IRO_IsUnsignedType(nd->rtype) &&
+ IRO_IsPow2(nd->u.diadic.right, &value)
+ )
+ {
+ nd->nodetype = EAND;
+ nd->u.diadic.right->u.node->data.intval = CInt64_Sub(nd->u.diadic.right->u.node->data.intval, cint64_one);
+ }
+ break;
+
+ case EEQU:
+ if (
+ (nd2 = IRO_LocateFather(nd)) &&
+ nd2->nodetype == ETYPCON &&
+ IS_TYPE_INT(nd2->rtype) &&
+ (nd3 = IRO_LocateFather(nd2)) &&
+ nd3->nodetype == ELOGNOT &&
+ (nd4 = IRO_LocateFather(nd3)) &&
+ nd4->nodetype == ETYPCON &&
+ IS_TYPE_INT(nd4->rtype) &&
+ (
+ ((nd5 = IRO_LocateFather(nd4)) && nd5->type == IROLinearIf) ||
+ nd5->type == IROLinearIfNot
+ )
+ )
+ {
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd4, nd);
+ nd->nodetype = ENOTEQU;
+ nd2->type = IROLinearNop;
+ nd3->type = IROLinearNop;
+ nd4->type = IROLinearNop;
+ }
+ break;
+ }
+ }
+}
+
+static void IRO_SwitchChildren(IROLinear *nd) {
+ IROLinear *tmp = nd->u.diadic.left;
+ nd->u.diadic.left = nd->u.diadic.right;
+ nd->u.diadic.right = tmp;
+}
+
+static void ReplaceExprWithConst(IROLinear *nd, CInt64 val) {
+ IRO_NopOut(nd);
+ nd->type = IROLinearOperand;
+ nd->nodetype = EINTCONST;
+ nd->u.node = IRO_NewENode(EINTCONST);
+ nd->u.node->data.intval = val;
+ nd->u.node->flags = nd->nodeflags;
+ nd->u.node->rtype = nd->rtype;
+
+ if (IS_TYPE_FLOAT(nd->rtype)) {
+ nd->u.node->type = EFLOATCONST;
+ nd->nodetype = EFLOATCONST;
+ nd->u.node->data.floatval = CMach_CalcFloatConvertFromInt(TYPE(&stsignedlong), val);
+ }
+}
+
+static void ReplaceExprWithLeftChild(IROLinear *nd) {
+ IROLinear *left = nd->u.diadic.left;
+ IROLinear *right = nd->u.diadic.right;
+
+ if (left->rtype == nd->rtype) {
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, left);
+ left->flags = nd->flags;
+ left->nodeflags = nd->nodeflags;
+ nd->type = IROLinearNop;
+ IRO_NopOut(right);
+ } else {
+ nd->type = IROLinearOp1Arg;
+ nd->nodetype = ETYPCON;
+ nd->u.monadic = left;
+ IRO_NopOut(right);
+ }
+}
+
+static void ReplaceExprWithRightChild(IROLinear *nd) {
+ IROLinear *left = nd->u.diadic.left;
+ IROLinear *right = nd->u.diadic.right;
+
+ if (right->rtype == nd->rtype) {
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, right);
+ right->flags = nd->flags;
+ right->nodeflags = nd->nodeflags;
+ nd->type = IROLinearNop;
+ IRO_NopOut(left);
+ } else {
+ nd->type = IROLinearOp1Arg;
+ nd->nodetype = ETYPCON;
+ nd->u.monadic = right;
+ IRO_NopOut(left);
+ }
+}
+
+static void ReplaceExprWithMonaminRight(IROLinear *nd) {
+ IROLinear *left = nd->u.diadic.left;
+ IROLinear *right = nd->u.diadic.right;
+
+ if (right->rtype == nd->rtype) {
+ nd->type = IROLinearOp1Arg;
+ nd->nodetype = EMONMIN;
+ nd->u.monadic = right;
+ IRO_NopOut(left);
+ } else {
+ IRO_NopOut(left);
+ left->type = IROLinearOp1Arg;
+ left->nodetype = ETYPCON;
+ left->expr = right->expr;
+ left->rtype = nd->rtype;
+ left->u.monadic = right;
+ nd->type = IROLinearOp1Arg;
+ nd->nodetype = EMONMIN;
+ nd->u.monadic = left;
+ }
+}
+
+static void ReplaceExprWithMonaminLeft(IROLinear *nd) {
+ IROLinear *left = nd->u.diadic.left;
+ IROLinear *right = nd->u.diadic.right;
+
+ if (left->rtype == nd->rtype) {
+ nd->type = IROLinearOp1Arg;
+ nd->nodetype = EMONMIN;
+ nd->u.monadic = left;
+ IRO_NopOut(right);
+ } else {
+ IRO_NopOut(right);
+ right->type = IROLinearOp1Arg;
+ right->nodetype = ETYPCON;
+ right->expr = left->expr;
+ right->rtype = nd->rtype;
+ right->u.monadic = left;
+ nd->type = IROLinearOp1Arg;
+ nd->nodetype = EMONMIN;
+ nd->u.monadic = right;
+ }
+}
+
+static void switchFatherLeftMonadic(IROLinear *nd) {
+ IROLinear *inner = nd->u.monadic;
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, inner);
+ nd->u.monadic = inner->u.monadic;
+ inner->u.monadic = nd;
+ inner->rtype = nd->rtype;
+ inner->flags = nd->flags;
+ inner->nodeflags = nd->nodeflags;
+ IRO_CutAndPasteAfter(inner, inner, nd);
+}
+
+static void switchFatherLeft(IROLinear *nd, int isRight) {
+ IROLinear *a;
+ IROLinear *b;
+
+ a = nd->u.diadic.left;
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd, a);
+
+ if (isRight) {
+ nd->u.diadic.left = a->u.diadic.left;
+ a->u.diadic.left = nd;
+ b = a->u.diadic.right;
+ } else {
+ nd->u.diadic.left = a->u.diadic.right;
+ a->u.diadic.right = nd;
+ b = a->u.diadic.left;
+ }
+
+ a->rtype = nd->rtype;
+ a->flags = nd->flags;
+ a->nodeflags = nd->nodeflags;
+ IRO_CutAndPasteAfter(a, a, nd);
+ IRO_CutAndPasteAfter(IRO_FindFirst(b), b, nd);
+}
+
+static void PickCommonsubAtLeftLeft(IROLinear *nd) {
+ switchFatherLeft(nd, 0);
+ ReplaceExprWithRightChild(nd->u.diadic.right);
+}
+
+static void PickCommonsubAtRightLeft(IROLinear *nd) {
+ switchFatherLeft(nd, 1);
+ ReplaceExprWithRightChild(nd->u.diadic.right);
+}
+
+static void PickCommonsubAtLeftRight(IROLinear *nd) {
+ switchFatherLeft(nd, 0);
+ ReplaceExprWithLeftChild(nd->u.diadic.right);
+}
+
+static void PickCommonsubAtRightRight(IROLinear *nd) {
+ switchFatherLeft(nd, 1);
+ ReplaceExprWithLeftChild(nd->u.diadic.right);
+}
+
+static void DoTransformations11(IROLinear *nd) {
+ IROLinear *left;
+ IROLinear *right;
+ int changed;
+ int compare;
+ Type *type;
+ SInt32 tmp1;
+ SInt32 tmp2;
+ CInt64 val;
+
+ if (nd->type == IROLinearOp2Arg) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype))
+ return;
+
+ changed = 0;
+ if (!IRO_HasSideEffect(left) && !IRO_HasSideEffect(right)) {
+ if (IRO_IsIntConstant(right) || IRO_IsFloatConstant(right)) {
+ if (IRO_IsConstantZero(right)) {
+ switch (nd->nodetype) {
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case ESHL:
+ case ESHR:
+ case EXOR:
+ case EOR:
+ case ELOR:
+ case EADDASS:
+ case ESUBASS:
+ case ESHLASS:
+ case ESHRASS:
+ case EXORASS:
+ case EORASS:
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ break;
+ case EMUL:
+ case EAND:
+ case ELAND:
+ ReplaceExprWithConst(nd, cint64_zero);
+ changed = 1;
+ break;
+ case EMULASS:
+ case EANDASS:
+ nd->nodetype = EASS;
+ nd->u.diadic.right->rtype = nd->rtype;
+ nd->u.diadic.right->u.node->rtype = nd->rtype;
+ changed = 1;
+ break;
+ case EDIV:
+ case EMODULO:
+ case EDIVASS:
+ case EMODASS:
+ if (nd->stmt->sourceoffset) {
+ TStreamElement *token = CPrep_CurStreamElement();
+ token->tokenoffset = nd->stmt->sourceoffset;
+ CError_SetErrorToken(token);
+ }
+ CError_Warning(CErrorStr139);
+ break;
+ }
+ } else if (nd->nodetype == ELAND) {
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ } else if (nd->nodetype == ELOR) {
+ ReplaceExprWithConst(nd, cint64_one);
+ changed = 1;
+ } else if (nd->nodetype == ESHL || nd->nodetype == ESHR || nd->nodetype == ESHLASS || nd->nodetype == ESHRASS) {
+ type = nd->rtype;
+ tmp1 = type->size * 8;
+ if (left->type == IROLinearOp1Arg && left->nodetype == ETYPCON) {
+ type = left->u.monadic->rtype;
+ if (
+ left->u.monadic->type == IROLinearOp1Arg &&
+ left->u.monadic->nodetype == EINDIRECT &&
+ left->u.monadic->u.monadic->type == IROLinearOp1Arg &&
+ left->u.monadic->u.monadic->nodetype == EBITFIELD &&
+ IS_TYPE_BITFIELD(left->u.monadic->u.monadic->rtype)
+ )
+ tmp2 = TYPE_BITFIELD(left->u.monadic->u.monadic->rtype)->bitlength;
+ else
+ tmp2 = type->size * 8;
+ } else {
+ tmp2 = tmp1;
+ }
+
+ switch (nd->nodetype) {
+ case ESHL:
+ case ESHLASS:
+ CInt64_SetLong(&val, tmp1);
+ if (IRO_IsUnsignedType(type))
+ compare = CInt64_GreaterEqualU(right->u.node->data.intval, val);
+ else
+ compare = CInt64_GreaterEqual(right->u.node->data.intval, val);
+ break;
+ case ESHR:
+ case ESHRASS:
+ CInt64_SetLong(&val, tmp2);
+ compare = IRO_IsUnsignedType(type) && CInt64_GreaterEqualU(right->u.node->data.intval, val);
+ break;
+ }
+
+ if (compare) {
+ switch (nd->nodetype) {
+ case ESHL:
+ case ESHR:
+ ReplaceExprWithConst(nd, cint64_zero);
+ break;
+ case ESHLASS:
+ case ESHRASS:
+ nd->nodetype = EASS;
+ ReplaceExprWithConst(right, cint64_zero);
+ break;
+ }
+ changed = 1;
+ }
+ } else if (IRO_IsConstantOne(right)) {
+ switch (nd->nodetype) {
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ case EMULASS:
+ case EDIVASS:
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ break;
+ case EMODULO:
+ ReplaceExprWithConst(nd, cint64_zero);
+ changed = 1;
+ break;
+ case EMODASS:
+ nd->nodetype = EASS;
+ ReplaceExprWithConst(right, cint64_zero);
+ nd->u.diadic.right->rtype = nd->rtype;
+ nd->u.diadic.right->u.node->rtype = nd->rtype;
+ changed = 1;
+ break;
+ }
+ } else if (IRO_IsConstantNegativeOne(right)) {
+ switch (nd->nodetype) {
+ case EMUL:
+ case EMULV:
+ case EDIV:
+ ReplaceExprWithMonaminLeft(nd);
+ changed = 1;
+ break;
+ case EMODULO:
+ ReplaceExprWithConst(nd, cint64_zero);
+ changed = 1;
+ break;
+ case EMODASS:
+ nd->nodetype = EASS;
+ ReplaceExprWithConst(right, cint64_zero);
+ nd->u.diadic.right->rtype = nd->rtype;
+ nd->u.diadic.right->u.node->rtype = nd->rtype;
+ changed = 1;
+ break;
+ }
+ }
+ }
+
+ if (!changed && (IRO_IsIntConstant(left) || IRO_IsFloatConstant(left))) {
+ if (IRO_IsConstantZero(left)) {
+ switch (nd->nodetype) {
+ case EADDV:
+ case EADD:
+ case EXOR:
+ case EOR:
+ case ELOR:
+ ReplaceExprWithRightChild(nd);
+ break;
+ case EMUL:
+ case ESHL:
+ case ESHR:
+ case EAND:
+ case ELAND:
+ ReplaceExprWithConst(nd, cint64_zero);
+ break;
+ case ESUBV:
+ case ESUB:
+ ReplaceExprWithMonaminRight(nd);
+ break;
+ }
+ } else if (nd->nodetype == ELAND) {
+ ReplaceExprWithRightChild(nd);
+ } else if (nd->nodetype == ELOR) {
+ ReplaceExprWithConst(nd, cint64_one);
+ } else if (IRO_IsConstantOne(left)) {
+ switch (nd->nodetype) {
+ case EMUL:
+ case EMULV:
+ ReplaceExprWithRightChild(nd);
+ break;
+ }
+ } else if (IRO_IsConstantNegativeOne(left)) {
+ switch (nd->nodetype) {
+ case EMUL:
+ case EMULV:
+ ReplaceExprWithMonaminRight(nd);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void DoTransformations12(IROLinear *nd) {
+ IROLinear *left;
+ IROLinear *right;
+
+ if (nd->type == IROLinearOp2Arg) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype))
+ return;
+
+ if (IRO_ExprsSameSemantically(left, right) && !IRO_HasSideEffect(left)) {
+ switch (nd->nodetype) {
+ case ESUBV:
+ case ESUB:
+ case ELESS:
+ case EGREATER:
+ case ENOTEQU:
+ case EXOR:
+ ReplaceExprWithConst(nd, cint64_zero);
+ break;
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ ReplaceExprWithConst(nd, cint64_one);
+ break;
+ case EAND:
+ case EOR:
+ case ELAND:
+ case ELOR:
+ case EASS:
+ case EANDASS:
+ case EORASS:
+ ReplaceExprWithLeftChild(nd);
+ break;
+ case ESUBASS:
+ case EXORASS:
+ nd->nodetype = EASS;
+ ReplaceExprWithConst(right, cint64_zero);
+ break;
+ }
+ }
+ }
+}
+
+static void DoTransformations13(IROLinear *nd) {
+ IROLinear *left;
+ IROLinear *right;
+ IROLinear *left2;
+ IROLinear *right2;
+ IROListNode *tmp;
+ IROListNode *leftlist;
+ IROListNode *rightlist;
+
+ if (nd->type == IROLinearOp2Arg) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+
+ if (
+ !IRO_HasSideEffect(left) &&
+ !IRO_HasSideEffect(right) &&
+ (nd->nodetype == EEQU || nd->nodetype == ENOTEQU) &&
+ PointerAnalysis_IsLinearNodePointerExprDefinite(FunctionName, left) &&
+ PointerAnalysis_IsLinearNodePointerExprDefinite(FunctionName, right)
+ )
+ {
+ leftlist = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, left, &leftlist);
+ if (leftlist) {
+ if (leftlist->list.head && leftlist->list.tail && !leftlist->nextList) {
+ rightlist = NULL;
+ PointerAnalysis_LookupLinearNodePointerExpr(FunctionName, right, &rightlist);
+ if (rightlist) {
+ if (rightlist->list.head && rightlist->list.tail && !rightlist->nextList) {
+ left2 = leftlist->list.tail;
+ right2 = rightlist->list.tail;
+ if (IRO_ExprsSameSemantically(left2, right2)) {
+ ReplaceExprWithConst(nd, (nd->nodetype == EEQU) ? cint64_one : cint64_zero);
+ } else if (left2->type == right2->type && IRO_TypesEqual(left2->rtype, right2->rtype)) {
+ ReplaceExprWithConst(nd, (nd->nodetype == EEQU) ? cint64_zero : cint64_one);
+ }
+ }
+
+ while (rightlist) {
+ tmp = rightlist->nextList;
+ IRO_free(rightlist);
+ rightlist = tmp;
+ }
+ }
+ }
+
+ while (leftlist) {
+ tmp = leftlist->nextList;
+ IRO_free(leftlist);
+ leftlist = tmp;
+ }
+ }
+ }
+ }
+}
+
+static void DoTransformations21(IROLinear *nd) {
+ IROLinear *left;
+ IROLinear *right;
+ Boolean changed;
+
+ if (nd->type == IROLinearOp2Arg) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+
+ if (left->type == IROLinearOp1Arg && right->type == IROLinearOp1Arg && left->nodetype == right->nodetype) {
+ switch (left->nodetype) {
+ case EMONMIN:
+ case EBINNOT:
+ case ELOGNOT:
+ changed = 0;
+ switch (nd->nodetype) {
+ case EXOR:
+ if (left->nodetype == EBINNOT)
+ goto collapse;
+ break;
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ if (left->nodetype == EMONMIN) {
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ goto collapse;
+ }
+ break;
+ case EMUL:
+ case EDIV:
+ if (left->nodetype == EMONMIN)
+ goto collapse;
+ break;
+ case EEQU:
+ case ENOTEQU:
+ if (left->nodetype != ELOGNOT) {
+ collapse:
+ nd->u.diadic.left = left->u.monadic;
+ nd->u.diadic.right = right->u.monadic;
+ left->type = right->type = IROLinearNop;
+ changed = 1;
+ }
+ break;
+ case ELAND:
+ case ELOR:
+ if (left->nodetype == ELOGNOT) {
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ goto switchfather;
+ }
+ break;
+ case EAND:
+ case EOR:
+ if (
+ !IS_TYPE_FLOAT(nd->rtype) &&
+ !IS_TYPE_FLOAT(left->rtype) &&
+ !IS_TYPE_FLOAT(right->rtype) &&
+ left->nodetype != EMONMIN
+ )
+ {
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ goto switchfather;
+ }
+ break;
+ case EADD:
+ case ESUB:
+ if (
+ !IS_TYPE_FLOAT(nd->rtype) &&
+ !IS_TYPE_FLOAT(left->rtype) &&
+ !IS_TYPE_FLOAT(right->rtype) &&
+ left->nodetype == EMONMIN
+ )
+ {
+ switchfather:
+ switchFatherLeftMonadic(nd);
+ nd->u.diadic.right = right->u.monadic;
+ right->type = IROLinearNop;
+ changed = 1;
+ }
+ break;
+ }
+
+ if (changed) {
+ DoTransformations(nd);
+ DoTransformations11(nd);
+ DoTransformations12(nd);
+ DoTransformations13(nd);
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void DoTransformations22(IROLinear *nd) {
+ IROLinear *left;
+ IROLinear *right;
+ IROLinear *ndtmp;
+
+ if (nd->type == IROLinearOp2Arg) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype))
+ return;
+
+ if (!IRO_HasSideEffect(left) && !IRO_HasSideEffect(right)) {
+ if (left->type == IROLinearOp1Arg && left->nodetype == EMONMIN) {
+ switch (nd->nodetype) {
+ case ESUB:
+ case ESUBV:
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ switchFatherLeftMonadic(nd);
+ break;
+
+ case EADD:
+ case EADDV:
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ nd->u.diadic.left = right;
+ nd->u.diadic.right = left->u.monadic;
+ left->type = IROLinearNop;
+ DoTransformations(nd);
+ DoTransformations12(nd);
+ DoTransformations21(nd);
+ break;
+
+ case EDIV:
+ if (IRO_ExprsSameSemantically(left->u.monadic, right))
+ ReplaceExprWithConst(nd, cint64_negone);
+ break;
+ }
+ } else {
+ ndtmp = NULL;
+ if (left->type == IROLinearOp1Arg && IRO_ExprsSameSemantically(left->u.monadic, right))
+ ndtmp = left;
+ else if (right->type == IROLinearOp1Arg && IRO_ExprsSameSemantically(left, right->u.monadic))
+ ndtmp = right;
+
+ if (ndtmp) {
+ switch (nd->nodetype) {
+ case EAND:
+ if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT)
+ ReplaceExprWithConst(nd, cint64_zero);
+ break;
+
+ case EANDASS:
+ if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT) {
+ nd->nodetype = EASS;
+ ReplaceExprWithConst(right, cint64_zero);
+ nd->u.diadic.right->rtype = nd->rtype;
+ nd->u.diadic.right->u.node->rtype = nd->rtype;
+ }
+ break;
+
+ case EXOR:
+ case EOR:
+ if (ndtmp->nodetype == EBINNOT) {
+ ReplaceExprWithConst(nd, cint64_zero);
+ nd->u.node->data.intval = CInt64_Inv(nd->u.node->data.intval);
+ }
+ break;
+
+ case EXORASS:
+ case EORASS:
+ if (ndtmp->nodetype == EBINNOT) {
+ nd->nodetype = EASS;
+ ReplaceExprWithConst(right, cint64_zero);
+ right->u.node->data.intval = CInt64_Inv(right->u.node->data.intval);
+ nd->u.diadic.right->rtype = nd->rtype;
+ nd->u.diadic.right->u.node->rtype = nd->rtype;
+ }
+ break;
+
+ case ELOR:
+ if (ndtmp->nodetype == EBINNOT || ndtmp->nodetype == ELOGNOT)
+ ReplaceExprWithConst(nd, cint64_one);
+ break;
+
+ case ELAND:
+ if (ndtmp->nodetype == ELOGNOT)
+ ReplaceExprWithConst(nd, cint64_zero);
+ break;
+
+ case EDIV:
+ if (ndtmp->nodetype == EMONMIN)
+ ReplaceExprWithConst(nd, cint64_negone);
+ break;
+
+ case EDIVASS:
+ if (ndtmp->nodetype == EMONMIN) {
+ nd->nodetype = EASS;
+ ReplaceExprWithConst(right, cint64_negone);
+ nd->u.diadic.right->rtype = nd->rtype;
+ nd->u.diadic.right->u.node->rtype = nd->rtype;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void DoTransformations23(IROLinear *nd) {
+ Boolean changed;
+ Boolean isCompare;
+ UInt8 which;
+ IROLinear *left;
+ IROLinear *right;
+ CInt64 size;
+ CInt64 val;
+
+ if (nd->type == IROLinearOp2Arg && !IRO_HasSideEffect(nd)) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype))
+ return;
+
+ isCompare = 0;
+ changed = 0;
+ which = 0;
+
+ switch (nd->nodetype) {
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ isCompare = 1;
+ case EADDV:
+ case EADD:
+ case EEQU:
+ case ENOTEQU:
+ case EAND:
+ case EOR:
+ if (left->type == IROLinearOp2Arg) {
+ if (IRO_ExprsSameSemantically(right, left->u.diadic.left))
+ which = 1;
+ else if (IRO_ExprsSameSemantically(right, left->u.diadic.right))
+ which = 2;
+
+ if (which) {
+ if (isCompare)
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ IRO_SwitchChildren(nd);
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ break;
+ }
+ }
+ case ESUBV:
+ case ESUB:
+ case EADDASS:
+ case ESUBASS:
+ case EANDASS:
+ case EORASS:
+ if (right->type == IROLinearOp2Arg) {
+ if (IRO_ExprsSameSemantically(left, right->u.diadic.left))
+ which = 1;
+ else if (IRO_ExprsSameSemantically(left, right->u.diadic.right))
+ which = 2;
+ }
+ break;
+
+ default:
+ goto done;
+ }
+
+ if (which) {
+ switch (right->nodetype) {
+ case EAND:
+ case EOR:
+ if (which == 2)
+ IRO_SwitchChildren(right);
+
+ if (
+ nd->nodetype == right->nodetype ||
+ (nd->nodetype == EANDASS && right->nodetype == EAND) ||
+ (nd->nodetype == EORASS && right->nodetype == EOR)
+ )
+ {
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ }
+ else if (
+ nd->nodetype == ComplementaryOp[right->nodetype] ||
+ (nd->nodetype == EANDASS && right->nodetype == EOR) ||
+ (nd->nodetype == EORASS && right->nodetype == EAND)
+ )
+ {
+ ReplaceExprWithLeftChild(nd);
+ }
+ break;
+
+ case EADD:
+ if (which == 2)
+ IRO_SwitchChildren(right);
+
+ switch (nd->nodetype) {
+ case EEQU:
+ case ENOTEQU:
+ ReplaceExprWithConst(left, cint64_zero);
+ ReplaceExprWithRightChild(right);
+ IRO_SwitchChildren(nd);
+ if (isCompare)
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ changed = 1;
+ break;
+
+ case ESUB:
+ case ESUBV:
+ ReplaceExprWithRightChild(right);
+ ReplaceExprWithMonaminRight(nd);
+ changed = 1;
+ break;
+
+ case ESUBASS:
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ break;
+ }
+ break;
+
+ case ESUB:
+ switch (nd->nodetype) {
+ case EEQU:
+ case ENOTEQU:
+ if (which == 1) {
+ ReplaceExprWithConst(left, cint64_zero);
+ ReplaceExprWithRightChild(right);
+ IRO_SwitchChildren(nd);
+ }
+ break;
+ case EADD:
+ case EADDV:
+ if (which == 2) {
+ ReplaceExprWithLeftChild(right);
+ ReplaceExprWithRightChild(nd);
+ }
+ break;
+ case ESUB:
+ case ESUBV:
+ if (which == 1) {
+ ReplaceExprWithRightChild(right);
+ ReplaceExprWithRightChild(nd);
+ }
+ break;
+ case EADDASS:
+ if (which == 2) {
+ nd->nodetype = EASS;
+ ReplaceExprWithLeftChild(right);
+ changed = 1;
+ }
+ break;
+ case ESUBASS:
+ if (which == 1) {
+ nd->nodetype = EASS;
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
+ done:
+ if (!changed) {
+ switch (nd->nodetype) {
+ case ESUB:
+ case ESUBV:
+ which = 0;
+ if (left->type == IROLinearOp2Arg) {
+ if (IRO_ExprsSameSemantically(right, left->u.diadic.left))
+ which = 1;
+ else if (IRO_ExprsSameSemantically(right, left->u.diadic.right))
+ which = 2;
+ }
+
+ if (which == 1) {
+ if (left->nodetype == ESUB) {
+ ReplaceExprWithMonaminRight(left);
+ ReplaceExprWithLeftChild(nd);
+ } else if (left->nodetype == EADD) {
+ ReplaceExprWithRightChild(left);
+ ReplaceExprWithLeftChild(nd);
+ }
+ } else if (which == 2) {
+ if (left->nodetype == EADD) {
+ ReplaceExprWithLeftChild(left);
+ ReplaceExprWithLeftChild(nd);
+ }
+ }
+ break;
+ }
+
+ switch (nd->nodetype) {
+ case ESHL:
+ case ESHR:
+ case ESHLASS:
+ case ESHRASS:
+ which = 0;
+ if (left->type == IROLinearOp2Arg) {
+ if (left->nodetype == ComplementaryOp[nd->nodetype] || left->nodetype == AssignmentOp[ComplementaryOp[nd->nodetype]]) {
+ if (IRO_IsIntConstant(right) && IRO_ExprsSameSemantically(right, left->u.diadic.right))
+ which = 2;
+ }
+ }
+
+ if (which == 2) {
+ val = right->u.node->data.intval;
+ if (left->nodetype == ESHR || left->nodetype == ESHRASS) {
+ ReplaceExprWithLeftChild(left);
+ nd->nodetype = (nd->nodetype == ESHL) ? EAND : EANDASS;
+ right->u.node->data.intval = CInt64_Shl(cint64_negone, val);
+ changed = 1;
+ } else if (IRO_IsUnsignedType(nd->rtype)) {
+ ReplaceExprWithLeftChild(left);
+ nd->nodetype = (nd->nodetype == ESHR) ? EAND : EANDASS;
+ if (nd->rtype->size < 8) {
+ CInt64_SetLong(&size, 64 - 8 * nd->rtype->size);
+ val = CInt64_Add(val, size);
+ }
+ right->u.node->data.intval = CInt64_ShrU(cint64_negone, val);
+ changed = 1;
+ }
+ }
+ break;
+ }
+ }
+
+ if (changed) {
+ DoTransformations(nd);
+ DoTransformations11(nd);
+ DoTransformations12(nd);
+ DoTransformations13(nd);
+ DoTransformations21(nd);
+ DoTransformations22(nd);
+ DoTransformations23(nd);
+ }
+ }
+}
+
+static void DoTransformations24(IROLinear *nd) {
+ IROLinear *left;
+ IROLinear *right;
+ UInt8 changed;
+
+ if (nd->type == IROLinearOp2Arg) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ if (IS_TYPE_FLOAT(nd->rtype) || IS_TYPE_FLOAT(left->rtype) || IS_TYPE_FLOAT(right->rtype))
+ return;
+
+ if (left->type == IROLinearOp2Arg && right->type == IROLinearOp2Arg && !IRO_HasSideEffect(nd)) {
+ changed = 0;
+
+ if (IRO_ExprsSameSemantically(left->u.diadic.left, right->u.diadic.left)) {
+ if (left->nodetype == right->nodetype) {
+ switch (left->nodetype) {
+ case EADD:
+ if (nd->nodetype == ComplementaryOp[left->nodetype]) {
+ ReplaceExprWithRightChild(left);
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ }
+ break;
+ case ESUB:
+ if (nd->nodetype == ESUB || nd->nodetype == ESUBV) {
+ ReplaceExprWithRightChild(left);
+ ReplaceExprWithRightChild(right);
+ IRO_SwitchChildren(nd);
+ changed = 1;
+ }
+ break;
+ case EMUL:
+ switch (nd->nodetype) {
+ case EADD:
+ case ESUB:
+ PickCommonsubAtLeftLeft(nd);
+ changed = 3;
+ break;
+ }
+ break;
+ case EAND:
+ if (nd->nodetype == EXOR) {
+ PickCommonsubAtLeftLeft(nd);
+ changed = 3;
+ break;
+ }
+ case EOR:
+ if (nd->nodetype == left->nodetype) {
+ ReplaceExprWithRightChild(left);
+ changed = 1;
+ } else if (nd->nodetype == ComplementaryOp[left->nodetype]) {
+ PickCommonsubAtLeftLeft(nd);
+ changed = 3;
+ }
+ break;
+ }
+ } else if (left->nodetype == ComplementaryOp[right->nodetype]) {
+ switch (nd->nodetype) {
+ case ESUB:
+ case ESUBV:
+ switch (left->nodetype) {
+ case EADD:
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ ReplaceExprWithRightChild(left);
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ break;
+ case ESUB:
+ ReplaceExprWithMonaminRight(left);
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ break;
+ }
+ break;
+
+ case EAND:
+ case EOR:
+ if (left->nodetype == nd->nodetype)
+ ReplaceExprWithLeftChild(nd);
+ else if (right->nodetype == nd->nodetype)
+ ReplaceExprWithRightChild(nd);
+ break;
+ }
+ }
+ } else if (IRO_ExprsSameSemantically(left->u.diadic.right, right->u.diadic.left)) {
+ if (left->nodetype == right->nodetype) {
+ switch (left->nodetype) {
+ case EADD:
+ if (nd->nodetype == ComplementaryOp[left->nodetype]) {
+ ReplaceExprWithLeftChild(left);
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ }
+ break;
+ case EMUL:
+ switch (nd->nodetype) {
+ case EADD:
+ case ESUB:
+ PickCommonsubAtRightLeft(nd);
+ changed = 3;
+ break;
+ }
+ break;
+ case EAND:
+ if (nd->nodetype == EXOR) {
+ PickCommonsubAtRightLeft(nd);
+ changed = 3;
+ break;
+ }
+ case EOR:
+ if (nd->nodetype == left->nodetype) {
+ ReplaceExprWithLeftChild(left);
+ changed = 1;
+ } else if (nd->nodetype == ComplementaryOp[left->nodetype]) {
+ PickCommonsubAtRightLeft(nd);
+ changed = 3;
+ }
+ break;
+ }
+ } else if (left->nodetype == ComplementaryOp[right->nodetype]) {
+ switch (nd->nodetype) {
+ case ESUB:
+ case ESUBV:
+ if (left->nodetype == EADD) {
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ ReplaceExprWithLeftChild(left);
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ }
+ break;
+
+ case EADD:
+ case EADDV:
+ if (left->nodetype == ESUB) {
+ ReplaceExprWithLeftChild(left);
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ }
+ break;
+
+ case EAND:
+ case EOR:
+ if (left->nodetype == nd->nodetype)
+ ReplaceExprWithLeftChild(nd);
+ else if (right->nodetype == nd->nodetype)
+ ReplaceExprWithRightChild(nd);
+ break;
+ }
+ }
+ } else if (IRO_ExprsSameSemantically(left->u.diadic.left, right->u.diadic.right)) {
+ if (left->nodetype == right->nodetype) {
+ switch (left->nodetype) {
+ case EADD:
+ if (nd->nodetype == ComplementaryOp[left->nodetype]) {
+ ReplaceExprWithRightChild(left);
+ ReplaceExprWithLeftChild(right);
+ changed = 1;
+ }
+ break;
+ case ESUB:
+ switch (nd->nodetype) {
+ case EADDV:
+ case EADD:
+ nd->nodetype = ComplementaryOp[nd->nodetype];
+ ReplaceExprWithRightChild(left);
+ ReplaceExprWithLeftChild(right);
+ IRO_SwitchChildren(nd);
+ changed = 1;
+ break;
+ }
+ break;
+ case EMUL:
+ switch (nd->nodetype) {
+ case EADD:
+ case ESUB:
+ PickCommonsubAtLeftRight(nd);
+ changed = 2;
+ break;
+ }
+ break;
+ case EAND:
+ if (nd->nodetype == EXOR) {
+ PickCommonsubAtLeftRight(nd);
+ changed = 2;
+ break;
+ }
+ case EOR:
+ if (nd->nodetype == left->nodetype) {
+ ReplaceExprWithRightChild(left);
+ changed = 1;
+ } else if (nd->nodetype == ComplementaryOp[left->nodetype]) {
+ PickCommonsubAtLeftRight(nd);
+ changed = 2;
+ }
+ break;
+ }
+ } else if (left->nodetype == ComplementaryOp[right->nodetype]) {
+ switch (nd->nodetype) {
+ case EADD:
+ case EADDV:
+ if (left->nodetype == EADD) {
+ ReplaceExprWithRightChild(left);
+ ReplaceExprWithLeftChild(right);
+ changed = 1;
+ }
+ break;
+
+ case ESUB:
+ case ESUBV:
+ if (left->nodetype == ESUB) {
+ ReplaceExprWithMonaminRight(left);
+ ReplaceExprWithRightChild(right);
+ changed = 1;
+ }
+ break;
+
+ case EAND:
+ case EOR:
+ if (left->nodetype == nd->nodetype)
+ ReplaceExprWithLeftChild(nd);
+ else if (right->nodetype == nd->nodetype)
+ ReplaceExprWithRightChild(nd);
+ break;
+ }
+ }
+ } else if (IRO_ExprsSameSemantically(left->u.diadic.right, right->u.diadic.right)) {
+ if (left->nodetype == right->nodetype) {
+ switch (nd->nodetype) {
+ case ESUB:
+ switch (left->nodetype) {
+ case EADD:
+ case ESUB:
+ ReplaceExprWithLeftChild(left);
+ ReplaceExprWithLeftChild(right);
+ changed = 1;
+ }
+ case EADD:
+ switch (left->nodetype) {
+ case EMUL:
+ case ESHL:
+ PickCommonsubAtRightRight(nd);
+ changed = 2;
+ break;
+ }
+ break;
+ case EXOR:
+ switch (left->nodetype) {
+ case ESHL:
+ case ESHR:
+ case EAND:
+ PickCommonsubAtRightRight(nd);
+ changed = 2;
+ break;
+ }
+ break;
+ case EAND:
+ case EOR:
+ if (left->nodetype == nd->nodetype) {
+ ReplaceExprWithLeftChild(right);
+ changed = 1;
+ } else if (
+ left->nodetype == ComplementaryOp[nd->nodetype] ||
+ left->nodetype == ESHR ||
+ left->nodetype == ESHL
+ )
+ {
+ PickCommonsubAtRightRight(nd);
+ changed = 2;
+ }
+ break;
+ }
+ } else if (left->nodetype == ComplementaryOp[right->nodetype]) {
+ switch (nd->nodetype) {
+ case EADD:
+ case EADDV:
+ switch (left->nodetype) {
+ case EADD:
+ case ESUB:
+ ReplaceExprWithLeftChild(left);
+ ReplaceExprWithLeftChild(right);
+ changed = 1;
+ break;
+ }
+ break;
+
+ case EAND:
+ case EOR:
+ if (left->nodetype == nd->nodetype)
+ ReplaceExprWithLeftChild(nd);
+ else if (right->nodetype == nd->nodetype)
+ ReplaceExprWithRightChild(nd);
+ break;
+ }
+ }
+ }
+
+ if (changed) {
+ DoDiadic(nd);
+ if (changed == 2)
+ DoDiadic(nd->u.diadic.left);
+ else if (changed == 3)
+ DoDiadic(nd->u.diadic.right);
+ IRO_Dump("remove common op at: %d\n", nd->index);
+ }
+ }
+ }
+}
+
+static void DoTransformations25(IROLinear *nd) {
+ int changed = 0;
+ IROLinear *left;
+ IROLinear *right;
+
+ if (nd->type == IROLinearOp2Arg) {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+
+ if (
+ (left->type == IROLinearOp2Arg && (IS_TYPE_FLOAT(left->u.diadic.left->rtype) || IS_TYPE_FLOAT(left->u.diadic.right->rtype))) ||
+ (right->type == IROLinearOp2Arg && (IS_TYPE_FLOAT(right->u.diadic.left->rtype) || IS_TYPE_FLOAT(right->u.diadic.right->rtype)))
+ )
+ return;
+
+ switch (left->nodetype) {
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ switch (nd->nodetype) {
+ case EEQU:
+ if (IRO_IsConstantOne(right)) {
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ } else if (IRO_IsConstantZero(right)) {
+ left->nodetype = ComplementaryOpLogical[left->nodetype];
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ }
+ break;
+ case ENOTEQU:
+ if (IRO_IsConstantOne(right)) {
+ left->nodetype = ComplementaryOpLogical[left->nodetype];
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ } else if (IRO_IsConstantZero(right)) {
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ }
+ break;
+ }
+ break;
+ case ELAND:
+ case ELOR:
+ switch (nd->nodetype) {
+ case EEQU:
+ if (IRO_IsConstantOne(right)) {
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ }
+ break;
+ case ENOTEQU:
+ if (IRO_IsConstantZero(right)) {
+ ReplaceExprWithLeftChild(nd);
+ changed = 1;
+ }
+ break;
+ }
+ break;
+ }
+
+ if (!changed) {
+ switch (right->nodetype) {
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ switch (nd->nodetype) {
+ case EEQU:
+ if (IRO_IsConstantOne(left)) {
+ ReplaceExprWithRightChild(nd);
+ } else if (IRO_IsConstantZero(left)) {
+ right->nodetype = ComplementaryOpLogical[right->nodetype];
+ ReplaceExprWithRightChild(nd);
+ }
+ break;
+ case ENOTEQU:
+ if (IRO_IsConstantOne(left)) {
+ right->nodetype = ComplementaryOpLogical[right->nodetype];
+ ReplaceExprWithRightChild(nd);
+ } else if (IRO_IsConstantZero(left)) {
+ ReplaceExprWithRightChild(nd);
+ }
+ break;
+ }
+ break;
+ case ELAND:
+ case ELOR:
+ switch (nd->nodetype) {
+ case EEQU:
+ if (IRO_IsConstantOne(left)) {
+ ReplaceExprWithRightChild(nd);
+ }
+ break;
+ case ENOTEQU:
+ if (IRO_IsConstantZero(left)) {
+ ReplaceExprWithRightChild(nd);
+ }
+ break;
+ }
+ break;
+ }
+ }
+ }
+}
+
+static Boolean isOrderingOperator(ENodeType op) {
+ switch (op) {
+ case ELAND:
+ case ELOR:
+ case ECOMMA:
+ case ECOND:
+ case ECONDASS:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static void RemoveUnreffed(IROLinear *nd) {
+ if (!(nd->flags & IROLF_Reffed)) {
+ switch (nd->type) {
+ case IROLinearOperand:
+ IRO_NopNonSideEffects(nd, 0);
+ break;
+ case IROLinearOp1Arg:
+ case IROLinearOp2Arg:
+ case IROLinearOp3Arg:
+ case IROLinearFunccall:
+ if (!isOrderingOperator(nd->nodetype))
+ IRO_NopNonSideEffects(nd, 0);
+ break;
+ }
+ }
+}
+
+static void RemoveRedundantMonadicOp(IROLinear *nd) {
+ IROLinear *nd2;
+ IROLinear *nd3;
+
+ if (nd->type == IROLinearOp1Arg && (nd2 = IRO_LocateFather(nd)) && nd2->nodetype == nd->nodetype) {
+ switch (nd->nodetype) {
+ case ELOGNOT:
+ if ((nd3 = IRO_LocateFather(nd2))) {
+ if (
+ nd3->rtype &&
+ TYPE_INTEGRAL(nd3->rtype)->integral == IT_BOOL &&
+ nd->u.monadic->rtype &&
+ TYPE_INTEGRAL(nd->u.monadic->rtype)->integral == IT_BOOL
+ )
+ goto remove;
+
+ if (nd3->type == IROLinearIf)
+ goto remove;
+ if (nd3->type == IROLinearIfNot)
+ goto remove;
+ if (nd3->type == IROLinearOp3Arg && nd == nd3->u.args3.a)
+ goto remove;
+
+ switch (nd3->nodetype) {
+ case ELOGNOT:
+ case ELAND:
+ case ELOR:
+ goto remove;
+ }
+ }
+
+ if (nd->u.monadic->type == IROLinearOp1Arg || nd->u.monadic->type == IROLinearOp2Arg) {
+ switch (nd->u.monadic->nodetype) {
+ case ELOGNOT:
+ case ELESS:
+ case EGREATER:
+ case ELESSEQU:
+ case EGREATEREQU:
+ case EEQU:
+ case ENOTEQU:
+ case ELAND:
+ case ELOR:
+ goto remove;
+ }
+ }
+ break;
+
+ case EMONMIN:
+ case EBINNOT:
+ remove:
+ IRO_LocateFather_Cut_And_Paste_Without_Nopping(nd2, nd->u.monadic);
+ nd2->type = IROLinearNop;
+ nd->type = IROLinearNop;
+ break;
+
+ case ETYPCON:
+ if (TYPE_INTEGRAL(nd->rtype)->integral == IT_FLOAT) {
+ switch (TYPE_INTEGRAL(nd2->rtype)->integral) {
+ case IT_DOUBLE:
+ case IT_LONGDOUBLE:
+ switch (TYPE_INTEGRAL(nd->u.monadic->rtype)->integral) {
+ case IT_BOOL:
+ case IT_CHAR:
+ case IT_SCHAR:
+ case IT_UCHAR:
+ case IT_SHORT:
+ case IT_USHORT:
+ nd->type = IROLinearNop;
+ nd2->u.monadic = nd->u.monadic;
+ break;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void ReverseOpForMonmin(IROLinear *nd) {
+ IROLinear *father;
+
+ if (
+ nd->type == IROLinearOp1Arg &&
+ nd->nodetype == EMONMIN &&
+ (father = IRO_LocateFather(nd)) &&
+ father->type == IROLinearOp2Arg &&
+ father->u.diadic.right == nd
+ )
+ {
+ switch (father->nodetype) {
+ case EADDV:
+ case ESUBV:
+ case EADD:
+ case ESUB:
+ case EADDASS:
+ case ESUBASS:
+ father->nodetype = ComplementaryOp[father->nodetype];
+ nd->type = IROLinearNop;
+ father->u.diadic.right = nd->u.monadic;
+ break;
+ }
+ }
+}
+
+static void DoDiadic(IROLinear *nd) {
+ RemoveUnreffed(nd);
+ DoTransformations(nd);
+ DoTransformations11(nd);
+ DoTransformations12(nd);
+ DoTransformations13(nd);
+ DoTransformations21(nd);
+ DoTransformations22(nd);
+ DoTransformations23(nd);
+ DoTransformations24(nd);
+ DoTransformations25(nd);
+}
+
+void IRO_DoTransformations(void) {
+ IROLinear *nd;
+
+ for (nd = IRO_FirstLinear; nd; nd = nd->next) {
+ switch (nd->type) {
+ case IROLinearOp2Arg:
+ DoDiadic(nd);
+ break;
+ case IROLinearOp1Arg:
+ RemoveUnreffed(nd);
+ RemoveRedundantMonadicOp(nd);
+ ReverseOpForMonmin(nd);
+ break;
+ case IROLinearOperand:
+ RemoveUnreffed(nd);
+ break;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}
+
+static Boolean ReconcileAssignments(IROLinear *nd1, IROLinear *nd2, IROList *list) {
+ IROLinear *copy;
+ Boolean result = 0;
+ int argCount;
+ int i;
+ IROLinear *tmp;
+
+ if (
+ (nd2->type == IROLinearOp1Arg && nd2->nodetype == ETYPCON) &&
+ !(nd1->type == IROLinearOp1Arg && nd1->nodetype == ETYPCON) &&
+ ReconcileAssignments(nd1, nd2->u.monadic, list)
+ )
+ {
+ result = 1;
+ }
+
+ if (
+ (nd1->type == IROLinearOp1Arg && nd1->nodetype == ETYPCON) &&
+ !(nd2->type == IROLinearOp1Arg && nd2->nodetype == ETYPCON) &&
+ ReconcileAssignments(nd1->u.monadic, nd2, list)
+ )
+ {
+ copy = IRO_NewLinear(IROLinearOp1Arg);
+ *copy = *nd2;
+ copy->index = IRO_NumLinear++;
+ copy->type = IROLinearOp1Arg;
+ copy->nodetype = ETYPCON;
+ copy->rtype = nd1->rtype;
+ copy->next = NULL;
+ copy->u.monadic = list->tail;
+ IRO_AddToList(copy, list);
+ result = 1;
+ }
+
+ if (nd1->type == nd2->type && nd1->nodetype == nd2->nodetype) {
+ copy = IRO_NewLinear(IROLinearNop);
+ *copy = *nd2;
+ copy->index = IRO_NumLinear++;
+ copy->rtype = nd1->rtype;
+ copy->next = NULL;
+ switch (nd1->type) {
+ case IROLinearOperand:
+ if (nd1->u.node->type == nd2->u.node->type) {
+ if (!(nd1->u.node->type == EOBJREF && nd1->u.node->data.objref != nd2->u.node->data.objref))
+ result = 1;
+ }
+ break;
+
+ case IROLinearOp1Arg:
+ if (ReconcileAssignments(nd1->u.monadic, nd2->u.monadic, list)) {
+ copy->u.monadic = list->tail;
+ result = 1;
+ }
+ break;
+
+ case IROLinearOp2Arg:
+ tmp = list->tail;
+ if (ReconcileAssignments(nd1->u.diadic.left, nd2->u.diadic.left, list)) {
+ copy->u.diadic.left = list->tail;
+ if (ReconcileAssignments(nd1->u.diadic.right, nd2->u.diadic.right, list)) {
+ copy->u.diadic.right = list->tail;
+ result = 1;
+ }
+ }
+
+ if (!result && !IRO_HasSideEffect(nd1) && !IRO_HasSideEffect(nd2)) {
+ if (nd1->nodetype == EMUL || nd1->nodetype == EADD || nd1->nodetype == EAND || nd1->nodetype == EXOR || nd1->nodetype == EOR) {
+ list->tail = tmp;
+ if (ReconcileAssignments(nd1->u.diadic.left, nd2->u.diadic.right, list)) {
+ copy->u.diadic.right = list->tail;
+ if (ReconcileAssignments(nd1->u.diadic.right, nd2->u.diadic.left, list)) {
+ copy->u.diadic.left = list->tail;
+ result = 1;
+ }
+ }
+ }
+ }
+ break;
+
+ case IROLinearOp3Arg:
+ if (ReconcileAssignments(nd1->u.args3.c, nd2->u.args3.c, list)) {
+ copy->u.args3.c = list->tail;
+ if (ReconcileAssignments(nd1->u.args3.b, nd2->u.args3.b, list)) {
+ copy->u.args3.b = list->tail;
+ if (ReconcileAssignments(nd1->u.args3.a, nd2->u.args3.a, list)) {
+ copy->u.args3.a = list->tail;
+ result = 1;
+ }
+ }
+ }
+ break;
+
+ case IROLinearFunccall:
+ argCount = nd1->u.funccall.argCount;
+ if (argCount == nd2->u.funccall.argCount) {
+ result = 1;
+ copy->u.funccall.args = oalloc(sizeof(IROLinear *) * argCount);
+ for (i = argCount - 1; i >= 0; i--) {
+ if (!ReconcileAssignments(nd1->u.funccall.args[i], nd2->u.funccall.args[i], list)) {
+ result = 0;
+ break;
+ }
+ copy->u.funccall.args[i] = list->tail;
+ }
+
+ if (result) {
+ if (!ReconcileAssignments(nd1->u.funccall.linear8, nd2->u.funccall.linear8, list)) {
+ result = 0;
+ break;
+ }
+ copy->u.funccall.linear8 = list->tail;
+ }
+ }
+ break;
+ }
+
+ if (result)
+ IRO_AddToList(copy, list);
+ }
+
+ return result;
+}
+
+static IROLinear *FrontendTransformSelfAssignmentToAssignment(IROLinear *nd) {
+ Statement *stmt;
+ IROList list;
+ IROLinearIRSave save;
+
+ IRO_SaveLinearIR(&save);
+
+ IRO_InitList(&list);
+ IRO_DuplicateExpr(nd, &list);
+
+ stmt = IRO_Delinearize(NULL, list.head);
+ CError_ASSERT(3550, stmt);
+ CError_ASSERT(3552, stmt->expr);
+ stmt->expr = CIRTrans_TransformOpAss(stmt->expr);
+ CError_ASSERT(3557, stmt->expr);
+
+ if (DoLinearize)
+ IRO_PreLinearize(stmt);
+ IRO_Linearize(stmt);
+
+ IRO_InitList(&list);
+ list.head = IRO_FirstLinear;
+ list.tail = IRO_LastLinear;
+
+ IRO_RestoreLinearIR(&save);
+
+ for (nd = list.head; nd; nd = nd->next) {
+ if (!(nd->flags & IROLF_Reffed) && IRO_IsAssignment(nd))
+ break;
+ }
+
+ return nd;
+}
+
+static Type *PromotedIntegralType(Type *type) {
+ CError_ASSERT(3586, IS_TYPE_ENUM(type) || IS_TYPE_INT(type));
+
+ if (IS_TYPE_ENUM(type))
+ type = TYPE_ENUM(type)->enumtype;
+
+ if (TYPE_INTEGRAL(type)->integral < IT_INT) {
+ if (IRO_IsUnsignedType(type))
+ return TYPE(&stunsignedint);
+ else
+ return TYPE(&stsignedint);
+ } else {
+ return type;
+ }
+}
+
+static Boolean TransformMonadicSelfAssignmentToDiadicSelfAssignment(IROLinear *nd) {
+ ENodeType t;
+ ENodeType newtype;
+ IROLinear *incExpr;
+ IROLinear *varExpr;
+
+ t = nd->nodetype;
+
+ if (IRO_IsAssignment(nd) && IRO_IsModifyOp[t]) {
+ incExpr = NULL;
+ varExpr = NULL;
+ newtype = MAXEXPR;
+
+ if (
+ nd->type == IROLinearOp1Arg &&
+ (t == EPOSTINC || t == EPOSTDEC || t == EPREINC || t == EPREDEC) &&
+ (!(nd->flags & IROLF_Reffed) || t == EPREINC || t == EPREDEC)
+ )
+ {
+ Type *type = nd->rtype;
+ TypeType typetype = type->type;
+ varExpr = nd->u.monadic;
+ if (typetype == TYPEINT || typetype == TYPEENUM) {
+ incExpr = IRO_NewIntConst(cint64_one, PromotedIntegralType(type));
+ } else if (typetype == TYPEPOINTER || typetype == TYPEARRAY || typetype == TYPEMEMBERPOINTER) {
+ Type *inner = NULL;
+ CInt64 val = cint64_zero;
+
+ if (typetype == TYPEPOINTER || typetype == TYPEARRAY)
+ inner = TPTR_TARGET(type);
+ else if (typetype == TYPEMEMBERPOINTER)
+ inner = TYPE_MEMBER_POINTER(type)->ty1;
+
+ if (inner)
+ CInt64_SetLong(&val, inner->size);
+
+ if (!CInt64_IsZero(&val)) {
+ incExpr = IRO_NewIntConst(val, TYPE(&stsignedlong));
+ } else {
+ return 0;
+ }
+ } else if (typetype == TYPEFLOAT) {
+ Float fval;
+ fval = CMach_CalcFloatConvertFromInt(type, cint64_one);
+ incExpr = IRO_NewFloatConst(fval, nd->rtype);
+ } else {
+ return 0;
+ }
+
+ if (t == EPOSTINC || t == EPREINC)
+ newtype = EADDASS;
+ else
+ newtype = ESUBASS;
+ }
+
+ if (
+ varExpr &&
+ incExpr &&
+ newtype != MAXEXPR &&
+ varExpr->u.diadic.left &&
+ varExpr->u.diadic.left->type == IROLinearOperand &&
+ varExpr->u.diadic.left->u.node &&
+ varExpr->u.diadic.left->u.node->type == EOBJREF &&
+ !IRO_HasSideEffect(varExpr)
+ )
+ {
+ incExpr->flags |= IROLF_Reffed;
+ nd->nodetype = newtype;
+ nd->u.diadic.right = incExpr;
+ nd->type = IROLinearOp2Arg;
+ IRO_Paste(incExpr, incExpr, nd);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+Boolean IRO_TransformSelfAssignmentToAssignment(IROLinear *nd) {
+ ENodeType nonAssOp;
+ IROLinear *left;
+ IROLinear *right;
+ ENodeType nodetype;
+ IROLinear *nonAss;
+ IROLinear *dupLeft;
+ IROLinear *last;
+ IROList list1;
+ IROList list2;
+
+ nodetype = nd->nodetype;
+ if (
+ IRO_IsAssignment(nd) &&
+ IRO_IsModifyOp[nodetype] &&
+ nd->type == IROLinearOp1Arg &&
+ TransformMonadicSelfAssignmentToDiadicSelfAssignment(nd)
+ )
+ nodetype = nd->nodetype;
+
+ if (
+ IRO_IsAssignment(nd) &&
+ IRO_IsModifyOp[nodetype] &&
+ nd->type == IROLinearOp2Arg &&
+ IRO_NonAssignmentOp[nodetype] != MAXEXPR
+ )
+ {
+ left = nd->u.diadic.left;
+ right = nd->u.diadic.right;
+ nonAssOp = IRO_NonAssignmentOp[nodetype];
+ if (
+ left &&
+ right &&
+ nonAssOp != MAXEXPR &&
+ left->u.monadic &&
+ left->u.monadic->type == IROLinearOperand &&
+ left->u.monadic->u.node &&
+ left->u.monadic->u.node->type == EOBJREF &&
+ !IRO_HasSideEffect(left)
+ )
+ {
+ IRO_InitList(&list1);
+ dupLeft = IRO_DuplicateExpr(left, &list1);
+
+ if (left->rtype != right->rtype) {
+ IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg);
+ tmp->nodetype = ETYPCON;
+ tmp->flags |= IROLF_Reffed;
+ tmp->rtype = right->rtype;
+ tmp->index = ++IRO_NumLinear;
+ tmp->u.monadic = dupLeft;
+ IRO_AddToList(tmp, &list1);
+ dupLeft = tmp;
+ }
+
+ nonAss = IRO_NewLinear(IROLinearOp2Arg);
+ nonAss->nodetype = nonAssOp;
+ nonAss->flags |= IROLF_Reffed;
+ nonAss->rtype = dupLeft->rtype;
+ nonAss->index = ++IRO_NumLinear;
+ nonAss->u.diadic.left = dupLeft;
+ nonAss->u.diadic.right = right;
+ IRO_AddToList(nonAss, &list1);
+
+ if (left->rtype != right->rtype) {
+ IROLinear *tmp = IRO_NewLinear(IROLinearOp1Arg);
+ tmp->nodetype = ETYPCON;
+ tmp->flags |= IROLF_Reffed;
+ tmp->rtype = left->rtype;
+ tmp->index = ++IRO_NumLinear;
+ tmp->u.monadic = nonAss;
+ IRO_AddToList(tmp, &list1);
+ nonAss = tmp;
+ }
+
+ IRO_InitList(&list2);
+ last = FrontendTransformSelfAssignmentToAssignment(nd);
+ if (
+ last &&
+ last->type == IROLinearOp2Arg &&
+ ReconcileAssignments(last->u.diadic.right, nonAss, &list2)
+ )
+ {
+ IRO_NopOut(nd->u.diadic.right);
+ nd->nodetype = EASS;
+ nd->u.diadic.right = list2.tail;
+ nd->type = IROLinearOp2Arg;
+ IRO_Paste(list2.head, list2.tail, nd);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void AddAddend(ENode *expr) {
+ if (expr->type == EADD) {
+ AddAddend(expr->data.diadic.left);
+ AddAddend(expr->data.diadic.right);
+ } else {
+ ENodeList *list = oalloc(sizeof(ENodeList));
+ list->node = expr;
+ list->next = NULL;
+
+ if (FirstAddend)
+ LastAddend->next = list;
+ else
+ FirstAddend = list;
+ LastAddend = list;
+ }
+}
+
+static ENode *CombineConstants(ENode *expr) {
+ ENode *addend;
+ ENodeList *el;
+ ENode *result;
+ ENode *var;
+ Type *type;
+ ENode *tmp;
+ ENodeList *prev;
+ CInt64 val;
+
+ FirstAddend = LastAddend = NULL;
+ AddAddend(expr->data.diadic.left);
+ AddAddend(expr->data.diadic.right);
+
+ // these variable names are courtesy of the resource fork in abort_exit.c
+ el = FirstAddend;
+ prev = NULL;
+ var = NULL;
+ while (el) {
+ addend = el->node;
+ if (addend->type == EOBJREF) {
+ var = addend;
+ if (prev)
+ prev->next = el->next;
+ else
+ FirstAddend = el->next;
+ break;
+ }
+ prev = el;
+ el = el->next;
+ }
+
+ if (!var) {
+ el = FirstAddend;
+ prev = NULL;
+ while (el) {
+ addend = el->node;
+ if (addend->type == EINDIRECT) {
+ var = addend;
+ if (prev)
+ prev->next = el->next;
+ else
+ FirstAddend = el->next;
+ break;
+ }
+ prev = el;
+ el = el->next;
+ }
+ }
+
+ prev = NULL;
+ CInt64_SetLong(&val, 0);
+ type = NULL;
+
+ for (el = FirstAddend; el; el = el->next) {
+ addend = el->node;
+ if (addend->type == EINTCONST && addend->rtype) {
+ if (!type || type->size < addend->rtype->size)
+ type = addend->rtype;
+ val = CInt64_Add(val, addend->data.intval);
+ if (prev)
+ prev->next = el->next;
+ else
+ FirstAddend = el->next;
+ } else if (addend->type == EMUL && addend->data.diadic.right->type == EINTCONST && addend->rtype) {
+ if (!type || type->size < addend->rtype->size)
+ type = addend->rtype;
+
+ tmp = addend->data.diadic.left;
+ if (tmp->type == EADD && tmp->data.diadic.right->type == EINTCONST) {
+ val = CInt64_Add(val, CInt64_MulU(tmp->data.diadic.right->data.intval, addend->data.diadic.right->data.intval));
+ addend->data.diadic.left = tmp->data.diadic.left;
+ }
+ prev = el;
+ } else {
+ prev = el;
+ }
+ }
+
+ result = NULL;
+ if (var) {
+ result = var;
+ if (!CInt64_IsZero(&val)) {
+ result = IRO_NewENode(EADD);
+ result->data.diadic.left = var;
+ result->data.diadic.right = IRO_NewENode(EINTCONST);
+ result->data.diadic.right->data.intval = val;
+ result->data.diadic.right->rtype = type;
+ result->rtype = var->rtype;
+ result->cost = 1;
+ CInt64_SetLong(&val, 0);
+ }
+ }
+
+ for (el = FirstAddend; el; el = el->next) {
+ addend = el->node;
+ if (result) {
+ tmp = IRO_NewENode(EADD);
+ tmp->data.diadic.left = result;
+ tmp->data.diadic.right = addend;
+ tmp->cost = result->cost + 1;
+ tmp->rtype = result->rtype;
+ result = tmp;
+ } else {
+ result = addend;
+ }
+ }
+
+ if (!CInt64_IsZero(&val)) {
+ tmp = IRO_NewENode(EADD);
+ tmp->data.diadic.left = result;
+ tmp->data.diadic.right = IRO_NewENode(EINTCONST);
+ tmp->data.diadic.right->data.intval = val;
+ tmp->data.diadic.right->rtype = type;
+ tmp->cost = result->cost + 1;
+ tmp->rtype = result->rtype;
+ result = tmp;
+ }
+
+ return result;
+}
+
+static ENode *TransformExprNode(ENode *expr) {
+ ENode *left;
+ ENode *right;
+
+ switch (expr->type) {
+ case EINDIRECT:
+ if (ENODE_IS(expr->data.monadic, EADD))
+ expr->data.monadic = CombineConstants(expr->data.monadic);
+ break;
+
+ case EMUL:
+ case EADD:
+ case EAND:
+ case EXOR:
+ case EOR:
+ if (
+ IS_TYPE_INT(expr->rtype) &&
+ !ENODE_IS(right = expr->data.diadic.right, EINTCONST) &&
+ ENODE_IS(left = expr->data.diadic.left, EINTCONST)
+ )
+ {
+ expr->data.diadic.left = right;
+ expr->data.diadic.right = left;
+ }
+ break;
+
+ case EEQU:
+ case ENOTEQU:
+ if (
+ IS_TYPE_INT(expr->rtype) &&
+ !ENODE_IS(left = expr->data.diadic.right, EINTCONST) &&
+ ENODE_IS(right = expr->data.diadic.left, EINTCONST)
+ )
+ {
+ expr->data.diadic.left = left;
+ expr->data.diadic.right = right;
+ }
+
+ if (
+ ENODE_IS(expr->data.diadic.right, EINTCONST) &&
+ ENODE_IS(left = expr->data.diadic.left, EBINNOT)
+ )
+ {
+ expr->data.diadic.left = left->data.monadic;
+ left->data.monadic = expr->data.diadic.right;
+ expr->data.diadic.right = left;
+ }
+
+ break;
+ }
+
+ return expr;
+}
+
+static ENode *TransformExprTree(ENode *expr) {
+ ENodeList *list;
+
+ switch (expr->type) {
+ ENODE_CASE_MONADIC:
+ expr->data.monadic = TransformExprTree(expr->data.monadic);
+ break;
+
+ ENODE_CASE_DIADIC_ALL:
+ expr->data.diadic.left = TransformExprTree(expr->data.diadic.left);
+ expr->data.diadic.right = TransformExprTree(expr->data.diadic.right);
+ break;
+
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ TransformExprTree(expr->data.funccall.funcref);
+ for (list = expr->data.funccall.args; list; list = list->next)
+ TransformExprTree(list->node);
+ break;
+
+ case ECOND:
+ TransformExprTree(expr->data.cond.cond);
+ TransformExprTree(expr->data.cond.expr1);
+ TransformExprTree(expr->data.cond.expr2);
+ break;
+
+ case ENULLCHECK:
+ TransformExprTree(expr->data.nullcheck.nullcheckexpr);
+ TransformExprTree(expr->data.nullcheck.condexpr);
+ break;
+ }
+
+ return TransformExprNode(expr);
+}
+
+static void FoldConstantsinAssociativeExprs(ENode *expr) {
+ short nodetype1;
+ short nodetype2;
+ short nodetype3;
+ Boolean changed;
+ short op;
+ CInt64 val1;
+ CInt64 val2;
+ CInt64 tmpval;
+
+ if (
+ (
+ expr->type == EADD ||
+ expr->type == EMUL ||
+ expr->type == EAND ||
+ expr->type == EXOR ||
+ expr->type == EOR ||
+ expr->type == ESHL ||
+ expr->type == ESHR
+ ) &&
+ IS_TYPE_INT(expr->rtype) &&
+ expr->data.diadic.right->type == EINTCONST
+ )
+ {
+ do {
+ changed = 0;
+
+ if (
+ expr->data.diadic.left->type == expr->type &&
+ expr->data.diadic.left->data.diadic.right->type == EINTCONST
+ )
+ {
+ val1 = expr->data.diadic.right->data.intval;
+ val2 = expr->data.diadic.left->data.diadic.right->data.intval;
+ switch (expr->type) {
+ case EADD:
+ case ESHL:
+ op = '+';
+ break;
+ case ESHR:
+ op = '+';
+ if (!IRO_IsUnsignedType(expr->rtype)) {
+ CInt64_SetLong(&tmpval, expr->rtype->size * 8);
+ if (CInt64_GreaterEqualU(val1, tmpval) || CInt64_GreaterEqualU(val2, tmpval))
+ return;
+
+ if (CInt64_GreaterEqualU(CMach_CalcIntDiadic(expr->rtype, val1, '+', val2), tmpval)) {
+ val1 = CInt64_Sub(tmpval, cint64_one);
+ val2 = cint64_zero;
+ }
+ }
+ break;
+ case EMUL:
+ op = '*';
+ break;
+ case EAND:
+ op = '&';
+ break;
+ case EOR:
+ op = '|';
+ break;
+ case EXOR:
+ op = '^';
+ break;
+ default:
+ return;
+ }
+
+ expr->data.diadic.right->data.intval = CMach_CalcIntDiadic(expr->rtype, val1, op, val2);
+ expr->data.diadic.left = expr->data.diadic.left->data.diadic.left;
+ changed = 1;
+ } else if (
+ ((nodetype1 = expr->type) == EAND || nodetype1 == EOR) &&
+ ((nodetype2 = expr->data.diadic.left->type) == EAND || nodetype2 == EOR) &&
+ ((nodetype3 = expr->data.diadic.left->data.diadic.left->type) == EAND || nodetype3 == EOR) &&
+ expr->data.diadic.left->data.diadic.left->data.diadic.right->type == EINTCONST
+ )
+ {
+ val1 = expr->data.diadic.right->data.intval;
+ if (CInt64_Equal(val1, expr->data.diadic.left->data.diadic.left->data.diadic.right->data.intval)) {
+ if (nodetype1 == nodetype3) {
+ expr->data.diadic.left->data.diadic.left = expr->data.diadic.left->data.diadic.left->data.diadic.left;
+ changed = 1;
+ } else if (nodetype2 == nodetype3) {
+ *expr = *expr->data.diadic.right;
+ changed = 1;
+ } else {
+ expr->data.diadic.left = expr->data.diadic.left->data.diadic.right;
+ changed = 1;
+ }
+ }
+ }
+ } while (changed);
+ }
+}
+
+static void TransformExprTree1(ENode *expr) {
+ ENodeList *list;
+
+ switch (expr->type) {
+ ENODE_CASE_MONADIC:
+ TransformExprTree1(expr->data.monadic);
+ break;
+
+ ENODE_CASE_DIADIC_ALL:
+ TransformExprTree1(expr->data.diadic.left);
+ TransformExprTree1(expr->data.diadic.right);
+ break;
+
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ TransformExprTree1(expr->data.funccall.funcref);
+ for (list = expr->data.funccall.args; list; list = list->next)
+ TransformExprTree1(list->node);
+ break;
+
+ case ECOND:
+ TransformExprTree1(expr->data.cond.cond);
+ TransformExprTree1(expr->data.cond.expr1);
+ TransformExprTree1(expr->data.cond.expr2);
+ break;
+
+ case ENULLCHECK:
+ TransformExprTree1(expr->data.nullcheck.nullcheckexpr);
+ TransformExprTree1(expr->data.nullcheck.condexpr);
+ break;
+ }
+
+ FoldConstantsinAssociativeExprs(expr);
+}
+
+static int RemoveRedundantBitOperations(ENode *expr) {
+ Boolean a;
+ Boolean b;
+
+ if (expr->type == ExprType) {
+ a = RemoveRedundantBitOperations(expr->data.diadic.left);
+ b = RemoveRedundantBitOperations(expr->data.diadic.right);
+ return a & b;
+ }
+
+ if (expr->type == EINDIRECT) {
+ if (expr->data.monadic->type == EOBJREF) {
+ if (!OperandObject) {
+ OperandObject = expr->data.monadic->data.objref;
+ IndirectRef = expr;
+ return 1;
+ } else {
+ return expr->data.monadic->data.objref == OperandObject;
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ if (expr->type == EINTCONST) {
+ if (FirstTime) {
+ OperandConst = expr->data.intval;
+ FirstTime = 0;
+ } else if (ExprType == EAND) {
+ OperandConst = CInt64_And(expr->data.intval, OperandConst);
+ } else if (ExprType == EOR) {
+ OperandConst = CInt64_Or(expr->data.intval, OperandConst);
+ } else if (ExprType == EXOR) {
+ OperandConst = CInt64_Xor(expr->data.intval, OperandConst);
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+static void TransformExprTree2(ENode *expr) {
+ ENodeList *list;
+
+ switch (expr->type) {
+ ENODE_CASE_MONADIC:
+ TransformExprTree2(expr->data.monadic);
+ break;
+
+ ENODE_CASE_DIADIC_ALL:
+ TransformExprTree2(expr->data.diadic.left);
+ TransformExprTree2(expr->data.diadic.right);
+ break;
+
+ case EFUNCCALL:
+ case EFUNCCALLP:
+ TransformExprTree2(expr->data.funccall.funcref);
+ for (list = expr->data.funccall.args; list; list = list->next)
+ TransformExprTree2(list->node);
+ break;
+
+ case ECOND:
+ TransformExprTree2(expr->data.cond.cond);
+ TransformExprTree2(expr->data.cond.expr1);
+ TransformExprTree2(expr->data.cond.expr2);
+ break;
+
+ case ENULLCHECK:
+ TransformExprTree2(expr->data.nullcheck.nullcheckexpr);
+ TransformExprTree2(expr->data.nullcheck.condexpr);
+ break;
+ }
+
+ if (
+ ENODE_IS3(expr, EAND, EOR, EXOR) &&
+ (expr->type == expr->data.diadic.left->type || expr->type == expr->data.diadic.right->type)
+ )
+ {
+ OperandObject = NULL;
+ ExprType = expr->type;
+ FirstTime = 1;
+ IndirectRef = NULL;
+
+ if (RemoveRedundantBitOperations(expr)) {
+ expr->data.diadic.left = IndirectRef;
+ expr->data.diadic.right->type = EINTCONST;
+ expr->data.diadic.right->data.intval = OperandConst;
+ }
+ }
+}
+
+static void PullOutPostOps(Statement *stmt, ENode **pExpr) {
+ ENode *ind;
+ ENode *inner;
+ Statement *newStmt;
+
+ switch ((*pExpr)->type) {
+ ENODE_CASE_MONADIC:
+ if ((*pExpr)->type != EFORCELOAD)
+ PullOutPostOps(stmt, &(*pExpr)->data.monadic);
+
+ if (ENODE_IS2(*pExpr, EPOSTINC, EPOSTDEC)) {
+ inner = (*pExpr)->data.monadic;
+ if (
+ ENODE_IS(inner, EINDIRECT) &&
+ inner->rtype &&
+ !CParser_IsVolatile(inner->rtype, ENODE_QUALS(inner)) &&
+ ENODE_IS(inner->data.monadic, EOBJREF) &&
+ !is_volatile_object(inner->data.monadic->data.objref)
+ )
+ {
+ newStmt = lalloc(sizeof(Statement));
+ memset(newStmt, 0, sizeof(Statement));
+ newStmt->type = ST_EXPRESSION;
+ newStmt->expr = *pExpr;
+ newStmt->dobjstack = stmt->dobjstack;
+ newStmt->sourceoffset = stmt->sourceoffset;
+ newStmt->sourcefilepath = stmt->sourcefilepath;
+ newStmt->value = stmt->value;
+ newStmt->flags = stmt->flags;
+ newStmt->next = stmt->next;
+ stmt->next = newStmt;
+
+ ind = IRO_NewENode(EINDIRECT);
+ *ind = *inner;
+ ind->data.monadic = IRO_NewENode(EOBJREF);
+ *ind->data.monadic = *inner->data.monadic;
+ *pExpr = ind;
+ }
+ }
+ break;
+
+ ENODE_CASE_DIADIC_ALL:
+ if (ENODE_IS(*pExpr, ECOND))
+ break;
+ if (ENODE_IS(*pExpr, ECOMMA))
+ break;
+ if (ENODE_IS(*pExpr, ELOR))
+ break;
+ if (ENODE_IS(*pExpr, ELAND))
+ break;
+ if (ENODE_IS(*pExpr, ENULLCHECK))
+ break;
+ PullOutPostOps(stmt, &(*pExpr)->data.diadic.left);
+ PullOutPostOps(stmt, &(*pExpr)->data.diadic.right);
+ break;
+ }
+}
+
+void IRO_TransformTree(Statement *statements) {
+ Statement *stmt;
+ Statement *next;
+
+ for (stmt = statements; stmt; stmt = next) {
+ next = stmt->next;
+ switch (stmt->type) {
+ case ST_EXPRESSION:
+ case ST_SWITCH:
+ case ST_IFGOTO:
+ case ST_IFNGOTO:
+ case ST_RETURN:
+ if (stmt->expr) {
+ stmt->expr = TransformExprTree(stmt->expr);
+ TransformExprTree2(stmt->expr);
+ TransformExprTree1(stmt->expr);
+ }
+ break;
+ }
+ }
+
+ IRO_CheckForUserBreak();
+}