Ordinary patch for PR1255.

Added new case-ranges orientated methods for adding/removing cases in SwitchInst. After this patch cases will internally representated as ConstantArray-s instead of ConstantInt, externally cases wrapped within the ConstantRangesSet object.
Old methods of SwitchInst are also works well, but marked as deprecated. So on this stage we have no side effects except that I added support for case ranges in BitcodeReader/Writer, of course test for Bitcode is also added. Old "switch" format is also supported.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156374 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Stepan Dyatkovskiy
2012-05-08 06:36:08 +00:00
parent b78d83d837
commit 85a4406959
6 changed files with 236 additions and 39 deletions

View File

@ -62,7 +62,10 @@ enum {
FUNCTION_INST_CAST_ABBREV,
FUNCTION_INST_RET_VOID_ABBREV,
FUNCTION_INST_RET_VAL_ABBREV,
FUNCTION_INST_UNREACHABLE_ABBREV
FUNCTION_INST_UNREACHABLE_ABBREV,
// SwitchInst Magic
SWITCH_INST_MAGIC = 0x4B5 // May 2012 => 1205 => Hex
};
static unsigned GetEncodedCastOpcode(unsigned Opcode) {
@ -719,6 +722,42 @@ static void WriteModuleMetadataStore(const Module *M, BitstreamWriter &Stream) {
Stream.ExitBlock();
}
template <typename intty>
static void EmitAPInt(SmallVectorImpl<intty> &Vals,
unsigned &Code, unsigned &AbbrevToUse, const APInt &Val,
bool EmitSizeForWideNumbers = false
) {
if (Val.getBitWidth() <= 64) {
uint64_t V = Val.getSExtValue();
if ((int64_t)V >= 0)
Vals.push_back(V << 1);
else
Vals.push_back((-V << 1) | 1);
Code = bitc::CST_CODE_INTEGER;
AbbrevToUse = CONSTANTS_INTEGER_ABBREV;
} else {
// Wide integers, > 64 bits in size.
// We have an arbitrary precision integer value to write whose
// bit width is > 64. However, in canonical unsigned integer
// format it is likely that the high bits are going to be zero.
// So, we only write the number of active words.
unsigned NWords = Val.getActiveWords();
if (EmitSizeForWideNumbers)
Vals.push_back(NWords);
const uint64_t *RawWords = Val.getRawData();
for (unsigned i = 0; i != NWords; ++i) {
int64_t V = RawWords[i];
if (V >= 0)
Vals.push_back(V << 1);
else
Vals.push_back((-V << 1) | 1);
}
Code = bitc::CST_CODE_WIDE_INTEGER;
}
}
static void WriteConstants(unsigned FirstVal, unsigned LastVal,
const ValueEnumerator &VE,
BitstreamWriter &Stream, bool isGlobal) {
@ -801,30 +840,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
} else if (isa<UndefValue>(C)) {
Code = bitc::CST_CODE_UNDEF;
} else if (const ConstantInt *IV = dyn_cast<ConstantInt>(C)) {
if (IV->getBitWidth() <= 64) {
uint64_t V = IV->getSExtValue();
if ((int64_t)V >= 0)
Record.push_back(V << 1);
else
Record.push_back((-V << 1) | 1);
Code = bitc::CST_CODE_INTEGER;
AbbrevToUse = CONSTANTS_INTEGER_ABBREV;
} else { // Wide integers, > 64 bits in size.
// We have an arbitrary precision integer value to write whose
// bit width is > 64. However, in canonical unsigned integer
// format it is likely that the high bits are going to be zero.
// So, we only write the number of active words.
unsigned NWords = IV->getValue().getActiveWords();
const uint64_t *RawWords = IV->getValue().getRawData();
for (unsigned i = 0; i != NWords; ++i) {
int64_t V = RawWords[i];
if (V >= 0)
Record.push_back(V << 1);
else
Record.push_back((-V << 1) | 1);
}
Code = bitc::CST_CODE_WIDE_INTEGER;
}
EmitAPInt(Record, Code, AbbrevToUse, IV->getValue());
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
Code = bitc::CST_CODE_FLOAT;
Type *Ty = CFP->getType();
@ -1139,12 +1155,31 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
{
Code = bitc::FUNC_CODE_INST_SWITCH;
SwitchInst &SI = cast<SwitchInst>(I);
uint32_t SwitchRecordHeader = SI.Hash() | (SWITCH_INST_MAGIC << 16);
Vals.push_back(SwitchRecordHeader);
Vals.push_back(VE.getTypeID(SI.getCondition()->getType()));
Vals.push_back(VE.getValueID(SI.getCondition()));
Vals.push_back(VE.getValueID(SI.getDefaultDest()));
Vals.push_back(SI.getNumCases());
for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end();
i != e; ++i) {
Vals.push_back(VE.getValueID(i.getCaseValue()));
ConstantRangesSet CRS = i.getCaseValueEx();
Vals.push_back(CRS.getNumItems());
for (unsigned ri = 0, rn = CRS.getNumItems(); ri != rn; ++ri) {
ConstantRangesSet::Range r = CRS.getItem(ri);
Vals.push_back(CRS.isSingleNumber(ri));
const APInt &Low = r.Low->getValue();
const APInt &High = r.High->getValue();
unsigned Code, Abbrev; // will unused.
EmitAPInt(Vals, Code, Abbrev, Low, true);
if (r.Low != r.High)
EmitAPInt(Vals, Code, Abbrev, High, true);
}
Vals.push_back(VE.getValueID(i.getCaseSuccessor()));
}
}