mirror of https://git.wuffs.org/MWCC
2795 lines
100 KiB
C
2795 lines
100 KiB
C
#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)->unkB;
|
|
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();
|
|
}
|