1 module d.semantic.vrp;
2 
3 import d.ir.expression;
4 import d.ir.symbol;
5 import d.ir.type;
6 
7 import d.semantic.semantic;
8 
9 import std.traits;
10 
11 // Conflict with Interface in object.di
12 alias Interface = d.ir.symbol.Interface;
13 
14 /**
15  * ValueRangePropagator to figure out if it is safe to truncate
16  * a value to make it fit in a smaller type.
17  *
18  * It does so by computing the range of possible values the
19  * expression can take and checking if that range fit in a given type.
20  *
21  * It is only specialized for uint and ulong, as smaller integral type
22  * are promoted before any computation to 32bits values and above.
23  * As a result, smaller types do not really matter as long as we promote
24  * them properly. As a result, ranges computed from improperly promoted
25  * expression may be extremely pessimistics.
26  */
27 struct ValueRangePropagator(T) if (is(T == uint) || is(T == ulong)) {
28 	private SemanticPass pass;
29 	alias pass this;
30 	
31 	alias VR = ValueRange!T;
32 	
33 	this(SemanticPass pass) {
34 		this.pass = pass;
35 	}
36 	
37 	bool canFit(Expression e, Type t) in {
38 		assert(isValidExpr(e), "VRP expect integral types.");
39 	} do {
40 		return canFit(e, getBuiltin(t));
41 	}
42 	
43 	bool canFit(Expression e, BuiltinType t) in {
44 		assert(isValidExpr(e), "VRP expect integral types.");
45 		assert(canConvertToIntegral(t), "VRP only supports integral types.");
46 	} do {
47 		static canFitDMDMonkeyDance(R)(R r, BuiltinType t) {
48 			auto mask = cast(R.U) ((1UL << t.getBits()) - 1);
49 			
50 			// Try to fit into the unsigned range.
51 			auto urange = r.unsigned.normalized;
52 			if (urange.max <= mask) {
53 				return true;
54 			}
55 			
56 			// Try to fit into the signed range.
57 			auto smask = mask >> 1;
58 			auto nmask = ~smask;
59 			
60 			auto srange = r.signed.normalized;
61 			if (srange.min >= nmask && srange.max <= smask) {
62 				return true;
63 			}
64 			
65 			// Ho noes, it doesn't fit /o\
66 			return false;
67 		}
68 		
69 		return processExpr!canFitDMDMonkeyDance(e, t);
70 	}
71 	
72 private:
73 	static asHandlerDMDMonkeyDance(R)(R r) {
74 		return r.as!T;
75 	}
76 	
77 	auto processExpr(alias handler = asHandlerDMDMonkeyDance, A...)(Expression e, A args) {
78 		import std.algorithm;
79 		auto s = max(getBuiltin(e.type).getSize(), uint.sizeof);
80 		if (s == T.sizeof) {
81 			return handler(visit(e), args);
82 		}
83 		
84 		switch (s) {
85 			case uint.sizeof :
86 				return handler(ValueRangePropagator!uint(pass).visit(e), args);
87 			
88 			case ulong.sizeof :
89 				return handler(ValueRangePropagator!ulong(pass).visit(e), args);
90 			
91 			default:
92 				assert(0, "Size not supported by VRP");
93 		}
94 	}
95 	
96 	BuiltinType getBuiltin(Type t) out(result) {
97 		assert(canConvertToIntegral(result), "VRP only supports integral types.");
98 	} do {
99 		t = t.getCanonicalAndPeelEnum();
100 		if (t.hasPointerABI()) {
101 			return getBuiltin(pass.object.getSizeT().type);
102 		}
103 		
104 		assert(t.kind == TypeKind.Builtin, "Invalid type for VRP");
105 		return t.builtin;
106 	}
107 	
108 	VR getRange(Type t) {
109 		return getRange(getBuiltin(t));
110 	}
111 	
112 	VR getRange(BuiltinType t) in {
113 		assert(t.getSize() <= T.sizeof);
114 	} do {
115 		if (t == BuiltinType.Bool) {
116 			return VR(0, 1);
117 		}
118 		
119 		if (isChar(t)) {
120 			t = integralOfChar(t);
121 		}
122 		
123 		return ValueRange!ulong(getMin(t), getMax(t)).as!T;
124 	}
125 	
126 public:
127 	VR visit(Expression e) in {
128 		assert(isValidExpr(e), "VRP expect integral types.");
129 	} do {
130 		return this.dispatch!(e => getRange(e.type))(e);
131 	}
132 	
133 	VR visit(BooleanLiteral e) {
134 		return VR(e.value);
135 	}
136 	
137 	VR visit(IntegerLiteral e) {
138 		return ValueRange!ulong(e.value).as!T;
139 	}
140 	
141 	VR visit(BinaryExpression e) {
142 		switch (e.op) with(BinaryOp) {
143 			case Comma, Assign :
144 				return visit(e.rhs);
145 			
146 			case Add :
147 				return visit(e.lhs) + visit(e.rhs);
148 			
149 			case Sub :
150 				return visit(e.lhs) - visit(e.rhs);
151 			
152 			case Mul :
153 				return visit(e.lhs) * visit(e.rhs);
154 			
155 			case UDiv :
156 				return visit(e.lhs) / visit(e.rhs);
157 			
158 			case SDiv :
159 				return (visit(e.lhs).signed / visit(e.rhs).signed).unsigned;
160 			
161 			case URem :
162 				return visit(e.lhs) % visit(e.rhs);
163 			
164 			case SRem :
165 				return (visit(e.lhs).signed % visit(e.rhs).signed).unsigned;
166 			
167 			case Or :
168 				return visit(e.lhs) | visit(e.rhs);
169 			
170 			case And :
171 				return visit(e.lhs) & visit(e.rhs);
172 			
173 			case Xor :
174 				return visit(e.lhs) ^ visit(e.rhs);
175 			
176 			case LeftShift :
177 				return visit(e.lhs) << visit(e.rhs);
178 			
179 			case UnsignedRightShift :
180 				return visit(e.lhs) >>> visit(e.rhs);
181 			
182 			case SignedRightShift :
183 				return (visit(e.lhs).signed >> visit(e.rhs).signed).unsigned;
184 			
185 			default :
186 				assert(0, "Not implemented.");
187 		}
188 	}
189 	
190 	VR visit(UnaryExpression e) {
191 		switch (e.op) with(UnaryOp) {
192 			case Plus :
193 				return visit(e.expr);
194 			
195 			case Minus :
196 				return -visit(e.expr);
197 			
198 			default :
199 				assert(0, "Not implemented.");
200 		}
201 	}
202 	
203 	VR visit(VariableExpression e) {
204 		auto v = e.var;
205 		scheduler.require(v, Step.Processed);
206 		return visit(v);
207 	}
208 	
209 	VR visit(Variable v) in {
210 		assert(v.step >= Step.Processed);
211 	} do {
212 		return (v.storage == Storage.Enum || v.type.getCanonical().qualifier == TypeQualifier.Immutable)
213 			? visit(v.value)
214 			: getRange(v.type);
215 	}
216 	
217 	VR visit(CastExpression e) {
218 		final switch (e.kind) with(CastKind) {
219 			case Invalid :
220 				assert(0, "Invalid cast");
221 			
222 			case IntToPtr, Down :
223 				assert(0, "Do not make any sense on integrals");
224 			
225 			case PtrToInt :
226 				assert(0, "Not implemented");
227 				// return ValueRange.get(e.type.builtin);
228 			
229 			case IntToBool :
230 				static doTheDMDMonkeyDance(R)(R r) {
231 					if (r == typeof(r)(0)) {
232 						return VR(0);
233 					}
234 					
235 					if (!r.containsZero) {
236 						return VR(1);
237 					}
238 					
239 					return VR(0, 1);
240 				}
241 				
242 				return processExpr!doTheDMDMonkeyDance(e.expr);
243 			
244 			case Trunc :
245 				static doTheDMDMonkeyDance(R)(R r, BuiltinType t) {
246 					auto signed = isIntegral(t) && isSigned(t);
247 					auto mask = cast(R.U) ((1UL << t.getBits()) - 1);
248 					
249 					return signed
250 						? r.signed.trunc(mask).as!T
251 						: r.trunc(mask).as!T;
252 				}
253 				
254 				return processExpr!doTheDMDMonkeyDance(e.expr, getBuiltin(e.type));
255 			
256 			case UPad :
257 				auto t = getBuiltin(e.expr.type);
258 				auto r = processExpr(e.expr);
259 				
260 				auto mask = cast(T) ((1UL << t.getBits()) - 1);
261 				return r.pad(mask);
262 			
263 			case SPad :
264 				auto t = getBuiltin(e.expr.type);
265 				auto r = processExpr(e.expr);
266 				
267 				auto mask = cast(T) ((1UL << t.getBits()) - 1);
268 				return r.signed.pad(mask).unsigned;
269 			
270 			case Bit, Qual, Exact :
271 				return visit(e.expr);
272 		}
273 	}
274 }
275 
276 unittest {
277 	import std.meta;
278 	foreach (T; AliasSeq!(uint, ulong)) {
279 		auto vrp = ValueRangePropagator!T();
280 		
281 		alias VR = ValueRange!T;
282 		VR v;
283 		
284 		enum LS = T.sizeof == long.sizeof;
285 		
286 		/**
287 		 * Test internal facilities
288 		 */
289 		assert(vrp.getRange(BuiltinType.Bool) == VR(0, 1));
290 		
291 		assert(vrp.getRange(BuiltinType.Byte) == VR(byte.min, byte.max));
292 		assert(vrp.getRange(BuiltinType.Ubyte) == VR(ubyte.min, ubyte.max));
293 		assert(vrp.getRange(BuiltinType.Short) == VR(short.min, short.max));
294 		assert(vrp.getRange(BuiltinType.Ushort) == VR(ushort.min, ushort.max));
295 		assert(vrp.getRange(BuiltinType.Int) == VR(int.min, int.max));
296 		assert(vrp.getRange(BuiltinType.Uint) == VR(uint.min, uint.max));
297 		
298 		static if (LS) {
299 			assert(vrp.getRange(BuiltinType.Long) == VR(long.min, long.max));
300 			assert(vrp.getRange(BuiltinType.Ulong) == VR(ulong.min, ulong.max));
301 		}
302 		
303 		assert(vrp.getRange(BuiltinType.Char) == VR(ubyte.min, ubyte.max));
304 		assert(vrp.getRange(BuiltinType.Wchar) == VR(ushort.min, ushort.max));
305 		assert(vrp.getRange(BuiltinType.Dchar) == VR(uint.min, uint.max));
306 		
307 		/**
308 		 * Literals
309 		 */
310 		import source.location;
311 		v = vrp.visit(new BooleanLiteral(Location.init, false));
312 		assert(v == VR(0));
313 		
314 		v = vrp.visit(new BooleanLiteral(Location.init, true));
315 		assert(v == VR(1));
316 		
317 		v = vrp.visit(new IntegerLiteral(Location.init, -9, BuiltinType.Byte));
318 		assert(v == VR(-9));
319 		
320 		v = vrp.visit(new IntegerLiteral(Location.init, 42, BuiltinType.Uint));
321 		assert(v == VR(42));
322 		
323 		// Let's define some values we can reuse.
324 		auto zero = new IntegerLiteral(Location.init, 0, BuiltinType.Int);
325 		auto i1 = new IntegerLiteral(Location.init, -7, BuiltinType.Int);
326 		auto i2 = new IntegerLiteral(Location.init, 42, BuiltinType.Int);
327 		auto i3 = new IntegerLiteral(Location.init, 2, BuiltinType.Uint);
328 		
329 		auto bmax = new IntegerLiteral(Location.init, 255, BuiltinType.Byte);
330 		
331 		auto tbool = Type.get(BuiltinType.Bool);
332 		auto tint = Type.get(BuiltinType.Int);
333 		auto tuint = Type.get(BuiltinType.Uint);
334 		auto tubyte = Type.get(BuiltinType.Ubyte);
335 		auto tlong = Type.get(BuiltinType.Long);
336 		
337 		/**
338 		 * Binary ops
339 		 */
340 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.Comma, i1, i2));
341 		assert(v == VR(42));
342 		
343 		// Technically, this is illegal, but it is out of scope of VRP to detect this, so will do.
344 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.Assign, i1, i2));
345 		assert(v == VR(42));
346 		
347 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.Add, i1, i2));
348 		assert(v == VR(35));
349 		
350 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.Sub, i1, i2));
351 		assert(v == VR(-49));
352 		
353 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.Mul, i1, i2));
354 		assert(v == VR(-294));
355 		
356 		v = vrp.visit(new BinaryExpression(Location.init, tuint, BinaryOp.UDiv, i1, i2));
357 		assert(v == VR((T.max - 6) / 42));
358 		
359 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.SDiv, i2, i1));
360 		assert(v == VR(-6));
361 		
362 		v = vrp.visit(new BinaryExpression(Location.init, tuint, BinaryOp.URem, i1, i2));
363 		assert(v == VR(LS ? 9 : 39));
364 		
365 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.SRem, i1, i3));
366 		assert(v == VR(-1));
367 		
368 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.Or, i1, i2));
369 		assert(v == VR(-5));
370 		
371 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.And, i1, i2));
372 		assert(v == VR(40));
373 		
374 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.Xor, i1, i2));
375 		assert(v == VR(-45));
376 		
377 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.LeftShift, i1, i3));
378 		assert(v == VR(-28));
379 		
380 		v = vrp.visit(new BinaryExpression(Location.init, tuint, BinaryOp.UnsignedRightShift, i1, i3));
381 		assert(v == VR((T.max >> 2) - 1));
382 		
383 		v = vrp.visit(new BinaryExpression(Location.init, tint, BinaryOp.SignedRightShift, i1, i3));
384 		assert(v == VR(-2));
385 		
386 		/**
387 		 * Unary ops
388 		 */
389 		v = vrp.visit(new UnaryExpression(Location.init, tuint, UnaryOp.Plus, i1));
390 		assert(v == VR(-7));
391 		
392 		v = vrp.visit(new UnaryExpression(Location.init, tuint, UnaryOp.Minus, i1));
393 		assert(v == VR(7));
394 		
395 		/**
396 		 * Variables
397 		 */
398 		import source.name;
399 		auto var = new Variable(
400 			Location.init,
401 			tuint.getParamType(ParamKind.Regular),
402 			BuiltinName!"",
403 			i1,
404 		);
405 		var.step = Step.Processed;
406 		
407 		v = vrp.visit(var);
408 		assert(v == VR(uint.min, uint.max));
409 		
410 		var.type = tbool;
411 		v = vrp.visit(var);
412 		assert(v == VR(0, 1));
413 		
414 		var.type = Type.get(BuiltinType.Short);
415 		v = vrp.visit(var);
416 		assert(v == VR(short.min, short.max));
417 		
418 		var.storage = Storage.Enum;
419 		v = vrp.visit(var);
420 		assert(v == VR(-7));
421 		
422 		var.storage = Storage.Static;
423 		v = vrp.visit(var);
424 		assert(v == VR(short.min, short.max));
425 		
426 		var.type = var.type.qualify(TypeQualifier.Immutable);
427 		v = vrp.visit(var);
428 		assert(v == VR(-7));
429 		
430 		/**
431 		 * Casts
432 		 */
433 		v = vrp.visit(new CastExpression(Location.init, CastKind.IntToBool, tbool, zero));
434 		assert(v == VR(0));
435 		
436 		v = vrp.visit(new CastExpression(Location.init, CastKind.IntToBool, tbool, i1));
437 		assert(v == VR(1));
438 		
439 		// FIXME: test the 0, 1 int to bool case ?
440 		
441 		v = vrp.visit(new CastExpression(Location.init, CastKind.Trunc, tubyte, i1));
442 		assert(v == VR(249));
443 		
444 		v = vrp.visit(new CastExpression(Location.init, CastKind.UPad, tint, bmax));
445 		assert(v == VR(255));
446 		
447 		v = vrp.visit(new CastExpression(Location.init, CastKind.SPad, tint, bmax));
448 		assert(v == VR(-1));
449 		
450 		v = vrp.visit(new CastExpression(Location.init, CastKind.Bit, tint, i1));
451 		assert(v == VR(-7));
452 		
453 		v = vrp.visit(new CastExpression(Location.init, CastKind.Qual, tint, i1));
454 		assert(v == VR(-7));
455 		
456 		v = vrp.visit(new CastExpression(Location.init, CastKind.Exact, tint, i1));
457 		assert(v == VR(-7));
458 	}
459 }
460 
461 private:
462 
463 auto isValidExpr(Expression e) {
464 	auto t = e.type.getCanonicalAndPeelEnum();
465 	return t.kind == TypeKind.Builtin && canConvertToIntegral(t.builtin);
466 }
467 
468 bool isMask(T)(T mask) if (isIntegral!T) {
469 	auto p = mask + 1;
470 	return (p & -p) == p;
471 }
472 
473 unittest {
474 	assert(isMask(0));
475 	assert(isMask(1));
476 	assert(!isMask(2));
477 	assert(isMask(3));
478 	assert(!isMask(10));
479 	assert(isMask(255));
480 }
481 
482 struct ValueRange(T) if(is(uint : T) && isIntegral!T) {
483 	T min = T.min;
484 	T max = T.max;
485 	
486 	this(T min, T max) {
487 		this.min = min;
488 		this.max = max;
489 	}
490 	
491 	this(T val) {
492 		this(val, val);
493 	}
494 	
495 	alias U = Unsigned!T;
496 	alias S = Signed!T;
497 	
498 	alias URange = ValueRange!U;
499 	alias SRange = ValueRange!S;
500 	
501 	enum Bits = T.sizeof * 8;
502 	
503 	@property
504 	U range() const {
505 		return max - min;
506 	}
507 	
508 	@property
509 	bool full() const {
510 		return range == typeof(range).max;
511 	}
512 	
513 	@property
514 	auto unsigned() const {
515 		return URange(min, max);
516 	}
517 	
518 	@property
519 	auto signed() const {
520 		return SRange(min, max);
521 	}
522 	
523 	@property
524 	auto normalized() const out(result) {
525 		assert(result.range >= range);
526 		assert(result.min <= result.max);
527 	} do {
528 		// This is lossy, only use when stritcly necessary.
529 		if (min > max) {
530 			return ValueRange();
531 		}
532 		
533 		return this;
534 	}
535 	
536 	@property
537 	bool containsZero() const {
538 		return unsigned.normalized.min == 0;
539 	}
540 	
541 	@property
542 	bool isReduced() const {
543 		// A reduced range if of the form XXXX0000 => XXXX1111.
544 		auto x = (min ^ max) + 1;
545 		return (x & -x) == x;
546 	}
547 	
548 	auto unionWith(ValueRange other) const {
549 		auto twraparound = this.max < this.min;
550 		auto owraparound = other.max < other.min;
551 		
552 		if (twraparound == owraparound) {
553 			import std.algorithm : min, max;
554 			auto rmin = min(this.min, other.min);
555 			auto rmax = max(this.max, other.max);
556 			
557 			auto r = ValueRange(rmin, rmax);
558 			
559 			if (twraparound) {
560 				// Checks if we don't do more than a full range
561 				if (rmin <= rmax) {
562 					return ValueRange();
563 				}
564 			} else {
565 				// Maybe a wraparound range would be tighter.
566 				auto wmin = max(this.min, other.min);
567 				auto wmax = min(this.max, other.max);
568 				
569 				auto w = ValueRange(wmin, wmax);
570 				
571 				// If so, wraparound !
572 				if (wmin > wmax && (w.range < r.range)) {
573 					return w;
574 				}
575 			}
576 			
577 			return r;
578 		}
579 		
580 		ValueRange wr = this;
581 		if (owraparound) {
582 			import std.algorithm : swap;
583 			swap(wr, other);
584 		}
585 		
586 		// Try to merge up and down, and chose the tighter.
587 		import std.algorithm : min, max;
588 		auto d = ValueRange(wr.min, max(wr.max, other.max));
589 		if (d.min <= d.max) {
590 			d = ValueRange();
591 		}
592 		
593 		auto u = ValueRange(min(wr.min, other.min), wr.max);
594 		if (u.min <= u.max) {
595 			u = ValueRange();
596 		}
597 		
598 		return u.range < d.range ? u : d;
599 	}
600 	
601 	@property
602 	ValueRange!A as(A)() const if (is(uint : A) && isIntegral!A) out(result) {
603 		assert(result.range <= Unsigned!A.max);
604 	} do {
605 		static if (T.sizeof <= A.sizeof) {
606 			// Type are the same size, it is a noop.
607 			return ValueRange!A(min, max);
608 		} else {
609 			enum MaxRange = Unsigned!A.max;
610 			
611 			// If the current range is larger than the destination: full range.
612 			if (range >= MaxRange) {
613 				return ValueRange!A();
614 			}
615 			
616 			// Now the range fits. It's now a matter
617 			// of wrapping things around the right way.
618 			
619 			// If we have a proper unsigned range, go for it.
620 			auto urange = this.unsigned;
621 			if (urange.min <= urange.max) {
622 				alias UA = Unsigned!A;
623 				auto umin = cast(UA) urange.min;
624 				auto umax = cast(UA) urange.max;
625 				
626 				// No overflow check because the high bits are lost anyway.
627 				return ValueRange!UA(umin, umax).as!A;
628 			}
629 			
630 			// If we have a proper signed range, go for it.
631 			auto srange = this.signed;
632 			if (srange.min <= srange.max) {
633 				alias SA = Unsigned!A;
634 				auto smin = cast(SA) srange.min;
635 				auto smax = cast(SA) srange.max;
636 				
637 				// No overflow check because the high bits are lost anyway.
638 				return ValueRange!SA(smin, smax).as!A;
639 			}
640 			
641 			// OK, we have some sort of screwed up range :)
642 			return ValueRange!A();
643 		}
644 	}
645 	
646 	/**
647 	 * Fit a range into a smaller type with less bits.
648 	 *
649 	 * Try to produce a wrappign around range when possible.
650 	 * This will create ranges needlessly large when normalizing,
651 	 * but it doesn't matter as well formed expression should
652 	 * UPad or SPad before normalizing due to integer promotion.
653 	 */
654 	ValueRange trunc(U mask) const out(result) {
655 		assert(isMask(mask));
656 		assert(result.range <= mask);
657 	} do {
658 		auto smask = mask >> 1;
659 		
660 		// Worse case scenario, we can return this.
661 		auto fail = isSigned!T
662 			? ValueRange(~smask, smask)
663 			: ValueRange(0, mask);
664 		
665 		// We do something similar to as!T, except that we sign extend
666 		// manually in the signed range case.
667 		if (range > mask) {
668 			return fail;
669 		}
670 		
671 		auto urange = this.unsigned;
672 		if (urange.min <= urange.max) {
673 			auto umin = urange.min & mask;
674 			auto umax = urange.max & mask;
675 			
676 			// Maybe umax wrapped around, in which case we wrap around.
677 			if (umax < umin) {
678 				umin = umin | ~mask;
679 			}
680 			
681 			return ValueRange(umin, umax);
682 		}
683 		
684 		auto srange = this.signed;
685 		if (srange.min <= srange.max) {
686 			// Other cases are already handled as unsigned.
687 			assert(srange.min < 0);
688 			assert(srange.max >= 0);
689 			
690 			auto smin = srange.min | ~mask;
691 			auto smax = srange.max & mask;
692 			return ValueRange(smin, smax);
693 		}
694 		
695 		// I don't think this can actually happen unless mask is all ones.
696 		// In which case, why we are truncating is a mystery to begin with.
697 		assert(mask + 1 == 0);
698 		return fail;
699 	}
700 	
701 	/**
702 	 * Because it is a signed operation, paddign is actually the one
703 	 * finishing the truncate work. It works because properly formed
704 	 * expression are promoted before being used, and this promotion
705 	 * translates into a pad operation here.
706 	 */
707 	ValueRange pad()(U mask) const if (isUnsigned!T) out(result) {
708 		assert(result.range <= mask);
709 		assert(isMask(mask));
710 	} do {
711 		auto bits = min ^ max;
712 		return ((min > max) || (bits & ~mask))
713 			? ValueRange(0, mask)
714 			: ValueRange(min & mask, max & mask);
715 	}
716 	
717 	ValueRange pad()(U mask) const if (isSigned!T) out(result) {
718 		assert(result.range <= mask);
719 		assert(isMask(mask));
720 	} do {
721 		auto offset = URange(~(mask >> 1));
722 		return ((unsigned - offset).pad(mask) + offset).signed;
723 	}
724 	
725 	bool opEquals(ValueRange rhs) const {
726 		return (full && rhs.full) || (min == rhs.min && max == rhs.max);
727 	}
728 	
729 	auto opUnary(string op : "-")() const {
730 		return ValueRange(-max, -min);
731 	}
732 	
733 	auto opUnary(string op : "~")() const {
734 		return ValueRange(~max, ~min);
735 	}
736 	
737 	auto opBinary(string op : "+")(ValueRange rhs) const {
738 		ulong lrange = this.range;
739 		ulong rrange = rhs.range;
740 		auto range = lrange + rrange;
741 		
742 		// If the type is small enough, do the easy dance.
743 		auto overflow = Bits < 64
744 			? range > U.max
745 			: range < lrange && range < rrange;
746 		
747 		return overflow
748 			? ValueRange()
749 			: ValueRange(min + rhs.min, max + rhs.max);
750 	}
751 	
752 	auto opBinary(string op : "-")(ValueRange rhs) const {
753 		return this + -rhs;
754 	}
755 	
756 	auto smul()(ValueRange rhs) const if (isUnsigned!T) in {
757 		assert(min > max && max != 0);
758 	} do {
759 		auto v0 = ValueRange(0, max) * rhs;
760 		auto v1 = ValueRange(0, -min) * -rhs;
761 		
762 		if (rhs.min <= rhs.max) {
763 			// If rhs don't wrap around, 0 should one of v0 bound.
764 			assert(v0.min == 0 || v0.max == 0);
765 			auto rmin = v0.min ? v0.min : v1.min;
766 			auto rmax = v0.min ? v1.max : v0.max;
767 			if (rmin > rmax) {
768 				return ValueRange(rmin, rmax);
769 			}
770 		} else {
771 			// If rhs wrap around, v1 and v0 will wrap around or be 0.
772 			import std.algorithm : min, max;
773 			auto rmin = min(v0.min, v1.min);
774 			auto rmax = max(v0.max, v1.max);
775 			if (rmin > rmax) {
776 				return ValueRange(rmin, rmax);
777 			}
778 		}
779 		
780 		// We have an overflow.
781 		return ValueRange();
782 	}
783 	
784 	auto umul()(ValueRange rhs) const if (isUnsigned!T) in {
785 		assert(min <= max);
786 		assert(rhs.min <= rhs.max);
787 	} do {
788 		// So we can swap modify.
789 		ValueRange lhs = this;
790 		
791 		// If the whole range is in the negative, a * b = -(a * b).
792 		auto lneg = lhs.min > S.max;
793 		if (lneg) {
794 			lhs = -lhs;
795 		}
796 		
797 		auto rneg = rhs.min > S.max;
798 		if (rneg) {
799 			rhs = -rhs;
800 		}
801 		
802 		// Zero is a special case as it always produce a
803 		// range containign only itself. By splitting it,
804 		// we can make sure we minimally extend the range
805 		// to include 0 at the end.
806 		bool hasZero;
807 		
808 		if (lhs.min == 0) {
809 			hasZero = true;
810 			lhs.min = 1;
811 		}
812 		
813 		if (rhs.min == 0) {
814 			hasZero = true;
815 			rhs.min = 1;
816 		}
817 		
818 		// Alright, now we are in a canonical form, we can proceed.
819 		static T mulhi(ulong a, ulong b) {
820 			static if (Bits < 64) {
821 				// XXX: VRP can't figure that one out aparently.
822 				return cast(T) ((a * b) >> Bits);
823 			} else {
824 				// (a0 << 32 + a1)(b0 << 32 + b1) = a0b0 << 64 + (a0b1 + a1b0) << 32 + a1b1
825 				auto a0 = a >> 32;
826 				auto a1 = a & uint.max;
827 				
828 				auto b0 = b >> 32;
829 				auto b1 = b & uint.max;
830 				
831 				auto a0b0 = a0 * b0;
832 				auto a0b1 = a0 * b1;
833 				auto a1b0 = a1 * b0;
834 				auto a1b1 = a1 * b1;
835 				
836 				auto carry = (a1b1 >> 32 + ((a0b1 + a1b0) & uint.max)) >> 32;
837 				return a0b0 + (a0b1 >> 32) + (a1b0 >> 32) + carry;
838 			}
839 		}
840 		
841 		// If this overflows, then return a full range.
842 		if (mulhi(lhs.min, rhs.min) != mulhi(lhs.max, rhs.max)) {
843 			return ValueRange();
844 		}
845 		
846 		auto res = ValueRange(lhs.min * rhs.min, lhs.max * rhs.max);
847 		if (lneg != rneg) {
848 			res = -res;
849 		}
850 		
851 		// We try to zero extend the range to be the most restrictive.
852 		if (!hasZero) {
853 			return res;
854 		}
855 		
856 		if (res.min <= -res.max) {
857 			return ValueRange(0, res.max);
858 		} else {
859 			return ValueRange(res.min, 0);
860 		}
861 	}
862 	
863 	auto opBinary(string op : "*")(ValueRange rhs) const if (isSigned!T) {
864 		// Multiplication doesn't care about sign.
865 		return (this.unsigned * rhs.unsigned).signed;
866 	}
867 	
868 	ValueRange opBinary(string op : "*")(ValueRange rhs) const if (isUnsigned!T) {
869 		// Multiplication by 0 is always 0.
870 		auto zero = ValueRange(0);
871 		if (this == zero || rhs == zero) {
872 			// Zero is pain in the ass as it reduce ranges
873 			// to one element, making it hard to figure out
874 			// if an overflow occured.
875 			return zero;
876 		}
877 		
878 		// Try to avoid slicing when not necessary.
879 		if (max == 0) {
880 			// [-a, 0] * rhs = -(rhs * [0 .. a])
881 			return -(rhs * -this);
882 		}
883 		
884 		if (rhs.max == 0) {
885 			return -(this * -rhs);
886 		}
887 		
888 		// If the range is of the kind [min .. T.max][0 .. max]
889 		// we split it in half and union the result.
890 		if (min > max) {
891 			return smul(rhs);
892 		}
893 		
894 		if (rhs.min > rhs.max) {
895 			return rhs.smul(this);
896 		}
897 		
898 		return umul(rhs);
899 	}
900 	
901 	auto opBinary(string op : "/")(ValueRange rhs) const {
902 		rhs = rhs.normalized;
903 		if (rhs == ValueRange(0)) {
904 			// We have a division by 0, bail out.
905 			return ValueRange();
906 		}
907 		
908 		// Remove 0 from rhs.
909 		rhs.min = rhs.min ? rhs.min : 1;
910 		rhs.max = rhs.max ? rhs.max : U.max;
911 		
912 		// Make sure we normalize full ranges.
913 		ValueRange lhs = this.normalized;
914 		if (isUnsigned!T) {
915 			return ValueRange(lhs.min / rhs.max, lhs.max / rhs.min);
916 		} else {
917 			if (rhs.containsZero) {
918 				import std.algorithm : min, max;
919 				return ValueRange(min(lhs.min, -lhs.max), max(lhs.max, -lhs.min));
920 			}
921 			
922 			// Alright, this is a signed division.
923 			bool neg = rhs.max < 0;
924 			if (neg) {
925 				// a / -b = -(a / b)
926 				rhs = -rhs;
927 			}
928 			
929 			auto min = lhs.min / (lhs.min < 0 ? rhs.min : rhs.max);
930 			auto max = lhs.max / (lhs.max < 0 ? rhs.max : rhs.min);
931 			return neg
932 				? ValueRange(-max, -min)
933 				: ValueRange(min, max);
934 		}
935 	}
936 	
937 	auto srem()(ValueRange rhs) const if (isSigned!T) in {
938 		assert(this != ValueRange(0));
939 		assert(rhs is rhs.normalized);
940 	} do {
941 		if (rhs.max < 0) {
942 			// a % -b = a % b
943 			rhs = -rhs;
944 		}
945 		
946 		if (rhs.containsZero) {
947 			import std.algorithm : max;
948 			rhs = ValueRange(1, max(-rhs.min, rhs.max));
949 		}
950 		
951 		auto lhs = this.normalized;
952 		
953 		// lhs is positive
954 		if (lhs.min >= 0) {
955 			return lhs.unsigned.urem(rhs.unsigned).signed;
956 		}
957 		
958 		// lhs is negative
959 		if (lhs.max <= 0) {
960 			lhs = -lhs;
961 			return -lhs.unsigned.urem(rhs.unsigned).signed;
962 		}
963 		
964 		// Ok lhs can be both positive and negative.
965 		// Compute both range and aggregate.
966 		auto pos = URange(0, lhs.max).urem(rhs.unsigned);
967 		auto neg = URange(0, -lhs.min).urem(rhs.unsigned);
968 		
969 		return ValueRange(-neg.max, pos.max);
970 	}
971 	
972 	auto urem()(ValueRange rhs) const if (isUnsigned!T) in {
973 		assert(this != ValueRange(0));
974 		assert(rhs is rhs.normalized);
975 		assert(rhs.min > 0);
976 	} do {
977 		auto lhs = this.normalized;
978 		
979 		// If lhs is within the bound of rhs.
980 		if (lhs.max < rhs.max) {
981 			// If rhs.min <= rhs.max we need to 0 extend.
982 			return ValueRange((lhs.max > rhs.min) ? 0 : lhs.min, lhs.max);
983 		}
984 		
985 		// We count how many time we can remove rhs.max from lhs.
986 		auto lminrmaxloop = lhs.min / rhs.max;
987 		auto lmaxrmaxloop = lhs.max / rhs.max;
988 		
989 		// If these counts aren't the same, we have the full modulo range.
990 		if (lminrmaxloop != lmaxrmaxloop) {
991 			return ValueRange(0, rhs.max - 1);
992 		}
993 		
994 		// Same process for rhs.min.
995 		auto lminrminloop = lhs.min / rhs.min;
996 		auto lmaxrminloop = lhs.max / rhs.min;
997 		
998 		// FIXME: Idealy, we would look for the biggest
999 		// value in rhs that have the correct count.
1000 		if (lminrminloop != lmaxrminloop || lminrminloop != lminrmaxloop) {
1001 			return ValueRange(0, rhs.max - 1);
1002 		}
1003 		
1004 		// At this point, we know that as rhs grow, the result will reduce.
1005 		// and as lhs grow, the result will increase.
1006 		return ValueRange(lhs.min % rhs.max, lhs.max % rhs.min);
1007 	}
1008 	
1009 	auto opBinary(string op : "%")(ValueRange rhs) const {
1010 		rhs = rhs.normalized;
1011 		if (rhs == ValueRange(0)) {
1012 			// We have a division by 0, bail out.
1013 			return this;
1014 		}
1015 		
1016 		static if (isSigned!T) {
1017 			return srem(rhs);
1018 		} else {
1019 			rhs.min = rhs.min ? rhs.min : 1;
1020 			return urem(rhs);
1021 		}
1022 	}
1023 	
1024 	auto sshl()(ValueRange rhs) const if (isUnsigned!T) in {
1025 		assert(rhs is rhs.normalized);
1026 		assert(rhs.max < Bits);
1027 	} do {
1028 		auto v0 = ValueRange(0, max).ushl(rhs);
1029 		auto v1 = -ValueRange(0, -min).ushl(rhs);
1030 		
1031 		if (v0.max >= v1.min) {
1032 			return ValueRange();
1033 		}
1034 		
1035 		return ValueRange(v1.min, v0.max);
1036 	}
1037 	
1038 	auto ushl()(ValueRange rhs) const if (isUnsigned!T) in {
1039 		assert(rhs is rhs.normalized);
1040 		assert(rhs.max < Bits);
1041 		assert(this.min <= Signed!T.max);
1042 	} do {
1043 		auto minhi = rhs.min ? (min >> (Bits - rhs.min)) : 0;
1044 		auto maxhi = rhs.max ? (max >> (Bits - rhs.max)) : 0;
1045 		if (minhi != maxhi) {
1046 			return ValueRange();
1047 		}
1048 		
1049 		return ValueRange(min << rhs.min, max << rhs.max);
1050 	}
1051 	
1052 	auto opBinary(string op : "<<")(ValueRange rhs) const if (isSigned!T) {
1053 		return (this.unsigned << rhs.unsigned).signed;
1054 	}
1055 	
1056 	auto opBinary(string op : "<<")(ValueRange rhs) const if (isUnsigned!T) {
1057 		rhs = rhs.normalized;
1058 		
1059 		// We are in undefined territory, pessimize.
1060 		if (rhs.max >= Bits) {
1061 			// We assume that shifting 0 is alright.
1062 			return this == ValueRange(0)
1063 				? ValueRange(0)
1064 				: ValueRange();
1065 		}
1066 		
1067 		if (min > max) {
1068 			return sshl(rhs);
1069 		}
1070 		
1071 		ValueRange lhs = this;
1072 		
1073 		auto lneg = min > S.max;
1074 		if (lneg) {
1075 			lhs = -lhs;
1076 		}
1077 		
1078 		auto res = lhs.ushl(rhs);
1079 		return lneg ? -res : res;
1080 	}
1081 	
1082 	auto sshr(URange rhs) const in {
1083 		assert(rhs is rhs.normalized);
1084 		assert(rhs.min < Bits);
1085 	} do {
1086 		auto v0 = ValueRange(0, max).ushr(rhs);
1087 		auto v1 = ValueRange(min, U.max).ushr(rhs);
1088 		
1089 		auto res = ValueRange();
1090 		
1091 		U rmax = v0.max;
1092 		U rmin = v1.min;
1093 		if (rmin > rmax) {
1094 			res = ValueRange(rmin, rmax);
1095 		}
1096 		
1097 		if (isUnsigned!T) {
1098 			rmax = U.max >> rhs.min;
1099 			if (res.range > rmax) {
1100 				// If 0 .. umax >> rhs.min is smaller than
1101 				// what we have now, use that instead.
1102 				res = ValueRange(0, rmax);
1103 			}
1104 		}
1105 		
1106 		return res;
1107 	}
1108 	
1109 	auto ushr(URange rhs) const in {
1110 		assert(rhs is rhs.normalized);
1111 		assert(rhs.min < Bits);
1112 	} do {
1113 		T rmin = min >> (min < 0 ? rhs.min : rhs.max);
1114 		if (min >= 0 && rhs.max >= Bits) {
1115 			rmin = 0;
1116 		}
1117 		
1118 		T rmax = max >> (max < 0 ? rhs.max : rhs.min);
1119 		if (max < 0 && rhs.max >= Bits) {
1120 			rmax = Unsigned!T.max;
1121 		}
1122 		
1123 		return ValueRange(rmin, rmax);
1124 	}
1125 	
1126 	auto opBinary(string op : ">>")(ValueRange other) const {
1127 		auto rhs = other.unsigned.normalized;
1128 		
1129 		// We are in undefined territory, pessimize.
1130 		if (rhs.min >= Bits) {
1131 			// We assume that shifting 0 is alright.
1132 			// XXX: This is undefined, so I'm not sure what to do.
1133 			// Probably anything is fine as it is undefined :)
1134 			return ValueRange(0);
1135 		}
1136 		
1137 		auto lhs = this.unsigned;
1138 		return lhs.min > lhs.max ? sshr(rhs) : ushr(rhs);
1139 	}
1140 	
1141 	auto opBinary(string op : ">>>")(ValueRange rhs) const if (isSigned!T) {
1142 		return (this.unsigned >>> rhs.unsigned).signed;
1143 	}
1144 	
1145 	auto opBinary(string op : ">>>")(ValueRange rhs) const if (isUnsigned!T) {
1146 		return this >> rhs;
1147 	}
1148 	
1149 	/**
1150 	 * This whole dance is O(n^2) but n is small, so it doesn't matter.
1151 	 * This split lhs into reduced ranges and combine the results.
1152 	 */
1153 	ValueRange reduceOrdered(alias doOp, bool hasFlipped = false)(
1154 		ValueRange rhs,
1155 	) const if (isUnsigned!T) in {
1156 		assert(min <= max && rhs.min <= rhs.max);
1157 	} do {
1158 		static nextRange(T t) out(result) {
1159 			assert((t & result) == 0);
1160 		} do {
1161 			return (t & -t) - 1;
1162 		}
1163 		
1164 		ValueRange lhs = this;
1165 		
1166 		// Just pick one value we know is in the range.
1167 		auto result = doOp(ValueRange(lhs.min), ValueRange(rhs.min));
1168 		
1169 		while (true) {
1170 			T split;
1171 			ValueRange reduced;
1172 			
1173 			auto lminrange = nextRange(lhs.min);
1174 			auto lmaxrange = nextRange(lhs.max + 1);
1175 			
1176 			auto reduceFromMin = lminrange <= lmaxrange;
1177 			if (reduceFromMin) {
1178 				split = lhs.min | lminrange;
1179 				reduced = ValueRange(lhs.min, split);
1180 			} else {
1181 				split = lhs.max - lmaxrange;
1182 				reduced = ValueRange(split, lhs.max);
1183 			}
1184 			
1185 			static if (hasFlipped) {
1186 				assert(reduced.isReduced && rhs.isReduced);
1187 				result = result.unionWith(doOp(reduced, rhs));
1188 			} else {
1189 				assert(reduced.isReduced);
1190 				result = result.unionWith(rhs.reduceOrdered!(doOp, true)(reduced));
1191 			}
1192 			
1193 			// We just fully reduced this range, return.
1194 			if (reduced == lhs) {
1195 				return result;
1196 			}
1197 			
1198 			lhs = reduceFromMin
1199 				? ValueRange(split + 1, lhs.max)
1200 				: ValueRange(lhs.min, split - 1);
1201 		}
1202 	}
1203 	
1204 	ValueRange reduce(alias doOp, bool hasFlipped = false)(
1205 		ValueRange rhs,
1206 	) const if (isUnsigned!T) {
1207 		if (min <= max) {
1208 			return hasFlipped
1209 				? reduceOrdered!doOp(rhs)
1210 				: rhs.reduce!(doOp, true)(this);
1211 		}
1212 		
1213 		return rhs.reduce!(doOp, true)(ValueRange(0, max))
1214 			.unionWith(rhs.reduce!(doOp, true)(ValueRange(min, T.max)));
1215 	}
1216 	
1217 	auto opBinary(string op : "&")(ValueRange rhs) const if (isSigned!T) {
1218 		return (this.unsigned & rhs.unsigned).signed;
1219 	}
1220 	
1221 	ValueRange opBinary(string op : "&")(ValueRange rhs) const if (isUnsigned!T) {
1222 		static doAnd(ValueRange lhs, ValueRange rhs) {
1223 			return ValueRange(lhs.min & rhs.min, lhs.max & rhs.max);
1224 		}
1225 		
1226 		return reduce!doAnd(rhs);
1227 	}
1228 	
1229 	auto opBinary(string op : "|")(ValueRange rhs) const {
1230 		// Just bitflip, and use the and logic.
1231 		return ~(~this & ~rhs);
1232 	}
1233 	
1234 	auto opBinary(string op : "^")(ValueRange rhs) const if (isSigned!T) {
1235 		return (this.unsigned ^ rhs.unsigned).signed;
1236 	}
1237 	
1238 	auto opBinary(string op : "^")(ValueRange rhs) const if (isUnsigned!T) {
1239 		static doXor(ValueRange lhs, ValueRange rhs) {
1240 			auto mask = (lhs.min ^ lhs.max) | (rhs.min ^ rhs.max);
1241 			auto base = lhs.min ^ rhs.min;
1242 			return ValueRange(base & ~mask, base | mask);
1243 		}
1244 		
1245 		return reduce!doXor(rhs);
1246 	}
1247 }
1248 
1249 unittest {
1250 	template coerceRange(T) {
1251 		auto coerceRange(A...)(A args) {
1252 			alias U = CommonType!(A, T);
1253 			return ValueRange!U(args).as!T;
1254 		}
1255 	}
1256 	
1257 	void testComplement(T)(ValueRange!T a, ValueRange!T b) {
1258 		assert(~a == b, "~a = b");
1259 		assert(a == ~b, "a = ~b");
1260 		
1261 		auto one = ValueRange!T(1);
1262 		assert(-a == b + one, "-a = b + 1");
1263 		assert(a == -b - one, "a = -b - 1");
1264 	}
1265 	
1266 	void testUnion(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1267 		assert(a.unionWith(b) == c, "a U b = c");
1268 		assert(b.unionWith(a) == c, "b U a = c");
1269 		
1270 		assert((-a).unionWith(-b) == -c, "-a U -b = -c");
1271 		assert((-b).unionWith(-a) == -c, "-b U -a = -c");
1272 	}
1273 	
1274 	void testAddSub(T)(
1275 		ValueRange!T a,
1276 		ValueRange!T b,
1277 		ValueRange!T c,
1278 		ValueRange!T d,
1279 	) {
1280 		// Add
1281 		assert(a + b == c, "a + b = c");
1282 		assert(b + a == c, "b + a = c");
1283 		assert(-a - b == -c, "-a - b = -c");
1284 		assert(-(a + b) == -c, "-(a + b) = -c");
1285 		assert(-a + -b == -c, "-a + -b = -c");
1286 		
1287 		// Sub
1288 		assert(a - b == d, "a - b = d");
1289 		assert(b - a == -d, "b - a = -d");
1290 		assert(a + -b == d, "a + -b = d");
1291 		assert(-a - -b == -d, "-a - -b = -d");
1292 	}
1293 	
1294 	void testMul(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1295 		assert(a * b == c, "a * b = c");
1296 		assert(b * a == c, "b * a = c");
1297 		
1298 		bool asym = a == -a;
1299 		bool bsym = b == -b;
1300 		
1301 		assert(-a * b == (asym ? c : -c), "-a * b = -c");
1302 		assert(b * -a == (asym ? c : -c), "b * -a = -c");
1303 		assert(a * -b == (bsym ? c : -c), "a * -b = -c");
1304 		assert(-b * a == (bsym ? c : -c), "-b * a = -c");
1305 		assert(-a * -b == ((asym == bsym) ? c : -c), "-a * -b = c");
1306 		assert(-b * -a == ((asym == bsym) ? c : -c), "-b * -a = c");
1307 	}
1308 	
1309 	void testDiv(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1310 		assert(a / b == c, "a / b = c");
1311 		
1312 		static if (isSigned!T) {
1313 			assert(-a / b == -c, "-a / b = -c");
1314 			assert(a / -b == -c, "a / -b = -c");
1315 			assert(-a / -b == c, "-a / -b = c");
1316 		}
1317 	}
1318 	
1319 	void testRem(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1320 		assert(a % b == c, "a % b = c");
1321 		
1322 		static if (isSigned!T) {
1323 			assert(-a % b == -c, "-a % b = -c");
1324 			assert(a % -b == c, "a % -b = c");
1325 			assert(-a % -b == -c, "-a % -b = -c");
1326 		}
1327 	}
1328 	
1329 	void testLShift(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1330 		assert(a << b == c, "a << b = c");
1331 	}
1332 	
1333 	void testSRShift(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1334 		assert(a >> b == c, "a >> b = c");
1335 	}
1336 	
1337 	void testURShift(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1338 		assert(a >>> b == c, "a >>> b = c");
1339 	}
1340 	
1341 	void testAnd(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1342 		assert((a & b) == c, "a & b = c");
1343 		assert((b & a) == c, "b & a = c");
1344 	}
1345 	
1346 	void testOr(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1347 		assert((a | b) == c, "a | b = c");
1348 		assert((b | a) == c, "b | a = c");
1349 	}
1350 	
1351 	void testXor(T)(ValueRange!T a, ValueRange!T b, ValueRange!T c) {
1352 		assert((a ^ b) == c, "a ^ b = c");
1353 		assert((b ^ a) == c, "b ^ a = c");
1354 	}
1355 	
1356 	import std.meta;
1357 	foreach (T; AliasSeq!(int, uint, long, ulong)) {
1358 		alias VR = coerceRange!T;
1359 		enum LS = T.sizeof == long.sizeof;
1360 		
1361 		// Some useful values
1362 		auto umax = Unsigned!T.max;
1363 		auto umin = Unsigned!T.min;
1364 		auto smax = umax >>> 1;
1365 		auto smin = smax + 1;
1366 		
1367 		/**
1368 		 * Test coercion
1369 		 */
1370 		assert(VR() == ValueRange!T());
1371 		assert(VR(0) == ValueRange!T(0));
1372 		assert(VR(1, 25) == ValueRange!T(1, 25));
1373 		assert(VR(-3, 12) == ValueRange!T(-3, 12));
1374 		assert(VR(-44, -26) == ValueRange!T(-44, -26));
1375 		
1376 		// Check coercion with wrap around
1377 		assert(ValueRange!int(25, 1).as!T == VR(25, 1));
1378 		assert(ValueRange!long(25, 1).as!T == (LS ? VR(25, 1) : VR()));
1379 		assert(ValueRange!int(-25, -37).as!T == VR(-25, -37));
1380 		assert(ValueRange!long(-25, -37).as!T == (LS ? VR(-25, -37) : VR()));
1381 		
1382 		/**
1383 		 * Test normalization
1384 		 */
1385 		assert(VR().normalized == VR());
1386 		assert(VR(15).normalized == VR(15));
1387 		assert(VR(3, 15).normalized == VR(3, 15));
1388 		assert(VR(-38, -15).normalized == VR(-38, -15));
1389 		
1390 		// Wraparound
1391 		assert(VR(-31, 11).normalized == (isSigned!T ? VR(-31, 11) : VR()));
1392 		assert(VR(31, smax + 31).normalized == (isSigned!T ? VR() : VR(31, smax + 31)));
1393 		
1394 		// Degenerate ranges
1395 		assert(VR(138, 15).normalized == VR());
1396 		assert(VR(-38, -153).normalized == VR());
1397 		
1398 		/**
1399 		 * Test truncation
1400 		 */
1401 		assert(VR(0).trunc(0xFF) == VR(0));
1402 		assert(VR(15).trunc(0xFF) == VR(15));
1403 		assert(VR(-8, 15).trunc(0xFF) == VR(-8, 15));
1404 		assert(VR(-80, -8).trunc(0xFF) == VR(176, 248));
1405 		
1406 		// Do not fit
1407 		assert(VR(5, 300).trunc(0xFF) == (isSigned!T ? VR(-0x80, 0x7F) : VR(0, 0xFF)));
1408 		assert(VR().trunc(0xFF) == (isSigned!T ? VR(-0x80, 0x7F) : VR(0, 0xFF)));
1409 		
1410 		// Fit via wraparound
1411 		assert(VR(250, 260).trunc(0xFF) == VR(-6, 4));
1412 		
1413 		/**
1414 		 * Test padding
1415 		 */
1416 		assert(VR(0).pad(0xFF) == VR(0));
1417 		assert(VR(15).pad(0xFF) == VR(15));
1418 		assert(VR(255).pad(0xFF) == (isSigned!T ? VR(-1) : VR(255)));
1419 		assert(VR(176, 248).pad(0xFF) == (isSigned!T ? VR(-80, -8) : VR(176, 248)));
1420 		assert(VR(-80, -8).pad(0xFF) == (isSigned!T ? VR(-80, -8) : VR(176, 248)));
1421 		
1422 		// Immaterializable ranges
1423 		assert(VR(1, 158).pad(0xFF) == (isSigned!T ? VR(-128, 127) : VR(1, 158)));
1424 		assert(VR(-8, 15).pad(0xFF) == (isSigned!T ? VR(-8, 15) : VR(0, 255)));
1425 		assert(VR(5, 300).pad(0xFF) == (isSigned!T ? VR(-0x80, 0x7F) : VR(0, 0xFF)));
1426 		
1427 		/**
1428 		 * Test complement
1429 		 */
1430 		testComplement(VR(0), VR(-1));
1431 		testComplement(VR(1), VR(-2));
1432 		testComplement(VR(42), VR(-43));
1433 		
1434 		// T.min and T.max are a special cases
1435 		testComplement(VR(T.min), VR(T.max));
1436 		
1437 		// Full range
1438 		testComplement(VR(), VR());
1439 		
1440 		// Various ranges
1441 		testComplement(VR(0, 42), VR(-43, -1));
1442 		testComplement(VR(42, 0), VR(-1, -43));
1443 		testComplement(VR(23, 38), VR(-39, -24));
1444 		testComplement(VR(-23, 38), VR(-39, 22));
1445 		
1446 		/**
1447 		 * Test union
1448 		 */
1449 		testUnion(VR(), VR(), VR());
1450 		testUnion(VR(0), VR(0), VR(0));
1451 		testUnion(VR(42), VR(42), VR(42));
1452 		testUnion(VR(1), VR(7), VR(1, 7));
1453 		
1454 		// Positive ranges
1455 		testUnion(VR(1, 7), VR(17, 23), VR(1, 23));  // disjoint
1456 		testUnion(VR(3, 23), VR(17, 27), VR(3, 27)); // overlaping
1457 		testUnion(VR(3, 27), VR(17, 23), VR(3, 27)); // contained
1458 		
1459 		// Negative ranges
1460 		testUnion(VR(-7, -1), VR(-23, -17), VR(-23, -1));  // disjoint
1461 		testUnion(VR(-17, -3), VR(-23, -13), VR(-23, -3)); // overlaping
1462 		testUnion(VR(-27, -3), VR(-23, -17), VR(-27, -3)); // contained
1463 		
1464 		// Signed ranges
1465 		testUnion(VR(-7, 1), VR(3, 12), VR(-7, 12));  // disjoint
1466 		testUnion(VR(-7, 7), VR(3, 12), VR(-7, 12));  // overlaping
1467 		testUnion(VR(-7, 12), VR(3, 5), VR(-7, 12));  // contained
1468 		
1469 		testUnion(VR(-7, -1), VR(3, 12), VR(-7, 12)); // disjoint
1470 		testUnion(VR(-7, 7), VR(-3, 12), VR(-7, 12)); // overlaping
1471 		testUnion(VR(-7, 12), VR(-3, 5), VR(-7, 12)); // contained
1472 		
1473 		// Degenerate ranges
1474 		testUnion(VR(23, 1), VR(3, 12), VR(23, 12));  // disjoint
1475 		testUnion(VR(23, 7), VR(3, 12), VR(23, 12));  // overlaping
1476 		testUnion(VR(23, 12), VR(3, 5), VR(23, 12));  // contained
1477 		
1478 		/**
1479 		 * Test add/sub
1480 		 */
1481 		testAddSub(VR(1), VR(-1), VR(0), VR(2));
1482 		testAddSub(VR(-5, 0), VR(-1, 5), VR(-6, 5), VR(-10, 1));
1483 		testAddSub(VR(5, 6), VR(-3, 5), VR(2, 11), VR(0, 9));
1484 		testAddSub(VR(-12, 85), VR(5, 53), VR(-7, 138), VR(-65, 80));
1485 		
1486 		// Flirting with the limit
1487 		testAddSub(VR(1, smax), VR(smin, -1), VR(smin + 1, smax - 1), VR(2, -1));
1488 		
1489 		// overflow
1490 		testAddSub(VR(0, -42), VR(42, -1), VR(), VR());
1491 		testAddSub(VR(1, long.max + 2), VR(long.min, -1), VR(), VR());
1492 		
1493 		/**
1494 		 * Test mul
1495 		 */
1496 		// Zero time all kind of things is always 0.
1497 		testMul(VR(0), VR(), VR(0));
1498 		testMul(VR(0), VR(0), VR(0));
1499 		testMul(VR(0), VR(2, 3), VR(0));
1500 		testMul(VR(0), VR(-7, 3), VR(0));
1501 		testMul(VR(0), VR(3, -23), VR(0));
1502 		testMul(VR(0), VR(-39, -23), VR(0));
1503 		
1504 		// One time all of things is all kind of things.
1505 		testMul(VR(1), VR(), VR());
1506 		testMul(VR(1), VR(2, 3), VR(2, 3));
1507 		testMul(VR(1), VR(-7, 3), VR(-7, 3));
1508 		testMul(VR(1), VR(3, -23), VR(3, -23));
1509 		testMul(VR(1), VR(-39, -23), VR(-39, -23));
1510 		
1511 		// Full ranges
1512 		testMul(VR(), VR(), VR());
1513 		
1514 		// [0 .. 1] do zero extend.
1515 		testMul(VR(0, 1), VR(2, 3), VR(0, 3));
1516 		testMul(VR(0, 1), VR(-7, 3), VR(-7, 3));
1517 		testMul(VR(0, 1), VR(3, -23), VR(0, -23));
1518 		testMul(VR(0, 1), VR(-39, -23), VR(-39, 0));
1519 		
1520 		// Symetric ranges are tools of the devil.
1521 		testMul(VR(0, 1), VR(3, -3), VR(0, -3));
1522 		testMul(VR(-1, 1), VR(3, 5), VR(-5, 5));
1523 		
1524 		// min < max
1525 		testMul(VR(2, 3), VR(7, 23), VR(14, 69));
1526 		testMul(VR(1), VR(125, -32), VR(125, -32));
1527 		testMul(VR(-7, -4), VR(-5, -3), VR(12, 35));
1528 		testMul(VR(3, 3037000500), VR(7, 3037000500), VR(21, 9223372037000250000UL));
1529 		
1530 		// min > max on one side
1531 		testMul(VR(-5, 42), VR(1), VR(-5, 42));
1532 		testMul(VR(-5, 42), VR(2, 5), VR(-25, 210));
1533 		testMul(VR(-5, 12), VR(0, 7), VR(-35, 84));
1534 		testMul(VR(-5, 42), VR(0), VR(0));
1535 		testMul(VR(5, 3037000500), VR(-12, 3037000500), VR(-36444006000, 9223372037000250000UL));
1536 		
1537 		// min > max on both side
1538 		testMul(VR(-1, 5), VR(-7, 22), VR(-35, 110));
1539 		testMul(VR(-11, 3037000500), VR(-8, 3037000500), VR(-33407005500, 9223372037000250000UL));
1540 		
1541 		// overflow
1542 		testMul(VR(123), VR(long.min, ulong.max), VR());
1543 		testMul(VR(0, 4294967296), VR(0, 4294967297), VR());
1544 		testMul(VR(-23, 4294967296), VR(10, 4294967297), VR());
1545 		testMul(VR(-3037000500, 3037000500), VR(-3037000500, 3037000500), VR());
1546 		
1547 		/**
1548 		 * Test div
1549 		 */
1550 		// unsigned numerator.
1551 		testDiv(VR(23), VR(5), VR(4));
1552 		testDiv(VR(23, 125), VR(5, 7), VR(3, 25));
1553 		testDiv(VR(0, 201), VR(12, 17), VR(0, 16));
1554 		
1555 		// signed numerator
1556 		testDiv(VR(-23), VR(5), isSigned!T ? VR(-4) : VR((T.min - 23) / 5));
1557 		testDiv(VR(-27, 31), VR(5, 9), isSigned!T ? VR(-5, 6) : VR(0, T.max / 5));
1558 		testDiv(VR(-23, 125), VR(89351496, 458963274), isSigned!T ? VR(0) : VR(0, (T.min - 23) / 89351496));
1559 		
1560 		// signed denumerator
1561 		testDiv(VR(23), VR(-5), isSigned!T ? VR(-4) : VR(0));
1562 		testDiv(VR(23, 125), VR(-7, -5), isSigned!T ? VR(-25, -3) : VR(0));
1563 		
1564 		// division by 0.
1565 		testDiv(VR(42), VR(0), VR());
1566 		testDiv(VR(42), VR(0, 25), VR(1, 42));
1567 		testDiv(VR(42), VR(-8, 0), isSigned!T ? VR(-42, -5) : VR(0, 42));
1568 		testDiv(VR(42), VR(-5, 7), isSigned!T ? VR(-42, 42) : VR(0, 42));
1569 		testDiv(VR(-47, 42), VR(-5, 7), isSigned!T ? VR(-47, 47) : VR());
1570 		
1571 		// degenerate numerator.
1572 		testDiv(VR(2, 1), VR(89351496, 458963274), VR(T.min / 89351496, T.max / 89351496));
1573 		testDiv(VR(125, -23), VR(89351496, 458963274), VR(T.min / 89351496, T.max / 89351496));
1574 		testDiv(VR(-12, -23), VR(89351496, 458963274), VR(T.min / 89351496, T.max / 89351496));
1575 		
1576 		/**
1577 		 * Test rem
1578 		 */
1579 		// non overflowing
1580 		testRem(VR(14, 52), VR(101, 109), VR(14, 52));
1581 		testRem(VR(18, 47), VR(9, 109), VR(0, 47));
1582 		testRem(VR(-21, 16), VR(123, 456), isSigned!T ? VR(-21, 16) : VR(0, 455));
1583 		
1584 		// within the same loop
1585 		testRem(VR(23), VR(5), VR(3));
1586 		testRem(VR(127), VR(121, 123), VR(4, 6));
1587 		testRem(VR(127, 132), VR(121, 125), VR(2, 11));
1588 		testRem(VR(144, 156), VR(136, 144), VR(0, 20));
1589 		
1590 		// not in the same loop
1591 		testRem(VR(12, 61), VR(49), VR(0, 48));
1592 		testRem(VR(23, 152), VR(50), VR(0, 49));
1593 		testRem(VR(12, 61), VR(49, 124), VR(0, 61));
1594 		testRem(VR(118, 152), VR(50, 57), VR(0, 56));
1595 		
1596 		// degenerate numerator
1597 		testRem(VR(125, -23), VR(210, 214), isSigned!T ? VR(-213, 213) : VR(0, 213));
1598 		
1599 		// modulo 0 elimination.
1600 		testRem(VR(23), VR(0, 3), VR(0, 2));
1601 		testRem(VR(121, 161), VR(-57, 52), isSigned!T ? VR(0, 56) : VR(0, 161));
1602 		testRem(VR(-21, 34), VR(-17, 24), isSigned!T ? VR(-21, 23) : VR(0, T.max - 1));
1603 		testRem(VR(34, 53), VR(-41, 36), isSigned!T ? VR(0, 40) : VR(0, 53));
1604 		testRem(VR(-25, 42), VR(-13, 75), isSigned!T ? VR(-25, 42) : VR(0, T.max - 1));
1605 		
1606 		/**
1607 		 * Test left shift
1608 		 */
1609 		testLShift(VR(42), VR(0), VR(42));
1610 		testLShift(VR(23), VR(2), VR(92));
1611 		testLShift(VR(13), VR(0, 2), VR(13, 52));
1612 		testLShift(VR(3, 13), VR(1, 7), VR(6, 1664));
1613 		testLShift(VR(-30, -18), VR(1, 7), VR(-3840, -36));
1614 		testLShift(VR(-5, 18), VR(1, 7), VR(-640, 2304));
1615 		
1616 		// full ranges and zeros
1617 		testLShift(VR(0), VR(0), VR(0));
1618 		testLShift(VR(0), VR(), VR(0));
1619 		testLShift(VR(), VR(0), VR());
1620 		testLShift(VR(), VR(), VR());
1621 		
1622 		// overflowing rhs
1623 		testLShift(VR(5), VR(32), VR(LS ? 5UL << 32 : 0, 5UL << 32));
1624 		testLShift(VR(5), VR(64), VR());
1625 		testLShift(VR(5), VR(78), VR());
1626 		testLShift(VR(5), VR(-1), VR());
1627 		testLShift(VR(5), VR(-1, 7), VR());
1628 		
1629 		// oveflow lhs
1630 		testLShift(VR(-1084, 1084), VR(21), VR(-1084UL << 21, 1084UL << 21));
1631 		
1632 		// degenerate ranges
1633 		testLShift(VR(23, 6), VR(0), VR(23, 6));
1634 		testLShift(VR(23, 6), VR(1), VR());
1635 		testLShift(VR(23, -6), VR(0, 2), VR());
1636 		testLShift(VR(-23, -62), VR(0, 2), VR());
1637 		
1638 		/**
1639 		 * Test signed right shift
1640 		 */
1641 		testSRShift(VR(42), VR(0), VR(42));
1642 		testSRShift(VR(42), VR(2), VR(10));
1643 		testSRShift(VR(4321), VR(2, 7), VR(33, 1080));
1644 		testSRShift(VR(12, 65), VR(1, 3), VR(1, 32));
1645 		
1646 		// Signed shift
1647 		testSRShift(VR(-35, -22), VR(1, 3), isSigned!T ? VR(-18, -3) : VR((umin - 35) >> 3, (umin - 22) >> 1));
1648 		testSRShift(VR(-35, 22), VR(0, 3), isSigned!T ? VR(-35, 22) : VR((umin - 35) >> 3, 22));
1649 		testSRShift(VR(-35, 22), VR(1, 3), isSigned!T ? VR(-18, 11) : VR(0, umax >> 1));
1650 		
1651 		// full ranges and zeros
1652 		testSRShift(VR(0), VR(0), VR(0));
1653 		testSRShift(VR(0), VR(), VR(0));
1654 		testSRShift(VR(), VR(0), VR());
1655 		testSRShift(VR(), VR(), VR());
1656 		
1657 		// degenerate ranges
1658 		testSRShift(VR(23, 6), VR(0), VR(23, 6));
1659 		testSRShift(VR(23, 6), VR(1), isSigned!T ? VR(11, 3) : VR(0, umax >> 1));
1660 		testSRShift(VR(23, -6), VR(0, 2), isSigned!T ? VR(5, -2) : VR(5, -6));
1661 		testSRShift(VR(23, -6), VR(1, 2), isSigned!T ? VR(5, -2) : VR(5, (umin - 6) >> 1));
1662 		testSRShift(VR(-23, -62), VR(0, 2), VR());
1663 		
1664 		/**
1665 		 * Test unsigned right shift
1666 		 */
1667 		testURShift(VR(42), VR(0), VR(42));
1668 		testURShift(VR(42), VR(2), VR(10));
1669 		testURShift(VR(4321), VR(2, 7), VR(33, 1080));
1670 		testURShift(VR(12, 65), VR(1, 3), VR(1, 32));
1671 		
1672 		// Signed shift
1673 		testURShift(VR(-35, -22), VR(1, 3), VR((umin - 35) >> 3, (umin - 22) >> 1));
1674 		testURShift(VR(-35, 22), VR(0, 3), VR((umin - 35) >> 3, 22));
1675 		testURShift(VR(-35, 22), VR(1, 3), VR(0, umax >> 1));
1676 		
1677 		// full ranges and zeros
1678 		testURShift(VR(0), VR(0), VR(0));
1679 		testURShift(VR(0), VR(), VR(0));
1680 		testURShift(VR(), VR(0), VR());
1681 		testURShift(VR(), VR(), VR());
1682 		
1683 		// degenerate ranges
1684 		testURShift(VR(23, 6), VR(0), VR(23, 6));
1685 		testURShift(VR(23, 6), VR(1), VR(0, umax >> 1));
1686 		testURShift(VR(23, -6), VR(0, 2), VR(5, -6));
1687 		testURShift(VR(23, -6), VR(2, 4), VR(1, (umin - 6) >> 2));
1688 		testURShift(VR(-23, -62), VR(0, 2), VR());
1689 		testURShift(VR(-23, -62), VR(1, 2), VR(0, umax >> 1));
1690 		
1691 		/**
1692 		 * Test and
1693 		 */
1694 		testAnd(VR(123), VR(1), VR(1));
1695 		testAnd(VR(11, 15), VR(1), VR(0, 1));
1696 		testAnd(VR(11, 15), VR(2), VR(0, 2));
1697 		testAnd(VR(10, 11), VR(2), VR(2, 2));
1698 		testAnd(VR(10, 11), VR(3), VR(2, 3));
1699 		testAnd(VR(9, 11), VR(3), VR(1, 3));
1700 		testAnd(VR(10, 12), VR(3), VR(0, 3));
1701 		testAnd(VR(21, 138), VR(0, 6), VR(0, 6));
1702 		
1703 		// Zero always gives 0
1704 		testAnd(VR(0), VR(0), VR(0));
1705 		testAnd(VR(123), VR(0), VR(0));
1706 		testAnd(VR(123, 456), VR(0), VR(0));
1707 		testAnd(VR(-5, 12), VR(0), VR(0));
1708 		testAnd(VR(5, -12), VR(0), VR(0));
1709 		
1710 		// -1 Does nothing
1711 		testAnd(VR(), VR(-1), VR());
1712 		testAnd(VR(123), VR(-1), VR(123));
1713 		testAnd(VR(123, 456), VR(-1), VR(123, 456));
1714 		testAnd(VR(-123, 456), VR(-1), VR(-123, 456));
1715 		// testAnd(VR(123, -456), VR(-1), VR(123, -456));
1716 		
1717 		// Full range extend to 0
1718 		testAnd(VR(), VR(), VR());
1719 		testAnd(VR(123), VR(), VR(0, 123));
1720 		testAnd(VR(123, 456), VR(), VR(0, 456));
1721 		testAnd(VR(-123, 456), VR(), VR());
1722 		
1723 		// Signed range
1724 		testAnd(VR(-123, 456), VR(-1, 0), VR(-123, 456));
1725 		testAnd(VR(-123, 456), VR(-1, 3), VR(-123, 456));
1726 		testAnd(VR(-123, 456), VR(-2, 0), VR(-124, 456));
1727 		
1728 		/**
1729 		 * Test or
1730 		 */
1731 		testOr(VR(), VR(), VR());
1732 		testOr(VR(0), VR(0), VR(0));
1733 		testOr(VR(1), VR(2), VR(3));
1734 		testOr(VR(10, 12), VR(2), VR(10, 14));
1735 		testOr(VR(10, 12), VR(3), VR(11, 15));
1736 		
1737 		// Zero does nothing
1738 		testOr(VR(0), VR(0), VR(0));
1739 		testOr(VR(123), VR(0), VR(123));
1740 		testOr(VR(-5, 12), VR(0), VR(-5, 12));
1741 		// testOr(VR(5, -12), VR(0), VR(5, -12));
1742 		
1743 		// -1 always gives -1
1744 		testOr(VR(), VR(-1), VR(-1));
1745 		testOr(VR(123), VR(-1), VR(-1));
1746 		testOr(VR(123, 456), VR(-1), VR(-1));
1747 		testOr(VR(-123, 456), VR(-1), VR(-1));
1748 		testOr(VR(123, -456), VR(-1), VR(-1));
1749 		
1750 		// Full range extends to -1
1751 		testOr(VR(), VR(), VR());
1752 		testOr(VR(123), VR(), VR(123, -1));
1753 		testOr(VR(123, 456), VR(), VR(123, -1));
1754 		testOr(VR(-123, 456), VR(), VR());
1755 		
1756 		// Signed range
1757 		testOr(VR(-123, 456), VR(-1, 0), VR(-123, 456));
1758 		testOr(VR(-123, 456), VR(-1, 3), VR(-123, 459));
1759 		testOr(VR(-123, 456), VR(1, 2), VR(-123, 458));
1760 		
1761 		/**
1762 		 * Test xor
1763 		 */
1764 		// To be 100% honest, I'm not sure what are good test cases for xor.
1765 		testXor(VR(), VR(), VR());
1766 		testXor(VR(0), VR(0), VR(0));
1767 		testXor(VR(1), VR(2), VR(3));
1768 		testXor(VR(1), VR(3), VR(2));
1769 		testXor(VR(123), VR(123), VR(0));
1770 		testXor(VR(123), VR(123, 124), VR(0, 7));
1771 		testXor(VR(3), VR(2, 3), VR(0, 1));
1772 	}
1773 }