/*
* This file is part of JOP, the Java Optimized Processor
* see <http://www.jopdesign.com/>
*
* Copyright (C) 2008, Wolfgang Puffitsch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jopdesign.dfa.analyses;
import java.io.Serializable;
public class ValueMapping implements Serializable {
private static final long serialVersionUID = 1L;
private static final int WIDEN_LIMIT = 2;
private static final int ASSIGN_LIMIT = 4;
private static final int CONSTRAINT_LIMIT = 64;
public Interval assigned;
public Interval constrained;
public Interval increment;
public Location source;
public int cnt;
public int defscope;
public boolean softinc;
public static int scope = 0;
public static int scopeCnt = 0;
public ValueMapping() {
assigned = new Interval();
constrained = new Interval();
increment = null;
source = null;
cnt = 0;
defscope = scope;
softinc = false;
}
public ValueMapping(int val) {
assigned = new Interval(val, val);
constrained = new Interval(val, val);
increment = null;
source = null;
cnt = 0;
defscope = scope;
softinc = false;
}
public ValueMapping(ValueMapping val, boolean full) {
assigned = new Interval(val.assigned);
constrained = new Interval(val.constrained);
if (full) {
if (val.increment != null) {
increment = new Interval(val.increment);
} else {
increment = null;
}
source = val.source;
cnt = val.cnt;
defscope = val.defscope;
softinc = val.softinc;
} else {
increment = null;
source = null;
cnt = 0;
defscope = scope;
softinc = false;
}
}
public void join(ValueMapping val) {
//System.out.print("join: "+this+", "+val+" = ");
if (val != null) {
final Interval old = new Interval(assigned);
// merge assigned values
if (cnt > ASSIGN_LIMIT) {
assigned = new Interval();
} else {
assigned.join(val.assigned);
}
// merge constraints
if (cnt > CONSTRAINT_LIMIT) {
constrained = new Interval();
} else {
constrained.join(val.constrained);
}
// apply new constraints
assigned.constrain(constrained);
if (cnt > WIDEN_LIMIT) {
// widen if possible
assigned.widen(constrained);
}
// merge increments
if (increment == null) {
increment = val.increment;
softinc = val.softinc;
} else if (val.increment != null) {
increment.join(val.increment);
if (softinc || val.softinc) {
increment.join(new Interval(0, 0));
softinc = true;
}
}
if (!old.equals(assigned)) {
cnt++;
}
defscope = Math.max(defscope, val.defscope);
}
//System.out.println(this);
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ValueMapping)) {
return false;
}
ValueMapping m = (ValueMapping) o;
boolean inceq;
if (increment == null && m.increment == null) {
inceq = true;
} else if (increment == null || m.increment == null) {
inceq = false;
} else {
inceq = increment.equals(m.increment);
}
@SuppressWarnings({"UnnecessaryLocalVariable"})
boolean retval = inceq
&& assigned.equals(m.assigned)
&& constrained.equals(m.constrained)
//&& defscope == m.defscope
&& softinc == m.softinc;
//System.out.println("equ: "+this+" vs "+m+" -> "+retval+ " / "+(this == m));
return retval;
}
public boolean compare(Object o) {
if (this == o) {
return true;
}
ValueMapping m = (ValueMapping) o;
boolean inceq;
if (increment == null) {
inceq = true;
} else if (m.increment == null) {
inceq = false;
} else {
inceq = increment.compare(m.increment);
}
@SuppressWarnings({"UnnecessaryLocalVariable"})
boolean retval = inceq
&& assigned.compare(m.assigned)
&& constrained.compare(m.constrained)
//&& defscope == m.defscope
&& softinc == m.softinc;
//System.out.println("cmp: "+this+" vs "+m+" -> "+retval+ " / "+(this == m));
return retval;
}
public int hashCode() {
return 1 + assigned.hashCode() + 31 * constrained.hashCode() + 31 * 31 * increment.hashCode();
}
public String toString() {
return "<" + assigned + ", " + constrained + ", =" + source + ", #" + cnt + ", +" + increment + ", $" + defscope + ", !" + softinc + ">";
}
public static int computeBound(ValueMapping first, ValueMapping second) {
// basic checks
if (//first == null ||
first.increment == null
// || second == null
|| second.increment == null) {
// System.out.println("no valid increment");
return -1;
}
// check for boundedness
if (!first.assigned.hasLb()
|| !first.assigned.hasUb()
|| !second.assigned.hasLb()
|| !second.assigned.hasUb()) {
// System.out.println("unbounded");
return -1;
}
// monotone increments?
if (first.increment.getLb() * first.increment.getUb() <= 0
|| second.increment.getLb() * second.increment.getUb() <= 0) {
// System.out.println("invalid increments");
return -1;
}
int firstRange = first.assigned.getUb() - first.assigned.getLb() + 1;
int secondRange = second.assigned.getUb() - second.assigned.getLb() + 1;
int firstBound;
if (first.assigned.getUb() < first.assigned.getLb()) {
firstBound = 0; //return -1;
} else {
firstBound = (int) Math.ceil((double) firstRange / Math.min(Math.abs(first.increment.getUb()), Math.abs(first.increment.getLb())));
}
int secondBound;
if (second.assigned.getUb() < second.assigned.getLb()) {
secondBound = 0; //return -1;
} else {
secondBound = (int) Math.ceil((double) secondRange / Math.min(Math.abs(second.increment.getUb()), Math.abs(second.increment.getLb())));
}
return Math.max(firstBound, secondBound);
}
}