blob: 714361d4580e139f274cdaee25c5a2bc865454f3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, Pavel A. Ozhdikhin
*
*/
#include <assert.h>
#include <iostream>
#include <algorithm>
#include "Stl.h"
#include "Log.h"
#include "open/types.h"
#include "Inst.h"
#include "irmanager.h"
#include "reassociate.h"
#include "CSEHash.h"
#include "Opcode.h"
#include "constantfolder.h"
#include "simplifier.h"
#include "FlowGraph.h"
namespace Jitrino {
DEFINE_SESSION_ACTION(ReassociationPass, reassoc, "Reassociation")
void
ReassociationPass::_run(IRManager& irm) {
Reassociate pass(irm, irm.getNestedMemoryManager());
pass.runPass(false);
}
DEFINE_SESSION_ACTION(DepthReassociationPass, reassocdepth, "Reassociation with Minimum Depth")
void
DepthReassociationPass::_run(IRManager& irm) {
Reassociate pass(irm, irm.getNestedMemoryManager());
pass.runPass(true);
}
DEFINE_SESSION_ACTION(LateDepthReassociationPass, latereassocdepth, "Reassociation with Minimum Depth + Constant Mul/Div Optimization")
void
LateDepthReassociationPass::_run(IRManager& irm) {
Reassociate pass(irm, irm.getNestedMemoryManager());
pass.runPass(true, true);
}
inline U_32 computePriority(U_32 op_cost, U_32 priority0) {
if (priority0 == 0) return 0;
else return op_cost + priority0;
}
inline U_32 computePriority(U_32 op_cost, U_32 priority0, U_32 priority1) {
if (priority0 == 0) return 0;
else return op_cost + ::std::max(priority0, priority1);
}
inline U_32 computePriority(U_32 op_cost, U_32 priority0, U_32 priority1, U_32 priority2) {
if ((priority0 == 0) && (priority1 == 0) && (priority2 == 0)) return 0;
else return op_cost + ::std::max(::std::max(priority0, priority1), priority2);
}
inline bool operator < (const OpndWithPriority &a, const OpndWithPriority &b)
{
if (a.priority < b.priority) return true;
if (a.priority == b.priority) {
if (b.negate && !a.negate) return true;
}
return false;
}
Reassociate::Reassociate(IRManager &irManager0,
MemoryManager& memManager)
: irManager(irManager0),
mm(memManager),
cfgRpoNum(memManager),
priority(memManager),
minDepth(false),
maxReassocDepth(64)
{
}
Reassociate::~Reassociate()
{
}
U_32 Reassociate::getPriority(Opnd *opnd)
{
if (priority.has(opnd)) return priority[opnd];
Inst *inst = opnd->getInst();
U_32 opriority = 0;
Operation operation = inst->getOperation();
Opcode opc = operation.getOpcode();
switch (opc) {
case Op_LdConstant:
opriority = 0; break;
case Op_Copy:
opriority = getPriority(inst->getSrc(0)); break;
case Op_LdVar:
{
Opnd *var = inst->getSrc(0);
SsaVarOpnd *ssaVarOpnd = var->asSsaVarOpnd();
assert(ssaVarOpnd);
opriority = getPriority(ssaVarOpnd);
}
break;
case Op_Add:
opriority = computePriority(costOfAdd, getPriority(inst->getSrc(0)),
getPriority(inst->getSrc(1)));
break;
case Op_Sub:
opriority = computePriority(costOfSub, getPriority(inst->getSrc(0)),
getPriority(inst->getSrc(1)));
break;
case Op_Neg:
opriority = computePriority(costOfNeg, getPriority(inst->getSrc(0)));
break;
case Op_Mul:
opriority = computePriority(costOfMul, getPriority(inst->getSrc(0)),
getPriority(inst->getSrc(1)));
break;
case Op_Conv:
opriority = computePriority(costOfConv, getPriority(inst->getSrc(0)));
break;
case Op_And:
case Op_Or:
case Op_Xor:
opriority = computePriority(costOfBoolOp, getPriority(inst->getSrc(0)),
getPriority(inst->getSrc(1)));
break;
case Op_Not:
opriority = computePriority(costOfNot, getPriority(inst->getSrc(0)));
break;
case Op_Shladd:
opriority = computePriority(costOfShladd,getPriority(inst->getSrc(0)),
getPriority(inst->getSrc(1)),
getPriority(inst->getSrc(2)));
break;
case Op_Shr:
case Op_Shl:
opriority = computePriority(costOfShift, getPriority(inst->getSrc(0)),
getPriority(inst->getSrc(1)));
break;
default:
if (operation.isMovable()) {
U_32 numOpnds = inst->getNumSrcOperands();
opriority = 0;
for (U_32 i = 0; i<numOpnds; i++) {
Opnd *opndi = inst->getSrc(i);
U_32 argpriority = getPriority(opndi);
opriority = ::std::max(opriority, argpriority);
}
opriority = computePriority(costOfMisc, opriority);
} else {
Inst *previ = inst->getPrevInst();
U_32 ipriority = 1;
while (!previ->isLabel()) {
++ipriority;
previ = previ->getPrevInst();
}
Node *block = previ->asLabelInst()->getNode();
U_32 bpriority = cfgRpoNum[block];
opriority = ((bpriority * priorityFactorOfBlock)
+ ipriority)*priorityFactorOfPosition;
}
break;
}
if (Log::isEnabled()) {
Log::out() << "Priority of ";
opnd->print(Log::out());
Log::out() << " computed is " << (int) opriority << ::std::endl;
}
priority[opnd] = opriority;
return opriority;
}
void Reassociate::runPass(bool minimizeDepth, bool isLate)
{
minDepth = minimizeDepth;
if (minimizeDepth) {
costOfAdd = 1;
costOfSub = 1;
costOfNeg = 1;
costOfMul = 15;
costOfConv = 1;
costOfBoolOp = 1;
costOfNot = 1;
costOfShladd = 1;
costOfShift = 1;
costOfMisc = 1;
priorityFactorOfBlock = 64;
priorityFactorOfPosition = 2;
} else {
costOfAdd = 0;
costOfSub = 0;
costOfNeg = 0;
costOfMul = 0;
costOfConv = 0;
costOfBoolOp = 0;
costOfNot = 0;
costOfShladd = 0;
costOfShift = 0;
costOfMisc = 0;
priorityFactorOfBlock = 64;
priorityFactorOfPosition = 1;
}
if (Log::isEnabled()) {
Log::out() << "IR before Reassociation pass" << ::std::endl;
FlowGraph::printHIR(Log::out(), irManager.getFlowGraph(), irManager.getMethodDesc());
FlowGraph::printDotFile(irManager.getFlowGraph(), irManager.getMethodDesc(), "beforereassoc");
}
// first, assign Reverse-PostOrder numbers to flowGraph nodes
StlVector<Node *> postOrderNodes(mm);
ControlFlowGraph &fg = irManager.getFlowGraph();
fg.getNodesPostOrder(postOrderNodes);
StlVector<Node *>::reverse_iterator
riter = postOrderNodes.rbegin(),
rend = postOrderNodes.rend();
U_32 i = 0;
while (riter != rend) {
Node *node = *riter;
if (Log::isEnabled()) {
Log::out() << "RPO[";
FlowGraph::printLabel(Log::out(), node);
Log::out() << "] = " << (int) i;
Log::out() << ::std::endl;
}
cfgRpoNum[node] = i++;
++riter;
}
numBlocks = i;
SimplifierWithInstFactory simplifier(irManager, isLate, this);
theSimp = &simplifier;
simplifier.simplifyControlFlowGraph();
if (Log::isEnabled()) {
Log::out() << "IR after Reassociation pass" << ::std::endl;
FlowGraph::printHIR(Log::out(), irManager.getFlowGraph(), irManager.getMethodDesc());
FlowGraph::printDotFile(irManager.getFlowGraph(), irManager.getMethodDesc(), "afterreassoc");
}
}
void
Reassociate::addAddAssoc(StlDeque<OpndWithPriority> &opnds,
bool negated,
Type* type, Opnd* opnd)
{
Inst *inst = opnd->getInst();
if (inst->getType() == type->tag && opnds.size() < maxReassocDepth) {
switch(inst->getOpcode()) {
case Op_Add:
if (inst->getOverflowModifier() != Overflow_None) break;
if (Log::isEnabled()) {
Log::out() << "addAddAssoc of operand ";
opnd->print(Log::out());
Log::out() << " is Add(";
inst->getSrc(0)->print(Log::out());
Log::out() << ", ";
inst->getSrc(1)->print(Log::out());
Log::out() << "), checking opnds" << ::std::endl;
}
addAddAssoc(opnds, negated, type, inst->getSrc(0));
addAddAssoc(opnds, negated, type, inst->getSrc(1));
return;
case Op_Neg:
if (Log::isEnabled()) {
Log::out() << "addAddAssoc of operand ";
opnd->print(Log::out());
Log::out() << " is Neg(";
inst->getSrc(0)->print(Log::out());
Log::out() << "), checking opnd" << ::std::endl;
}
addAddAssoc(opnds, !negated, type, inst->getSrc(0));
return;
case Op_Sub:
if (inst->getOverflowModifier() != Overflow_None) break;
if (Log::isEnabled()) {
Log::out() << "addAddAssoc of operand ";
opnd->print(Log::out());
Log::out() << " is Sub(";
inst->getSrc(0)->print(Log::out());
Log::out() << ", ";
inst->getSrc(1)->print(Log::out());
Log::out() << "), checking opnds" << ::std::endl;
}
addAddAssoc(opnds, negated, type, inst->getSrc(0));
addAddAssoc(opnds, !negated, type, inst->getSrc(1));
return;
case Op_Copy:
if (Log::isEnabled()) {
Log::out() << "addAddAssoc of operand ";
opnd->print(Log::out());
Log::out() << " is Copy(";
inst->getSrc(0)->print(Log::out());
Log::out() << "), checking opnd" << ::std::endl;
}
addAddAssoc(opnds, negated, type, inst->getSrc(0));
return;
default:
break;
}
}
if (Log::isEnabled()) {
Log::out() << "addAddAssoc of operand ";
opnd->print(Log::out());
Log::out() << " is terminal, adding" << ::std::endl;
}
opnds.push_back(OpndWithPriority(opnd, getPriority(opnd), negated));
}
void
Reassociate::addMulAssoc(StlDeque<OpndWithPriority> &opnds,
bool negated,
Type* type, Opnd* opnd)
{
Inst *inst = opnd->getInst();
if (inst->getType() == type->tag && opnds.size() < maxReassocDepth) {
switch(inst->getOpcode()) {
case Op_Mul:
if (inst->getOverflowModifier() != Overflow_None) break;
addMulAssoc(opnds, negated, type, inst->getSrc(0));
addMulAssoc(opnds, negated, type, inst->getSrc(1));
return;
case Op_Copy:
addAddAssoc(opnds, negated, type, inst->getSrc(0));
return;
default:
break;
}
}
opnds.push_back(OpndWithPriority(opnd, getPriority(opnd), negated));
}
void
Reassociate::addAddOffsetAssoc(StlDeque<OpndWithPriority> &opnds,
bool compressed,
Type* type, Opnd* opnd)
{
Inst *inst = opnd->getInst();
if (inst->getType() == type->tag && opnds.size() < maxReassocDepth) {
switch(inst->getOpcode()) {
case Op_AddOffset:
addAddOffsetAssoc(opnds, compressed, type, inst->getSrc(0));
addAddOffsetAssoc(opnds, compressed, type, inst->getSrc(1));
return;
case Op_AddOffsetPlusHeapbase:
addAddOffsetAssoc(opnds, compressed, type, inst->getSrc(0));
addAddOffsetAssoc(opnds, compressed, type, inst->getSrc(1));
return;
case Op_UncompressRef:
case Op_CompressRef:
case Op_Copy:
case Op_LdFieldOffset:
case Op_LdFieldOffsetPlusHeapbase:
case Op_LdArrayBaseOffsetPlusHeapbase:
case Op_LdArrayLenOffset:
case Op_LdArrayLenOffsetPlusHeapbase:
case Op_AddScaledIndex:
case Op_TauArrayLen:
default:
break;
}
}
opnds.push_back(OpndWithPriority(opnd, getPriority(opnd), compressed));
}
// maybe this stuff should be in simplifier.
Opnd*
Reassociate::simplifyReassociatedAdd(Type *type,
StlDeque<OpndWithPriority> &opnds)
{
typedef StlDeque<OpndWithPriority> VectType;
::std::sort(opnds.begin(), opnds.end());
if (Log::isEnabled()) {
VectType::iterator
iter = opnds.begin(),
end = opnds.end();
Log::out() << "BEGIN simplifyReassociatedAdd: ";
for ( ; iter != end ; iter++) {
OpndWithPriority &owd = *iter;
Log::out() << (owd.negate ? "-" : "+") << "(";
owd.opnd->print(Log::out());
Log::out() << ", " << (int)owd.priority << ") ";
}
Log::out() << ::std::endl;
}
// algorithm:
// first, if all opnds are negated, wantToNegate=true
// while (opnds.size > 1)
// if (opnds[0].negate != opnds[1].negate) {
// if (opnds[0].negate)
// newop = Op_Sub(opnds[1], opnds[0]);
// else
// newop = Op_Sub(opnds[0], opnds[1]);
// else
// if (wantToNegate && (computePriority(costofNeg, opnds[0].priority) < opnds[1].priority)
// newop = Op_Sub(Op_Neg(opnds[0]), opnds[1])
// wantToNegate = false
// else
// newop = Op_Add(opnds[0], opnds[1]);
VectType::size_type size = opnds.size();
if (size < 2) { return 0; }
bool wantToNegate = true;
VectType::iterator
iter = opnds.begin(),
end = opnds.end();
for ( ; iter != end; ++iter) {
if (!(*iter).negate) wantToNegate=false;
}
if ((!wantToNegate) && (size < 3)) { return 0; }
while (size > 1) {
OpndWithPriority owd0 = opnds[0];
OpndWithPriority owd1 = opnds[1];
opnds.pop_front();
opnds.pop_front();
size -= 2;
Opnd *opnd0 = owd0.opnd;
Opnd *opnd1 = owd1.opnd;
Opnd *newOpnd = 0;
bool newNegated = 0;
U_32 priority0 = owd0.priority;
U_32 priority1 = owd1.priority;
const char *debug_op = "";
bool debug_swapped = false;
U_32 newPriority = 0;
if (owd0.negate != owd1.negate) {
if (owd0.negate) {
newOpnd = theSimp->genSub(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
opnd1, opnd0)->getDst();
newPriority = computePriority(costOfSub, priority1, priority0);
newNegated = false;
debug_swapped = true;
} else {
newOpnd = theSimp->genSub(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
opnd0, opnd1)->getDst();
newPriority = computePriority(costOfSub, priority0, priority1);
newNegated = false;
}
debug_op = "sub";
} else {
if (wantToNegate && (computePriority(costOfNeg, priority0) < priority1)) {
// we can effort to negate here, negate deeper argument
Opnd *negated = theSimp->genNeg(type, opnd0)->getDst();
newOpnd = theSimp->genSub(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
negated, opnd1)->getDst();
newNegated = false;
wantToNegate = false;
newPriority = computePriority(costOfSub, computePriority(costOfNeg, priority0), priority1);
debug_op = "negsub";
} else {
newNegated = owd0.negate;
newOpnd = theSimp->genAdd(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
opnd0, opnd1)->getDst();
newPriority = computePriority(costOfAdd, priority0, priority1);
debug_op = "add";
}
}
OpndWithPriority newelt(newOpnd, newPriority, newNegated);
opnds.push_front(newelt);
size += 1;
if (Log::isEnabled()) {
Log::out() << " new " << (newNegated ? "-" : "+") << "(";
newOpnd->print(Log::out());
Log::out() << ", " << (int) newPriority << ") = " << debug_op << "(";
if (debug_swapped) {
opnd1->print(Log::out());
} else {
opnd0->print(Log::out());
}
Log::out() << ", ";
if (debug_swapped) {
opnd0->print(Log::out());
} else {
opnd1->print(Log::out());
}
Log::out() << ")" << ::std::endl;
}
}
assert(size == 1);
Opnd *res = opnds[0].opnd;
if (wantToNegate) {
assert(opnds[0].negate);
// need to neg result
Opnd *newres = theSimp->genNeg(type, res)->getDst();
if (Log::isEnabled()) {
Log::out() << " negated: ";
newres->print(Log::out());
Log::out() << " = neg(";
res->print(Log::out());
Log::out() << ")" << ::std::endl;
}
res = newres;
} else {
assert(!opnds[0].negate);
}
if (Log::isEnabled()) {
Log::out() << "FINISHED simplifyReassociatedAdd: ";
res->print(Log::out());
Log::out() << ::std::endl;
}
return res;
}
Opnd*
Reassociate::simplifyReassociatedMul(Type *type,
StlDeque<OpndWithPriority> &opnds)
{
typedef StlDeque<OpndWithPriority> VectType;
if (Log::isEnabled()) {
VectType::iterator
iter = opnds.begin(),
end = opnds.end();
Log::out() << "BEGIN simplifyReassociatedMul: ";
for ( ; iter != end ; iter++) {
OpndWithPriority &owd = *iter;
Log::out() << "(";
owd.opnd->print(Log::out());
Log::out() << ", " << (int)owd.priority << ") ";
}
Log::out() << ::std::endl;
}
::std::sort(opnds.begin(), opnds.end());
// general algorithm: for priority reduction, we just repeatedly reduce
// 2 highest-priority operands
VectType::size_type opndsize = opnds.size();
while (opndsize > 1) {
OpndWithPriority owd0 = opnds[0];
OpndWithPriority owd1 = opnds[1];
Opnd *opnd0 = owd0.opnd;
U_32 priority0 = owd0.priority;
bool neg0 = owd0.negate;
Opnd *opnd1 = owd1.opnd;
U_32 priority1 = owd1.priority;
bool neg1 = owd1.negate;
if ((opnd0 == opnd1) && (opndsize > 3)
&& (opnds[2].opnd == opnds[3].opnd)) {
// we have (a * a * b * b)
// convert to (a*b)*(a*b)
OpndWithPriority owd2 = opnds[2];
OpndWithPriority owd3 = opnds[3];
Opnd *opnd2 = owd2.opnd;
U_32 priority2 = owd2.priority;
Opnd *newOpnd0 = theSimp->genMul(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
opnd0, opnd2)->getDst();
Opnd *newOpnd1 = theSimp->genMul(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
newOpnd0, newOpnd0)->getDst();
opnds.pop_front();
opnds.pop_front();
opnds.pop_front();
U_32 priorityNew0 = computePriority(costOfMul, priority0,
priority2);
U_32 priorityNew1 = computePriority(costOfMul,
priorityNew0,
priorityNew0);
OpndWithPriority newelt(newOpnd1, priorityNew1,
false // negs negate each other
);
if (Log::isEnabled()) {
Log::out() << " new (";
newOpnd1->print(Log::out());
Log::out() << ", " << (int) priorityNew1 << ") = sqr(mul(";
opnd0->print(Log::out());
Log::out() << ", " << (int) priority0 << "), (";
opnd2->print(Log::out());
Log::out() << ", " << (int) priority2 << "))" << ::std::endl;
}
opnds[0] = newelt;
opndsize -= 3;
U_32 i = 1;
while (i < opndsize) {
if (opnds[i].priority < priorityNew1) {
opnds[i-1] = opnds[i];
opnds[i] = newelt;
} else {
break;
}
}
} else {
Opnd *newOpnd = theSimp->genMul(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
opnd0, opnd1)->getDst();
opnds.pop_front();
U_32 priority = computePriority(costOfMul, priority0, priority1);
OpndWithPriority newelt(newOpnd, priority, neg0 ^ neg1);
if (Log::isEnabled()) {
Log::out() << " new (";
newOpnd->print(Log::out());
Log::out() << ", " << (int) priority << ") = mul((";
opnd0->print(Log::out());
Log::out() << ", " << (int) priority0 << "), (";
opnd1->print(Log::out());
Log::out() << ", " << (int) priority1 << "))" << ::std::endl;
}
opnds[0] = newelt;
opndsize -= 1;
U_32 i = 1;
while (i < opndsize) {
if (opnds[i].priority < priority) {
opnds[i-1] = opnds[i];
opnds[i] = newelt;
} else {
break;
}
}
}
}
if (Log::isEnabled()) {
VectType::iterator
iter = opnds.begin(),
end = opnds.end();
Log::out() << "FINISHED simplifyReassociatedMul: ";
opnds[0].opnd->print(Log::out());
Log::out() << ::std::endl;
}
return opnds[0].opnd;
}
Opnd*
Reassociate::simplifyReassociatedAddOffset(Type *type,
StlDeque<OpndWithPriority> &opnds)
{
typedef StlDeque<OpndWithPriority> VectType;
::std::sort(opnds.begin(), opnds.end());
if (Log::isEnabled()) {
VectType::iterator
iter = opnds.begin(),
end = opnds.end();
Log::out() << "BEGIN simplifyReassociatedAddOffset: ";
for ( ; iter != end ; iter++) {
OpndWithPriority &owd = *iter;
Log::out() << (owd.negate ? "-" : "+") << "(";
owd.opnd->print(Log::out());
Log::out() << ", " << (int)owd.priority << ") ";
}
Log::out() << ::std::endl;
}
assert(0);
// algorithm:
// first, if all opnds are negated, wantToNegate=true
// while (opnds.size > 1)
// if (opnds[0].negate != opnds[1].negate) {
// if (opnds[0].negate)
// newop = Op_Sub(opnds[1], opnds[0]);
// else
// newop = Op_Sub(opnds[0], opnds[1]);
// else
// if (wantToNegate && (computePriority(costofNeg, opnds[0].priority) < opnds[1].priority)
// newop = Op_Sub(Op_Neg(opnds[0]), opnds[1])
// wantToNegate = false
// else
// newop = Op_Add(opnds[0], opnds[1]);
VectType::size_type size = opnds.size();
if (size < 2) { return 0; } // don't rewrite, no point
bool wantToNegate = true;
VectType::iterator
iter = opnds.begin(),
end = opnds.end();
for ( ; iter != end; ++iter) {
if (!(*iter).negate) wantToNegate=false;
}
if ((!wantToNegate) && (size < 3)) { return 0; } // don't bother
while (size > 1) {
OpndWithPriority owd0 = opnds[0];
OpndWithPriority owd1 = opnds[1];
opnds.pop_front();
opnds.pop_front();
size -= 2;
Opnd *opnd0 = owd0.opnd;
Opnd *opnd1 = owd1.opnd;
Opnd *newOpnd = 0;
bool newNegated = 0;
U_32 priority0 = owd0.priority;
U_32 priority1 = owd1.priority;
const char *debug_op = "";
bool debug_swapped = false;
U_32 newPriority = 0;
if (owd0.negate != owd1.negate) {
if (owd0.negate) {
newOpnd = theSimp->genSub(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
opnd1, opnd0)->getDst();
newPriority = computePriority(costOfSub, priority1, priority0);
newNegated = false;
debug_swapped = true;
} else {
newOpnd = theSimp->genSub(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
opnd0, opnd1)->getDst();
newPriority = computePriority(costOfSub, priority0, priority1);
newNegated = false;
}
debug_op = "sub";
} else {
if (wantToNegate && (computePriority(costOfNeg, priority0) < priority1)) {
// we can effort to negate here, negate deeper arguments
Opnd *negated = theSimp->genNeg(type, opnd0)->getDst();
newOpnd = theSimp->genSub(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
negated, opnd1)->getDst();
newNegated = false;
wantToNegate = false;
newPriority = computePriority(costOfSub, computePriority(costOfNeg, priority0), priority1);
debug_op = "negsub";
} else {
newNegated = owd0.negate;
newOpnd = theSimp->genAdd(type, Modifier(Overflow_None)|Modifier(Exception_Never)|Modifier(Strict_No),
opnd0, opnd1)->getDst();
newPriority = computePriority(costOfAdd, priority0, priority1);
debug_op = "add";
}
}
OpndWithPriority newelt(newOpnd, newPriority, newNegated);
opnds.push_front(newelt);
size += 1;
if (Log::isEnabled()) {
Log::out() << " new " << (newNegated ? "-" : "+") << "(";
newOpnd->print(Log::out());
Log::out() << ", " << (int) newPriority << ") = " << debug_op << "(";
if (debug_swapped) {
opnd1->print(Log::out());
} else {
opnd0->print(Log::out());
}
Log::out() << ", ";
if (debug_swapped) {
opnd0->print(Log::out());
} else {
opnd1->print(Log::out());
}
Log::out() << ")" << ::std::endl;
}
}
assert(size == 1);
Opnd *res = opnds[0].opnd;
if (wantToNegate) {
assert(opnds[0].negate);
// need to neg result
Opnd *newres = theSimp->genNeg(type, res)->getDst();
if (Log::isEnabled()) {
Log::out() << " negated: ";
newres->print(Log::out());
Log::out() << " = neg(";
res->print(Log::out());
Log::out() << ")" << ::std::endl;
}
res = newres;
} else {
assert(!opnds[0].negate);
}
if (Log::isEnabled()) {
Log::out() << "FINISHED simplifyReassociatedAdd: ";
res->print(Log::out());
Log::out() << ::std::endl;
}
return res;
}
// checks for and performs possible re-associations of add
// makes no assumptions about types
Opnd*
Simplifier::simplifyAddViaReassociation2(Type* type, Opnd* src1, Opnd* src2) {
assert(theReassociate);
StlDeque<OpndWithPriority> opnds(theReassociate->mm);
if (Log::isEnabled()) {
Log::out() << "simplifyAddViaReassociation2 Add(";
src1->print(Log::out());
Log::out() << ", ";
src2->print(Log::out());
Log::out() << "): " << ::std::endl;
}
theReassociate->addAddAssoc(opnds, false, type, src1);
theReassociate->addAddAssoc(opnds, false, type, src2);
return theReassociate->simplifyReassociatedAdd(type, opnds);
}
// checks for and performs possible re-associations of neg
// makes no assumptions about types
Opnd*
Simplifier::simplifyNegViaReassociation2(Type* type, Opnd* src1) {
assert(theReassociate);
StlDeque<OpndWithPriority> opnds(theReassociate->mm);
if (Log::isEnabled()) {
Log::out() << "simplifyNegViaReassociation2 Neg(";
src1->print(Log::out());
Log::out() << "): " << ::std::endl;
}
theReassociate->addAddAssoc(opnds, true, type, src1);
return theReassociate->simplifyReassociatedAdd(type, opnds);
}
// checks for and performs possible re-associations of neg
// makes no assumptions about types
Opnd*
Simplifier::simplifySubViaReassociation2(Type* type, Opnd* src1, Opnd *src2) {
assert(theReassociate);
StlDeque<OpndWithPriority> opnds(theReassociate->mm);
if (Log::isEnabled()) {
Log::out() << "simplifySubViaReassociation2 Sub(";
src1->print(Log::out());
Log::out() << ", ";
src2->print(Log::out());
Log::out() << "): " << ::std::endl;
}
theReassociate->addAddAssoc(opnds, false, type, src1);
theReassociate->addAddAssoc(opnds, true, type, src2);
return theReassociate->simplifyReassociatedAdd(type, opnds);
}
// checks for and performs possible re-associations of add
// makes no assumptions about types
Opnd*
Simplifier::simplifyMulViaReassociation2(Type* type, Opnd* src1, Opnd* src2) {
assert(theReassociate);
StlDeque<OpndWithPriority> opnds(theReassociate->mm);
if (Log::isEnabled()) {
Log::out() << "simplifyMulViaReassociation2 Mul(";
src1->print(Log::out());
Log::out() << ", ";
src2->print(Log::out());
Log::out() << "): " << ::std::endl;
}
theReassociate->addMulAssoc(opnds, false, type, src1);
theReassociate->addMulAssoc(opnds, false, type, src2);
return theReassociate->simplifyReassociatedMul(type, opnds);
}
// checks for and performs possible re-associations of addOffset
Opnd*
Simplifier::simplifyAddOffsetViaReassociation(Opnd* uncompBase,
Opnd* offset) {
assert(theReassociate);
StlDeque<OpndWithPriority> opnds(theReassociate->mm);
if (Log::isEnabled()) {
Log::out() << "simplifyAddOffsetViaReassociation AddOffset(";
uncompBase->print(Log::out());
Log::out() << ", ";
offset->print(Log::out());
Log::out() << "): " << ::std::endl;
}
theReassociate->addAddOffsetAssoc(opnds, false, uncompBase->getType(), uncompBase);
theReassociate->addAddOffsetAssoc(opnds, false, uncompBase->getType(), offset);
return theReassociate->simplifyReassociatedAddOffset(uncompBase->getType(), opnds);
}
// checks for and performs possible re-associations of addOffsetPlusHeapbase
Opnd*
Simplifier::simplifyAddOffsetPlusHeapbaseViaReassociation(Opnd* compBase,
Opnd* offsetPlusHeapbase) {
assert(theReassociate);
StlDeque<OpndWithPriority> opnds(theReassociate->mm);
if (Log::isEnabled()) {
Log::out() << "simplifyAddViaReassociation2 Add(";
compBase->print(Log::out());
Log::out() << ", ";
offsetPlusHeapbase->print(Log::out());
Log::out() << "): " << ::std::endl;
}
Type *type = irManager.getTypeManager().uncompressType(compBase->getType());
theReassociate->addAddOffsetAssoc(opnds, false, type, compBase);
theReassociate->addAddOffsetAssoc(opnds, false, type, offsetPlusHeapbase);
return theReassociate->simplifyReassociatedAddOffset(type, opnds);
}
} //namespace Jitrino