IceOperand.cpp revision 5fa0a5f7f730f33e6987527a261de8d833d7585c
1f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===- subzero/src/IceOperand.cpp - High-level operand implementation -----===//
2f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
3f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//                        The Subzero Code Generator
4f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
5f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// This file is distributed under the University of Illinois Open Source
6f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// License. See LICENSE.TXT for details.
7f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//
8f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file
1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Implements the Operand class and its target-independent subclasses,
1292a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// primarily for the methods of the Variable class.
139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull///
14f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth//===----------------------------------------------------------------------===//
15f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
1667f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceOperand.h"
1767f8de9adf6439881a00d8e0f081918436c71f62John Porto
18f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceCfg.h"
19144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth#include "IceCfgNode.h"
20f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth#include "IceInst.h"
21ec3f56532be1792d04ed470221df663bb8ca9c19John Porto#include "IceInstVarIter.h"
225bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth#include "IceTargetLowering.h" // dumping stack/frame pointer register
23f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
24f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnothnamespace Ice {
25f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
26d2cb4361c732dcddc98659415f37be45982e20c3Jim Stichnothbool operator==(const RelocatableTuple &A, const RelocatableTuple &B) {
2727fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  // A and B are the same if:
2827fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  //   (1) they have the same name; and
2927fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  //   (2) they have the same offset.
3027fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  //
3127fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  // (1) is trivial to check, but (2) requires some care.
3227fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  //
3327fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  // For (2):
3427fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  //  if A and B have known offsets (i.e., no symbolic references), then
3527fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  //     A == B -> A.Offset == B.Offset.
3627fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  //  else each element i in A.OffsetExpr[i] must be the same (or have the same
3727fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  //    value) as B.OffsetExpr[i].
3827fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  if (A.Name != B.Name) {
3927fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    return false;
4027fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  }
4127fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto
4227fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  bool BothHaveKnownOffsets = true;
4327fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  RelocOffsetT OffsetA = 0;
4427fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  RelocOffsetT OffsetB = 0;
4527fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  for (SizeT i = 0; i < A.OffsetExpr.size() && BothHaveKnownOffsets; ++i) {
4627fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    BothHaveKnownOffsets = A.OffsetExpr[i]->hasOffset();
4727fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    if (BothHaveKnownOffsets) {
4827fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      OffsetA += A.OffsetExpr[i]->getOffset();
4927fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    }
5027fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  }
5127fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  for (SizeT i = 0; i < B.OffsetExpr.size() && BothHaveKnownOffsets; ++i) {
5227fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    BothHaveKnownOffsets = B.OffsetExpr[i]->hasOffset();
5327fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    if (BothHaveKnownOffsets) {
5427fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      OffsetB += B.OffsetExpr[i]->getOffset();
5527fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    }
5627fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  }
5727fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  if (BothHaveKnownOffsets) {
5827fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    // Both have known offsets (i.e., no unresolved symbolic references), so
5927fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    // A == B -> A.Offset == B.Offset.
6027fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    return OffsetA == OffsetB;
6127fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  }
6227fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto
6327fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  // Otherwise, A and B are not the same if their OffsetExpr's have different
6427fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  // sizes.
6527fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  if (A.OffsetExpr.size() != B.OffsetExpr.size()) {
6627fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    return false;
6727fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  }
6827fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto
6927fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  // If the OffsetExprs' sizes are the same, then
7027fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  // for each i in OffsetExprSize:
7127fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  for (SizeT i = 0; i < A.OffsetExpr.size(); ++i) {
7227fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    const auto *const RelocOffsetA = A.OffsetExpr[i];
7327fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    const auto *const RelocOffsetB = B.OffsetExpr[i];
7427fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    if (RelocOffsetA->hasOffset() && RelocOffsetB->hasOffset()) {
7527fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      // A.OffsetExpr[i].Offset == B.OffsetExpr[i].Offset iff they are both
7627fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      // defined;
7727fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      if (RelocOffsetA->getOffset() != RelocOffsetB->getOffset()) {
7827fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto        return false;
7927fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      }
8027fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    } else if (RelocOffsetA != RelocOffsetB) {
8127fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      // or, if they are undefined, then the RelocOffsets must be the same.
8227fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      return false;
8327fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    }
8427fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  }
8527fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto
8627fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  return true;
87f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}
88f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
898aa396610b7baf728631a43ea16ad3d13e38397aJim StichnothRegNumT::BaseType RegNumT::Limit = 0;
908aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth
915bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothbool operator<(const RegWeight &A, const RegWeight &B) {
925bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  return A.getWeight() < B.getWeight();
935bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}
945bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothbool operator<=(const RegWeight &A, const RegWeight &B) { return !(B < A); }
955bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothbool operator==(const RegWeight &A, const RegWeight &B) {
965bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  return !(B < A) && !(A < B);
975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}
985bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
99d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnothvoid LiveRange::addSegment(InstNumberT Start, InstNumberT End) {
100e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth  if (!Range.empty()) {
101e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    // Check for merge opportunity.
102e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    InstNumberT CurrentEnd = Range.back().second;
103e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    assert(Start >= CurrentEnd);
104e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    if (Start == CurrentEnd) {
105e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth      Range.back().second = End;
106e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth      return;
107e5b73e6e3aa4e9f9819494d34662f3f6d928b078Jim Stichnoth    }
108d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
109d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  Range.push_back(RangeElementType(Start, End));
110d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth}
111d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
11257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// Returns true if this live range ends before Other's live range starts. This
11357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// means that the highest instruction number in this live range is less than or
11457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// equal to the lowest instruction number of the Other live range.
115d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnothbool LiveRange::endsBefore(const LiveRange &Other) const {
116d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // Neither range should be empty, but let's be graceful.
117d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  if (Range.empty() || Other.Range.empty())
118d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    return true;
119d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT MyEnd = (*Range.rbegin()).second;
120d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  InstNumberT OtherStart = (*Other.Range.begin()).first;
121d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  return MyEnd <= OtherStart;
122d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth}
123d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
124d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth// Returns true if there is any overlap between the two live ranges.
125037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnothbool LiveRange::overlaps(const LiveRange &Other, bool UseTrimmed) const {
126d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  // Do a two-finger walk through the two sorted lists of segments.
127037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth  auto I1 = (UseTrimmed ? TrimmedBegin : Range.begin()),
128037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth       I2 = (UseTrimmed ? Other.TrimmedBegin : Other.Range.begin());
129037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth  auto E1 = Range.end(), E2 = Other.Range.end();
130d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  while (I1 != E1 && I2 != E2) {
131d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (I1->second <= I2->first) {
132d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      ++I1;
133d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      continue;
134d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    }
135d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    if (I2->second <= I1->first) {
136d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      ++I2;
137d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      continue;
138d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    }
139d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth    return true;
140d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
141d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  return false;
142d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth}
143d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
144037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnothbool LiveRange::overlapsInst(InstNumberT OtherBegin, bool UseTrimmed) const {
145c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth  bool Result = false;
146037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth  for (auto I = (UseTrimmed ? TrimmedBegin : Range.begin()), E = Range.end();
147037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth       I != E; ++I) {
148037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth    if (OtherBegin < I->first) {
149c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth      Result = false;
150c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth      break;
151c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    }
152037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth    if (OtherBegin < I->second) {
153c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth      Result = true;
154c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth      break;
155c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth    }
156c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth  }
15757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // This is an equivalent but less inefficient implementation. It's expensive
15857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // enough that we wouldn't want to run it under any build, but it could be
15957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // enabled if e.g. the LiveRange implementation changes and extra testing is
16057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // needed.
16120b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (BuildDefs::extraValidation()) {
16220b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    LiveRange Temp;
16320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    Temp.addSegment(OtherBegin, OtherBegin + 1);
16420b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    bool Validation = overlaps(Temp);
16520b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    (void)Validation;
16620b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth    assert(Result == Validation);
16720b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  }
168c4554d784583d26a02eca8610b43511ade516082Jim Stichnoth  return Result;
169d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth}
170d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
17157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// Returns true if the live range contains the given instruction number. This
17257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// is only used for validating the live range calculation. The IsDest argument
17357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// indicates whether the Variable being tested is used in the Dest position (as
17457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// opposed to a Src position).
1754775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnothbool LiveRange::containsValue(InstNumberT Value, bool IsDest) const {
176f44f371b7f3fab5683e6781873d71987e44fea2fJim Stichnoth  for (const RangeElementType &I : Range) {
1774775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth    if (I.first <= Value &&
1784775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth        (Value < I.second || (!IsDest && Value == I.second)))
179d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      return true;
180d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
181d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  return false;
182d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth}
183d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
184037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnothvoid LiveRange::trim(InstNumberT Lower) {
185037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth  while (TrimmedBegin != Range.end() && TrimmedBegin->second <= Lower)
186037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth    ++TrimmedBegin;
187037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth}
188037fa1d997307fd68c7e6d9c385e30890d65604dJim Stichnoth
1899a04c0760fe48d0003ffcc5be13f67ccd924a9a4Jim StichnothIceString Variable::getName(const Cfg *Func) const {
1909a04c0760fe48d0003ffcc5be13f67ccd924a9a4Jim Stichnoth  if (Func && NameIndex >= 0)
1919a04c0760fe48d0003ffcc5be13f67ccd924a9a4Jim Stichnoth    return Func->getIdentifierName(NameIndex);
192088b2be278dde516d097caec0d1bfb5c47e7bb04Jim Stichnoth  return "__" + std::to_string(getIndex());
193f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}
194f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
1958aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnothconst Variable *Variable::asType(Type Ty, RegNumT NewRegNum) const {
19657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // Note: This returns a Variable, even if the "this" object is a subclass of
19757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // Variable.
19820b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (!BuildDefs::dump() || getType() == Ty)
19931c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth    return this;
20031c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth  Variable *V = new (getCurrentCfgAllocator()->Allocate<Variable>())
20131c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth      Variable(kVariable, Ty, Number);
20231c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth  V->NameIndex = NameIndex;
2035fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler  V->RegNum = NewRegNum.hasValue() ? NewRegNum : RegNum;
20431c955905a2d861a944f1e0ca60cd9e4c6f1b37dJim Stichnoth  V->StackOffset = StackOffset;
2055bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  return V;
2065bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}
2075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
20811c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew ScullRegWeight Variable::getWeight(const Cfg *Func) const {
20911c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull  VariablesMetadata *VMetadata = Func->getVMetadata();
210aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  return mustHaveReg() ? RegWeight(RegWeight::Inf)
211aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull                       : mustNotHaveReg() ? RegWeight(RegWeight::Zero)
212aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull                                          : VMetadata->getUseWeight(this);
21311c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull}
21411c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull
215877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnothvoid VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
216a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth                               CfgNode *Node, bool IsImplicit) {
217877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  (void)TrackingKind;
21811c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull
219aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  // Increment the use weight depending on the loop nest depth. The weight is
220aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  // exponential in the nest depth as inner loops are expected to be executed
221aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  // an exponentially greater number of times.
222aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  constexpr uint32_t LogLoopTripCountEstimate = 2; // 2^2 = 4
223aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  constexpr SizeT MaxShift = sizeof(uint32_t) * CHAR_BIT - 1;
224aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  constexpr SizeT MaxLoopNestDepth = MaxShift / LogLoopTripCountEstimate;
225aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  const uint32_t LoopNestDepth =
226aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull      std::min(Node->getLoopNestDepth(), MaxLoopNestDepth);
227aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  const uint32_t ThisUseWeight = uint32_t(1)
228aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull                                 << LoopNestDepth * LogLoopTripCountEstimate;
229aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull  UseWeight.addWeight(ThisUseWeight);
23011c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull
2314775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth  if (MultiBlock == MBS_MultiBlock)
2324775255d4244c3425da0a7afd5f2c1ccb3a7dca9Jim Stichnoth    return;
23357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // TODO(stichnot): If the use occurs as a source operand in the first
23457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // instruction of the block, and its definition is in this block's only
23557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // predecessor, we might consider not marking this as a separate use. This
23657e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // may also apply if it's the first instruction of the block that actually
23757e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // uses a Variable.
238144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  assert(Node);
239144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  bool MakeMulti = false;
240ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  if (IsImplicit)
241ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    MakeMulti = true;
24257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // A phi source variable conservatively needs to be marked as multi-block,
24357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // even if its definition is in the same block. This is because there can be
24457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // additional control flow before branching back to this node, and the
24557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // variable is live throughout those nodes.
246a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth  if (Instr && llvm::isa<InstPhi>(Instr))
247144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    MakeMulti = true;
248144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
249144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  if (!MakeMulti) {
250144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    switch (MultiBlock) {
251144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    case MBS_Unknown:
252144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth      MultiBlock = MBS_SingleBlock;
253144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth      SingleUseNode = Node;
254144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth      break;
255144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    case MBS_SingleBlock:
256144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth      if (SingleUseNode != Node)
257144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth        MakeMulti = true;
258144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth      break;
259144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    case MBS_MultiBlock:
260144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth      break;
261144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    }
262144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  }
263144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
264144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  if (MakeMulti) {
265144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    MultiBlock = MBS_MultiBlock;
266ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth    SingleUseNode = nullptr;
267144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  }
268144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth}
269144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
270877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnothvoid VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr,
271a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth                               CfgNode *Node) {
27257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // TODO(stichnot): If the definition occurs in the last instruction of the
27357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // block, consider not marking this as a separate use. But be careful not to
27457e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // omit all uses of the variable if markDef() and markUse() both use this
27557e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull  // optimization.
276ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  assert(Node);
27748e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  // Verify that instructions are added in increasing order.
27848e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  if (BuildDefs::asserts()) {
27948e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth    if (TrackingKind == VMK_All) {
28048e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth      const Inst *LastInstruction =
28148e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth          Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
28248e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth      (void)LastInstruction;
28348e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth      assert(LastInstruction == nullptr ||
28448e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth             Instr->getNumber() >= LastInstruction->getNumber());
28548e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth    }
286877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  }
287a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth  constexpr bool IsImplicit = false;
288a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth  markUse(TrackingKind, Instr, Node, IsImplicit);
289877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  if (TrackingKind == VMK_Uses)
290877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth    return;
291ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  if (FirstOrSingleDefinition == nullptr)
292877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth    FirstOrSingleDefinition = Instr;
293877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  else if (TrackingKind == VMK_All)
294877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth    Definitions.push_back(Instr);
295144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  switch (MultiDef) {
296144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  case MDS_Unknown:
297ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth    assert(SingleDefNode == nullptr);
298144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    MultiDef = MDS_SingleDef;
299ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    SingleDefNode = Node;
300144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    break;
301144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  case MDS_SingleDef:
302ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    assert(SingleDefNode);
303ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    if (Node == SingleDefNode) {
304ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth      MultiDef = MDS_MultiDefSingleBlock;
305ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    } else {
306ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth      MultiDef = MDS_MultiDefMultiBlock;
307ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth      SingleDefNode = nullptr;
308ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    }
309ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    break;
310ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_MultiDefSingleBlock:
311ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    assert(SingleDefNode);
312ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    if (Node != SingleDefNode) {
313ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth      MultiDef = MDS_MultiDefMultiBlock;
314ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth      SingleDefNode = nullptr;
315ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    }
316144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    break;
317ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_MultiDefMultiBlock:
318ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth    assert(SingleDefNode == nullptr);
319144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    break;
320144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  }
321144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth}
322144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
32348e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnothconst Inst *VariableTracking::getFirstDefinitionSingleBlock() const {
324ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  switch (MultiDef) {
325ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_Unknown:
326ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_MultiDefMultiBlock:
327ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth    return nullptr;
328ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_SingleDef:
329ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_MultiDefSingleBlock:
330877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth    assert(FirstOrSingleDefinition);
331877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth    return FirstOrSingleDefinition;
332ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  }
333ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  return nullptr;
334ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth}
335ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
336ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnothconst Inst *VariableTracking::getSingleDefinition() const {
337ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  switch (MultiDef) {
338ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_Unknown:
339ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_MultiDefMultiBlock:
340ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_MultiDefSingleBlock:
341ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth    return nullptr;
342ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  case MDS_SingleDef:
343877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth    assert(FirstOrSingleDefinition);
344877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth    return FirstOrSingleDefinition;
345ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  }
346ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  return nullptr;
347ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth}
348ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
34948e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnothconst Inst *VariableTracking::getFirstDefinition() const {
35048e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  switch (MultiDef) {
35148e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  case MDS_Unknown:
35248e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth    return nullptr;
35348e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  case MDS_MultiDefMultiBlock:
35448e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  case MDS_SingleDef:
35548e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  case MDS_MultiDefSingleBlock:
35648e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth    assert(FirstOrSingleDefinition);
35748e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth    return FirstOrSingleDefinition;
35848e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  }
35948e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  return nullptr;
36048e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth}
36148e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth
362877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnothvoid VariablesMetadata::init(MetadataKind TrackingKind) {
3638363a0668ce21ea0c2a61f78083b0536dbd89860Jim Stichnoth  TimerMarker T(TimerStack::TT_vmetadata, Func);
364877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  Kind = TrackingKind;
365144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Metadata.clear();
366144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  Metadata.resize(Func->getNumVariables());
367144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
368144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  // Mark implicit args as being used in the entry node.
369f44f371b7f3fab5683e6781873d71987e44fea2fJim Stichnoth  for (Variable *Var : Func->getImplicitArgs()) {
370a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth    constexpr Inst *NoInst = nullptr;
371a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth    CfgNode *EntryNode = Func->getEntryNode();
372a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth    constexpr bool IsImplicit = true;
373a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth    Metadata[Var->getIndex()].markUse(Kind, NoInst, EntryNode, IsImplicit);
374144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  }
375144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
376336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  for (CfgNode *Node : Func->getNodes())
377336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    addNode(Node);
378336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth}
379336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth
380336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnothvoid VariablesMetadata::addNode(CfgNode *Node) {
38148e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  if (Func->getNumVariables() > Metadata.size())
382336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    Metadata.resize(Func->getNumVariables());
383336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth
38429841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth  for (Inst &I : Node->getPhis()) {
38529841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth    if (I.isDeleted())
386336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth      continue;
38729841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth    if (Variable *Dest = I.getDest()) {
388336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth      SizeT DestNum = Dest->getIndex();
389336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth      assert(DestNum < Metadata.size());
39029841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth      Metadata[DestNum].markDef(Kind, &I, Node);
391336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    }
39229841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth    for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
39354f3d518805b04b3f2958b7906a7d07dedb4e1aeJim Stichnoth      if (auto *Var = llvm::dyn_cast<Variable>(I.getSrc(SrcNum))) {
394336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth        SizeT VarNum = Var->getIndex();
395336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth        assert(VarNum < Metadata.size());
396a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth        constexpr bool IsImplicit = false;
397a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim Stichnoth        Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
398144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth      }
399336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    }
400336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth  }
401336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth
40229841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth  for (Inst &I : Node->getInsts()) {
40329841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth    if (I.isDeleted())
404336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth      continue;
405bb8b624e7c2a4fcdf9275bad310df779797e91a8Jim Stichnoth    // Note: The implicit definitions (and uses) from InstFakeKill are
406bb8b624e7c2a4fcdf9275bad310df779797e91a8Jim Stichnoth    // deliberately ignored.
40729841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth    if (Variable *Dest = I.getDest()) {
408336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth      SizeT DestNum = Dest->getIndex();
409336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth      assert(DestNum < Metadata.size());
41029841e84014ccbe7344e00f44ce7695a017de69aJim Stichnoth      Metadata[DestNum].markDef(Kind, &I, Node);
411336f6c4a90e7f5ee156bc9a339d80c7def5ddeffJim Stichnoth    }
412ec3f56532be1792d04ed470221df663bb8ca9c19John Porto    FOREACH_VAR_IN_INST(Var, I) {
413ec3f56532be1792d04ed470221df663bb8ca9c19John Porto      SizeT VarNum = Var->getIndex();
414ec3f56532be1792d04ed470221df663bb8ca9c19John Porto      assert(VarNum < Metadata.size());
415ec3f56532be1792d04ed470221df663bb8ca9c19John Porto      constexpr bool IsImplicit = false;
416ec3f56532be1792d04ed470221df663bb8ca9c19John Porto      Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
417144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    }
418144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  }
419144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth}
420144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
421144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnothbool VariablesMetadata::isMultiDef(const Variable *Var) const {
422877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  assert(Kind != VMK_Uses);
423144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  if (Var->getIsArg())
424144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    return false;
425144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  if (!isTracked(Var))
426144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    return true; // conservative answer
427144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  SizeT VarNum = Var->getIndex();
428144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  // Conservatively return true if the state is unknown.
429144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
430144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth}
431144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
432144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnothbool VariablesMetadata::isMultiBlock(const Variable *Var) const {
433ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  if (Var->getIsArg())
434144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth    return true;
435ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  if (!isTracked(Var))
436ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    return true; // conservative answer
437144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  SizeT VarNum = Var->getIndex();
438144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  // Conservatively return true if the state is unknown.
439144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
440144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth}
441144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
44248e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnothconst Inst *
44348e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim StichnothVariablesMetadata::getFirstDefinitionSingleBlock(const Variable *Var) const {
444877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  assert(Kind != VMK_Uses);
445ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  if (!isTracked(Var))
446ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth    return nullptr; // conservative answer
447ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  SizeT VarNum = Var->getIndex();
44848e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  return Metadata[VarNum].getFirstDefinitionSingleBlock();
449ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth}
450ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
451ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnothconst Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
452877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  assert(Kind != VMK_Uses);
453144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  if (!isTracked(Var))
454ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth    return nullptr; // conservative answer
455144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  SizeT VarNum = Var->getIndex();
456ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  return Metadata[VarNum].getSingleDefinition();
457ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth}
458ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
45948e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnothconst Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
46048e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  assert(Kind != VMK_Uses);
46148e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  if (!isTracked(Var))
46248e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth    return nullptr; // conservative answer
46348e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  SizeT VarNum = Var->getIndex();
46448e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth  return Metadata[VarNum].getFirstDefinition();
46548e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth}
46648e3ae5c62d7e626ed1a0dbbe38a7cc11a356260Jim Stichnoth
467ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnothconst InstDefList &
468877b04e409637216712d3c36fc155b47f8bd8d38Jim StichnothVariablesMetadata::getLatterDefinitions(const Variable *Var) const {
469877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  assert(Kind == VMK_All);
470ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  if (!isTracked(Var))
471ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth    return NoDefinitions;
472ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth  SizeT VarNum = Var->getIndex();
473877b04e409637216712d3c36fc155b47f8bd8d38Jim Stichnoth  return Metadata[VarNum].getLatterDefinitions();
474144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth}
475144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
476a3f57b9a6c7dbd3be7bf86dba697e9219c3413b2Jim StichnothCfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
477144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  if (!isTracked(Var))
478ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth    return nullptr; // conservative answer
479144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  SizeT VarNum = Var->getIndex();
480144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth  return Metadata[VarNum].getNode();
481144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth}
482144cdceaebc730d39e35861e4cc9577545e26bceJim Stichnoth
483aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew ScullRegWeight VariablesMetadata::getUseWeight(const Variable *Var) const {
48411c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull  if (!isTracked(Var))
485aa6c109366408d066c4ac9e22c8c0ded6d18092fAndrew Scull    return RegWeight(1); // conservative answer
48611c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull  SizeT VarNum = Var->getIndex();
48711c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull  return Metadata[VarNum].getUseWeight();
48811c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull}
48911c9a325399b282cb4ea7d1d24d42fceeec2a09aAndrew Scull
490ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnothconst InstDefList VariablesMetadata::NoDefinitions;
491ad4035397bdf3484dbc12ade5f9ebd87fb5f037dJim Stichnoth
492f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth// ======================== dump routines ======================== //
493f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
4945bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnothvoid Variable::emit(const Cfg *Func) const {
49520b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (BuildDefs::dump())
496b6c96af1e5f019374ab93b2b66fbf79247d24660Karl Schimpf    Func->getTarget()->emitVariable(this);
4975bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}
4985bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
4992e8bfbb9e2a5be0271d771f197d629e6f7d3568eJim Stichnothvoid Variable::dump(const Cfg *Func, Ostream &Str) const {
50020b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (!BuildDefs::dump())
501b6c96af1e5f019374ab93b2b66fbf79247d24660Karl Schimpf    return;
502ae953202e3a647dde1c0778432a3e92dd2eff3f2Jim Stichnoth  if (Func == nullptr) {
5039a04c0760fe48d0003ffcc5be13f67ccd924a9a4Jim Stichnoth    Str << "%" << getName(Func);
5042e8bfbb9e2a5be0271d771f197d629e6f7d3568eJim Stichnoth    return;
5052e8bfbb9e2a5be0271d771f197d629e6f7d3568eJim Stichnoth  }
506fa4efea5413aa993e8e6ba10579e0934d1a3e784Jim Stichnoth  if (Func->isVerbose(IceV_RegOrigins) ||
5075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      (!hasReg() && !Func->getTarget()->hasComputedFrame()))
5089a04c0760fe48d0003ffcc5be13f67ccd924a9a4Jim Stichnoth    Str << "%" << getName(Func);
5095bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  if (hasReg()) {
510fa4efea5413aa993e8e6ba10579e0934d1a3e784Jim Stichnoth    if (Func->isVerbose(IceV_RegOrigins))
5115bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      Str << ":";
5125bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Str << Func->getTarget()->getRegName(RegNum, getType());
5135bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  } else if (Func->getTarget()->hasComputedFrame()) {
514fa4efea5413aa993e8e6ba10579e0934d1a3e784Jim Stichnoth    if (Func->isVerbose(IceV_RegOrigins))
5155bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      Str << ":";
5168aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth    const auto BaseRegisterNumber =
5178aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth        hasReg() ? getBaseRegNum() : Func->getTarget()->getFrameOrStackReg();
518dd842dbb57b825ed0dd6400648d0602b74c90affJim Stichnoth    Str << "["
51928068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung        << Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
5205bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    int32_t Offset = getStackOffset();
5215bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    if (Offset) {
5225bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      if (Offset > 0)
5235bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth        Str << "+";
5245bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth      Str << Offset;
5255bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    }
5265bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Str << "]";
5275bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  }
528f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}
529f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
53076bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voungtemplate <> void ConstantInteger32::emit(TargetLowering *Target) const {
53176bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung  Target->emit(this);
532f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}
533f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
53476bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voungtemplate <> void ConstantInteger64::emit(TargetLowering *Target) const {
53576bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung  Target->emit(this);
53676bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung}
53776bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung
53876bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voungtemplate <> void ConstantFloat::emit(TargetLowering *Target) const {
53976bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung  Target->emit(this);
54076bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung}
54176bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung
54276bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voungtemplate <> void ConstantDouble::emit(TargetLowering *Target) const {
54376bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung  Target->emit(this);
54476bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung}
54576bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung
54676bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voungvoid ConstantRelocatable::emit(TargetLowering *Target) const {
54776bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung  Target->emit(this);
54876bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung}
54976bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung
5508ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnothvoid ConstantRelocatable::emitWithoutPrefix(const TargetLowering *Target,
5518ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth                                            const char *Suffix) const {
5528ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth  Target->emitWithoutPrefix(this, Suffix);
553bca2f65551c65fdc18278bf88025c11d8af18579Jim Stichnoth}
554bca2f65551c65fdc18278bf88025c11d8af18579Jim Stichnoth
555df6f9d18fce6750872dba5686ed6032949ca01c6Karl Schimpfvoid ConstantRelocatable::dump(const Cfg *Func, Ostream &Str) const {
55620b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (!BuildDefs::dump())
557b6c96af1e5f019374ab93b2b66fbf79247d24660Karl Schimpf    return;
558dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto  if (!EmitString.empty()) {
559dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto    Str << EmitString;
560dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto    return;
561dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto  }
562df6f9d18fce6750872dba5686ed6032949ca01c6Karl Schimpf  Str << "@";
563df6f9d18fce6750872dba5686ed6032949ca01c6Karl Schimpf  if (Func && !SuppressMangling) {
564df6f9d18fce6750872dba5686ed6032949ca01c6Karl Schimpf    Str << Func->getContext()->mangleName(Name);
565df6f9d18fce6750872dba5686ed6032949ca01c6Karl Schimpf  } else {
566df6f9d18fce6750872dba5686ed6032949ca01c6Karl Schimpf    Str << Name;
567df6f9d18fce6750872dba5686ed6032949ca01c6Karl Schimpf  }
56827fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  const RelocOffsetT Offset = getOffset();
56927fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  if (Offset) {
57027fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    if (Offset >= 0) {
57127fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto      Str << "+";
57227fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    }
57327fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto    Str << Offset;
57427fddcc36ad3f0c7531e481f9b249bd36ef83057John Porto  }
575f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth}
576f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth
57776bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voungvoid ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
57876bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung
579d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnothvoid LiveRange::dump(Ostream &Str) const {
58020b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (!BuildDefs::dump())
581b6c96af1e5f019374ab93b2b66fbf79247d24660Karl Schimpf    return;
582f44f371b7f3fab5683e6781873d71987e44fea2fJim Stichnoth  bool First = true;
583f44f371b7f3fab5683e6781873d71987e44fea2fJim Stichnoth  for (const RangeElementType &I : Range) {
5848363a0668ce21ea0c2a61f78083b0536dbd89860Jim Stichnoth    if (!First)
585d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth      Str << ", ";
586f44f371b7f3fab5683e6781873d71987e44fea2fJim Stichnoth    First = false;
587f44f371b7f3fab5683e6781873d71987e44fea2fJim Stichnoth    Str << "[" << I.first << ":" << I.second << ")";
588d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  }
589d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth}
590d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
591d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim StichnothOstream &operator<<(Ostream &Str, const LiveRange &L) {
59220b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (!BuildDefs::dump())
593b6c96af1e5f019374ab93b2b66fbf79247d24660Karl Schimpf    return Str;
594d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  L.dump(Str);
595d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth  return Str;
596d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth}
597d97c7df5a3c94fc0d1ad42acbf79756f15682919Jim Stichnoth
5985bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim StichnothOstream &operator<<(Ostream &Str, const RegWeight &W) {
59920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth  if (!BuildDefs::dump())
600b6c96af1e5f019374ab93b2b66fbf79247d24660Karl Schimpf    return Str;
6015bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  if (W.getWeight() == RegWeight::Inf)
6025bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Str << "Inf";
6035bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  else
6045bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth    Str << W.getWeight();
6055bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth  return Str;
6065bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth}
6075bc2b1d163123ef17e0a14f50aae3bc8e4cd243eJim Stichnoth
608253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu// =========== Immediate Randomization and Pooling routines ==============
609253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu// Specialization of the template member function for ConstantInteger32
61057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// TODO(stichnot): try to move this specialization into a target-specific file.
611253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lutemplate <>
612253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lubool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
613253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu  uint32_t Threshold = Ctx->getFlags().getRandomizeAndPoolImmediatesThreshold();
614253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu  if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None)
615253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu    return false;
616253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu  if (getType() != IceType_i32 && getType() != IceType_i16 &&
617253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu      getType() != IceType_i8)
618253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu    return false;
619253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu  // The Following checks if the signed representation of Value is between
620253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu  // -Threshold/2 and +Threshold/2
621253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu  bool largerThanThreshold = Threshold / 2 + Value >= Threshold;
622253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu  return largerThanThreshold;
623253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu}
624253dc8a870cbd144ba217a44efbd07e6bcd71e97Qining Lu
625f7c9a14151ecfc9c642bf3e1dba9341d49e9ec67Jim Stichnoth} // end of namespace Ice
626