bool args_empty() const { return arguments.empty(); }
- /// Add one value to the operand list.
+ /// Add one value to the argument list.
BBArgument *addArgument(Type type);
/// Add one argument to the argument list for each type specified in the list.
llvm::iterator_range<args_iterator> addArguments(ArrayRef<Type> types);
+ /// Erase the argument at 'index' and remove it from the argument list.
+ void eraseArgument(unsigned index);
+
unsigned getNumArguments() const { return arguments.size(); }
BBArgument *getArgument(unsigned i) { return arguments[i]; }
const BBArgument *getArgument(unsigned i) const { return arguments[i]; }
return *this;
}
+ /// Get the successor number in the predecessor terminator.
+ unsigned getSuccessorIndex() const {
+ return bbUseIterator->getOperandNumber();
+ }
+
private:
using BBUseIterator = SSAValueUseIterator<BasicBlockOperand, Instruction>;
BBUseIterator bbUseIterator;
BlockType *operator*() const {
return this->object->getSuccessor(this->index);
}
+
+ /// Get the successor number in the terminator.
+ unsigned getSuccessorIndex() const { return this->index; }
};
inline auto BasicBlock::succ_begin() const -> const_succ_iterator {
/// Add a list of values to the operand list.
void addOperands(ArrayRef<SSAValue *> values);
- /// Erase a specific argument from the arg list.
- // TODO: void eraseArgument(int Index);
+ /// Erase the operand at 'index' from the operand list.
+ void eraseOperand(unsigned index);
private:
friend class Operation;
/// Add a list of values to the operand list.
void addTrueOperands(ArrayRef<SSAValue *> values);
+ /// Erase the operand at 'index' from the true operand list.
+ void eraseTrueOperand(unsigned index);
+
// Accessors for operands to the 'false' destination.
SSAValue *getFalseOperand(unsigned idx) {
assert(idx < getNumFalseOperands());
/// Add a list of values to the false operand list.
void addFalseOperands(ArrayRef<SSAValue *> values);
+ /// Erase the operand at 'index' from the false operand list.
+ void eraseFalseOperand(unsigned index);
+
private:
/// Get the index of the first true destination operand.
unsigned getTrueDestOperandIndex() { return 1; }
/// index.
void addSuccessorOperands(unsigned index, ArrayRef<CFGValue *> values);
- /// Erase a specific argument from the arg list.
- // TODO: void eraseSuccessorOperand(unsigned index, unsigned argIndex);
+ /// Erase a specific operand from the operand list of the successor at
+ /// 'index'.
+ void eraseSuccessorOperand(unsigned succIndex, unsigned opIndex) {
+ assert(succIndex < getNumSuccessors());
+ assert(opIndex < getNumSuccessorOperands(succIndex));
+ eraseOperand(getSuccessorOperandIndex(succIndex) + opIndex);
+ --getTrailingObjects<unsigned>()[succIndex];
+ }
/// Get the index of the first operand of the successor at the provided
/// index.
// does not have a virtual destructor.
~Instruction();
+ /// Erase the operand at 'index'.
+ void eraseOperand(unsigned index);
+
friend struct llvm::ilist_traits<Instruction>;
friend class BasicBlock;
for (auto *value : values)
addSuccessorOperand(index, value);
}
+ void eraseSuccessorOperand(unsigned succIndex, unsigned opIndex);
llvm::iterator_range<const_operand_iterator>
getSuccessorOperands(unsigned index) const;
llvm::iterator_range<operand_iterator> getSuccessorOperands(unsigned index);
return {arguments.data() + initialSize, arguments.data() + arguments.size()};
}
+void BasicBlock::eraseArgument(unsigned index) {
+ assert(index < arguments.size());
+
+ // Delete the argument.
+ delete arguments[index];
+ arguments.erase(arguments.begin() + index);
+
+ // Erase this argument from each of the predecessor's terminator.
+ for (auto predIt = pred_begin(), predE = pred_end(); predIt != predE;
+ ++predIt) {
+ auto *predTerminator = (*predIt)->getTerminator();
+ predTerminator->eraseSuccessorOperand(predIt.getSuccessorIndex(), index);
+ }
+}
+
//===----------------------------------------------------------------------===//
// Terminator management
//===----------------------------------------------------------------------===//
return getOperation()->addSuccessorOperands(0, values);
}
+void BranchOp::eraseOperand(unsigned index) {
+ getOperation()->eraseSuccessorOperand(0, index);
+}
+
//===----------------------------------------------------------------------===//
// CondBranchOp
//===----------------------------------------------------------------------===//
return getOperation()->addSuccessorOperands(trueIndex, values);
}
+void CondBranchOp::eraseTrueOperand(unsigned index) {
+ getOperation()->eraseSuccessorOperand(trueIndex, index);
+}
+
unsigned CondBranchOp::getNumFalseOperands() const {
return getOperation()->getNumSuccessorOperands(falseIndex);
}
return getOperation()->addSuccessorOperands(falseIndex, values);
}
+void CondBranchOp::eraseFalseOperand(unsigned index) {
+ getOperation()->eraseSuccessorOperand(falseIndex, index);
+}
+
//===----------------------------------------------------------------------===//
// Constant*Op
//===----------------------------------------------------------------------===//
successor.~BasicBlockOperand();
}
+void Instruction::eraseOperand(unsigned index) {
+ assert(index < operands.size());
+
+ // Shift all operands down by 1.
+ for (unsigned i = index, e = operands.size() - 1; i != e; ++i)
+ operands[i].set(operands[i + 1].get());
+ // Drop the last operand.
+ operands.pop_back();
+}
+
/// Destroy this instruction.
void Instruction::destroy() {
this->~Instruction();
return llvm::cast<Instruction>(this)->addSuccessorOperand(
index, llvm::cast<CFGValue>(value));
}
+void Operation::eraseSuccessorOperand(unsigned succIndex, unsigned opIndex) {
+ assert(isTerminator() && "Only terminators have successors.");
+ assert(llvm::isa<Instruction>(this) && "Only instructions have successors.");
+ return llvm::cast<Instruction>(this)->eraseSuccessorOperand(succIndex,
+ opIndex);
+}
auto Operation::getSuccessorOperands(unsigned index) const
-> llvm::iterator_range<const_operand_iterator> {
assert(isTerminator() && "Only terminators have successors.");