#include "compiler/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 "compiler/IroDump.h" #include "compiler/IroLinearForm.h" #include "compiler/IroMalloc.h" #include "compiler/IroPointerAnalysis.h" #include "compiler/IROUseDef.h" #include "compiler/IroUtil.h" #include "compiler/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(); }