Nikita Popov 941c8e0ea5 [Bitcode] Support expanding constant expressions into instructions
This implements an autoupgrade from constant expressions to
instructions, which is needed for
https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179.

The basic approach is that constant expressions (CST_CODE_CE_*
records) now initially only create a BitcodeConstant value that
holds opcode, flags and operands IDs. Then, when the value actually
gets used, it can be converted either into a constant expression
(if that expression type is still supported) or into a sequence of
instructions. As currently all expressions are still supported,
-expand-constant-exprs is added for testing purposes, to force
expansion.

PHI nodes require special handling, because the constant expression
needs to be evaluated on the incoming edge. We do this by putting
it into a temporary block and then wiring it up appropriately
afterwards (for non-critical edges, we could also move the
instructions into the predecessor).

This also removes the need for the forward referenced constants
machinery, as the BitcodeConstants only hold value IDs. At the
point where the value is actually materialized, no forward
references are needed anymore.

Differential Revision: https://reviews.llvm.org/D127729
2022-06-28 11:09:46 +02:00

88 lines
2.6 KiB
C++

//===- ValueList.cpp - Internal BitcodeReader implementation --------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "ValueList.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include <cstddef>
using namespace llvm;
Error BitcodeReaderValueList::assignValue(unsigned Idx, Value *V,
unsigned TypeID) {
if (Idx == size()) {
push_back(V, TypeID);
return Error::success();
}
if (Idx >= size())
resize(Idx + 1);
auto &Old = ValuePtrs[Idx];
if (!Old.first) {
Old.first = V;
Old.second = TypeID;
return Error::success();
}
assert(!isa<Constant>(&*Old.first) && "Shouldn't update constant");
// If there was a forward reference to this value, replace it.
Value *PrevVal = Old.first;
if (PrevVal->getType() != V->getType())
return createStringError(
std::errc::illegal_byte_sequence,
"Assigned value does not match type of forward declaration");
Old.first->replaceAllUsesWith(V);
PrevVal->deleteValue();
return Error::success();
}
Value *BitcodeReaderValueList::getValueFwdRef(unsigned Idx, Type *Ty,
unsigned TyID,
BasicBlock *ConstExprInsertBB) {
// Bail out for a clearly invalid value.
if (Idx >= RefsUpperBound)
return nullptr;
if (Idx >= size())
resize(Idx + 1);
if (Value *V = ValuePtrs[Idx].first) {
// If the types don't match, it's invalid.
if (Ty && Ty != V->getType())
return nullptr;
Expected<Value *> MaybeV = MaterializeValueFn(Idx, ConstExprInsertBB);
if (!MaybeV) {
// TODO: We might want to propagate the precise error message here.
consumeError(MaybeV.takeError());
return nullptr;
}
return MaybeV.get();
}
// No type specified, must be invalid reference.
if (!Ty)
return nullptr;
// Create and return a placeholder, which will later be RAUW'd.
Value *V = new Argument(Ty);
ValuePtrs[Idx] = {V, TyID};
return V;
}