[IR]重构常量定义,引入undefvalue定义,修改常量方法使用尽量适配旧版
This commit is contained in:
266
src/include/IR.h
266
src/include/IR.h
@@ -268,6 +268,51 @@ class ValueCounter {
|
||||
} ///< 清空ValueCounter
|
||||
};
|
||||
|
||||
|
||||
// --- Refactored ConstantValue and related classes start here ---
|
||||
|
||||
using ConstantValVariant = std::variant<intmax_t, float>;
|
||||
|
||||
// Helper for hashing std::variant
|
||||
struct VariantHash {
|
||||
template <class T>
|
||||
std::size_t operator()(const T& val) const {
|
||||
return std::hash<T>{}(val);
|
||||
}
|
||||
std::size_t operator()(const ConstantValVariant& v) const {
|
||||
return std::visit(*this, v);
|
||||
}
|
||||
};
|
||||
|
||||
struct ConstantValueKey {
|
||||
Type* type;
|
||||
ConstantValVariant val;
|
||||
|
||||
bool operator==(const ConstantValueKey& other) const {
|
||||
// Assuming Type objects are canonicalized, or add Type::isSame()
|
||||
// If Type::isSame() is not available and Type objects are not canonicalized,
|
||||
// this comparison might not be robust enough for structural equivalence of types.
|
||||
return type == other.type && val == other.val;
|
||||
}
|
||||
};
|
||||
|
||||
struct ConstantValueHash {
|
||||
std::size_t operator()(const ConstantValueKey& key) const {
|
||||
std::size_t typeHash = std::hash<Type*>{}(key.type);
|
||||
std::size_t valHash = VariantHash{}(key.val);
|
||||
// A simple way to combine hashes
|
||||
return typeHash ^ (valHash << 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct ConstantValueEqual {
|
||||
bool operator()(const ConstantValueKey& lhs, const ConstantValueKey& rhs) const {
|
||||
// Assuming Type objects are canonicalized (e.g., Type::getIntType() always returns same pointer)
|
||||
// If not, and Type::isSame() is intended, it should be added to Type class.
|
||||
return lhs.type == rhs.type && lhs.val == rhs.val;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* Static constants known at compile time.
|
||||
*
|
||||
@@ -275,46 +320,178 @@ class ValueCounter {
|
||||
* `Value`s. It's type is either `int` or `float`.
|
||||
* `ConstantValue`并不由指令定义, 也不使用任何Value。它的类型为int/float。
|
||||
*/
|
||||
|
||||
|
||||
class ConstantValue : public Value {
|
||||
protected:
|
||||
/// 定义字面量类型的聚合类型
|
||||
union {
|
||||
int iScalar;
|
||||
float fScalar;
|
||||
};
|
||||
protected:
|
||||
static std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValueHash, ConstantValueEqual> mConstantPool;
|
||||
|
||||
protected:
|
||||
explicit ConstantValue(int value, const std::string &name = "") : Value(Type::getIntType(), name), iScalar(value) {}
|
||||
explicit ConstantValue(float value, const std::string &name = "")
|
||||
: Value(Type::getFloatType(), name), fScalar(value) {}
|
||||
public:
|
||||
explicit ConstantValue(Type* type, const std::string& name = "") : Value(type, name) {}
|
||||
virtual ~ConstantValue() = default;
|
||||
|
||||
public:
|
||||
static ConstantValue* get(int value); ///< 获取一个int类型的ConstValue *,其值为value
|
||||
static ConstantValue* get(float value); ///< 获取一个float类型的ConstValue *,其值为value
|
||||
virtual size_t hash() const = 0;
|
||||
virtual ConstantValVariant getValue() const = 0;
|
||||
|
||||
public:
|
||||
// Static factory method to get a canonical ConstantValue from the pool
|
||||
static ConstantValue* get(Type* type, ConstantValVariant val);
|
||||
|
||||
// Helper methods to access constant values with appropriate casting
|
||||
int getInt() const {
|
||||
assert(isInt());
|
||||
return iScalar;
|
||||
} ///< 返回int类型的值
|
||||
assert(getType()->isInt() && "Calling getInt() on non-integer type");
|
||||
return std::get<int>(getValue());
|
||||
}
|
||||
float getFloat() const {
|
||||
assert(isFloat());
|
||||
return fScalar;
|
||||
} ///< 返回float类型的值
|
||||
template <typename T>
|
||||
assert(getType()->isFloat() && "Calling getFloat() on non-float type");
|
||||
return std::get<float>(getValue());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T getValue() const {
|
||||
if (std::is_same<T, int>::value && isInt()) {
|
||||
return getInt();
|
||||
}
|
||||
if (std::is_same<T, float>::value && isFloat()) {
|
||||
return getFloat();
|
||||
}
|
||||
throw std::bad_cast(); // 或者其他适当的异常处理
|
||||
} ///< 返回值,getInt和getFloat统一化,整数返回整形,浮点返回浮点型
|
||||
if constexpr (std::is_same_v<T, int>) {
|
||||
return getInt();
|
||||
} else if constexpr (std::is_same_v<T, float>) {
|
||||
return getFloat();
|
||||
} else {
|
||||
// This ensures a compilation error if an unsupported type is used
|
||||
static_assert(std::always_false_v<T>, "Unsupported type for ConstantValue::getValue()");
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isZero() const = 0;
|
||||
virtual bool isOne() const = 0;
|
||||
};
|
||||
|
||||
class ConstantInteger : public ConstantValue {
|
||||
int constVal;
|
||||
public:
|
||||
explicit ConstantInteger(Type* type, int val, const std::string& name = "")
|
||||
: ConstantValue(type, name), constVal(val) {}
|
||||
|
||||
size_t hash() const override {
|
||||
std::size_t typeHash = std::hash<Type*>{}(getType());
|
||||
std::size_t valHash = std::hash<int>{}(constVal);
|
||||
return typeHash ^ (valHash << 1);
|
||||
}
|
||||
int getInt() const { return constVal; }
|
||||
ConstantValVariant getValue() const override { return constVal; }
|
||||
|
||||
static ConstantInteger* get(Type* type, int val);
|
||||
static ConstantInteger* get(int val) { return get(Type::getIntType(), val); }
|
||||
|
||||
ConstantInteger* getNeg() const {
|
||||
assert(getType()->isInt() && "Cannot negate non-integer constant");
|
||||
return ConstantInteger::get(-constVal);
|
||||
}
|
||||
|
||||
bool isZero() const override { return constVal == 0; }
|
||||
bool isOne() const override { return constVal == 1; }
|
||||
};
|
||||
|
||||
class ConstantFloating : public ConstantValue {
|
||||
float constFVal;
|
||||
public:
|
||||
explicit ConstantFloating(Type* type, float val, const std::string& name = "")
|
||||
: ConstantValue(type, name), constFVal(val) {}
|
||||
|
||||
size_t hash() const override {
|
||||
std::size_t typeHash = std::hash<Type*>{}(getType());
|
||||
std::size_t valHash = std::hash<float>{}(constFVal);
|
||||
return typeHash ^ (valHash << 1);
|
||||
}
|
||||
float getFloat() const { return constFVal; }
|
||||
ConstantValVariant getValue() const override { return constFVal; }
|
||||
|
||||
static ConstantFloating* get(Type* type, float val);
|
||||
static ConstantFloating* get(float val) { return get(Type::getFloatType(), val); }
|
||||
|
||||
ConstantFloating* getNeg() const {
|
||||
assert(getType()->isFloat() && "Cannot negate non-float constant");
|
||||
return ConstantFloating::get(-constFVal);
|
||||
}
|
||||
|
||||
bool isZero() const override { return constFVal == 0.0f; }
|
||||
bool isOne() const override { return constFVal == 1.0f; }
|
||||
};
|
||||
|
||||
class UndefinedValue : public ConstantValue {
|
||||
private:
|
||||
static std::unordered_map<Type*, UndefinedValue*> UndefValues;
|
||||
|
||||
protected:
|
||||
explicit UndefinedValue(Type* type, const std::string& name = "")
|
||||
: ConstantValue(type, name) {
|
||||
assert(!type->isVoid() && "Cannot create UndefinedValue of void type!");
|
||||
}
|
||||
|
||||
public:
|
||||
static UndefinedValue* get(Type* type);
|
||||
|
||||
size_t hash() const override {
|
||||
return std::hash<Type*>{}(getType());
|
||||
}
|
||||
|
||||
ConstantValVariant getValue() const override {
|
||||
if (getType()->isInt()) {
|
||||
return 0; // Return 0 for undefined integer
|
||||
} else if (getType()->isFloat()) {
|
||||
return 0.0f; // Return 0.0f for undefined float
|
||||
}
|
||||
assert(false && "UndefinedValue has unexpected type for getValue()");
|
||||
return 0; // Should not be reached
|
||||
}
|
||||
|
||||
bool isZero() const override { return false; }
|
||||
bool isOne() const override { return false; }
|
||||
};
|
||||
|
||||
// Implementations for static members (typically in .cpp, but for single-file, put here)
|
||||
|
||||
std::unordered_map<ConstantValueKey, ConstantValue*, ConstantValueHash, ConstantValueEqual> ConstantValue::mConstantPool;
|
||||
std::unordered_map<Type*, UndefinedValue*> UndefinedValue::UndefValues;
|
||||
|
||||
ConstantValue* ConstantValue::get(Type* type, ConstantValVariant val) {
|
||||
ConstantValueKey key = {type, val};
|
||||
auto it = mConstantPool.find(key);
|
||||
if (it != mConstantPool.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ConstantValue* newConstant = nullptr;
|
||||
if (std::holds_alternative<int>(val)) {
|
||||
newConstant = new ConstantInteger(type, std::get<int>(val));
|
||||
} else if (std::holds_alternative<float>(val)) {
|
||||
newConstant = new ConstantFloating(type, std::get<float>(val));
|
||||
} else {
|
||||
assert(false && "Unsupported ConstantValVariant type");
|
||||
}
|
||||
|
||||
mConstantPool[key] = newConstant;
|
||||
return newConstant;
|
||||
}
|
||||
|
||||
ConstantInteger* ConstantInteger::get(Type* type, int val) {
|
||||
return dynamic_cast<ConstantInteger*>(ConstantValue::get(type, val));
|
||||
}
|
||||
|
||||
ConstantFloating* ConstantFloating::get(Type* type, float val) {
|
||||
return dynamic_cast<ConstantFloating*>(ConstantValue::get(type, val));
|
||||
}
|
||||
|
||||
UndefinedValue* UndefinedValue::get(Type* type) {
|
||||
assert(!type->isVoid() && "Cannot get UndefinedValue of void type!");
|
||||
|
||||
auto it = UndefValues.find(type);
|
||||
if (it != UndefValues.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
UndefinedValue* newUndef = new UndefinedValue(type);
|
||||
UndefValues[type] = newUndef;
|
||||
return newUndef;
|
||||
}
|
||||
|
||||
// --- End of refactored ConstantValue and related classes ---
|
||||
|
||||
|
||||
class Instruction;
|
||||
class Function;
|
||||
class BasicBlock;
|
||||
@@ -562,8 +739,8 @@ class Instruction : public User {
|
||||
kLa = 0x1UL << 36,
|
||||
kMemset = 0x1UL << 37,
|
||||
kGetSubArray = 0x1UL << 38,
|
||||
// constant
|
||||
kConstant = 0x1UL << 37,
|
||||
// Constant Kind removed as Constants are now Values, not Instructions.
|
||||
// kConstant = 0x1UL << 37, // Conflicts with kMemset if kept as is
|
||||
// phi
|
||||
kPhi = 0x1UL << 39,
|
||||
kBitItoF = 0x1UL << 40,
|
||||
@@ -1258,12 +1435,15 @@ protected:
|
||||
if (init.size() == 0) {
|
||||
unsigned num = 1;
|
||||
for (unsigned i = 0; i < numDims; i++) {
|
||||
num *= dynamic_cast<ConstantValue *>(dims[i])->getInt();
|
||||
// Assume dims elements are ConstantInteger and cast appropriately
|
||||
auto dim_val = dynamic_cast<ConstantInteger*>(dims[i]);
|
||||
assert(dim_val && "GlobalValue dims must be constant integers");
|
||||
num *= dim_val->getInt();
|
||||
}
|
||||
if (dynamic_cast<PointerType *>(type)->getBaseType() == Type::getFloatType()) {
|
||||
init.push_back(ConstantValue::get(0.0F), num);
|
||||
init.push_back(ConstantFloating::get(0.0F), num); // Use new constant factory
|
||||
} else {
|
||||
init.push_back(ConstantValue::get(0), num);
|
||||
init.push_back(ConstantInteger::get(0), num); // Use new constant factory
|
||||
}
|
||||
}
|
||||
initValues = init;
|
||||
@@ -1289,8 +1469,11 @@ public:
|
||||
Value* getByIndices(const std::vector<Value *> &indices) const {
|
||||
int index = 0;
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
index = dynamic_cast<ConstantValue *>(getDim(i))->getInt() * index +
|
||||
dynamic_cast<ConstantValue *>(indices[i])->getInt();
|
||||
// Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
|
||||
auto dim_val = dynamic_cast<ConstantInteger*>(getDim(i));
|
||||
auto idx_val = dynamic_cast<ConstantInteger*>(indices[i]);
|
||||
assert(dim_val && idx_val && "Dims and indices must be constant integers");
|
||||
index = dim_val->getInt() * index + idx_val->getInt();
|
||||
}
|
||||
return getByIndex(index);
|
||||
} ///< 通过多维索引indices获取初始值
|
||||
@@ -1331,8 +1514,11 @@ class ConstantVariable : public User, public LVal {
|
||||
int index = 0;
|
||||
// 计算偏移量
|
||||
for (size_t i = 0; i < indices.size(); i++) {
|
||||
index = dynamic_cast<ConstantValue *>(getDim(i))->getInt() * index +
|
||||
dynamic_cast<ConstantValue *>(indices[i])->getInt();
|
||||
// Ensure dims[i] and indices[i] are ConstantInteger and retrieve their values correctly
|
||||
auto dim_val = dynamic_cast<ConstantInteger*>(getDim(i));
|
||||
auto idx_val = dynamic_cast<ConstantInteger*>(indices[i]);
|
||||
assert(dim_val && idx_val && "Dims and indices must be constant integers");
|
||||
index = dim_val->getInt() * index + idx_val->getInt();
|
||||
}
|
||||
|
||||
return getByIndex(index);
|
||||
|
||||
Reference in New Issue
Block a user