Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions llvm/include/llvm/IR/Instructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -2665,7 +2665,7 @@ class PHINode : public Instruction {
// User::allocHungoffUses, because we have to allocate Uses for the incoming
// values and pointers to the incoming blocks, all in one allocation.
void allocHungoffUses(unsigned N) {
User::allocHungoffUses(N, /* IsPhi */ true);
User::allocHungoffUses(N, /*WithExtraValues=*/true);
}

public:
Expand Down Expand Up @@ -3198,10 +3198,10 @@ class SwitchInst : public Instruction {

unsigned ReservedSpace;

// Operand[0] = Value to switch on
// Operand[1] = Default basic block destination
// Operand[2n ] = Value to match
// Operand[2n+1] = BasicBlock to go to on match
// Operand[0] = Value to switch on
// Operand[1] = Default basic block destination
// Operand[n] = BasicBlock to go to on match
// Values are stored after the Uses similar to PHINode's basic blocks.
SwitchInst(const SwitchInst &SI);

/// Create a new switch instruction, specifying a value to switch on and a
Expand All @@ -3223,6 +3223,17 @@ class SwitchInst : public Instruction {

LLVM_ABI SwitchInst *cloneImpl() const;

void allocHungoffUses(unsigned N) {
User::allocHungoffUses(N, /*WithExtraValues=*/true);
}

ConstantInt *const *case_values() const {
return reinterpret_cast<ConstantInt *const *>(op_begin() + ReservedSpace);
}
ConstantInt **case_values() {
return reinterpret_cast<ConstantInt **>(op_begin() + ReservedSpace);
}

public:
void operator delete(void *Ptr) { User::operator delete(Ptr); }

Expand Down Expand Up @@ -3257,7 +3268,7 @@ class SwitchInst : public Instruction {
ConstantIntT *getCaseValue() const {
assert((unsigned)Index < SI->getNumCases() &&
"Index out the number of cases.");
return reinterpret_cast<ConstantIntT *>(SI->getOperand(2 + Index * 2));
return SI->case_values()[Index];
}

/// Resolves successor for current case.
Expand Down Expand Up @@ -3299,7 +3310,7 @@ class SwitchInst : public Instruction {
void setValue(ConstantInt *V) const {
assert((unsigned)Index < SI->getNumCases() &&
"Index out the number of cases.");
SI->setOperand(2 + Index*2, reinterpret_cast<Value*>(V));
SI->case_values()[Index] = V;
}

/// Sets the new successor for current case.
Expand Down Expand Up @@ -3406,9 +3417,7 @@ class SwitchInst : public Instruction {

/// Return the number of 'cases' in this switch instruction, excluding the
/// default case.
unsigned getNumCases() const {
return getNumOperands()/2 - 1;
}
unsigned getNumCases() const { return getNumOperands() - 2; }

/// Returns a read/write iterator that points to the first case in the
/// SwitchInst.
Expand Down Expand Up @@ -3510,14 +3519,14 @@ class SwitchInst : public Instruction {
/// case.
LLVM_ABI CaseIt removeCase(CaseIt I);

unsigned getNumSuccessors() const { return getNumOperands()/2; }
unsigned getNumSuccessors() const { return getNumOperands() - 1; }
BasicBlock *getSuccessor(unsigned idx) const {
assert(idx < getNumSuccessors() &&"Successor idx out of range for switch!");
return cast<BasicBlock>(getOperand(idx*2+1));
return cast<BasicBlock>(getOperand(idx + 1));
}
void setSuccessor(unsigned idx, BasicBlock *NewSucc) {
assert(idx < getNumSuccessors() && "Successor # out of range for switch!");
setOperand(idx * 2 + 1, NewSucc);
setOperand(idx + 1, NewSucc);
}

// Methods for support type inquiry through isa, cast, and dyn_cast:
Expand Down
8 changes: 4 additions & 4 deletions llvm/include/llvm/IR/User.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,13 @@ class User : public Value {

/// Allocate the array of Uses, followed by a pointer
/// (with bottom bit set) to the User.
/// \param IsPhi identifies callers which are phi nodes and which need
/// N BasicBlock* allocated along with N
LLVM_ABI void allocHungoffUses(unsigned N, bool IsPhi = false);
/// \param WithExtraValues identifies callers which need N Value* allocated
/// along the N operands.
LLVM_ABI void allocHungoffUses(unsigned N, bool WithExtraValues = false);

/// Grow the number of hung off uses. Note that allocHungoffUses
/// should be called if there are no uses.
LLVM_ABI void growHungoffUses(unsigned N, bool IsPhi = false);
LLVM_ABI void growHungoffUses(unsigned N, bool WithExtraValues = false);

protected:
~User() = default; // Use deleteValue() to delete a generic Instruction.
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/SandboxIR/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1892,6 +1892,7 @@ class SwitchInst : public SingleLLVMInstructionImpl<llvm::SwitchInst> {
using CaseIt = llvm::SwitchInst::CaseIteratorImpl<CaseHandle>;
using ConstCaseIt = llvm::SwitchInst::CaseIteratorImpl<ConstCaseHandle>;

ConstantInt *const *case_values() const { return nullptr; } // XXX
/// Returns a read/write iterator that points to the first case in the
/// SwitchInst.
CaseIt case_begin() { return CaseIt(this, 0); }
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ static OrderMap orderModule(const Module &M) {
orderConstantValue(Op);
if (auto *SVI = dyn_cast<ShuffleVectorInst>(&I))
orderValue(SVI->getShuffleMaskForBitcode(), OM);
if (auto *SI = dyn_cast<SwitchInst>(&I)) {
for (const auto &Case : SI->cases())
orderValue(Case.getCaseValue(), OM);
}
orderValue(&I, OM);
}
}
Expand Down Expand Up @@ -1093,6 +1097,10 @@ void ValueEnumerator::incorporateFunction(const Function &F) {
}
if (auto *SVI = dyn_cast<ShuffleVectorInst>(&I))
EnumerateValue(SVI->getShuffleMaskForBitcode());
if (auto *SI = dyn_cast<SwitchInst>(&I)) {
for (const auto &Case : SI->cases())
EnumerateValue(Case.getCaseValue());
}
}
BasicBlocks.push_back(&BB);
ValueMap[&BB] = BasicBlocks.size();
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/CodeGen/TypePromotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,14 @@ void IRPromoter::PromoteTree() {
I->setOperand(i, ConstantInt::get(ExtTy, 0));
}

// For switch, also mutate case values, which are not operands.
if (auto *SI = dyn_cast<SwitchInst>(I)) {
for (auto Case : SI->cases()) {
APInt NewConst = Case.getCaseValue()->getValue().zext(PromotedWidth);
Case.setValue(ConstantInt::get(SI->getContext(), NewConst));
}
}

// Mutate the result type, unless this is an icmp or switch.
if (!isa<ICmpInst>(I) && !isa<SwitchInst>(I)) {
I->mutateType(ExtTy);
Expand Down
33 changes: 18 additions & 15 deletions llvm/lib/IR/Instructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ void PHINode::growOperands() {
if (NumOps < 2) NumOps = 2; // 2 op PHI nodes are VERY common.

ReservedSpace = NumOps;
growHungoffUses(ReservedSpace, /* IsPhi */ true);
growHungoffUses(ReservedSpace, /*WithExtraValues=*/true);
}

/// hasConstantValue - If the specified PHI node always merges together the same
Expand Down Expand Up @@ -4074,18 +4074,20 @@ SwitchInst::SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases,
InsertPosition InsertBefore)
: Instruction(Type::getVoidTy(Value->getContext()), Instruction::Switch,
AllocMarker, InsertBefore) {
init(Value, Default, 2+NumCases*2);
init(Value, Default, 2 + NumCases);
}

SwitchInst::SwitchInst(const SwitchInst &SI)
: Instruction(SI.getType(), Instruction::Switch, AllocMarker) {
init(SI.getCondition(), SI.getDefaultDest(), SI.getNumOperands());
setNumHungOffUseOperands(SI.getNumOperands());
Use *OL = getOperandList();
ConstantInt **VL = case_values();
const Use *InOL = SI.getOperandList();
for (unsigned i = 2, E = SI.getNumOperands(); i != E; i += 2) {
ConstantInt *const *InVL = SI.case_values();
for (unsigned i = 2, E = SI.getNumOperands(); i != E; ++i) {
OL[i] = InOL[i];
OL[i+1] = InOL[i+1];
VL[i - 2] = InVL[i - 2];
}
SubclassOptionalData = SI.SubclassOptionalData;
}
Expand All @@ -4095,11 +4097,11 @@ SwitchInst::SwitchInst(const SwitchInst &SI)
void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
unsigned NewCaseIdx = getNumCases();
unsigned OpNo = getNumOperands();
if (OpNo+2 > ReservedSpace)
if (OpNo + 1 > ReservedSpace)
growOperands(); // Get more space!
// Initialize some new operands.
assert(OpNo+1 < ReservedSpace && "Growing didn't work!");
setNumHungOffUseOperands(OpNo+2);
assert(OpNo < ReservedSpace && "Growing didn't work!");
setNumHungOffUseOperands(OpNo + 1);
CaseHandle Case(this, NewCaseIdx);
Case.setValue(OnVal);
Case.setSuccessor(Dest);
Expand All @@ -4110,21 +4112,22 @@ void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
SwitchInst::CaseIt SwitchInst::removeCase(CaseIt I) {
unsigned idx = I->getCaseIndex();

assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!");
assert(2 + idx < getNumOperands() && "Case index out of range!!!");

unsigned NumOps = getNumOperands();
Use *OL = getOperandList();
ConstantInt **VL = case_values();

// Overwrite this case with the end of the list.
if (2 + (idx + 1) * 2 != NumOps) {
OL[2 + idx * 2] = OL[NumOps - 2];
OL[2 + idx * 2 + 1] = OL[NumOps - 1];
if (2 + idx + 1 != NumOps) {
OL[2 + idx] = OL[NumOps - 1];
VL[idx] = VL[NumOps - 2 - 1];
}

// Nuke the last value.
OL[NumOps-2].set(nullptr);
OL[NumOps-2+1].set(nullptr);
setNumHungOffUseOperands(NumOps-2);
OL[NumOps - 1].set(nullptr);
VL[NumOps - 2 - 1] = nullptr;
setNumHungOffUseOperands(NumOps - 1);

return CaseIt(this, idx);
}
Expand All @@ -4137,7 +4140,7 @@ void SwitchInst::growOperands() {
unsigned NumOps = e*3;

ReservedSpace = NumOps;
growHungoffUses(ReservedSpace);
growHungoffUses(ReservedSpace, /*WithExtraValues=*/true);
}

void SwitchInstProfUpdateWrapper::init() {
Expand Down
20 changes: 10 additions & 10 deletions llvm/lib/IR/User.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,24 @@ bool User::replaceUsesOfWith(Value *From, Value *To) {
// User allocHungoffUses Implementation
//===----------------------------------------------------------------------===//

void User::allocHungoffUses(unsigned N, bool IsPhi) {
void User::allocHungoffUses(unsigned N, bool WithExtraValues) {
assert(HasHungOffUses && "alloc must have hung off uses");

static_assert(alignof(Use) >= alignof(BasicBlock *),
static_assert(alignof(Use) >= alignof(Value *),
"Alignment is insufficient for 'hung-off-uses' pieces");

// Allocate the array of Uses
size_t size = N * sizeof(Use);
if (IsPhi)
size += N * sizeof(BasicBlock *);
if (WithExtraValues)
size += N * sizeof(Value *);
Use *Begin = static_cast<Use*>(::operator new(size));
Use *End = Begin + N;
setOperandList(Begin);
for (; Begin != End; Begin++)
new (Begin) Use(this);
}

void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) {
void User::growHungoffUses(unsigned NewNumUses, bool WithExtraValues) {
assert(HasHungOffUses && "realloc must have hung off uses");

unsigned OldNumUses = getNumOperands();
Expand All @@ -74,22 +74,22 @@ void User::growHungoffUses(unsigned NewNumUses, bool IsPhi) {
assert(NewNumUses > OldNumUses && "realloc must grow num uses");

Use *OldOps = getOperandList();
allocHungoffUses(NewNumUses, IsPhi);
allocHungoffUses(NewNumUses, WithExtraValues);
Use *NewOps = getOperandList();

// Now copy from the old operands list to the new one.
std::copy(OldOps, OldOps + OldNumUses, NewOps);

// If this is a Phi, then we need to copy the BB pointers too.
if (IsPhi) {
// If the User has extra values (phi basic blocks, switch case values), then
// we need to copy these, too.
if (WithExtraValues) {
auto *OldPtr = reinterpret_cast<char *>(OldOps + OldNumUses);
auto *NewPtr = reinterpret_cast<char *>(NewOps + NewNumUses);
std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(BasicBlock *)), NewPtr);
std::copy(OldPtr, OldPtr + (OldNumUses * sizeof(Value *)), NewPtr);
}
Use::zap(OldOps, OldOps + OldNumUses, true);
}


// This is a private struct used by `User` to track the co-allocated descriptor
// section.
struct DescriptorInfo {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3357,7 +3357,7 @@ void Verifier::visitSwitchInst(SwitchInst &SI) {
Type *SwitchTy = SI.getCondition()->getType();
SmallPtrSet<ConstantInt*, 32> Constants;
for (auto &Case : SI.cases()) {
Check(isa<ConstantInt>(SI.getOperand(Case.getCaseIndex() * 2 + 2)),
Check(isa<ConstantInt>(Case.getCaseValue()),
"Case value is not a constant integer.", &SI);
Check(Case.getCaseValue()->getType() == SwitchTy,
"Switch constants must all be same type as switch value!", &SI);
Expand Down
2 changes: 1 addition & 1 deletion llvm/unittests/IR/VerifierTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ TEST(VerifierTest, SwitchInst) {
Switch->addCase(ConstantInt::get(Int32Ty, 2), OnTwo);

EXPECT_FALSE(verifyFunction(*F));
// set one case value to function argument.
// set one successor to function argument.
Switch->setOperand(2, F->getArg(1));
EXPECT_TRUE(verifyFunction(*F));
}
Expand Down
Loading