package synthesijer.scheduler.opt; import synthesijer.IdentifierGenerator; import synthesijer.scheduler.ConstantOperand; import synthesijer.scheduler.Op; import synthesijer.scheduler.Operand; import synthesijer.scheduler.SchedulerBoard; import synthesijer.scheduler.SchedulerInfo; import synthesijer.scheduler.SchedulerItem; import synthesijer.scheduler.SchedulerSlot; import synthesijer.scheduler.VariableOperand; public class OperationStrengthReduction implements SchedulerInfoOptimizer{ private final IdentifierGenerator idGen = new IdentifierGenerator(); public SchedulerInfo opt(SchedulerInfo info){ SchedulerInfo result = info.getSameInfo(); for(SchedulerBoard b: info.getBoardsList()){ result.addBoard(conv(b)); } return result; } public String getKey(){ return "strength_reduction"; } public SchedulerBoard conv(SchedulerBoard src){ SchedulerBoard ret = src.genSameEnvBoard(); for(SchedulerSlot slot: src.getSlots()){ SchedulerSlot newSlot = new SchedulerSlot(slot.getStepId()); for(SchedulerItem item: slot.getItems()){ newSlot.addItem(conv(item)); } ret.addSlot(newSlot); } return ret; } private double log2(double x){ return Math.log(x) / Math.log(2); } private boolean isPowerOfTwo(long x){ return ((int)log2(x)) == log2(x); } private SchedulerItem convMulToShift(SchedulerItem item){ Operand[] src = item.getSrcOperand(); if(src[0] instanceof VariableOperand && src[1] instanceof VariableOperand){ return item; } if(src[0] instanceof ConstantOperand && src[1] instanceof ConstantOperand){ return item; } ConstantOperand k = (src[0] instanceof ConstantOperand) ? (ConstantOperand)src[0] : (ConstantOperand)src[1]; VariableOperand v = (src[0] instanceof VariableOperand) ? (VariableOperand)src[0] : (VariableOperand)src[1]; long value = Long.parseLong(k.getValue()); if(value < 0 || isPowerOfTwo(value) == false){ return item; } int shift = (int)log2(value); item.overwriteOp(Op.SIMPLE_LSHIFT32); item.overwriteSrc(0, v); item.overwriteSrc(1, new ConstantOperand(String.format("reduction_constant_%05d", idGen.id()), String.valueOf(shift), k.getType())); return item; } private SchedulerItem convDivToShift(SchedulerItem item){ Operand[] src = item.getSrcOperand(); if((src[0] instanceof VariableOperand && src[1] instanceof ConstantOperand) == false){ return item; } ConstantOperand k = (ConstantOperand)src[1]; long value = Long.parseLong(k.getValue()); if(value < 0 || isPowerOfTwo(value) == false){ return item; } int shift = (int)log2(value); item.overwriteOp(Op.SIMPLE_ARITH_RSHIFT32); item.overwriteSrc(1, new ConstantOperand(String.format("reduction_constant_%05d", idGen.id()), String.valueOf(shift), k.getType())); return item; } public SchedulerItem conv(SchedulerItem item){ if(item.getOp() == Op.MUL32 || item.getOp() == Op.MUL64){ return convMulToShift(item); }else if(item.getOp() == Op.DIV32 || item.getOp() == Op.DIV64){ return convDivToShift(item); }else{ return item; } } }