PandA-2024.02
Range.cpp
Go to the documentation of this file.
1 /*
2  *
3  * _/_/_/ _/_/ _/ _/ _/_/_/ _/_/
4  * _/ _/ _/ _/ _/_/ _/ _/ _/ _/ _/
5  * _/_/_/ _/_/_/_/ _/ _/_/ _/ _/ _/_/_/_/
6  * _/ _/ _/ _/ _/ _/ _/ _/ _/
7  * _/ _/ _/ _/ _/ _/_/_/ _/ _/
8  *
9  * ***********************************************
10  * PandA Project
11  * URL: http://panda.dei.polimi.it
12  * Politecnico di Milano - DEIB
13  * System Architectures Group
14  * ***********************************************
15  * Copyright (C) 2004-2024 Politecnico di Milano
16  *
17  * This file is part of the PandA framework.
18  *
19  * The PandA framework is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <http://www.gnu.org/licenses/>.
31  *
32  */
44 #include "Range.hpp"
45 
46 #include "exceptions.hpp"
47 #include "math_function.hpp"
48 #include "string_manipulation.hpp"
49 #include "tree_node.hpp"
50 
51 #define CASE_MISCELLANEOUS \
52  aggr_init_expr_K: \
53  case case_label_expr_K: \
54  case lut_expr_K: \
55  case target_expr_K: \
56  case target_mem_ref_K: \
57  case target_mem_ref461_K: \
58  case binfo_K: \
59  case block_K: \
60  case constructor_K: \
61  case error_mark_K: \
62  case identifier_node_K: \
63  case ssa_name_K: \
64  case statement_list_K: \
65  case tree_list_K: \
66  case tree_vec_K: \
67  case call_expr_K
68 
69 using bw_t = Range::bw_t;
70 
71 // The number of bits needed to store the largest variable of the function (APInt).
72 const bw_t Range::max_digits = static_cast<bw_t>(std::numeric_limits<APInt::number>::digits);
75 const APInt Range::MinDelta(1);
76 
77 Range::Range(RangeType rType, bw_t rbw) : l(Min), u(Max), bw(rbw), type(rType)
78 {
79  THROW_ASSERT(rbw > 0 && rbw <= max_digits, "Invalid bitwidth for range (bw = " + STR(rbw) + ")");
80 }
81 
82 Range::Range(RangeType rType, bw_t rbw, const APInt& lb, const APInt& ub) : l(lb), u(ub), bw(rbw), type(rType)
83 {
84  THROW_ASSERT(rbw > 0 && rbw <= max_digits, "Invalid bitwidth for range (bw = " + STR(rbw) + ")");
85  normalizeRange(lb, ub, rType);
86 }
87 
89 {
90  return new Range(*this);
91 }
92 
93 void Range::normalizeRange(const APInt& lb, const APInt& ub, RangeType rType)
94 {
95  type = rType;
96  switch(rType)
97  {
98  case Empty:
99  case Unknown:
100  {
101  l = Min;
102  u = Max;
103  break;
104  }
105  case Anti:
106  {
107  if(lb > ub)
108  {
109  return normalizeRange(ub + MinDelta, lb - MinDelta, Regular);
110  }
111  else if((lb == Min) && (ub == Max))
112  {
113  type = Empty;
114  return;
115  }
116  else if(lb == Min)
117  {
118  return normalizeRange(ub + MinDelta, Max, Regular);
119  }
120  else if(ub == Max)
121  {
122  return normalizeRange(Min, lb - MinDelta, Regular);
123  }
124  else
125  {
126  THROW_ASSERT(ub >= lb, "");
127  const auto maxS = APInt::getSignedMaxValue(bw);
128  const auto minS = APInt::getSignedMinValue(bw);
129  const bool lbgt = lb > maxS;
130  const bool ubgt = ub > maxS;
131  const bool lblt = lb < minS;
132  const bool ublt = ub < minS;
133  if(lbgt && ubgt)
134  {
135  if((ub - lb).abs() < APInt::getMaxValue(bw))
136  {
137  l = lb.extOrTrunc(bw, true);
138  u = ub.extOrTrunc(bw, true);
139  }
140  else
141  {
142  type = Regular;
145  }
146  }
147  else if(lblt && ublt)
148  {
149  if((ub - lb).abs() < APInt::getMaxValue(bw))
150  {
151  l = ub.extOrTrunc(bw, true);
152  u = lb.extOrTrunc(bw, true);
153  }
154  else
155  {
156  type = Regular;
159  }
160  }
161  else if(!lblt && ubgt)
162  {
163  const auto ubnew = ub.extOrTrunc(bw, true);
164  type = Regular;
165  if((ub - lb).abs() < APInt::getMaxValue(bw) && ubnew != (lb - MinDelta))
166  {
167  l = ubnew + MinDelta;
168  u = lb - MinDelta;
169  }
170  else
171  {
174  }
175  }
176  else if(lblt && !ubgt)
177  {
178  const auto lbnew = lb.extOrTrunc(bw, true);
179  type = Regular;
180  if((ub - lb).abs() < APInt::getMaxValue(bw) && lbnew != (ub + MinDelta))
181  {
182  l = ub + MinDelta;
183  u = lbnew - MinDelta;
184  }
185  else
186  {
189  }
190  }
191  else if(!lblt && !ubgt)
192  {
193  l = lb;
194  u = ub;
195  }
196  else
197  {
198  THROW_UNREACHABLE("unexpected condition");
199  }
200  }
201  break;
202  }
203  case Regular:
204  {
205  if((lb - MinDelta) == ub)
206  {
209  }
210  else if(lb > ub)
211  {
212  return normalizeRange(ub + MinDelta, lb - MinDelta, Anti);
213  }
214  else if(lb == Min && ub == Max)
215  {
218  }
219  else if(ub == Max)
220  {
221  const auto maxS = APInt::getSignedMaxValue(bw);
222  const auto minS = APInt::getSignedMinValue(bw);
223  if(lb < minS)
224  {
225  l = maxS;
226  u = minS;
227  }
228  else if(lb >= minS && lb < 0)
229  {
230  l = lb;
231  u = maxS;
232  }
233  else if(lb >= 0 && lb <= maxS)
234  {
235  l = lb;
237  }
238  else if(lb > maxS && lb <= APInt::getMaxValue(bw))
239  {
240  l = lb.extOrTrunc(bw, true);
241  u = -1;
242  }
243  else
244  {
245  l = maxS;
246  u = minS;
247  }
248  }
249  else if(lb == Min)
250  {
251  const auto maxS = APInt::getSignedMaxValue(bw);
252  const auto minS = APInt::getSignedMinValue(bw);
253  if(ub < minS)
254  {
255  l = maxS;
256  u = minS;
257  }
258  else if(ub >= minS && ub < 0)
259  {
260  l = minS;
261  u = ub;
262  }
263  else if(ub >= 0 && ub <= maxS)
264  {
266  u = ub;
267  }
268  else if(ub > maxS && ub < APInt::getMaxValue(bw))
269  {
270  type = Anti;
271  u = -1;
272  l = ub.extOrTrunc(bw, true) + MinDelta;
273  }
274  else
275  {
276  l = maxS;
277  u = minS;
278  }
279  }
280  else
281  {
282  THROW_ASSERT(ub >= lb, "");
283  const auto maxS = APInt::getSignedMaxValue(bw);
284  const auto minS = APInt::getSignedMinValue(bw);
285  const bool lbgt = lb > maxS;
286  const bool ubgt = ub > maxS;
287  const bool lblt = lb < minS;
288  const bool ublt = ub < minS;
289  if(ubgt && lblt)
290  {
291  l = maxS;
292  u = minS;
293  }
294  else if(lbgt && ubgt)
295  {
296  l = lb.extOrTrunc(bw, true);
297  u = ub.extOrTrunc(bw, true);
298  }
299  else if(lblt && ublt)
300  {
301  l = ub.extOrTrunc(bw, true);
302  u = lb.extOrTrunc(bw, true);
303  }
304  else if(!lblt && ubgt)
305  {
306  const auto ubnew = ub.extOrTrunc(bw, true);
307  if((ub - lb).abs() < APInt::getMaxValue(bw) && ubnew != (lb - MinDelta))
308  {
309  type = Anti;
310  l = ubnew + MinDelta;
311  u = lb - MinDelta;
312  }
313  else
314  {
315  l = maxS;
316  u = minS;
317  }
318  }
319  else if(lblt && !ubgt)
320  {
321  const auto lbnew = lb.extOrTrunc(bw, true);
322  if((ub - lb).abs() < APInt::getMaxValue(bw) && lbnew != (ub + MinDelta))
323  {
324  type = Anti;
325  l = ub + MinDelta;
326  u = lbnew - MinDelta;
327  }
328  else
329  {
330  l = maxS;
331  u = minS;
332  }
333  }
334  else if(!lblt && !ubgt)
335  {
336  l = lb;
337  u = ub;
338  }
339  else
340  {
341  THROW_UNREACHABLE("unexpected condition");
342  }
343  }
344  break;
345  }
346  case Real:
347  default:
348  {
349  THROW_UNREACHABLE("Real range is a storage class only");
350  break;
351  }
352  }
353  if(u < l)
354  {
355  l = Min;
356  u = Max;
357  }
358 }
359 
360 bw_t Range::neededBits(const APInt& a, const APInt& b, bool sign)
361 {
362  return std::max(a.minBitwidth(sign), b.minBitwidth(sign));
363 }
364 
365 RangeRef Range::fromBitValues(const std::deque<bit_lattice>& bv, bw_t bitwidth, bool isSigned)
366 {
367  THROW_ASSERT(bv.size() <= bitwidth, "BitValues size not appropriate");
368  auto bitstring_to_int = [&](const std::deque<bit_lattice>& bv_in) {
369  long long out = isSigned && bv_in.front() == bit_lattice::ONE ? std::numeric_limits<long long>::min() : 0LL;
370  auto bv_it = bv_in.crbegin();
371  const auto bv_end = bv_in.crend();
372  for(size_t i = 0; bv_it != bv_end; ++i, ++bv_it)
373  {
374  if(*bv_it == bit_lattice::ONE)
375  {
376  out |= 1LL << i;
377  }
378  else
379  {
380  out &= ~(1LL << i);
381  }
382  }
383  return out;
384  };
385  auto manip = [&](const std::deque<bit_lattice>& bv_in) {
386  if(bv_in.size() < bitwidth)
387  {
388  return APInt(bitstring_to_int(BitLatticeManipulator::sign_extend_bitstring(bv_in, isSigned, bitwidth)))
389  .extOrTrunc(bitwidth, isSigned);
390  }
391  return APInt(bitstring_to_int(bv_in)).extOrTrunc(bitwidth, isSigned);
392  };
393  const auto max = [&]() {
394  std::deque<bit_lattice> bv_out;
395  bv_out.push_back((bv.front() == bit_lattice::U || bv.front() == bit_lattice::X) ?
396  (isSigned ? bit_lattice::ZERO : bit_lattice::ONE) :
397  bv.front());
398  for(auto it = ++(bv.begin()); it != bv.end(); ++it)
399  {
400  bv_out.push_back((*it == bit_lattice::U || *it == bit_lattice::X) ? bit_lattice::ONE : *it);
401  }
402  return manip(bv_out);
403  }();
404  const auto min = [&]() {
405  std::deque<bit_lattice> bv_out;
406  bv_out.push_back((bv.front() == bit_lattice::U || bv.front() == bit_lattice::X) ?
407  (isSigned ? bit_lattice::ONE : bit_lattice::ZERO) :
408  bv.front());
409  for(auto it = ++(bv.begin()); it != bv.end(); ++it)
410  {
411  bv_out.push_back((*it == bit_lattice::U || *it == bit_lattice::X) ? bit_lattice::ZERO : *it);
412  }
413  return manip(bv_out);
414  }();
415 
416  THROW_ASSERT(min <= max, "");
417  return RangeRef(new Range(Regular, bitwidth, min, max));
418 }
419 
420 std::deque<bit_lattice> Range::getBitValues(bool isSigned) const
421 {
422  if(isEmpty() || isAnti() || isUnknown())
423  {
424  return create_u_bitstring(bw);
425  }
426  if(isConstant())
427  {
428  return create_bitstring_from_constant(isSigned ? getSignedMin() : getUnsignedMin(), bw, isSigned);
429  }
430 
431  auto min = create_bitstring_from_constant(isSigned ? getSignedMin() : getUnsignedMin(), bw, isSigned);
432  auto max = create_bitstring_from_constant(isSigned ? getSignedMax() : getUnsignedMax(), bw, isSigned);
433  auto& longer = min.size() >= max.size() ? min : max;
434  auto& shorter = min.size() >= max.size() ? max : min;
435  if(shorter.size() < longer.size())
436  {
437  shorter = BitLatticeManipulator::sign_extend_bitstring(shorter, isSigned, longer.size());
438  }
439 
440  std::deque<bit_lattice> range_bv;
441  auto s_it = shorter.cbegin();
442  auto l_it = longer.cbegin();
443  const auto s_end = shorter.cend();
444  const auto l_end = longer.cend();
445  for(; s_it != s_end && l_it != l_end; s_it++, l_it++)
446  {
447  if(*s_it == *l_it)
448  {
449  range_bv.push_back(*s_it);
450  }
451  else
452  {
453  break;
454  }
455  }
456  while(range_bv.size() < longer.size())
457  {
458  range_bv.push_back(bit_lattice::U);
459  }
461  return range_bv;
462 }
463 
464 RangeRef Range::getAnti() const
465 {
466  if(type == Anti)
467  {
468  return RangeRef(new Range(Regular, bw, l, u));
469  }
470  if(type == Regular)
471  {
472  return RangeRef(new Range(Anti, bw, l, u));
473  }
474  if(type == Empty)
475  {
476  return RangeRef(new Range(Regular, bw));
477  }
478  if(type == Unknown)
479  {
480  return RangeRef(this->clone());
481  }
482  if(type == Real)
483  {
484  THROW_UNREACHABLE("Real range is a storage class only");
485  }
486  THROW_UNREACHABLE("unexpected condition");
487  return nullptr;
488 }
489 
491 {
492  return bw;
493 }
494 
495 const APInt& Range::getLower() const
496 {
497  THROW_ASSERT(!isReal(), "Real range is a storage class only");
498  THROW_ASSERT(!isAnti(), "Lower bound not valid for Anti range");
499  return l;
500 }
501 
502 const APInt& Range::getUpper() const
503 {
504  THROW_ASSERT(!isReal(), "Real range is a storage class only");
505  THROW_ASSERT(!isAnti(), "Upper bound not valid for Anti range");
506  return u;
507 }
508 
510 {
511  THROW_ASSERT(!isReal(), "Real range is a storage class only");
512  THROW_ASSERT(!isUnknown() && !isEmpty(), "Max not valid for Unknown/Empty range");
513  const auto maxS = APInt::getSignedMaxValue(bw);
514  if(type == Regular)
515  {
516  return u > maxS ? maxS : u;
517  }
518  return maxS;
519 }
520 
522 {
523  THROW_ASSERT(!isReal(), "Real range is a storage class only");
524  THROW_ASSERT(!isUnknown() && !isEmpty(), "Min not valid for Unknown/Empty range");
525  const auto minS = APInt::getSignedMinValue(bw);
526  if(type == Regular)
527  {
528  return l < minS ? minS : l;
529  }
530  return minS;
531 }
532 
534 {
535  THROW_ASSERT(!isReal(), "Real range is a storage class only");
536  THROW_ASSERT(!isUnknown() && !isEmpty(), "UMax not valid for Unknown/Empty range");
537  if(isAnti())
538  {
539  auto lb = l - MinDelta;
540  auto ub = u + MinDelta;
541  return (lb >= 0 || ub < 0) ? APInt::getMaxValue(bw) : lb.extOrTrunc(bw, false);
542  }
543  return (u < 0 || l >= 0) ? u.extOrTrunc(bw, false) : APInt::getMaxValue(bw);
544 }
545 
547 {
548  THROW_ASSERT(!isReal(), "Real range is a storage class only");
549  THROW_ASSERT(!isUnknown() && !isEmpty(), "UMin not valid for Unknown/Empty range");
550  if(isAnti())
551  {
552  return (l > 0 || u < 0) ? APInt::getMinValue(bw) : (u + MinDelta);
553  }
554  return (l > 0 || u < 0) ? l.extOrTrunc(bw, false) : APInt::getMinValue(bw);
555 }
556 
558 {
559  THROW_ASSERT(!isReal(), "Real range is a storage class only");
560  if(isEmpty())
561  {
562  return 0;
563  }
564  if(isUnknown() || isFullSet())
565  {
566  return APInt::getMaxValue(bw) + 1;
567  }
568  if(isAnti())
569  {
570  return APInt::getMaxValue(bw) - (u - l);
571  }
572  const auto uLimit = u == Max ? APInt::getSignedMaxValue(bw) : u;
573  const auto lLimit = l == Min ? APInt::getSignedMinValue(bw) : l;
574  return 1 + uLimit - lLimit;
575 }
576 
577 bool Range::isUnknown() const
578 {
579  return type == Unknown;
580 }
581 
583 {
584  type = Unknown;
585 }
586 
587 bool Range::isRegular() const
588 {
589  return type == Regular;
590 }
591 
592 bool Range::isAnti() const
593 {
594  return type == Anti;
595 }
596 
597 bool Range::isEmpty() const
598 {
599  return type == Empty;
600 }
601 
602 bool Range::isReal() const
603 {
604  return false;
605 }
606 
607 bool Range::isSameType(const RangeConstRef& other) const
608 {
609  return type == other->type;
610 }
611 
612 bool Range::isSameRange(const RangeConstRef& other) const
613 {
614  return this->bw == other->bw && isSameType(other) && (l == other->l) && (u == other->u);
615 }
616 
617 bool Range::isFullSet() const
618 {
619  THROW_ASSERT(!isUnknown(), "");
620  if(isEmpty() || isAnti())
621  {
622  return false;
623  }
625 }
626 
628 {
629  if(isUnknown() || isEmpty())
630  {
631  return false;
632  }
633  return l == u;
634 }
635 
636 bool Range::isConstant() const
637 {
638  return isRegular() && l == u;
639 }
640 
641 #define RETURN_EMPTY_ON_EMPTY(b) \
642  if(this->isEmpty() || other->isEmpty()) \
643  { \
644  return RangeRef(new Range(Empty, b)); \
645  }
646 #define RETURN_UNKNOWN_ON_UNKNOWN(b) \
647  if(this->isUnknown() || other->isUnknown()) \
648  { \
649  return RangeRef(new Range(Unknown, b)); \
650  }
651 
652 RangeRef Range::add(const RangeConstRef& other) const
653 {
654  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
657  if(this->isFullSet() || other->isFullSet())
658  {
659  return RangeRef(new Range(Regular, bw));
660  }
661  if(isAnti() && other->isConstant())
662  {
663  auto ol = other->getLower();
664  if(ol >= (Max - u))
665  {
666  return RangeRef(new Range(Regular, bw));
667  }
668  return RangeRef(new Range(Anti, bw, l + ol, u + ol));
669  }
670  if(this->isAnti() || other->isAnti())
671  {
672  return RangeRef(new Range(Regular, bw));
673  }
674  if(other->isConstant())
675  {
676  auto ol = other->getLower();
677  if(l == Min)
678  {
679  THROW_ASSERT(u != Max, "");
680  return RangeRef(new Range(Regular, bw, l, u + ol));
681  }
682  if(u == Max)
683  {
684  THROW_ASSERT(l != Min, "");
685  return RangeRef(new Range(Regular, bw, l + ol, u));
686  }
687 
688  return RangeRef(new Range(Regular, bw, l + ol, u + ol));
689  }
690 
691  const auto min = getLower() + other->getLower();
692  const auto max = getUpper() + other->getUpper();
693  RangeRef res(new Range(Regular, bw, min, max));
694  if(res->getSpan() <= getSpan() || res->getSpan() <= other->getSpan())
695  {
696  return RangeRef(new Range(Regular, bw));
697  }
698  return res;
699 }
700 
701 RangeRef Range::sat_add(const RangeConstRef& other) const
702 {
703  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
706  if(this->isFullSet() || other->isFullSet())
707  {
708  return RangeRef(new Range(Regular, bw));
709  }
710  if(isAnti() && other->isConstant())
711  {
712  auto ol = other->getLower();
713  if(ol == 0)
714  {
715  return RangeRef(this->clone());
716  }
717  if(ol > 0)
718  {
719  return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw) + ol, APInt::getSignedMaxValue(bw)));
720  }
721  return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw), APInt::getSignedMaxValue(bw) + ol));
722  }
723  if(this->isAnti() || other->isAnti())
724  {
725  return RangeRef(new Range(Regular, bw));
726  }
727  if(other->isConstant())
728  {
729  auto ol = other->getLower();
730  if(ol == 0)
731  {
732  return RangeRef(this->clone());
733  }
734  if(l == Min)
735  {
736  THROW_ASSERT(u != Max, "");
737  if(ol > 0)
738  {
739  return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw) + ol,
741  }
742  return RangeRef(
744  }
745  if(u == Max)
746  {
747  THROW_ASSERT(l != Min, "");
748  if(ol > 0)
749  {
750  return RangeRef(
752  }
753  return RangeRef(
755  }
756  }
757 
758  const auto min =
760  const auto max =
762  RangeRef res(new Range(Regular, bw, min, max));
763  if(res->getSpan() <= getSpan() || res->getSpan() <= other->getSpan())
764  {
765  return RangeRef(new Range(Regular, bw));
766  }
767  return res;
768 }
769 
770 RangeRef Range::usat_add(const RangeConstRef& other) const
771 {
772  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
775  if(this->isFullSet() || other->isFullSet())
776  {
777  return RangeRef(new Range(Regular, bw));
778  }
779  if(isAnti() && other->isConstant())
780  {
781  auto ol = other->getLower();
782  if(l + ol >= APInt::getMaxValue(bw))
783  {
784  return RangeRef(new Range(Anti, bw, 0, u + ol));
785  }
786  return RangeRef(new Range(Anti, bw, l + ol, u + ol));
787  }
788  if(this->isAnti() || other->isAnti())
789  {
790  return RangeRef(new Range(Regular, bw));
791  }
792  if(other->isConstant())
793  {
794  auto ol = other->getLower();
795  if(l == Min)
796  {
797  THROW_ASSERT(u != Max, "");
798  return RangeRef(new Range(Regular, bw, 0, std::min(APInt::getMaxValue(bw), u + ol)));
799  }
800  if(u == Max)
801  {
802  THROW_ASSERT(l != Min, "");
803  return RangeRef(new Range(Regular, bw, std::min(APInt::getMaxValue(bw), l + ol), APInt::getMaxValue(bw)));
804  }
805 
806  return RangeRef(new Range(Regular, bw, l + ol, std::min(APInt::getMaxValue(bw), u + ol)));
807  }
808 
809  const auto min = std::min(APInt::getMaxValue(bw), getLower() + other->getLower());
810  const auto max = std::min(APInt::getMaxValue(bw), getUpper() + other->getUpper());
811  RangeRef res(new Range(Regular, bw, min, max));
812  if(res->getSpan() <= getSpan() || res->getSpan() <= other->getSpan())
813  {
814  return RangeRef(new Range(Regular, bw));
815  }
816  return res;
817 }
818 
819 RangeRef Range::sub(const RangeConstRef& other) const
820 {
821  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
824  if(this->isFullSet() || other->isFullSet())
825  {
826  return RangeRef(new Range(Regular, bw));
827  }
828  if(this->isAnti() && other->isConstant())
829  {
830  auto ol = other->getLower();
831  if(l <= (Min + ol))
832  {
833  return RangeRef(new Range(Regular, bw));
834  }
835 
836  return RangeRef(new Range(Anti, bw, l - ol, u - ol));
837  }
838  if(this->isAnti() || other->isAnti())
839  {
840  return RangeRef(new Range(Regular, bw));
841  }
842  if(other->isConstant())
843  {
844  auto ol = other->getLower();
845  if(l == Min)
846  {
847  THROW_ASSERT(u != Max, "");
848  auto minValue = APInt::getSignedMinValue(bw);
849  auto upper = u - ol;
850  if(minValue > upper)
851  {
852  return RangeRef(new Range(Regular, bw));
853  }
854 
855  return RangeRef(new Range(Regular, bw, l, upper));
856  }
857  if(u == Max)
858  {
859  THROW_ASSERT(l != Min, "");
860  auto maxValue = APInt::getSignedMaxValue(bw);
861  auto lower = l - ol;
862  if(maxValue < lower)
863  {
864  return RangeRef(new Range(Regular, bw));
865  }
866 
867  return RangeRef(new Range(Regular, bw, l - ol, u));
868  }
869 
870  auto lower = (l - ol).extOrTrunc(bw, true);
871  auto upper = (u - ol).extOrTrunc(bw, true);
872  if(lower <= upper)
873  {
874  return RangeRef(new Range(Regular, bw, lower, upper));
875  }
876  return RangeRef(new Range(Anti, bw, upper + 1, lower - 1));
877  }
878 
879  const auto min = getLower() - other->getUpper();
880  const auto max = getUpper() - other->getLower();
881  RangeRef res(new Range(Regular, bw, min, max));
882  if(res->getSpan() < getSpan() || res->getSpan() < other->getSpan())
883  {
884  return RangeRef(new Range(Regular, bw));
885  }
886  return res;
887 }
888 
889 RangeRef Range::sat_sub(const RangeConstRef& other) const
890 {
891  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
894  if(this->isFullSet() || other->isFullSet())
895  {
896  return RangeRef(new Range(Regular, bw));
897  }
898  if(this->isAnti() && other->isConstant())
899  {
900  auto ol = other->getLower();
901  if(ol == 0)
902  {
903  return RangeRef(this->clone());
904  }
905  if(ol < 0)
906  {
907  return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw) - ol, APInt::getSignedMaxValue(bw)));
908  }
909  return RangeRef(new Range(Anti, bw, APInt::getSignedMinValue(bw), APInt::getSignedMaxValue(bw) - ol));
910  }
911  if(this->isAnti() || other->isAnti())
912  {
913  return RangeRef(new Range(Regular, bw));
914  }
915  if(other->isConstant())
916  {
917  auto ol = other->getLower();
918  if(l == Min)
919  {
920  THROW_ASSERT(u != Max, "");
921  if(ol < 0)
922  {
923  return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw) - ol,
925  }
926  return RangeRef(
928  }
929  if(u == Max)
930  {
931  THROW_ASSERT(l != Min, "");
932  if(ol < 0)
933  {
934  return RangeRef(
936  }
937  return RangeRef(
939  }
940  }
941 
942  const auto min =
944  const auto max =
946  RangeRef res(new Range(Regular, bw, min, max));
947  if(res->getSpan() < getSpan() || res->getSpan() < other->getSpan())
948  {
949  return RangeRef(new Range(Regular, bw));
950  }
951  return res;
952 }
953 
954 RangeRef Range::usat_sub(const RangeConstRef& other) const
955 {
956  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
959  if(this->isFullSet() || other->isFullSet())
960  {
961  return RangeRef(new Range(Regular, bw));
962  }
963  if(this->isAnti() && other->isConstant())
964  {
965  auto ol = other->getLower();
966  if(ol == 0)
967  {
968  return RangeRef(this->clone());
969  }
970  if(ol < 0)
971  {
972  return RangeRef(new Range(Regular, bw, 0 - ol, APInt::getMaxValue(bw)));
973  }
974  return RangeRef(new Range(Regular, bw, 0, APInt::getMaxValue(bw) - ol));
975  }
976  if(this->isAnti() || other->isAnti())
977  {
978  return RangeRef(new Range(Regular, bw));
979  }
980  if(other->isConstant())
981  {
982  auto ol = other->getLower();
983  if(l == Min)
984  {
985  THROW_ASSERT(u != Max, "");
986  if(ol < 0)
987  {
988  return RangeRef(new Range(Regular, bw, 0 - ol, std::min(APInt::getMaxValue(bw), u - ol)));
989  }
990  return RangeRef(new Range(Regular, bw, 0, std::max(APInt(0), u - ol)));
991  }
992  if(u == Max)
993  {
994  THROW_ASSERT(l != Min, "");
995  if(ol < 0)
996  {
997  return RangeRef(new Range(Regular, bw, std::min(APInt::getMaxValue(bw), l - ol), APInt::getMaxValue(bw)));
998  }
999  return RangeRef(new Range(Regular, bw, std::max(APInt(0), l - ol), APInt::getMaxValue(bw) - ol));
1000  }
1001  }
1002 
1003  const auto min = std::max(APInt(0), std::min(APInt::getMaxValue(bw), getLower() - other->getUpper()));
1004  const auto max = std::max(APInt(0), std::min(APInt::getMaxValue(bw), getUpper() - other->getLower()));
1005  RangeRef res(new Range(Regular, bw, min, max));
1006  if(res->getSpan() < getSpan() || res->getSpan() < other->getSpan())
1007  {
1008  return RangeRef(new Range(Regular, bw));
1009  }
1010  return res;
1011 }
1012 
1013 RangeRef Range::mul(const RangeConstRef& other) const
1014 {
1015  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1018  if(this->isFullSet() || other->isFullSet() || this->isAnti() || other->isAnti())
1019  {
1020  return RangeRef(new Range(Regular, bw));
1021  }
1022 
1023  // Multiplication is signedness-independent. However different ranges can be
1024  // obtained depending on how the input ranges are treated. These different
1025  // ranges are all conservatively correct, but one might be better than the
1026  // other. We calculate two ranges; one treating the inputs as unsigned
1027  // and the other signed, then return the smallest of these ranges.
1028 
1029  // Unsigned range first.
1030  auto this_min = getUnsignedMin();
1031  auto this_max = getUnsignedMax();
1032  auto Other_min = other->getUnsignedMin();
1033  auto Other_max = other->getUnsignedMax();
1034 
1035  const auto Result_zext = Range(Regular, static_cast<bw_t>(bw * 2), this_min * Other_min, this_max * Other_max);
1036  const auto UR = Result_zext.truncate(bw);
1037 
1038  // Now the signed range. Because we could be dealing with negative numbers
1039  // here, the lower bound is the smallest of the Cartesian product of the
1040  // lower and upper ranges; for example:
1041  // [-1,4] * [-2,3] = min(-1*-2, -1*-3, 4*-2, 4*3) = -8.
1042  // Similarly for the upper bound, swapping min for max.
1043 
1044  this_min = getSignedMin();
1045  this_max = getSignedMax();
1046  Other_min = other->getSignedMin();
1047  Other_max = other->getSignedMax();
1048 
1049  const auto res =
1050  std::minmax({this_min * Other_min, this_min * Other_max, this_max * Other_min, this_max * Other_max});
1051  const auto Result_sext = Range(Regular, static_cast<bw_t>(bw * 2), res.first, res.second);
1052  const auto SR = Result_sext.truncate(bw);
1053 
1054  return UR->getSpan() < SR->getSpan() ? UR : SR;
1055 }
1056 
1057 RangeRef Range::udiv(const RangeConstRef& other) const
1058 {
1059  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1062  if(this->isFullSet())
1063  {
1064  return RangeRef(new Range(Regular, bw));
1065  }
1066 
1067  auto a = getUnsignedMin();
1068  auto b = getUnsignedMax();
1069  auto c = other->getUnsignedMin();
1070  auto d = other->getUnsignedMax();
1071 
1072  // Deal with division by 0 exception
1073  if((c == 0) && (d == 0))
1074  {
1075  return RangeRef(new Range(Regular, bw));
1076  }
1077  if(c == 0)
1078  {
1079  c = 1;
1080  }
1081  RangeRef res(new Range(Regular, bw, a / d, b / c));
1082  return res;
1083 }
1084 
1085 #define DIV_HELPER(x, y) \
1086  ((x) == Max) ? \
1087  (((y) < 0) ? Min : (((y) == 0) ? 0 : Max)) : \
1088  (((y) == Max) ? 0 : \
1089  (((x) == Min) ? (((y) < 0) ? Max : (((y) == 0) ? 0 : Min)) : (((y) == Min) ? 0 : ((x) / (y)))))
1090 
1091 RangeRef Range::sdiv(const RangeConstRef& other) const
1092 {
1093  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1096  if(this->isFullSet() || this->isAnti())
1097  {
1098  return RangeRef(new Range(Regular, bw));
1099  }
1100 
1101  const APInt& a = this->getLower();
1102  const APInt& b = this->getUpper();
1103  APInt c1, d1, c2, d2;
1104  bool is_zero_in = false;
1105  if(other->isAnti())
1106  {
1107  auto antiRange = other->getAnti();
1108  c1 = Min;
1109  d1 = antiRange->getLower() - 1;
1110  if(d1 == 0)
1111  {
1112  d1 = -1;
1113  }
1114  else if(d1 > 0)
1115  {
1116  return RangeRef(new Range(Regular, bw));
1117  }
1118  c2 = antiRange->getUpper() + 1;
1119  if(c2 == 0)
1120  {
1121  c2 = 1;
1122  }
1123  else if(c2 < 0)
1124  {
1125  return RangeRef(new Range(Regular, bw));
1126  }
1127  d2 = Max;
1128  }
1129  else
1130  {
1131  c1 = other->getLower();
1132  d1 = other->getUpper();
1133  // Deal with division by 0 exception
1134  if((c1 == 0) && (d1 == 0))
1135  {
1136  return RangeRef(new Range(Regular, bw));
1137  }
1138  is_zero_in = (c1 < 0) && (d1 > 0);
1139  if(is_zero_in)
1140  {
1141  d1 = -1;
1142  c2 = 1;
1143  }
1144  else
1145  {
1146  c2 = other->getLower();
1147  if(c2 == 0)
1148  {
1149  c1 = c2 = 1;
1150  }
1151  }
1152  d2 = other->getUpper();
1153  if(d2 == 0)
1154  {
1155  d1 = d2 = -1;
1156  }
1157  }
1158  auto n_iters = (is_zero_in || other->isAnti()) ? 8u : 4u;
1159 
1160  APInt candidates[8];
1161  candidates[0] = DIV_HELPER(a, c1);
1162  candidates[1] = DIV_HELPER(a, d1);
1163  candidates[2] = DIV_HELPER(b, c1);
1164  candidates[3] = DIV_HELPER(b, d1);
1165  if(n_iters == 8)
1166  {
1167  candidates[4] = DIV_HELPER(a, c2);
1168  candidates[5] = DIV_HELPER(a, d2);
1169  candidates[6] = DIV_HELPER(b, c2);
1170  candidates[7] = DIV_HELPER(b, d2);
1171  }
1172  // Lower bound is the min value from the vector, while upper bound is the max value
1173  auto res = std::minmax_element(candidates, candidates + n_iters);
1174  return RangeRef(new Range(Regular, bw, *res.first, *res.second));
1175 }
1176 
1177 RangeRef Range::urem(const RangeConstRef& other) const
1178 {
1179  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1182  if(this->isAnti() || other->isAnti())
1183  {
1184  return RangeRef(new Range(Regular, bw));
1185  }
1186  if(other->isConstant())
1187  {
1188  if(other->getLower() == 0)
1189  {
1190  return RangeRef(new Range(Empty, bw));
1191  }
1192  else if(other->getUnsignedMin() == 1)
1193  {
1194  return RangeRef(new Range(Regular, bw, 0, 0));
1195  }
1196  }
1197 
1198  const APInt& a = this->getUnsignedMin();
1199  const APInt& b = this->getUnsignedMax();
1200  APInt c = other->getUnsignedMin();
1201  const APInt& d = other->getUnsignedMax();
1202 
1203  // Deal with mod 0 exception
1204  if((c == 0) && (d == 0))
1205  {
1206  return RangeRef(new Range(Regular, bw));
1207  }
1208  if(c == 0)
1209  {
1210  c = 1;
1211  }
1212 
1213  APInt candidates[8];
1214 
1215  candidates[0] = a < c ? a : 0;
1216  candidates[1] = a < d ? a : 0;
1217  candidates[2] = b < c ? b : 0;
1218  candidates[3] = b < d ? b : 0;
1219  candidates[4] = a < c ? a : c - 1;
1220  candidates[5] = a < d ? a : d - 1;
1221  candidates[6] = b < c ? b : c - 1;
1222  candidates[7] = b < d ? b : d - 1;
1223 
1224  // Lower bound is the min value from the vector, while upper bound is the max value
1225  auto res = std::minmax_element(candidates, candidates + 8);
1226  return RangeRef(new Range(Regular, bw, *res.first, *res.second));
1227 }
1228 
1229 RangeRef Range::srem(const RangeConstRef& other) const
1230 {
1231  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1234  if(this->isFullSet() || this->isAnti() || other->isAnti())
1235  {
1236  return RangeRef(new Range(Regular, bw));
1237  }
1238 
1239  const auto& a = this->getLower();
1240  const auto& b = this->getUpper();
1241  const auto& c = other->getLower();
1242  const auto& d = other->getUpper();
1243 
1244  // Deal with mod 0 exception
1245  if(c <= 0 && d >= 0)
1246  {
1247  return RangeRef(new Range(Regular, bw));
1248  }
1249 
1250  const auto dmin = std::min(c.abs(), d.abs());
1251  const auto dmax = std::max(c.abs(), d.abs());
1252  const auto abs_min = std::min(a.abs(), b.abs());
1253  const auto abs_max = std::max(a.abs(), b.abs());
1254  if((abs_min < dmin && dmin < abs_max) || (abs_min < dmax && dmax < abs_max))
1255  {
1256  return RangeRef(new Range(Regular, bw, a >= 0 ? 0 : (a.abs() < dmax ? a : -(dmax - 1)),
1257  b <= 0 ? 0 : (b.abs() < dmax ? b : (dmax - 1))));
1258  }
1259  else if(abs_max < dmin)
1260  {
1261  return RangeRef(this->clone());
1262  }
1263  return RangeRef(new Range(Regular, bw, a < 0 ? -(dmax - 1) : 0, b > 0 ? (dmax - 1) : 0));
1264 }
1265 
1266 RangeRef Range::shl(const RangeConstRef& other) const
1267 {
1268  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1271  if(this->isFullSet() || other->isFullSet() || this->isAnti() || other->isAnti())
1272  {
1273  return RangeRef(new Range(Regular, bw));
1274  }
1275  if(this->isConstant() && other->isConstant())
1276  {
1277  const auto c = (this->getLower() << other->getLower().extOrTrunc(static_cast<APInt::bw_t>(ceil_log2(bw)), false))
1278  .extOrTrunc(bw, true);
1279  return RangeRef(new Range(Regular, bw, c, c));
1280  }
1281 
1282  const auto a = this->getLower();
1283  const auto b = this->getUpper();
1284  const auto fix = other->zextOrTrunc(static_cast<bw_t>(ceil_log2(bw)));
1285  const auto c = fix->getUnsignedMin();
1286  const auto d = fix->getUnsignedMax();
1287 
1288  if(c >= bw)
1289  {
1290  return RangeRef(new Range(Regular, bw, 0, 0));
1291  }
1292  if(d >= bw)
1293  {
1294  return RangeRef(new Range(Regular, bw));
1295  }
1296  if(a < 0 && b < 0)
1297  {
1298  if(d > a.leadingOnes(bw))
1299  {
1300  return RangeRef(new Range(Regular, bw));
1301  }
1302  return RangeRef(new Range(Regular, bw, a << d, b << c));
1303  }
1304  if(a < 0 && b >= 0)
1305  {
1306  if(d > std::min(a.leadingOnes(bw), b.leadingZeros(bw)))
1307  {
1308  return RangeRef(new Range(Regular, bw));
1309  }
1310  return RangeRef(new Range(Regular, bw, a << d, b << d));
1311  }
1312  if(d > b.leadingZeros(bw))
1313  {
1314  return RangeRef(new Range(Regular, bw));
1315  }
1316  return RangeRef(new Range(Regular, bw, a << c, b << d));
1317 }
1318 
1319 RangeRef Range::shr(const RangeConstRef& other, bool sign) const
1320 {
1321  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1324  if(this->isAnti() || other->isAnti())
1325  {
1326  return RangeRef(new Range(Regular, bw));
1327  }
1328 
1329  const auto fix = other->zextOrTrunc(static_cast<bw_t>(ceil_log2(bw)));
1330  const auto c = fix->getUnsignedMin();
1331  const auto d = fix->getUnsignedMax();
1332 
1333  if(sign)
1334  {
1335  const auto a = getSignedMin();
1336  const auto b = getSignedMax();
1337  const auto min = a >= 0 ? a >> d : a >> c;
1338  const auto max = b >= 0 ? b >> c : b >> d;
1339 
1340  return RangeRef(new Range(Regular, bw, min, max));
1341  }
1342  else
1343  {
1344  const auto a = getUnsignedMin();
1345  const auto b = getUnsignedMax();
1346 
1347  return RangeRef(new Range(Regular, bw, a >> d, b >> c));
1348  }
1349 }
1350 
1351 /*
1352  * This and operations are coded following Hacker's Delight algorithm.
1353  * According to the author, they provide tight results.
1354  */
1355 namespace
1356 {
1357  APInt minOR(bw_t bw, APInt a, const APInt& b, APInt c, const APInt& d)
1358  {
1359  APInt temp;
1360  APInt m = APInt(1) << (bw - 1U);
1361  APInt nm = APInt(-1) << (bw - 1U);
1362  for(auto i = 0; i < bw; ++i)
1363  {
1364  if(~a & c & m)
1365  {
1366  temp = (a | m) & nm;
1367  if(temp <= b)
1368  {
1369  a = temp;
1370  break;
1371  }
1372  }
1373  else if(a & ~c & m)
1374  {
1375  temp = (c | m) & nm;
1376  if(temp <= d)
1377  {
1378  c = temp;
1379  break;
1380  }
1381  }
1382  m >>= 1;
1383  nm >>= 1;
1384  }
1385  return a | c;
1386  }
1387 
1388  APInt maxOR(bw_t bw, const APInt& a, APInt b, const APInt& c, APInt d)
1389  {
1390  APInt temp;
1391  APInt m = APInt(1) << (bw - 1);
1392  APInt mm = m - 1;
1393  for(auto i = 0; i < bw; ++i)
1394  {
1395  if(b & d & m)
1396  {
1397  temp = (b - m) | mm;
1398  if(temp >= a)
1399  {
1400  b = temp;
1401  break;
1402  }
1403  temp = (d - m) | mm;
1404  if(temp >= c)
1405  {
1406  d = temp;
1407  break;
1408  }
1409  }
1410  m >>= 1;
1411  mm >>= 1;
1412  }
1413  return b | d;
1414  }
1415 
1416  std::pair<APInt, APInt> OR(bw_t bw, const APInt& a, const APInt& b, const APInt& c, const APInt& d)
1417  {
1418  auto abcd = ((a >= 0) << 3) | ((b >= 0) << 2) | ((c >= 0) << 1) | (d >= 0);
1419 
1420  APInt res_l = 0, res_u = 0;
1421  switch(abcd)
1422  {
1423  case 0:
1424  case 3:
1425  case 12:
1426  case 15:
1427  res_l = minOR(bw, a, b, c, d);
1428  res_u = maxOR(bw, a, b, c, d);
1429  break;
1430  case 1:
1431  return std::make_pair(a, -1);
1432  case 4:
1433  return std::make_pair(c, -1);
1434  case 5:
1435  res_l = std::min({a, c});
1436  res_u = maxOR(bw, 0, b, 0, d);
1437  break;
1438  case 7:
1439  res_l = minOR(bw, a, -1, c, d);
1440  res_u = maxOR(bw, 0, b, c, d);
1441  break;
1442  case 13:
1443  res_l = minOR(bw, a, b, c, -1);
1444  res_u = maxOR(bw, a, b, 0, d);
1445  break;
1446  default:
1447  THROW_UNREACHABLE("OR unreachable state " + STR(abcd));
1448  }
1449  return std::make_pair(res_l, res_u);
1450  }
1451 
1452  APInt minAND(bw_t bw, APInt a, const APInt& b, APInt c, const APInt& d)
1453  {
1454  APInt temp;
1455  APInt m = APInt(1) << (bw - 1U);
1456  APInt nm = APInt(-1) << (bw - 1U);
1457  for(auto i = 0; i < bw; ++i)
1458  {
1459  if(~a & ~c & m)
1460  {
1461  temp = (a | m) & nm;
1462  if(temp <= b)
1463  {
1464  a = temp;
1465  break;
1466  }
1467  temp = (c | m) & nm;
1468  if(temp <= d)
1469  {
1470  c = temp;
1471  break;
1472  }
1473  }
1474  m >>= 1;
1475  nm >>= 1;
1476  }
1477  return a & c;
1478  }
1479 
1480  APInt maxAND(bw_t bw, const APInt& a, APInt b, const APInt& c, APInt d)
1481  {
1482  APInt temp;
1483  APInt m = APInt(1) << (bw - 1);
1484  APInt mm = m - 1;
1485  for(auto i = 0; i < bw; ++i)
1486  {
1487  if(b & ~d & m)
1488  {
1489  temp = (b & ~m) | mm;
1490  if(temp >= a)
1491  {
1492  b = temp;
1493  break;
1494  }
1495  }
1496  else if(~b & d & m)
1497  {
1498  temp = (d & ~m) | mm;
1499  if(temp >= c)
1500  {
1501  d = temp;
1502  break;
1503  }
1504  }
1505  m >>= 1;
1506  mm >>= 1;
1507  }
1508  return b & d;
1509  }
1510 
1511  std::pair<APInt, APInt> AND(bw_t bw, const APInt& a, const APInt& b, const APInt& c, const APInt& d)
1512  {
1513  auto abcd = ((a >= 0) << 3) | ((b >= 0) << 2) | ((c >= 0) << 1) | (d >= 0);
1514 
1515  APInt res_l = 0, res_u = 0;
1516  switch(abcd)
1517  {
1518  case 0:
1519  case 3:
1520  case 12:
1521  case 15:
1522  res_l = minAND(bw, a, b, c, d);
1523  res_u = maxAND(bw, a, b, c, d);
1524  break;
1525  case 1:
1526  res_l = minAND(bw, a, b, c, -1);
1527  res_u = maxAND(bw, a, b, 0, d);
1528  break;
1529  case 4:
1530  res_l = minAND(bw, a, -1, c, d);
1531  res_u = maxAND(bw, 0, b, c, d);
1532  break;
1533  case 5:
1534  res_l = minAND(bw, a, -1, c, -1);
1535  res_u = std::max({b, d});
1536  break;
1537  case 7:
1538  return std::make_pair(0, d);
1539  case 13:
1540  return std::make_pair(0, b);
1541  default:
1542  THROW_UNREACHABLE("AND unreachable state " + STR(abcd));
1543  }
1544  return std::make_pair(res_l, res_u);
1545  }
1546 
1547  APInt minXOR(bw_t bw, APInt a, const APInt& b, APInt c, const APInt& d)
1548  {
1549  APInt temp;
1550  APInt m = APInt(1) << (bw - 1U);
1551  APInt nm = APInt(-1) << (bw - 1U);
1552  for(auto i = 0; i < bw; ++i)
1553  {
1554  if(~a & c & m)
1555  {
1556  temp = (a | m) & nm;
1557  if(temp <= b)
1558  {
1559  a = temp;
1560  }
1561  }
1562  else if(a & ~c & m)
1563  {
1564  temp = (c | m) & nm;
1565  if(temp <= d)
1566  {
1567  c = temp;
1568  }
1569  }
1570  m >>= 1;
1571  nm >>= 1;
1572  }
1573  return a ^ c;
1574  }
1575 
1576  APInt maxXOR(bw_t bw, const APInt& a, APInt b, const APInt& c, APInt d)
1577  {
1578  APInt temp;
1579  APInt m = APInt(1) << (bw - 1);
1580  APInt mm = m - 1;
1581  for(auto i = 0; i < bw; ++i)
1582  {
1583  if(b & d & m)
1584  {
1585  temp = (b - m) | mm;
1586  if(temp >= a)
1587  {
1588  b = temp;
1589  }
1590  else
1591  {
1592  temp = (d - m) | mm;
1593  if(temp >= c)
1594  {
1595  d = temp;
1596  }
1597  }
1598  }
1599  m >>= 1;
1600  mm >>= 1;
1601  }
1602  return b ^ d;
1603  }
1604 
1605  std::pair<APInt, APInt> uXOR(bw_t bw, const APInt& a, const APInt& b, const APInt& c, const APInt& d)
1606  {
1607  return std::make_pair(minXOR(bw, a, b, c, d), maxXOR(bw, a, b, c, d));
1608  }
1609 
1610 } // namespace
1611 
1612 RangeRef Range::Or(const RangeConstRef& other) const
1613 {
1614  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1617  if(this->isConstant() && this->getSignedMax() == 0)
1618  {
1619  return RangeRef(other->clone());
1620  }
1621  if(other->isConstant() && other->getSignedMax() == 0)
1622  {
1623  return RangeRef(this->clone());
1624  }
1625 
1626  const auto& a = this->isAnti() ? Min : this->getLower();
1627  const auto& b = this->isAnti() ? Max : this->getUpper();
1628  const auto& c = other->isAnti() ? Min : other->getLower();
1629  const auto& d = other->isAnti() ? Max : other->getUpper();
1630 
1631  const auto res = OR(bw, a, b, c, d);
1632  return RangeRef(new Range(Regular, bw, res.first, res.second));
1633 }
1634 
1635 RangeRef Range::And(const RangeConstRef& other) const
1636 {
1637  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1640  if(this->isConstant() && this->getSignedMax() == -1)
1641  {
1642  return RangeRef(other->clone());
1643  }
1644  if(other->isConstant() && other->getSignedMax() == -1)
1645  {
1646  return RangeRef(this->clone());
1647  }
1648 
1649  const auto& a = this->isAnti() ? Min : this->getLower();
1650  const auto& b = this->isAnti() ? Max : this->getUpper();
1651  const auto& c = other->isAnti() ? Min : other->getLower();
1652  const auto& d = other->isAnti() ? Max : other->getUpper();
1653 
1654  const auto res = AND(bw, a, b, c, d);
1655  return RangeRef(new Range(Regular, bw, res.first, res.second));
1656 }
1657 
1658 RangeRef Range::Xor(const RangeConstRef& other) const
1659 {
1660  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1663 
1664  const auto& a = this->isAnti() ? Min : this->getLower();
1665  const auto& b = this->isAnti() ? Max : this->getUpper();
1666  const auto& c = other->isAnti() ? Min : other->getLower();
1667  const auto& d = other->isAnti() ? Max : other->getUpper();
1668 
1669  if(a >= 0 && b >= 0 && c >= 0 && d >= 0)
1670  {
1671  const auto res = uXOR(bw, a, b, c, d);
1672  return RangeRef(new Range(Regular, bw, res.first, res.second));
1673  }
1674  else if(a == -1 && b == -1 && c >= 0 && d >= 0)
1675  {
1676  return this->sub(other);
1677  }
1678  else if(c == -1 && d == -1 && a >= 0 && b >= 0)
1679  {
1680  return other->sub(RangeRef(this->clone()));
1681  }
1682  return RangeRef(new Range(Regular, bw));
1683 }
1684 
1685 RangeRef Range::Not() const
1686 {
1687  THROW_ASSERT(!isReal(), "Real range is a storage class only");
1688  if(isEmpty() || isUnknown())
1689  {
1690  return RangeRef(new Range(this->type, bw));
1691  }
1692 
1693  const auto min = ~this->u;
1694  const auto max = ~this->l;
1695 
1696  return RangeRef(new Range(this->type, bw, min, max));
1697 }
1698 
1699 RangeRef Range::Eq(const RangeConstRef& other, bw_t _bw) const
1700 {
1701  THROW_ASSERT(!other->isReal(), "Real range is a storage class only");
1704  if(this->isAnti() && other->isAnti())
1705  {
1706  return RangeRef(new Range(Regular, _bw, 0, 1));
1707  }
1708  if(!this->isAnti() && !other->isAnti())
1709  {
1710  if((l == Min) || (u == Max) || (other->l == Min) || (other->u == Max))
1711  {
1712  return RangeRef(new Range(Regular, _bw, 0, 1));
1713  }
1714  }
1715  bool areTheyEqual = !this->intersectWith(other)->isEmpty();
1716  bool areTheyDifferent = !((l == u) && this->isSameRange(other));
1717 
1718  if(areTheyEqual && areTheyDifferent)
1719  {
1720  return RangeRef(new Range(Regular, _bw, 0, 1));
1721  }
1722  if(areTheyEqual && !areTheyDifferent)
1723  {
1724  return RangeRef(new Range(Regular, _bw, 1, 1));
1725  }
1726  if(!areTheyEqual && areTheyDifferent)
1727  {
1728  return RangeRef(new Range(Regular, _bw, 0, 0));
1729  }
1730 
1731  THROW_UNREACHABLE("condition unexpected");
1732  return nullptr;
1733 }
1734 
1735 RangeRef Range::Ne(const RangeConstRef& other, bw_t _bw) const
1736 {
1737  THROW_ASSERT(!other->isReal(), "Real range is a storage class only");
1740  if(this->isAnti() && other->isAnti())
1741  {
1742  return RangeRef(new Range(Regular, _bw, 0, 1));
1743  }
1744  if(!this->isAnti() && !other->isAnti())
1745  {
1746  if((l == Min) || (u == Max) || (other->l == Min) || (other->u == Max))
1747  {
1748  return RangeRef(new Range(Regular, _bw, 0, 1));
1749  }
1750  }
1751  bool areTheyEqual = !this->intersectWith(other)->isEmpty();
1752  bool areTheyDifferent = !((l == u) && this->isSameRange(other));
1753  if(areTheyEqual && areTheyDifferent)
1754  {
1755  return RangeRef(new Range(Regular, _bw, 0, 1));
1756  }
1757  if(areTheyEqual && !areTheyDifferent)
1758  {
1759  return RangeRef(new Range(Regular, _bw, 0, 0));
1760  }
1761  if(!areTheyEqual && areTheyDifferent)
1762  {
1763  return RangeRef(new Range(Regular, _bw, 1, 1));
1764  }
1765 
1766  THROW_UNREACHABLE("condition unexpected");
1767  return nullptr;
1768 }
1769 
1770 RangeRef Range::Ugt(const RangeConstRef& other, bw_t _bw) const
1771 {
1772  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1775  if(isAnti() || other->isAnti())
1776  {
1777  return RangeRef(new Range(Regular, _bw, 0, 1));
1778  }
1779 
1780  const auto a = this->getUnsignedMin();
1781  const auto b = this->getUnsignedMax();
1782  const auto c = other->getUnsignedMin();
1783  const auto d = other->getUnsignedMax();
1784  if(a > d)
1785  {
1786  return RangeRef(new Range(Regular, _bw, 1, 1));
1787  }
1788  if(c >= b)
1789  {
1790  return RangeRef(new Range(Regular, _bw, 0, 0));
1791  }
1792 
1793  return RangeRef(new Range(Regular, _bw, 0, 1));
1794 }
1795 
1796 RangeRef Range::Uge(const RangeConstRef& other, bw_t _bw) const
1797 {
1798  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1801  if(isAnti() || other->isAnti())
1802  {
1803  return RangeRef(new Range(Regular, _bw, 0, 1));
1804  }
1805 
1806  const auto a = this->getUnsignedMin();
1807  const auto b = this->getUnsignedMax();
1808  const auto c = other->getUnsignedMin();
1809  const auto d = other->getUnsignedMax();
1810  if(a >= d)
1811  {
1812  return RangeRef(new Range(Regular, _bw, 1, 1));
1813  }
1814  if(c > b)
1815  {
1816  return RangeRef(new Range(Regular, _bw, 0, 0));
1817  }
1818 
1819  return RangeRef(new Range(Regular, _bw, 0, 1));
1820 }
1821 
1822 RangeRef Range::Ult(const RangeConstRef& other, bw_t _bw) const
1823 {
1824  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1827  if(isAnti() || other->isAnti())
1828  {
1829  return RangeRef(new Range(Regular, _bw, 0, 1));
1830  }
1831 
1832  const auto a = this->getUnsignedMin();
1833  const auto b = this->getUnsignedMax();
1834  const auto c = other->getUnsignedMin();
1835  const auto d = other->getUnsignedMax();
1836  if(b < c)
1837  {
1838  return RangeRef(new Range(Regular, _bw, 1, 1));
1839  }
1840  if(d <= a)
1841  {
1842  return RangeRef(new Range(Regular, _bw, 0, 0));
1843  }
1844 
1845  return RangeRef(new Range(Regular, _bw, 0, 1));
1846 }
1847 
1848 RangeRef Range::Ule(const RangeConstRef& other, bw_t _bw) const
1849 {
1850  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1853  if(isAnti() || other->isAnti())
1854  {
1855  return RangeRef(new Range(Regular, _bw, 0, 1));
1856  }
1857 
1858  const auto a = this->getUnsignedMin();
1859  const auto b = this->getUnsignedMax();
1860  const auto c = other->getUnsignedMin();
1861  const auto d = other->getUnsignedMax();
1862  if(b <= c)
1863  {
1864  return RangeRef(new Range(Regular, _bw, 1, 1));
1865  }
1866  if(d < a)
1867  {
1868  return RangeRef(new Range(Regular, _bw, 0, 0));
1869  }
1870 
1871  return RangeRef(new Range(Regular, _bw, 0, 1));
1872 }
1873 
1874 RangeRef Range::Sgt(const RangeConstRef& other, bw_t _bw) const
1875 {
1876  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1879  if(isAnti() || other->isAnti())
1880  {
1881  return RangeRef(new Range(Regular, _bw, 0, 1));
1882  }
1883 
1884  const auto a = this->getSignedMin();
1885  const auto b = this->getSignedMax();
1886  const auto c = other->getSignedMin();
1887  const auto d = other->getSignedMax();
1888  if(a > d)
1889  {
1890  return RangeRef(new Range(Regular, _bw, 1, 1));
1891  }
1892  if(c >= b)
1893  {
1894  return RangeRef(new Range(Regular, _bw, 0, 0));
1895  }
1896 
1897  return RangeRef(new Range(Regular, _bw, 0, 1));
1898 }
1899 
1900 RangeRef Range::Sge(const RangeConstRef& other, bw_t _bw) const
1901 {
1902  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1905  if(isAnti() || other->isAnti())
1906  {
1907  return RangeRef(new Range(Regular, _bw, 0, 1));
1908  }
1909 
1910  const auto a = this->getSignedMin();
1911  const auto b = this->getSignedMax();
1912  const auto c = other->getSignedMin();
1913  const auto d = other->getSignedMax();
1914  if(a >= d)
1915  {
1916  return RangeRef(new Range(Regular, _bw, 1, 1));
1917  }
1918  if(c > b)
1919  {
1920  return RangeRef(new Range(Regular, _bw, 0, 0));
1921  }
1922 
1923  return RangeRef(new Range(Regular, _bw, 0, 1));
1924 }
1925 
1926 RangeRef Range::Slt(const RangeConstRef& other, bw_t _bw) const
1927 {
1928  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1931  if(isAnti() || other->isAnti())
1932  {
1933  return RangeRef(new Range(Regular, _bw, 0, 1));
1934  }
1935 
1936  const auto a = this->getSignedMin();
1937  const auto b = this->getSignedMax();
1938  const auto c = other->getSignedMin();
1939  const auto d = other->getSignedMax();
1940  if(b < c)
1941  {
1942  return RangeRef(new Range(Regular, _bw, 1, 1));
1943  }
1944  if(d <= a)
1945  {
1946  return RangeRef(new Range(Regular, _bw, 0, 0));
1947  }
1948 
1949  return RangeRef(new Range(Regular, _bw, 0, 1));
1950 }
1951 
1952 RangeRef Range::Sle(const RangeConstRef& other, bw_t _bw) const
1953 {
1954  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1957  if(isAnti() || other->isAnti())
1958  {
1959  return RangeRef(new Range(Regular, _bw, 0, 1));
1960  }
1961 
1962  const auto a = this->getSignedMin();
1963  const auto b = this->getSignedMax();
1964  const auto c = other->getSignedMin();
1965  const auto d = other->getSignedMax();
1966  if(b <= c)
1967  {
1968  return RangeRef(new Range(Regular, _bw, 1, 1));
1969  }
1970  if(d < a)
1971  {
1972  return RangeRef(new Range(Regular, _bw, 0, 0));
1973  }
1974 
1975  return RangeRef(new Range(Regular, _bw, 0, 1));
1976 }
1977 
1978 RangeRef Range::SMin(const RangeConstRef& other) const
1979 {
1980  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
1983  if(isAnti() || other->isAnti())
1984  {
1985  return RangeRef(new Range(Regular, bw));
1986  }
1987 
1988  const auto thisMin = this->Slt(other, 1);
1989  if(thisMin->isConstant())
1990  {
1991  return thisMin->getUnsignedMin() ? RangeRef(this->clone()) : RangeRef(other->clone());
1992  }
1993  const auto min = std::min({this->getSignedMin(), other->getSignedMin()});
1994  const auto max = std::min({this->getSignedMax(), other->getSignedMax()});
1995  return RangeRef(new Range(Regular, bw, min, max));
1996 }
1997 
1998 RangeRef Range::SMax(const RangeConstRef& other) const
1999 {
2000  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
2003  if(isAnti() || other->isAnti())
2004  {
2005  return RangeRef(new Range(Regular, bw));
2006  }
2007 
2008  const auto thisMax = this->Sgt(other, 1);
2009  if(thisMax->isConstant())
2010  {
2011  return thisMax->getUnsignedMin() ? RangeRef(this->clone()) : RangeRef(other->clone());
2012  }
2013  const auto min = std::max({this->getSignedMin(), other->getSignedMin()});
2014  const auto max = std::max({this->getSignedMax(), other->getSignedMax()});
2015  return RangeRef(new Range(Regular, bw, min, max));
2016 }
2017 
2018 RangeRef Range::UMin(const RangeConstRef& other) const
2019 {
2020  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
2023  if(isAnti() || other->isAnti())
2024  {
2025  return RangeRef(new Range(Regular, bw));
2026  }
2027 
2028  const auto thisMin = this->Ult(other, 1);
2029  if(thisMin->isConstant())
2030  {
2031  return thisMin->getUnsignedMin() ? RangeRef(this->clone()) : RangeRef(other->clone());
2032  }
2033  const auto min = std::min({this->getUnsignedMin(), other->getUnsignedMin()});
2034  const auto max = std::min({this->getUnsignedMax(), other->getUnsignedMax()});
2035  return RangeRef(new Range(Regular, bw, min, max));
2036 }
2037 
2038 RangeRef Range::UMax(const RangeConstRef& other) const
2039 {
2040  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
2043  if(isAnti() || other->isAnti())
2044  {
2045  return RangeRef(new Range(Regular, bw));
2046  }
2047 
2048  const auto thisMax = this->Ugt(other, 1);
2049  if(thisMax->isConstant())
2050  {
2051  return thisMax->getUnsignedMin() ? RangeRef(this->clone()) : RangeRef(other->clone());
2052  }
2053  const auto min = std::max({this->getUnsignedMin(), other->getUnsignedMin()});
2054  const auto max = std::max({this->getUnsignedMax(), other->getUnsignedMax()});
2055  return RangeRef(new Range(Regular, bw, min, max));
2056 }
2057 
2058 RangeRef Range::abs() const
2059 {
2060  if(isEmpty() || isUnknown())
2061  {
2062  return RangeRef(this->clone());
2063  }
2064  if(isAnti())
2065  {
2066  if(u < 0)
2067  {
2068  if(l == APInt::getSignedMinValue(bw))
2069  {
2070  return RangeRef(new Range(Regular, bw, 0, APInt::getSignedMaxValue(bw)));
2071  }
2072  return RangeRef(new Range(Anti, bw, APInt::getSignedMinValue(bw) + 1, -1));
2073  }
2074  if(l < 0)
2075  {
2076  if(l == APInt::getSignedMinValue(bw))
2077  {
2078  return RangeRef(new Range(Regular, bw, u + 1, APInt::getSignedMaxValue(bw)));
2079  }
2080  const auto min = std::min({-l, u});
2081  return RangeRef(new Range(Anti, bw, APInt::getSignedMinValue(bw) + 1, min));
2082  }
2083  return RangeRef(new Range(Anti, bw, APInt::getSignedMinValue(bw) + 1, l == 0 ? 0 : -1));
2084  }
2085 
2086  const auto smin = getSignedMin();
2087  const auto smax = getSignedMax();
2088  if(smax < 0)
2089  {
2090  if(smin == APInt::getSignedMinValue(bw))
2091  {
2092  return RangeRef(new Range(Anti, bw, smin + 1, -smax - 1));
2093  }
2094  return RangeRef(new Range(Regular, bw, -smax, -smin));
2095  }
2096  if(smin < 0)
2097  {
2098  if(smin == APInt::getSignedMinValue(bw))
2099  {
2100  return RangeRef(new Range(Anti, bw, smin + 1, -1));
2101  }
2102  const auto max = std::max({smax, -smin});
2103  return RangeRef(new Range(Regular, bw, 0, max));
2104  }
2105  return RangeRef(this->clone());
2106 }
2107 
2108 RangeRef Range::negate() const
2109 {
2110  THROW_ASSERT(!isReal(), "Real range is a storage class only");
2111  if(isEmpty() || isUnknown())
2112  {
2113  return RangeRef(this->clone());
2114  }
2115  if(isAnti())
2116  {
2117  return RangeRef(new Range(Anti, bw, -u, -l));
2118  }
2119  return RangeRef(new Range(Regular, bw, -u, -l));
2120 }
2121 
2122 // Truncate
2123 // - if the source range is entirely inside max bit range, it is the result
2124 // - else, the result is the max bit range
2125 RangeRef Range::truncate(bw_t bitwidth) const
2126 {
2127  THROW_ASSERT(!isReal(), "Real range is a storage class only");
2128  if(isEmpty())
2129  {
2130  return RangeRef(new Range(Empty, bitwidth));
2131  }
2132  if(isUnknown())
2133  {
2134  return RangeRef(new Range(Unknown, bitwidth));
2135  }
2136  if(bitwidth == bw)
2137  {
2138  return RangeRef(this->clone());
2139  }
2140  const auto a = this->getSignedMin();
2141  const auto b = this->getSignedMax();
2142  if(isFullSet() || isAnti() || (b - a).abs() > APInt::getMaxValue(bitwidth))
2143  {
2144  return RangeRef(new Range(Regular, bitwidth));
2145  }
2146 
2147  const auto stmin = a.extOrTrunc(bitwidth, true);
2148  const auto stmax = b.extOrTrunc(bitwidth, true);
2149 
2150  if(a < 0 && b >= 0) // Zero crossing range
2151  {
2152  if(stmax < 0) // overflow
2153  {
2154  if(stmax >= stmin)
2155  {
2156  return RangeRef(new Range(Regular, bitwidth));
2157  }
2158  return RangeRef(new Range(Anti, bitwidth, stmax + 1, (stmin < 0 ? stmin : 0) - 1));
2159  }
2160  if(stmin > 0) // underflow
2161  {
2162  if(stmax >= stmin)
2163  {
2164  return RangeRef(new Range(Regular, bitwidth));
2165  }
2166  return RangeRef(new Range(Anti, bitwidth, stmax + 1, stmin - 1));
2167  }
2168  }
2169 
2170  if(stmin > stmax)
2171  {
2172  if(a.sign() == 1)
2173  {
2174  return RangeRef(new Range(Regular, bitwidth, stmax, stmin));
2175  }
2176  return RangeRef(new Range(Anti, bitwidth, stmax + 1, stmin - 1));
2177  }
2178  return RangeRef(new Range(Regular, bitwidth, stmin, stmax));
2179 }
2180 
2181 RangeRef Range::sextOrTrunc(bw_t bitwidth) const
2182 {
2183  if(bitwidth <= bw)
2184  {
2185  return truncate(bitwidth);
2186  }
2187  THROW_ASSERT(!isReal(), "Real range is a storage class only");
2188  if(isEmpty())
2189  {
2190  return RangeRef(new Range(Empty, bitwidth));
2191  }
2192  if(isUnknown())
2193  {
2194  return RangeRef(new Range(Unknown, bitwidth));
2195  }
2196 
2197  const auto this_min = this->getSignedMin();
2198  const auto this_max = this->getSignedMax();
2199 
2200  const auto res = std::minmax({this_min.extOrTrunc(bitwidth, true), this_max.extOrTrunc(bitwidth, true)});
2201  RangeRef sextRes(new Range(Regular, bitwidth, res.first, res.second));
2202  if(sextRes->isFullSet())
2203  {
2204  return RangeRef(new Range(Regular, bitwidth));
2205  }
2206  return sextRes;
2207 }
2208 
2209 RangeRef Range::zextOrTrunc(bw_t bitwidth) const
2210 {
2211  if(bitwidth <= bw)
2212  {
2213  return truncate(bitwidth);
2214  }
2215  THROW_ASSERT(!isReal(), "Real range is a storage class only");
2216  if(isEmpty())
2217  {
2218  return RangeRef(new Range(Empty, bitwidth));
2219  }
2220  if(isUnknown())
2221  {
2222  return RangeRef(new Range(Unknown, bitwidth));
2223  }
2224  if(isAnti())
2225  {
2227  {
2228  return RangeRef(new Range(Regular, bitwidth, u + 1, getUnsignedMax()));
2229  }
2230  return RangeRef(new Range(Regular, bitwidth, 0, APInt::getMaxValue(bw)));
2231  }
2232 
2233  if(this->getSignedMin() < 0 && this->getSignedMax() >= 0)
2234  {
2235  return RangeRef(new Range(Regular, bitwidth, 0, APInt::getMaxValue(bw)));
2236  }
2237 
2238  return RangeRef(new Range(Regular, bitwidth, this->getSignedMin().extOrTrunc(bw, false),
2239  this->getSignedMax().extOrTrunc(bw, false)));
2240 }
2241 
2242 RangeRef Range::intersectWith(const RangeConstRef& other) const
2243 {
2244 #ifdef DEBUG_RANGE_OP
2245  PRINT_MSG("intersectWith-this: " << *this << std::endl << "intersectWith-other: " << *other);
2246 #endif
2247  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
2250 
2251  if(!this->isAnti() && !other->isAnti())
2252  {
2253  APInt res_l = getLower() > other->getLower() ? getLower() : other->getLower();
2254  APInt res_u = getUpper() < other->getUpper() ? getUpper() : other->getUpper();
2255  if(res_u < res_l)
2256  {
2257  return RangeRef(new Range(Empty, bw));
2258  }
2259 
2260  return RangeRef(new Range(Regular, bw, res_l, res_u));
2261  }
2262  if(this->isAnti() && !other->isAnti())
2263  {
2264  auto antiRange = this->getAnti();
2265  auto antil = antiRange->getLower();
2266  auto antiu = antiRange->getUpper();
2267  if(antil <= other->getLower())
2268  {
2269  if(other->getUpper() <= antiu)
2270  {
2271  return RangeRef(new Range(Empty, bw));
2272  }
2273  APInt res_l = other->getLower() > antiu ? other->getLower() : antiu + 1;
2274  APInt res_u = other->getUpper();
2275  return RangeRef(new Range(Regular, bw, res_l, res_u));
2276  }
2277  if(antiu >= other->getUpper())
2278  {
2279  THROW_ASSERT(other->getLower() < antil, "");
2280  APInt res_l = other->getLower();
2281  APInt res_u = other->getUpper() < antil ? other->getUpper() : antil - 1;
2282  return RangeRef(new Range(Regular, bw, res_l, res_u));
2283  }
2284  if(other->getLower() == Min && other->getUpper() == Max)
2285  {
2286  return RangeRef(this->clone());
2287  }
2288  if(antil > other->getUpper() || antiu < other->getLower())
2289  {
2290  return RangeRef(other->clone());
2291  }
2292 
2293  // we approximate to the range of other
2294  return RangeRef(other->clone());
2295  }
2296  if(!this->isAnti() && other->isAnti())
2297  {
2298  auto antiRange = other->getAnti();
2299  auto antil = antiRange->getLower();
2300  auto antiu = antiRange->getUpper();
2301  if(antil <= this->getLower())
2302  {
2303  if(this->getUpper() <= antiu)
2304  {
2305  return RangeRef(new Range(Empty, bw));
2306  }
2307  APInt res_l = this->getLower() > antiu ? this->getLower() : antiu + 1;
2308  APInt res_u = this->getUpper();
2309  return RangeRef(new Range(Regular, bw, res_l, res_u));
2310  }
2311  if(antiu >= this->getUpper())
2312  {
2313  THROW_ASSERT(this->getLower() < antil, "");
2314  APInt res_l = this->getLower();
2315  APInt res_u = this->getUpper() < antil ? this->getUpper() : antil - 1;
2316  return RangeRef(new Range(Regular, bw, res_l, res_u));
2317  }
2318  if(this->getLower() == Min && this->getUpper() == Max)
2319  {
2320  return RangeRef(other->clone());
2321  }
2322  if(antil > this->getUpper() || antiu < this->getLower())
2323  {
2324  return RangeRef(this->clone());
2325  }
2326 
2327  // we approximate to the range of this
2328  return RangeRef(this->clone());
2329  }
2330 
2331  auto antiRange_a = this->getAnti();
2332  auto antiRange_b = other->getAnti();
2333  auto antil_a = antiRange_a->getLower();
2334  auto antiu_a = antiRange_a->getUpper();
2335  auto antil_b = antiRange_b->getLower();
2336  auto antiu_b = antiRange_b->getUpper();
2337  if(antil_a > antil_b)
2338  {
2339  std::swap(antil_a, antil_b);
2340  std::swap(antiu_a, antiu_b);
2341  }
2342  if(antil_b > (antiu_a + 1))
2343  {
2344  return RangeRef(new Range(Anti, bw, antil_a, antiu_a));
2345  }
2346  auto res_l = antil_a;
2347  auto res_u = antiu_a > antiu_b ? antiu_a : antiu_b;
2348  if(res_l == Min && res_u == Max)
2349  {
2350  return RangeRef(new Range(Empty, bw));
2351  }
2352 
2353  return RangeRef(new Range(Anti, bw, res_l, res_u));
2354 }
2355 
2356 RangeRef Range::unionWith(const RangeConstRef& other) const
2357 {
2358 #ifdef DEBUG_RANGE_OP
2359  PRINT_MSG("unionWith-this: " << *this << std::endl << "unionWith-other: " << *other);
2360 #endif
2361  THROW_ASSERT(!isReal() && !other->isReal(), "Real range is a storage class only");
2362  if(this->isEmpty() || this->isUnknown())
2363  {
2364  return RangeRef(other->clone());
2365  }
2366  if(other->isEmpty() || other->isUnknown())
2367  {
2368  return RangeRef(this->clone());
2369  }
2370  if(!this->isAnti() && !other->isAnti())
2371  {
2372  APInt res_l = getLower() < other->getLower() ? getLower() : other->getLower();
2373  APInt res_u = getUpper() > other->getUpper() ? getUpper() : other->getUpper();
2374  return RangeRef(new Range(Regular, bw, res_l, res_u));
2375  }
2376  if(this->isAnti() && !other->isAnti())
2377  {
2378  auto antiRange = this->getAnti();
2379  auto antil = antiRange->getLower();
2380  auto antiu = antiRange->getUpper();
2381  THROW_ASSERT(antil != Min, "");
2382  THROW_ASSERT(antiu != Max, "");
2383  if(antil > other->getUpper() || antiu < other->getLower())
2384  {
2385  return RangeRef(this->clone());
2386  }
2387  if(antil > other->getLower() && antiu < other->getUpper())
2388  {
2389  return RangeRef(new Range(Regular, bw));
2390  }
2391  if(antil >= other->getLower() && antiu > other->getUpper())
2392  {
2393  return RangeRef(new Range(Anti, bw, other->getUpper() + 1, antiu));
2394  }
2395  if(antil < other->getLower() && antiu <= other->getUpper())
2396  {
2397  return RangeRef(new Range(Anti, bw, antil, other->getLower() - 1));
2398  }
2399 
2400  return RangeRef(new Range(Regular, bw)); // approximate to the full set
2401  }
2402  if(!this->isAnti() && other->isAnti())
2403  {
2404  auto antiRange = other->getAnti();
2405  auto antil = antiRange->getLower();
2406  auto antiu = antiRange->getUpper();
2407  THROW_ASSERT(antil != Min, "");
2408  THROW_ASSERT(antiu != Max, "");
2409  if(antil > this->getUpper() || antiu < this->getLower())
2410  {
2411  return RangeRef(other->clone());
2412  }
2413  if(antil > this->getLower() && antiu < this->getUpper())
2414  {
2415  return RangeRef(new Range(Regular, bw));
2416  }
2417  if(antil >= this->getLower() && antiu > this->getUpper())
2418  {
2419  return RangeRef(new Range(Anti, bw, this->getUpper() + 1, antiu));
2420  }
2421  if(antil < this->getLower() && antiu <= this->getUpper())
2422  {
2423  return RangeRef(new Range(Anti, bw, antil, this->getLower() - 1));
2424  }
2425 
2426  return RangeRef(new Range(Regular, bw)); // approximate to the full set
2427  }
2428 
2429  auto antiRange_a = this->getAnti();
2430  auto antiRange_b = other->getAnti();
2431  auto antil_a = antiRange_a->getLower();
2432  auto antiu_a = antiRange_a->getUpper();
2433  THROW_ASSERT(antil_a != Min, "");
2434  THROW_ASSERT(antiu_a != Max, "");
2435  auto antil_b = antiRange_b->getLower();
2436  auto antiu_b = antiRange_b->getUpper();
2437  THROW_ASSERT(antil_b != Min, "");
2438  THROW_ASSERT(antiu_b != Max, "");
2439  if(antil_a > antiu_b || antiu_a < antil_b)
2440  {
2441  return RangeRef(new Range(Regular, bw));
2442  }
2443  if(antil_a > antil_b && antiu_a < antiu_b)
2444  {
2445  return RangeRef(this->clone());
2446  }
2447  if(antil_b > antil_a && antiu_b < antiu_a)
2448  {
2449  return RangeRef(this->clone());
2450  }
2451  if(antil_a >= antil_b && antiu_b <= antiu_a)
2452  {
2453  return RangeRef(new Range(Anti, bw, antil_a, antiu_b));
2454  }
2455  if(antil_b >= antil_a && antiu_a <= antiu_b)
2456  {
2457  return RangeRef(new Range(Anti, bw, antil_b, antiu_a));
2458  }
2459 
2460  THROW_UNREACHABLE("unsupported condition");
2461  return nullptr;
2462 }
2463 
2464 void Range::print(std::ostream& OS) const
2465 {
2466  if(this->isUnknown())
2467  {
2468  OS << "[Unknown," << +bw << "]";
2469  }
2470  else if(this->isEmpty())
2471  {
2472  OS << "[Empty," << +bw << "]";
2473  }
2474  else if(this->isAnti())
2475  {
2476  if(l == Min)
2477  {
2478  OS << ")-inf,";
2479  }
2480  else
2481  {
2482  OS << ")" << l << ",";
2483  }
2484  OS << +bw << ",";
2485  if(u == Max)
2486  {
2487  OS << "+inf(";
2488  }
2489  else
2490  {
2491  OS << u << "(";
2492  }
2493  }
2494  else
2495  {
2496  if(l == Min)
2497  {
2498  OS << "[-inf,";
2499  }
2500  else
2501  {
2502  OS << "[" << l << ",";
2503  }
2504  OS << +bw << ",";
2505  if(u == Max)
2506  {
2507  OS << "+inf]";
2508  }
2509  else
2510  {
2511  OS << u << "]";
2512  }
2513  }
2514 }
2515 
2516 std::string Range::ToString() const
2517 {
2518  std::stringstream ss;
2519  print(ss);
2520  return ss.str();
2521 }
2522 
2523 std::ostream& operator<<(std::ostream& OS, const Range& R)
2524 {
2525  R.print(OS);
2526  return OS;
2527 }
2528 
2529 RangeRef Range::makeSatisfyingCmpRegion(kind pred, const RangeConstRef& Other)
2530 {
2531  const auto bw = Other->bw;
2532  if(Other->isUnknown() || Other->isEmpty())
2533  {
2534  return RangeRef(Other->clone());
2535  }
2536  if(Other->isAnti() && pred != eq_expr_K && pred != ne_expr_K && pred != uneq_expr_K)
2537  {
2538  THROW_UNREACHABLE("Invalid request " + tree_node::GetString(pred) + " " + Other->ToString());
2539  return RangeRef(new Range(Empty, bw));
2540  }
2541  if(Other->isReal() && pred != eq_expr_K && pred != ne_expr_K && pred != uneq_expr_K)
2542  {
2543  THROW_UNREACHABLE("Compare region for real range not handled (" + tree_node::GetString(pred) + ")");
2544  }
2545 
2546  switch(pred)
2547  {
2548  case ge_expr_K:
2549  return RangeRef(new Range(Regular, bw, Other->getSignedMax(), APInt::getSignedMaxValue(bw)));
2550  case gt_expr_K:
2551  return RangeRef(new Range(Regular, bw, Other->getSignedMax() + MinDelta, APInt::getSignedMaxValue(bw)));
2552  case le_expr_K:
2553  return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw), Other->getSignedMin()));
2554  case lt_expr_K:
2555  return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw), Other->getSignedMin() - MinDelta));
2556  case unge_expr_K:
2557  return RangeRef(new Range(Regular, bw, Other->getUnsignedMax(), APInt::getMaxValue(bw)));
2558  case ungt_expr_K:
2559  return RangeRef(new Range(Regular, bw, Other->getUnsignedMax() + MinDelta, APInt::getMaxValue(bw)));
2560  case unle_expr_K:
2561  return RangeRef(new Range(Regular, bw, APInt::getMinValue(bw), Other->getUnsignedMin()));
2562  case unlt_expr_K:
2563  return RangeRef(new Range(Regular, bw, APInt::getMinValue(bw), Other->getUnsignedMin() - MinDelta));
2564  case uneq_expr_K:
2565  case eq_expr_K:
2566  return RangeRef(Other->clone());
2567  case ne_expr_K:
2568  return Other->getAnti();
2569 
2570  case assert_expr_K:
2571  case bit_and_expr_K:
2572  case bit_ior_expr_K:
2573  case bit_xor_expr_K:
2574  case catch_expr_K:
2575  case ceil_div_expr_K:
2576  case ceil_mod_expr_K:
2577  case complex_expr_K:
2578  case compound_expr_K:
2579  case eh_filter_expr_K:
2580  case exact_div_expr_K:
2581  case fdesc_expr_K:
2582  case floor_div_expr_K:
2583  case floor_mod_expr_K:
2584  case goto_subroutine_K:
2585  case in_expr_K:
2586  case init_expr_K:
2587  case lrotate_expr_K:
2588  case lshift_expr_K:
2589  case max_expr_K:
2590  case mem_ref_K:
2591  case min_expr_K:
2592  case minus_expr_K:
2593  case modify_expr_K:
2594  case mult_expr_K:
2595  case mult_highpart_expr_K:
2596  case ordered_expr_K:
2597  case plus_expr_K:
2598  case pointer_plus_expr_K:
2599  case postdecrement_expr_K:
2600  case postincrement_expr_K:
2601  case predecrement_expr_K:
2602  case preincrement_expr_K:
2603  case range_expr_K:
2604  case rdiv_expr_K:
2605  case round_div_expr_K:
2606  case round_mod_expr_K:
2607  case rrotate_expr_K:
2608  case rshift_expr_K:
2609  case set_le_expr_K:
2610  case trunc_div_expr_K:
2611  case trunc_mod_expr_K:
2612  case truth_and_expr_K:
2613  case truth_andif_expr_K:
2614  case truth_or_expr_K:
2615  case truth_orif_expr_K:
2616  case truth_xor_expr_K:
2617  case try_catch_expr_K:
2618  case try_finally_K:
2619  case ltgt_expr_K:
2620  case unordered_expr_K:
2621  case widen_sum_expr_K:
2622  case widen_mult_expr_K:
2623  case with_size_expr_K:
2624  case vec_lshift_expr_K:
2625  case vec_rshift_expr_K:
2626  case widen_mult_hi_expr_K:
2627  case widen_mult_lo_expr_K:
2628  case vec_pack_trunc_expr_K:
2629  case vec_pack_sat_expr_K:
2630  case vec_pack_fix_trunc_expr_K:
2631  case vec_extracteven_expr_K:
2632  case vec_extractodd_expr_K:
2633  case vec_interleavehigh_expr_K:
2634  case vec_interleavelow_expr_K:
2635  case extract_bit_expr_K:
2636  case sat_plus_expr_K:
2637  case sat_minus_expr_K:
2638  case extractvalue_expr_K:
2639  case extractelement_expr_K:
2640  case frem_expr_K:
2641  case CASE_UNARY_EXPRESSION:
2644  case CASE_TYPE_NODES:
2645  case CASE_CST_NODES:
2646  case CASE_DECL_NODES:
2647  case CASE_FAKE_NODES:
2648  case CASE_GIMPLE_NODES:
2649  case CASE_PRAGMA_NODES:
2650  case CASE_CPP_NODES:
2651  case CASE_MISCELLANEOUS:
2652  default:
2653  break;
2654  }
2655  THROW_UNREACHABLE("Unhandled compare operation (" + STR(pred) + ")");
2656  return nullptr;
2657 }
2658 
2659 // ========================================================================== //
2660 // RealRange
2661 // ========================================================================== //
2662 RealRange::RealRange(const Range& s, const Range& e, const Range& f)
2663  : Range(Real, static_cast<bw_t>(s.getBitWidth() + e.getBitWidth() + f.getBitWidth())),
2664  sign(s.clone()),
2665  exponent(e.clone()),
2666  significand(f.clone())
2667 {
2668  THROW_ASSERT(getBitWidth() == 32 || getBitWidth() == 64, "Composed range bitwidth not valid [" + s.ToString() + " " +
2669  e.ToString() + " " + f.ToString() + "]<" +
2670  STR(getBitWidth()) + ">");
2671  THROW_ASSERT(!s.isReal() && !e.isReal() && !f.isReal(), "Real range components shouldn't be real ranges");
2672 }
2673 
2674 RealRange::RealRange(const RangeConstRef& s, const RangeConstRef& e, const RangeConstRef& f)
2675  : Range(Real, static_cast<bw_t>(s->getBitWidth() + e->getBitWidth() + f->getBitWidth())),
2676  sign(s->clone()),
2677  exponent(e->clone()),
2678  significand(f->clone())
2679 {
2680  THROW_ASSERT(getBitWidth() == 32 || getBitWidth() == 64, "Composed range bitwidth not valid [" + s->ToString() +
2681  " " + e->ToString() + " " + f->ToString() + "]<" +
2682  STR(getBitWidth()) + ">");
2683  THROW_ASSERT(!s->isReal() && !e->isReal() && !f->isReal(), "Real range components shouldn't be real ranges");
2684 }
2685 
2686 RealRange::RealRange(const RangeConstRef& vc)
2687  : Range(Real, vc->getBitWidth()), sign(vc->Slt(RangeRef(new Range(Regular, 1, 0, 0)), 1))
2688 {
2689  if(vc->getBitWidth() == 32)
2690  {
2691  exponent = vc->shr(RangeRef(new Range(Regular, max_digits, 23, 23)), false)->zextOrTrunc(8);
2692  significand = vc->zextOrTrunc(23);
2693  }
2694  else if(vc->getBitWidth() == 64)
2695  {
2696  exponent = vc->shr(RangeRef(new Range(Regular, max_digits, 52, 52)), false)->zextOrTrunc(11);
2697  significand = vc->zextOrTrunc(52);
2698  }
2699  else
2700  {
2701  THROW_UNREACHABLE("Unhandled view convert bitwidth: could not transform " + vc->ToString() + " into real range");
2702  }
2703 }
2704 
2705 RangeRef RealRange::getRange() const
2706 {
2707  const auto _bw = getBitWidth();
2708  if(_bw == 32)
2709  {
2710  auto s = sign->zextOrTrunc(32)->shl(RangeRef(new Range(Regular, max_digits, 31, 31)));
2711  auto e = exponent->zextOrTrunc(32)->shl(RangeRef(new Range(Regular, max_digits, 23, 23)));
2712  return significand->zextOrTrunc(32)->Or(e)->Or(s);
2713  }
2714  else if(_bw == 64)
2715  {
2716  auto s = sign->zextOrTrunc(64)->shl(RangeRef(new Range(Regular, max_digits, 63, 63)));
2717  auto e = exponent->zextOrTrunc(64)->shl(RangeRef(new Range(Regular, max_digits, 52, 52)));
2718  return significand->zextOrTrunc(64)->Or(e)->Or(s);
2719  }
2720  THROW_UNREACHABLE("Unhandled view convert bitwidth");
2721  return nullptr;
2722 }
2723 
2724 RangeRef RealRange::getSign() const
2725 {
2726  return sign;
2727 }
2728 
2729 RangeRef RealRange::getExponent() const
2730 {
2731  return exponent;
2732 }
2733 
2735 {
2736  return significand;
2737 }
2738 
2739 std::deque<bit_lattice> RealRange::getBitValues(bool) const
2740 {
2741  const auto sign_bv = sign->getBitValues(true);
2742  auto exp_bv = exponent->getBitValues(true);
2743  if(exp_bv.size() < exponent->getBitWidth())
2744  {
2745  exp_bv = BitLatticeManipulator::sign_extend_bitstring(exp_bv, true, exponent->getBitWidth());
2746  }
2747  auto sig_bv = significand->getBitValues(true);
2748  if(sig_bv.size() < significand->getBitWidth())
2749  {
2750  sig_bv = BitLatticeManipulator::sign_extend_bitstring(sig_bv, true, significand->getBitWidth());
2751  }
2752  sig_bv.insert(sig_bv.begin(), exp_bv.begin(), exp_bv.end());
2753  sig_bv.insert(sig_bv.begin(), sign_bv.front());
2754  THROW_ASSERT(sig_bv.size() == getBitWidth(), "Floating-point bit_values must be exact");
2755  return sig_bv;
2756 }
2757 
2758 RangeRef RealRange::getAnti() const
2759 {
2760  return RangeRef(new RealRange(sign->getAnti(), exponent->getAnti(), significand->getAnti()));
2761 }
2762 
2763 void RealRange::setSign(const RangeConstRef& s)
2764 {
2765  sign.reset(s->clone());
2766 }
2767 
2768 void RealRange::setExponent(const RangeConstRef& e)
2769 {
2770  exponent.reset(e->clone());
2771 }
2772 
2773 void RealRange::setSignificand(const RangeConstRef& f)
2774 {
2775  significand.reset(f->clone());
2776 }
2777 
2778 bool RealRange::isSameRange(const RangeConstRef& other) const
2779 {
2780  if(other->isReal())
2781  {
2782  auto rOther = RefcountCast<const RealRange>(other);
2783  return this->getBitWidth() == other->getBitWidth() && sign->isSameRange(rOther->sign) &&
2784  exponent->isSameRange(rOther->exponent) && significand->isSameRange(rOther->significand);
2785  }
2786  return false;
2787 }
2788 
2790 {
2791  return sign->isEmpty() || exponent->isEmpty() || significand->isEmpty();
2792 }
2793 
2795 {
2796  return sign->isUnknown() || exponent->isUnknown() || significand->isUnknown();
2797 }
2798 
2800 {
2801  sign->setUnknown();
2802  exponent->setUnknown();
2803  significand->setUnknown();
2804 }
2805 
2807 {
2808  return sign->isFullSet() && exponent->isFullSet() && significand->isFullSet();
2809 }
2810 
2812 {
2813  return sign->isSingleElement() && exponent->isSingleElement() && significand->isSingleElement();
2814 }
2815 
2817 {
2818  return sign->isConstant() && exponent->isConstant() && significand->isConstant();
2819 }
2820 
2821 bool RealRange::isReal() const
2822 {
2823  return true;
2824 }
2825 
2826 void RealRange::print(std::ostream& OS) const
2827 {
2828  OS << "[ ";
2829  sign->print(OS);
2830  OS << ", ";
2831  exponent->print(OS);
2832  OS << ", ";
2833  significand->print(OS);
2834  OS << ", " << STR(getBitWidth()) << "]";
2835 }
2836 
2838 {
2839  return new RealRange(sign, exponent, significand);
2840 }
2841 
2842 RangeRef RealRange::abs() const
2843 {
2844  return RangeRef(new RealRange(RangeRef(new Range(Regular, 1, 0, 0)), exponent, significand));
2845 }
2846 
2847 RangeRef RealRange::negate() const
2848 {
2849  if(sign->isAnti() || sign->isConstant())
2850  {
2851  const auto s = sign->getUnsignedMin() ? 0 : 1;
2852  return RangeRef(new RealRange(RangeRef(new Range(Regular, 1, s, s)), exponent, significand));
2853  }
2854  return RangeRef(this->clone());
2855 }
2856 
2857 RangeRef RealRange::Eq(const RangeConstRef& other, bw_t _bw) const
2858 {
2859  if(const auto rOther = RefcountCast<const RealRange>(other))
2860  {
2861  const auto zeroEt = exponent->Eq(RangeRef(new Range(Regular, exponent->getBitWidth(), 0, 0)), 1);
2862  const auto zeroMt = significand->Eq(RangeRef(new Range(Regular, significand->getBitWidth(), 0, 0)), 1);
2863  const auto zeroContainedt = zeroEt->And(zeroMt);
2864  const auto zeroEo = rOther->exponent->Eq(RangeRef(new Range(Regular, rOther->exponent->getBitWidth(), 0, 0)), 1);
2865  const auto zeroMo =
2866  rOther->significand->Eq(RangeRef(new Range(Regular, rOther->significand->getBitWidth(), 0, 0)), 1);
2867  const auto zeroContainedo = zeroEo->And(zeroMo);
2868  const auto zeroContained = zeroContainedt->And(zeroContainedo);
2869  if(!zeroContained->isConstant() || zeroContained->getUnsignedMin() == 1)
2870  {
2871  return zeroContained->zextOrTrunc(_bw);
2872  }
2873  return sign->Eq(rOther->sign, 1)
2874  ->And(exponent->Eq(rOther->exponent, 1))
2875  ->And(significand->Eq(rOther->significand, 1))
2876  ->zextOrTrunc(_bw);
2877  }
2878  return RangeRef(new Range(Regular, _bw, 0, 0));
2879 }
2880 
2881 RangeRef RealRange::Ne(const RangeConstRef& other, bw_t _bw) const
2882 {
2883  return Eq(other, 1)->Not()->zextOrTrunc(_bw);
2884 }
2885 
2886 RangeRef RealRange::intersectWith(const RangeConstRef& other) const
2887 {
2888 #ifdef DEBUG_RANGE_OP
2889  PRINT_MSG("intersectWith-this: " << *this << std::endl << "intersectWith-other: " << *other);
2890 #endif
2891  THROW_ASSERT(other->isReal(), "Real range should intersect with real range only");
2892  auto rrOther = RefcountCast<const RealRange>(other);
2893  return RangeRef(new RealRange(sign->intersectWith(rrOther->sign), exponent->intersectWith(rrOther->exponent),
2894  significand->intersectWith(rrOther->significand)));
2895 }
2896 
2897 RangeRef RealRange::unionWith(const RangeConstRef& other) const
2898 {
2899 #ifdef DEBUG_RANGE_OP
2900  PRINT_MSG("unionWith-this: " << *this << std::endl << "unionWith-other: " << *other);
2901 #endif
2902  THROW_ASSERT(other->isReal(), "Real range should unite to real range only");
2903  auto rrOther = RefcountCast<const RealRange>(other);
2904  return RangeRef(new RealRange(sign->unionWith(rrOther->sign), exponent->unionWith(rrOther->exponent),
2905  significand->unionWith(rrOther->significand)));
2906 }
2907 
2908 RangeRef RealRange::toFloat64() const
2909 {
2910  if(getBitWidth() == 64)
2911  {
2912  return RangeRef(this->clone());
2913  }
2914 
2915  RangeRef exponent64;
2916  // Denormalized case
2917  if(exponent->isConstant() && exponent->getUnsignedMin() == 0)
2918  {
2919  exponent64.reset(new Range(Regular, 11, 0, 0));
2920  }
2921  else if(exponent->isFullSet())
2922  {
2923  exponent64.reset(new Range(Regular, 11));
2924  }
2925  else
2926  {
2927  exponent64.reset(new Range(Regular, 11, (exponent->getUnsignedMin() + 896).extOrTrunc(11, true),
2928  (exponent->getUnsignedMax() + 896).extOrTrunc(11, true)));
2929  }
2930 
2931  return RangeRef(
2932  new RealRange(sign, exponent64, significand->zextOrTrunc(52)->shl(RangeRef(new Range(Regular, 52, 29, 29)))));
2933 }
2934 
2935 RangeRef RealRange::toFloat32() const
2936 {
2937  if(getBitWidth() == 32)
2938  {
2939  return RangeRef(this->clone());
2940  }
2941 
2942  RangeRef exponent32;
2943  RangeRef significand32 = significand->shr(RangeRef(new Range(Regular, 52, 29, 29)), false)->zextOrTrunc(23);
2944  const auto min = exponent->getUnsignedMin() - 896;
2945  const auto max = exponent->getUnsignedMax() - 896;
2946  if(min < 0 && max > APInt::getMaxValue(8))
2947  {
2948  exponent32.reset(new Range(Regular, 8));
2949  }
2950  else if(exponent->isConstant() && min < 0)
2951  {
2952  exponent32.reset(new Range(Regular, 8, 0, 0));
2953  }
2954  else if(exponent->isConstant() && max >= APInt::getMaxValue(8))
2955  {
2956  exponent32.reset(new Range(Regular, 8, -1, -1));
2957  significand32.reset(new Range(Regular, 23, 0, 0));
2958  }
2959  else
2960  {
2961  exponent32.reset(new Range(Regular, 8, std::max({min, APInt(0)}).extOrTrunc(8, true),
2962  std::min({max, APInt(255)}).extOrTrunc(8, true)));
2963  }
2964 
2965  return RangeRef(new RealRange(sign, exponent32, significand32));
2966 }
2967 
2968 refcount<RealRange> RealRange::fromBitValues(const std::deque<bit_lattice>& bv)
2969 {
2970  THROW_ASSERT(bv.size() == 32 || bv.size() == 64, "Floating-point bit_values must be exact");
2971  const std::deque<bit_lattice> bv_exp(bv.begin() + 1, bv.begin() + (bv.size() == 64 ? 12 : 9));
2972  const std::deque<bit_lattice> bv_sigf(bv.begin() + 1 + static_cast<long>(bv_exp.size()), bv.end());
2973  return refcount<RealRange>(new RealRange(Range::fromBitValues({bv.front()}, 1, false),
2974  Range::fromBitValues(bv_exp, static_cast<bw_t>(bv_exp.size()), true),
2975  Range::fromBitValues(bv_sigf, static_cast<bw_t>(bv_sigf.size()), true)));
2976 }
virtual bool isSameRange(const RangeConstRef &other) const
Definition: Range.cpp:612
APInt & extOrTrunc(bw_t bw, bool sign)
Definition: APInt.cpp:285
bool isSingleElement() const override
Definition: Range.cpp:2811
Definition: Range.hpp:56
RangeRef getSign() const
Definition: Range.cpp:2724
void print(std::ostream &OS) const override
Definition: Range.cpp:2826
RangeRef zextOrTrunc(bw_t bitwidth) const
Definition: Range.cpp:2209
std::deque< bit_lattice > create_bitstring_from_constant(integer_cst_t value, unsigned long long len, bool signed_value)
Creates a bitstring from a constant input.
static APInt getSignedMinValue(bw_t bw)
Definition: APInt.cpp:434
RangeRef srem(const RangeConstRef &other) const
Definition: Range.cpp:1229
Range * clone() const override
Definition: Range.cpp:2837
APInt l
The lower bound of the range.
Definition: Range.hpp:70
RangeRef getExponent() const
Definition: Range.cpp:2729
virtual void print(std::ostream &OS) const
Definition: Range.cpp:2464
APInt getSignedMin() const
Definition: Range.cpp:521
virtual bool isConstant() const
Definition: Range.cpp:636
bool isSameRange(const RangeConstRef &other) const override
Definition: Range.cpp:2778
RangeRef Ne(const RangeConstRef &other, bw_t bw) const override
Definition: Range.cpp:2881
RangeRef significand
Definition: Range.hpp:177
TVMArray c2[1]
TVMArray c1[1]
RangeRef Ugt(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1770
RangeRef usat_add(const RangeConstRef &other) const
Definition: Range.cpp:770
APInt getSignedMax() const
Definition: Range.cpp:509
#define R
Definition: mips.c:40
RangeRef Sgt(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1874
virtual bool isFullSet() const
Definition: Range.cpp:617
RangeRef getRange() const
Definition: Range.cpp:2705
#define CASE_DECL_NODES
NOTE that cast_expr is a unary expression but it could not be included in the CASE_UNARY_EXPRESSION b...
Definition: tree_node.hpp:672
RangeRef SMax(const RangeConstRef &other) const
Definition: Range.cpp:1998
virtual RangeRef negate() const
Definition: Range.cpp:2108
std::string ToString() const
Definition: Range.cpp:2516
mathematical utility function not provided by standard libraries
const APInt & getUpper() const
Definition: Range.cpp:502
bool isSameType(const RangeConstRef &other) const
Definition: Range.cpp:607
static std::string GetString(const enum kind k)
Given a kind, return the corresponding string.
Definition: tree_node.cpp:120
RangeRef shl(const RangeConstRef &other) const
Definition: Range.cpp:1266
APInt::bw_t bw_t
Definition: Range.hpp:66
static const APInt MinDelta
Definition: Range.hpp:164
RangeRef add(const RangeConstRef &other) const
Definition: Range.cpp:652
Definition: Range.hpp:63
exceptions managed by PandA
Range::bw_t bw_t
Definition: Range.cpp:69
APInt u
The upper bound of the range.
Definition: Range.hpp:72
RangeRef sign
Definition: Range.hpp:175
static APInt getSignedMaxValue(bw_t bw)
Definition: APInt.cpp:429
RangeRef Xor(const RangeConstRef &other) const
Definition: Range.cpp:1658
void setSign(const RangeConstRef &s)
Definition: Range.cpp:2763
#define min(x, y)
RangeRef Ult(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1822
static refcount< RealRange > fromBitValues(const std::deque< bit_lattice > &bv)
Definition: Range.cpp:2968
#define DIV_HELPER(x, y)
Definition: Range.cpp:1085
void mm(int in_a[A_ROWS][A_COLS], int in_b[A_COLS][B_COLS], int out_c[A_ROWS][B_COLS])
Definition: module.c:6
static const APInt Max
Definition: Range.hpp:163
void setSignificand(const RangeConstRef &f)
Definition: Range.cpp:2773
bool isReal() const override
Definition: Range.cpp:2821
bool isFullSet() const override
Definition: Range.cpp:2806
#define STR(s)
Macro which performs a lexical_cast to a string.
APInt getSpan() const
Definition: Range.cpp:557
Auxiliary methods for manipulating string.
#define max
Definition: backprop.h:17
static void sign_reduce_bitstring(std::deque< bit_lattice > &bitstring, bool bitstring_is_signed)
Reduce the size of a bitstring erasing all but one most significant zeros in unsigned bitstring and a...
bw_t minBitwidth(bool sign) const
Definition: APInt.cpp:395
bool isRegular() const
Definition: Range.cpp:587
RangeRef unionWith(const RangeConstRef &other) const override
Definition: Range.cpp:2897
#define THROW_UNREACHABLE(str_expr)
helper function used to specify that some points should never be reached
Definition: exceptions.hpp:292
T ceil_log2(T x)
Return the smallest n such that 2**n >= X.
RangeRef Not() const
Definition: Range.cpp:1685
RangeRef exponent
Definition: Range.hpp:176
RangeRef And(const RangeConstRef &other) const
Definition: Range.cpp:1635
virtual bool isUnknown() const
Definition: Range.cpp:577
virtual RangeRef abs() const
Definition: Range.cpp:2058
#define CASE_QUATERNARY_EXPRESSION
This macro collects all case labels for quaternary_expr objects.
Definition: tree_node.hpp:574
#define CASE_UNARY_EXPRESSION
This macro collects all case labels for unary_expr objects.
Definition: tree_node.hpp:371
std::deque< bit_lattice > create_u_bitstring(size_t lenght)
Creates a bitstring containing bits initialized at <U>
static RangeRef makeSatisfyingCmpRegion(kind pred, const RangeConstRef &Other)
Definition: Range.cpp:2529
virtual bool isSingleElement() const
Definition: Range.cpp:627
RangeRef udiv(const RangeConstRef &other) const
Definition: Range.cpp:1057
void normalizeRange(const APInt &lb, const APInt &ub, RangeType rType)
Definition: Range.cpp:93
RangeRef sub(const RangeConstRef &other) const
Definition: Range.cpp:819
bool isUnknown() const override
Definition: Range.cpp:2794
static const bw_t max_digits
Definition: Range.hpp:161
bw_t getBitWidth() const
Definition: Range.cpp:490
static APInt getMaxValue(bw_t bw)
Definition: APInt.cpp:419
kind
APInt getUnsignedMin() const
Definition: Range.cpp:546
virtual void setUnknown()
Definition: Range.cpp:582
void setUnknown() override
Definition: Range.cpp:2799
RangeRef toFloat64() const
Definition: Range.cpp:2908
RangeRef abs() const override
Definition: Range.cpp:2842
RealRange(const Range &s, const Range &e, const Range &f)
Definition: Range.cpp:2662
RangeRef mul(const RangeConstRef &other) const
Definition: Range.cpp:1013
Classes specification of the tree_node data structures.
RangeRef getSignificand() const
Definition: Range.cpp:2734
bool isEmpty() const override
Definition: Range.cpp:2789
#define RETURN_EMPTY_ON_EMPTY(b)
Definition: Range.cpp:641
RangeRef Sge(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1900
RangeRef Or(const RangeConstRef &other) const
Definition: Range.cpp:1612
bw_t bw
the range bit-width
Definition: Range.hpp:74
#define CASE_TYPE_NODES
This macro collects all case labels for type objects.
Definition: tree_node.hpp:581
void setExponent(const RangeConstRef &e)
Definition: Range.cpp:2768
virtual RangeRef intersectWith(const RangeConstRef &other) const
Definition: Range.cpp:2242
RangeType type
the range type
Definition: Range.hpp:76
RangeRef truncate(bw_t bitwidth) const
Definition: Range.cpp:2125
#define OR
Definition: mips.c:52
#define CASE_MISCELLANEOUS
Definition: Range.cpp:51
Definition: APInt.hpp:53
RangeRef sextOrTrunc(bw_t bitwidth) const
Definition: Range.cpp:2181
bool isAnti() const
Definition: Range.cpp:592
RangeRef UMin(const RangeConstRef &other) const
Definition: Range.cpp:2018
RangeRef shr(const RangeConstRef &other, bool sign) const
Definition: Range.cpp:1319
virtual RangeRef Eq(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1699
#define CASE_CST_NODES
This macro collects all case labels for cast nodes.
Definition: tree_node.hpp:689
RangeRef Uge(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1796
RangeRef SMin(const RangeConstRef &other) const
Definition: Range.cpp:1978
#define CASE_FAKE_NODES
This macro collects all case labels for fake or empty nodes.
Definition: tree_node.hpp:635
Range(RangeType type, bw_t bw)
Definition: Range.cpp:77
Definition: Range.hpp:60
APInt getUnsignedMax() const
Definition: Range.cpp:533
virtual RangeRef unionWith(const RangeConstRef &other) const
Definition: Range.cpp:2356
RangeRef Slt(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1926
#define RETURN_UNKNOWN_ON_UNKNOWN(b)
Definition: Range.cpp:646
static bw_t neededBits(const APInt &a, const APInt &b, bool sign)
Definition: Range.cpp:360
#define AND
Definition: mips.c:51
static APInt getMinValue(bw_t bw)
Definition: APInt.cpp:424
RangeRef UMax(const RangeConstRef &other) const
Definition: Range.cpp:2038
Template borrowed from the ANTLR library by Terence Parr (http://www.jGuru.com - Software rights: htt...
Definition: refcount.hpp:94
std::ostream & operator<<(std::ostream &OS, const Range &R)
Definition: Range.cpp:2523
static std::deque< bit_lattice > sign_extend_bitstring(const std::deque< bit_lattice > &bitstring, bool bitstring_is_signed, size_t final_size)
Extends a bitstring.
RangeRef usat_sub(const RangeConstRef &other) const
Definition: Range.cpp:954
RangeRef urem(const RangeConstRef &other) const
Definition: Range.cpp:1177
#define CASE_CPP_NODES
This macro collects all case labels for cpp nodes.
Definition: tree_node.hpp:644
const APInt & getLower() const
Definition: Range.cpp:495
RangeRef Ule(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1848
RangeRef sat_sub(const RangeConstRef &other) const
Definition: Range.cpp:889
RangeRef Sle(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1952
virtual bool isEmpty() const
Definition: Range.cpp:597
Definition: Range.hpp:59
static const APInt Min
Definition: Range.hpp:162
uint32_t sign
#define CASE_GIMPLE_NODES
This macro collects all cases labels for gimple nodes.
Definition: tree_node.hpp:700
RangeType
Definition: Range.hpp:54
virtual RangeRef Ne(const RangeConstRef &other, bw_t bw) const
Definition: Range.cpp:1735
#define PRINT_MSG(mex)
RangeRef Eq(const RangeConstRef &other, bw_t bw) const override
Definition: Range.cpp:2857
static RangeRef fromBitValues(const std::deque< bit_lattice > &bv, bw_t bitwidth, bool isSigned)
Definition: Range.cpp:365
std::deque< bit_lattice > getBitValues(bool) const override
Definition: Range.cpp:2739
RangeRef intersectWith(const RangeConstRef &other) const override
Definition: Range.cpp:2886
bool isConstant() const override
Definition: Range.cpp:2816
virtual bool isReal() const
Definition: Range.cpp:602
virtual RangeRef getAnti() const
Definition: Range.cpp:464
RangeRef sdiv(const RangeConstRef &other) const
Definition: Range.cpp:1091
virtual Range * clone() const
Definition: Range.cpp:88
RangeRef getAnti() const override
Definition: Range.cpp:2758
virtual std::deque< bit_lattice > getBitValues(bool isSigned) const
Definition: Range.cpp:420
#define CASE_TERNARY_EXPRESSION
This macro collects all case labels for ternary_expr objects.
Definition: tree_node.hpp:550
RangeRef toFloat32() const
Definition: Range.cpp:2935
RangeRef sat_add(const RangeConstRef &other) const
Definition: Range.cpp:701
RangeRef negate() const override
Definition: Range.cpp:2847
#define CASE_PRAGMA_NODES
This macro collects all case labels for pragma objects.
Definition: tree_node.hpp:610
#define THROW_ASSERT(cond, str_expr)
helper function used to check an assert and if needed to throw an error in a standard way ...
Definition: exceptions.hpp:289

Generated on Mon Feb 12 2024 13:02:52 for PandA-2024.02 by doxygen 1.8.13