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