deploy-20250820-3 #1
@@ -68,7 +68,7 @@ private:
|
|||||||
MagicNumber computeMagicNumber(uint32_t divisor);
|
MagicNumber computeMagicNumber(uint32_t divisor);
|
||||||
std::pair<int, int> computeMulhMagicNumbers(int divisor);
|
std::pair<int, int> computeMulhMagicNumbers(int divisor);
|
||||||
Value* createMagicDivision(BinaryInst* divInst, uint32_t divisor, const MagicNumber& magic);
|
Value* createMagicDivision(BinaryInst* divInst, uint32_t divisor, const MagicNumber& magic);
|
||||||
Value* createMagicDivisionLibdivide(BinaryInst* divInst, int divisor, const std::pair<int, int>& magicPair);
|
Value* createMagicDivisionLibdivide(BinaryInst* divInst, int divisor);
|
||||||
bool isPowerOfTwo(uint32_t n);
|
bool isPowerOfTwo(uint32_t n);
|
||||||
int log2OfPowerOfTwo(uint32_t n);
|
int log2OfPowerOfTwo(uint32_t n);
|
||||||
|
|
||||||
|
|||||||
@@ -127,13 +127,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
bool analyzeInductionVariableRange(const InductionVarInfo* ivInfo, Loop* loop) const;
|
bool analyzeInductionVariableRange(const InductionVarInfo* ivInfo, Loop* loop) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算用于除法优化的魔数和移位量
|
|
||||||
* @param divisor 除数
|
|
||||||
* @return {魔数, 移位量}
|
|
||||||
*/
|
|
||||||
std::pair<int, int> computeMulhMagicNumbers(int divisor) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成除法替换代码
|
* 生成除法替换代码
|
||||||
* @param candidate 优化候选项
|
* @param candidate 优化候选项
|
||||||
|
|||||||
@@ -107,6 +107,190 @@ public:
|
|||||||
// 所以当AllocaInst的basetype是PointerType时(一维数组)或者是指向ArrayType的PointerType(多位数组)时,返回true
|
// 所以当AllocaInst的basetype是PointerType时(一维数组)或者是指向ArrayType的PointerType(多位数组)时,返回true
|
||||||
return aval && (baseType->isPointer() || baseType->as<PointerType>()->getBaseType()->isArray());
|
return aval && (baseType->isPointer() || baseType->as<PointerType>()->getBaseType()->isArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//该实现参考了libdivide的算法
|
||||||
|
static std::pair<int, int> computeMulhMagicNumbers(int divisor) {
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "\n[SR] ===== Computing magic numbers for divisor " << divisor << " (libdivide algorithm) =====" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (divisor == 0) {
|
||||||
|
if (DEBUG) std::cout << "[SR] Error: divisor must be != 0" << std::endl;
|
||||||
|
return {-1, -1};
|
||||||
|
}
|
||||||
|
|
||||||
|
// libdivide 常数
|
||||||
|
const uint8_t LIBDIVIDE_ADD_MARKER = 0x40;
|
||||||
|
const uint8_t LIBDIVIDE_NEGATIVE_DIVISOR = 0x80;
|
||||||
|
|
||||||
|
// 辅助函数:计算前导零个数
|
||||||
|
auto count_leading_zeros32 = [](uint32_t val) -> uint32_t {
|
||||||
|
if (val == 0) return 32;
|
||||||
|
return __builtin_clz(val);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 辅助函数:64位除法返回32位商和余数
|
||||||
|
auto div_64_32 = [](uint32_t high, uint32_t low, uint32_t divisor, uint32_t* rem) -> uint32_t {
|
||||||
|
uint64_t dividend = ((uint64_t)high << 32) | low;
|
||||||
|
uint32_t quotient = dividend / divisor;
|
||||||
|
*rem = dividend % divisor;
|
||||||
|
return quotient;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] Input divisor: " << divisor << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// libdivide_internal_s32_gen 算法实现
|
||||||
|
int32_t d = divisor;
|
||||||
|
uint32_t ud = (uint32_t)d;
|
||||||
|
uint32_t absD = (d < 0) ? -ud : ud;
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] absD = " << absD << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t floor_log_2_d = 31 - count_leading_zeros32(absD);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] floor_log_2_d = " << floor_log_2_d << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 absD 是否为2的幂
|
||||||
|
if ((absD & (absD - 1)) == 0) {
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] " << absD << " 是2的幂,使用移位方法" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于2的幂,我们只使用移位,不需要魔数
|
||||||
|
int shift = floor_log_2_d;
|
||||||
|
if (d < 0) shift |= 0x80; // 标记负数
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] Power of 2 result: magic=0, shift=" << shift << std::endl;
|
||||||
|
std::cout << "[SR] ===== End magic computation =====" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于我们的目的,我们将在IR生成中以不同方式处理2的幂
|
||||||
|
// 返回特殊标记
|
||||||
|
return {0, shift};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] " << absD << " is not a power of 2, computing magic number" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 非2的幂除数的魔数计算
|
||||||
|
uint8_t more;
|
||||||
|
uint32_t rem, proposed_m;
|
||||||
|
|
||||||
|
// 计算 proposed_m = floor(2^(floor_log_2_d + 31) / absD)
|
||||||
|
proposed_m = div_64_32((uint32_t)1 << (floor_log_2_d - 1), 0, absD, &rem);
|
||||||
|
const uint32_t e = absD - rem;
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] proposed_m = " << proposed_m << ", rem = " << rem << ", e = " << e << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确定是否需要"加法"版本
|
||||||
|
const bool branchfree = false; // 使用分支版本
|
||||||
|
|
||||||
|
if (!branchfree && e < ((uint32_t)1 << floor_log_2_d)) {
|
||||||
|
// 这个幂次有效
|
||||||
|
more = (uint8_t)(floor_log_2_d - 1);
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] Using basic algorithm, shift = " << (int)more << std::endl;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 我们需要上升一个等级
|
||||||
|
proposed_m += proposed_m;
|
||||||
|
const uint32_t twice_rem = rem + rem;
|
||||||
|
if (twice_rem >= absD || twice_rem < rem) {
|
||||||
|
proposed_m += 1;
|
||||||
|
}
|
||||||
|
more = (uint8_t)(floor_log_2_d | LIBDIVIDE_ADD_MARKER);
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] Using add algorithm, proposed_m = " << proposed_m << ", more = " << (int)more << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proposed_m += 1;
|
||||||
|
int32_t magic = (int32_t)proposed_m;
|
||||||
|
|
||||||
|
// 处理负除数
|
||||||
|
if (d < 0) {
|
||||||
|
more |= LIBDIVIDE_NEGATIVE_DIVISOR;
|
||||||
|
if (!branchfree) {
|
||||||
|
magic = -magic;
|
||||||
|
}
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] Negative divisor, magic = " << magic << ", more = " << (int)more << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 为我们的IR生成提取移位量和标志
|
||||||
|
int shift = more & 0x3F; // 移除标志,保留移位量(位0-5)
|
||||||
|
bool need_add = (more & LIBDIVIDE_ADD_MARKER) != 0;
|
||||||
|
bool is_negative = (more & LIBDIVIDE_NEGATIVE_DIVISOR) != 0;
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] Final result: magic = " << magic << ", more = " << (int)more
|
||||||
|
<< " (0x" << std::hex << (int)more << std::dec << ")" << std::endl;
|
||||||
|
std::cout << "[SR] Shift = " << shift << ", need_add = " << need_add
|
||||||
|
<< ", is_negative = " << is_negative << std::endl;
|
||||||
|
|
||||||
|
// Test the magic number using the correct libdivide algorithm
|
||||||
|
std::cout << "[SR] Testing magic number (libdivide algorithm):" << std::endl;
|
||||||
|
int test_values[] = {1, 7, 37, 100, 999, -1, -7, -37, -100};
|
||||||
|
|
||||||
|
for (int test_val : test_values) {
|
||||||
|
int64_t quotient;
|
||||||
|
|
||||||
|
// 实现正确的libdivide算法
|
||||||
|
int64_t product = (int64_t)test_val * magic;
|
||||||
|
int64_t high_bits = product >> 32;
|
||||||
|
|
||||||
|
if (need_add) {
|
||||||
|
// ADD_MARKER情况:移位前加上被除数
|
||||||
|
// 这是libdivide的关键洞察!
|
||||||
|
high_bits += test_val;
|
||||||
|
quotient = high_bits >> shift;
|
||||||
|
} else {
|
||||||
|
// 正常情况:只是移位
|
||||||
|
quotient = high_bits >> shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 符号修正:这是libdivide有符号除法的关键部分!
|
||||||
|
// 如果被除数为负,商需要加1来匹配C语言的截断除法语义
|
||||||
|
if (test_val < 0) {
|
||||||
|
quotient += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int expected = test_val / divisor;
|
||||||
|
|
||||||
|
bool correct = (quotient == expected);
|
||||||
|
std::cout << "[SR] " << test_val << " / " << divisor << " = " << quotient
|
||||||
|
<< " (expected " << expected << ") " << (correct ? "✓" : "✗") << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "[SR] ===== End magic computation =====" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回魔数、移位量,并在移位中编码ADD_MARKER标志
|
||||||
|
// 我们将使用移位的第6位表示ADD_MARKER,第7位表示负数(如果需要)
|
||||||
|
int encoded_shift = shift;
|
||||||
|
if (need_add) {
|
||||||
|
encoded_shift |= 0x40; // 设置第6位表示ADD_MARKER
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] Encoding ADD_MARKER in shift: " << encoded_shift << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {magic, encoded_shift};
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}// namespace sysy
|
}// namespace sysy
|
||||||
@@ -123,25 +123,24 @@ bool GlobalStrengthReductionContext::processBasicBlock(BasicBlock *bb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GlobalStrengthReductionContext::processInstruction(Instruction *inst) {
|
bool GlobalStrengthReductionContext::processInstruction(Instruction *inst) {
|
||||||
bool changed = false;
|
|
||||||
|
|
||||||
if (DEBUG >= 2) {
|
if (DEBUG) {
|
||||||
std::cout << " Processing instruction: " << inst->getName() << std::endl;
|
std::cout << " Processing instruction: " << inst->getName() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 先尝试代数优化
|
// 先尝试代数优化
|
||||||
if (tryAlgebraicOptimization(inst)) {
|
if (tryAlgebraicOptimization(inst)) {
|
||||||
changed = true;
|
|
||||||
algebraicOptCount++;
|
algebraicOptCount++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 再尝试强度削弱
|
// 再尝试强度削弱
|
||||||
if (tryStrengthReduction(inst)) {
|
if (tryStrengthReduction(inst)) {
|
||||||
changed = true;
|
|
||||||
strengthReductionCount++;
|
strengthReductionCount++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
@@ -638,7 +637,9 @@ bool GlobalStrengthReductionContext::reduceDivision(BinaryInst *inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
|
builder->setPosition(inst->getParent(), inst->getParent()->findInstIterator(inst));
|
||||||
auto shiftInst = builder->createBinaryInst(Instruction::kSra, Type::getIntType(), lhs, getConstantInt(shiftAmount));
|
Value* divisor_minus_1 = ConstantInteger::get(constVal - 1);
|
||||||
|
Value* adjusted = builder->createAddInst(lhs, divisor_minus_1);
|
||||||
|
Value* shiftInst = builder->createBinaryInst(Instruction::kSra, Type::getIntType(), adjusted, getConstantInt(shiftAmount));
|
||||||
replaceWithOptimized(inst, shiftInst);
|
replaceWithOptimized(inst, shiftInst);
|
||||||
strengthReductionCount++;
|
strengthReductionCount++;
|
||||||
return true;
|
return true;
|
||||||
@@ -646,18 +647,11 @@ bool GlobalStrengthReductionContext::reduceDivision(BinaryInst *inst) {
|
|||||||
|
|
||||||
// x / c = x * magic_number (魔数乘法优化 - 使用libdivide算法)
|
// x / c = x * magic_number (魔数乘法优化 - 使用libdivide算法)
|
||||||
if (isConstantInt(rhs, constVal) && constVal > 1 && constVal != (uint32_t)(-1)) {
|
if (isConstantInt(rhs, constVal) && constVal > 1 && constVal != (uint32_t)(-1)) {
|
||||||
auto magicPair = computeMulhMagicNumbers(static_cast<int>(constVal));
|
// auto magicPair = computeMulhMagicNumbers(static_cast<int>(constVal));
|
||||||
if (magicPair.first != -1) { // 有效的魔数
|
Value* magicResult = createMagicDivisionLibdivide(inst, static_cast<int>(constVal));
|
||||||
if (DEBUG) {
|
replaceWithOptimized(inst, magicResult);
|
||||||
std::cout << " StrengthReduction: " << inst->getName()
|
divisionOptCount++;
|
||||||
<< " = x / " << constVal << " -> libdivide magic multiplication" << std::endl;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
Value* magicResult = createMagicDivisionLibdivide(inst, static_cast<int>(constVal), magicPair);
|
|
||||||
replaceWithOptimized(inst, magicResult);
|
|
||||||
divisionOptCount++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -709,251 +703,98 @@ bool GlobalStrengthReductionContext::reducePower(CallInst *inst) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================================================================
|
Value* GlobalStrengthReductionContext::createMagicDivisionLibdivide(BinaryInst* divInst, int divisor) {
|
||||||
// 魔数乘法相关方法
|
|
||||||
// ======================================================================
|
|
||||||
|
|
||||||
// 该实现参考了libdivide的算法
|
|
||||||
std::pair<int, int> GlobalStrengthReductionContext::computeMulhMagicNumbers(int divisor) {
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "\n[SR] ===== Computing magic numbers for divisor " << divisor << " (libdivide algorithm) =====" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (divisor == 0) {
|
|
||||||
if (DEBUG) std::cout << "[SR] Error: divisor must be != 0" << std::endl;
|
|
||||||
return {-1, -1};
|
|
||||||
}
|
|
||||||
|
|
||||||
// libdivide 常数
|
|
||||||
const uint8_t LIBDIVIDE_ADD_MARKER = 0x40;
|
|
||||||
const uint8_t LIBDIVIDE_NEGATIVE_DIVISOR = 0x80;
|
|
||||||
|
|
||||||
// 辅助函数:计算前导零个数
|
|
||||||
auto count_leading_zeros32 = [](uint32_t val) -> uint32_t {
|
|
||||||
if (val == 0) return 32;
|
|
||||||
return __builtin_clz(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 辅助函数:64位除法返回32位商和余数
|
|
||||||
auto div_64_32 = [](uint32_t high, uint32_t low, uint32_t divisor, uint32_t* rem) -> uint32_t {
|
|
||||||
uint64_t dividend = ((uint64_t)high << 32) | low;
|
|
||||||
uint32_t quotient = dividend / divisor;
|
|
||||||
*rem = dividend % divisor;
|
|
||||||
return quotient;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Input divisor: " << divisor << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// libdivide_internal_s32_gen 算法实现
|
|
||||||
int32_t d = divisor;
|
|
||||||
uint32_t ud = (uint32_t)d;
|
|
||||||
uint32_t absD = (d < 0) ? -ud : ud;
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] absD = " << absD << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t floor_log_2_d = 31 - count_leading_zeros32(absD);
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] floor_log_2_d = " << floor_log_2_d << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查 absD 是否为2的幂
|
|
||||||
if ((absD & (absD - 1)) == 0) {
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] " << absD << " 是2的幂,使用移位方法" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对于2的幂,我们只使用移位,不需要魔数
|
|
||||||
int shift = floor_log_2_d;
|
|
||||||
if (d < 0) shift |= 0x80; // 标记负数
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Power of 2 result: magic=0, shift=" << shift << std::endl;
|
|
||||||
std::cout << "[SR] ===== End magic computation =====" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对于我们的目的,我们将在IR生成中以不同方式处理2的幂
|
|
||||||
// 返回特殊标记
|
|
||||||
return {0, shift};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] " << absD << " is not a power of 2, computing magic number" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 非2的幂除数的魔数计算
|
|
||||||
uint8_t more;
|
|
||||||
uint32_t rem, proposed_m;
|
|
||||||
|
|
||||||
// 计算 proposed_m = floor(2^(floor_log_2_d + 31) / absD)
|
|
||||||
proposed_m = div_64_32((uint32_t)1 << (floor_log_2_d - 1), 0, absD, &rem);
|
|
||||||
const uint32_t e = absD - rem;
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] proposed_m = " << proposed_m << ", rem = " << rem << ", e = " << e << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确定是否需要"加法"版本
|
|
||||||
const bool branchfree = false; // 使用分支版本
|
|
||||||
|
|
||||||
if (!branchfree && e < ((uint32_t)1 << floor_log_2_d)) {
|
|
||||||
// 这个幂次有效
|
|
||||||
more = (uint8_t)(floor_log_2_d - 1);
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Using basic algorithm, shift = " << (int)more << std::endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 我们需要上升一个等级
|
|
||||||
proposed_m += proposed_m;
|
|
||||||
const uint32_t twice_rem = rem + rem;
|
|
||||||
if (twice_rem >= absD || twice_rem < rem) {
|
|
||||||
proposed_m += 1;
|
|
||||||
}
|
|
||||||
more = (uint8_t)(floor_log_2_d | LIBDIVIDE_ADD_MARKER);
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Using add algorithm, proposed_m = " << proposed_m << ", more = " << (int)more << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proposed_m += 1;
|
|
||||||
int32_t magic = (int32_t)proposed_m;
|
|
||||||
|
|
||||||
// 处理负除数
|
|
||||||
if (d < 0) {
|
|
||||||
more |= LIBDIVIDE_NEGATIVE_DIVISOR;
|
|
||||||
if (!branchfree) {
|
|
||||||
magic = -magic;
|
|
||||||
}
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Negative divisor, magic = " << magic << ", more = " << (int)more << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为我们的IR生成提取移位量和标志
|
|
||||||
int shift = more & 0x3F; // 移除标志,保留移位量(位0-5)
|
|
||||||
bool need_add = (more & LIBDIVIDE_ADD_MARKER) != 0;
|
|
||||||
bool is_negative = (more & LIBDIVIDE_NEGATIVE_DIVISOR) != 0;
|
|
||||||
// 返回魔数、移位量,并在移位中编码ADD_MARKER标志
|
|
||||||
// 我们将使用移位的第6位表示ADD_MARKER,第7位表示负数(如果需要)
|
|
||||||
int encoded_shift = shift;
|
|
||||||
if (need_add) {
|
|
||||||
encoded_shift |= 0x40; // 设置第6位表示ADD_MARKER
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Encoding ADD_MARKER in shift: " << encoded_shift << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {magic, encoded_shift};
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* GlobalStrengthReductionContext::createMagicDivision(BinaryInst* divInst, uint32_t divisor, const MagicNumber& magic) {
|
|
||||||
builder->setPosition(divInst->getParent(), divInst->getParent()->findInstIterator(divInst));
|
builder->setPosition(divInst->getParent(), divInst->getParent()->findInstIterator(divInst));
|
||||||
|
// 使用mulh指令优化任意常数除法
|
||||||
|
auto [magic, shift] = SysYIROptUtils::computeMulhMagicNumbers(divisor);
|
||||||
|
|
||||||
Value* dividend = divInst->getLhs();
|
// 检查是否无法优化(magic == -1, shift == -1 表示失败)
|
||||||
|
if (magic == -1 && shift == -1) {
|
||||||
// 创建魔数常量
|
|
||||||
Value* magicConst = getConstantInt(static_cast<int>(magic.multiplier));
|
|
||||||
|
|
||||||
// 执行乘法: tmp = dividend * magic
|
|
||||||
Value* tmp = builder->createMulInst(dividend, magicConst);
|
|
||||||
|
|
||||||
if (magic.needAdd) {
|
|
||||||
// 需要额外加法的情况
|
|
||||||
Value* sum = builder->createAddInst(tmp, dividend);
|
|
||||||
if (magic.shift > 0) {
|
|
||||||
Value* shiftConst = getConstantInt(magic.shift);
|
|
||||||
tmp = builder->createBinaryInst(Instruction::kSra, Type::getIntType(), sum, shiftConst);
|
|
||||||
} else {
|
|
||||||
tmp = sum;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 直接右移
|
|
||||||
if (magic.shift > 0) {
|
|
||||||
Value* shiftConst = getConstantInt(magic.shift);
|
|
||||||
tmp = builder->createBinaryInst(Instruction::kSra, Type::getIntType(), tmp, shiftConst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理符号:如果被除数为负,结果需要调整
|
|
||||||
// 这里简化处理,假设都是正数除法
|
|
||||||
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* GlobalStrengthReductionContext::createMagicDivisionLibdivide(BinaryInst* divInst, int divisor, const std::pair<int, int>& magicPair) {
|
|
||||||
builder->setPosition(divInst->getParent(), divInst->getParent()->findInstIterator(divInst));
|
|
||||||
|
|
||||||
Value* dividend = divInst->getLhs();
|
|
||||||
int magic = magicPair.first;
|
|
||||||
int encoded_shift = magicPair.second;
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Creating libdivide magic division: magic=" << magic
|
|
||||||
<< ", encoded_shift=" << encoded_shift << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查是否为2的幂(magic=0表示是2的幂)
|
|
||||||
if (magic == 0) {
|
|
||||||
// 2的幂除法,直接使用算术右移
|
|
||||||
int shift = encoded_shift & 0x3F; // 获取实际移位量
|
|
||||||
bool is_negative = (encoded_shift & 0x80) != 0;
|
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
std::cout << "[SR] Power of 2 division: shift=" << shift
|
std::cout << "[SR] Cannot optimize division by " << divisor
|
||||||
<< ", negative=" << is_negative << std::endl;
|
<< ", keeping original division" << std::endl;
|
||||||
}
|
}
|
||||||
|
// 返回 nullptr 表示无法优化,调用方应该保持原始除法
|
||||||
Value* result = dividend;
|
return nullptr;
|
||||||
if (shift > 0) {
|
|
||||||
Value* shiftConst = getConstantInt(shift);
|
|
||||||
result = builder->createBinaryInst(Instruction::kSra, Type::getIntType(), dividend, shiftConst);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果原除数为负,需要取反结果
|
|
||||||
if (is_negative) {
|
|
||||||
result = builder->createNegInst(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 非2的幂除法,使用魔数乘法
|
// 2的幂次方除法可以用移位优化(但这不是魔数法的情况)这种情况应该不会被分类到这里但是还是做一个保护措施
|
||||||
int shift = encoded_shift & 0x3F; // 获取移位量(位0-5)
|
if ((divisor & (divisor - 1)) == 0 && divisor > 0) {
|
||||||
bool need_add = (encoded_shift & 0x40) != 0; // 检查ADD_MARKER标志(位6)
|
// 是2的幂次方,可以用移位
|
||||||
|
int shift_amount = 0;
|
||||||
if (DEBUG) {
|
int temp = divisor;
|
||||||
std::cout << "[SR] Magic multiplication: shift=" << shift
|
while (temp > 1) {
|
||||||
<< ", need_add=" << need_add << std::endl;
|
temp >>= 1;
|
||||||
|
shift_amount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* shiftConstant = ConstantInteger::get(shift_amount);
|
||||||
|
// 对于有符号除法,需要先加上除数-1然后再移位(为了正确处理负数舍入)
|
||||||
|
Value* divisor_minus_1 = ConstantInteger::get(divisor - 1);
|
||||||
|
Value* adjusted = builder->createAddInst(divInst->getOperand(0), divisor_minus_1);
|
||||||
|
return builder->createBinaryInst(
|
||||||
|
Instruction::Kind::kSra, // 算术右移
|
||||||
|
divInst->getOperand(0)->getType(),
|
||||||
|
adjusted,
|
||||||
|
shiftConstant
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建魔数常量
|
// 创建魔数常量
|
||||||
Value* magicConst = getConstantInt(magic);
|
// 检查魔数是否能放入32位,如果不能,则不进行优化
|
||||||
|
if (magic > INT32_MAX || magic < INT32_MIN) {
|
||||||
// 执行高位乘法:mulh(dividend, magic)
|
if (DEBUG) {
|
||||||
// 由于我们的IR可能没有直接的mulh指令,我们使用64位乘法然后取高32位
|
std::cout << "[SR] Magic number " << magic << " exceeds 32-bit range, skipping optimization" << std::endl;
|
||||||
// 这里需要根据实际的IR指令集进行调整
|
}
|
||||||
Value* tmp = builder->createMulInst(dividend, magicConst);
|
return nullptr; // 无法优化,保持原始除法
|
||||||
|
|
||||||
if (need_add) {
|
|
||||||
// ADD算法:(mulh(dividend, magic) + dividend) >> shift
|
|
||||||
tmp = builder->createAddInst(tmp, dividend);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shift > 0) {
|
Value* magicConstant = ConstantInteger::get((int32_t)magic);
|
||||||
Value* shiftConst = getConstantInt(shift);
|
|
||||||
tmp = builder->createBinaryInst(Instruction::kSra, Type::getIntType(), tmp, shiftConst);
|
// 检查是否需要ADD_MARKER处理(加法调整)
|
||||||
|
bool needAdd = (shift & 0x40) != 0;
|
||||||
|
int actualShift = shift & 0x3F; // 提取真实的移位量
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] IR Generation: magic=" << magic << ", needAdd=" << needAdd
|
||||||
|
<< ", actualShift=" << actualShift << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理符号位调整
|
// 执行高位乘法:mulh(x, magic)
|
||||||
// 如果被除数为负数,可能需要额外的符号处理
|
Value* mulhResult = builder->createBinaryInst(
|
||||||
// 这里简化处理,实际实现可能需要更复杂的符号位处理
|
Instruction::Kind::kMulh, // 高位乘法
|
||||||
|
divInst->getOperand(0)->getType(),
|
||||||
|
divInst->getOperand(0),
|
||||||
|
magicConstant
|
||||||
|
);
|
||||||
|
|
||||||
return tmp;
|
if (needAdd) {
|
||||||
|
// ADD_MARKER 情况:需要在移位前加上被除数
|
||||||
|
// 这对应于 libdivide 的加法调整算法
|
||||||
|
if (DEBUG) {
|
||||||
|
std::cout << "[SR] Applying ADD_MARKER: adding dividend before shift" << std::endl;
|
||||||
|
}
|
||||||
|
mulhResult = builder->createAddInst(mulhResult, divInst->getOperand(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualShift > 0) {
|
||||||
|
// 如果需要额外移位
|
||||||
|
Value* shiftConstant = ConstantInteger::get(actualShift);
|
||||||
|
mulhResult = builder->createBinaryInst(
|
||||||
|
Instruction::Kind::kSra, // 算术右移
|
||||||
|
divInst->getOperand(0)->getType(),
|
||||||
|
mulhResult,
|
||||||
|
shiftConstant
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标准的有符号除法符号修正:如果被除数为负,商需要加1
|
||||||
|
// 这对所有有符号除法都需要,不管是否可能有负数
|
||||||
|
Value* isNegative = builder->createICmpLTInst(divInst->getOperand(0), ConstantInteger::get(0));
|
||||||
|
// 将i1转换为i32:负数时为1,非负数时为0 ICmpLTInst的结果会默认转化为32位
|
||||||
|
mulhResult = builder->createAddInst(mulhResult, isNegative);
|
||||||
|
|
||||||
|
return mulhResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
@@ -1010,7 +851,7 @@ bool GlobalStrengthReductionContext::hasOnlyLocalUses(Instruction* inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GlobalStrengthReductionContext::replaceWithOptimized(Instruction* original, Value* replacement) {
|
void GlobalStrengthReductionContext::replaceWithOptimized(Instruction* original, Value* replacement) {
|
||||||
if (DEBUG >= 2) {
|
if (DEBUG) {
|
||||||
std::cout << " Replacing " << original->getName()
|
std::cout << " Replacing " << original->getName()
|
||||||
<< " with " << replacement->getName() << std::endl;
|
<< " with " << replacement->getName() << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,187 +106,6 @@ bool StrengthReductionContext::analyzeInductionVariableRange(
|
|||||||
return hasNegativePotential;
|
return hasNegativePotential;
|
||||||
}
|
}
|
||||||
|
|
||||||
//该实现参考了libdivide的算法
|
|
||||||
std::pair<int, int> StrengthReductionContext::computeMulhMagicNumbers(int divisor) const {
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "\n[SR] ===== Computing magic numbers for divisor " << divisor << " (libdivide algorithm) =====" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (divisor == 0) {
|
|
||||||
if (DEBUG) std::cout << "[SR] Error: divisor must be != 0" << std::endl;
|
|
||||||
return {-1, -1};
|
|
||||||
}
|
|
||||||
|
|
||||||
// libdivide 常数
|
|
||||||
const uint8_t LIBDIVIDE_ADD_MARKER = 0x40;
|
|
||||||
const uint8_t LIBDIVIDE_NEGATIVE_DIVISOR = 0x80;
|
|
||||||
|
|
||||||
// 辅助函数:计算前导零个数
|
|
||||||
auto count_leading_zeros32 = [](uint32_t val) -> uint32_t {
|
|
||||||
if (val == 0) return 32;
|
|
||||||
return __builtin_clz(val);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 辅助函数:64位除法返回32位商和余数
|
|
||||||
auto div_64_32 = [](uint32_t high, uint32_t low, uint32_t divisor, uint32_t* rem) -> uint32_t {
|
|
||||||
uint64_t dividend = ((uint64_t)high << 32) | low;
|
|
||||||
uint32_t quotient = dividend / divisor;
|
|
||||||
*rem = dividend % divisor;
|
|
||||||
return quotient;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Input divisor: " << divisor << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// libdivide_internal_s32_gen 算法实现
|
|
||||||
int32_t d = divisor;
|
|
||||||
uint32_t ud = (uint32_t)d;
|
|
||||||
uint32_t absD = (d < 0) ? -ud : ud;
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] absD = " << absD << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t floor_log_2_d = 31 - count_leading_zeros32(absD);
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] floor_log_2_d = " << floor_log_2_d << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查 absD 是否为2的幂
|
|
||||||
if ((absD & (absD - 1)) == 0) {
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] " << absD << " 是2的幂,使用移位方法" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对于2的幂,我们只使用移位,不需要魔数
|
|
||||||
int shift = floor_log_2_d;
|
|
||||||
if (d < 0) shift |= 0x80; // 标记负数
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Power of 2 result: magic=0, shift=" << shift << std::endl;
|
|
||||||
std::cout << "[SR] ===== End magic computation =====" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对于我们的目的,我们将在IR生成中以不同方式处理2的幂
|
|
||||||
// 返回特殊标记
|
|
||||||
return {0, shift};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] " << absD << " is not a power of 2, computing magic number" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 非2的幂除数的魔数计算
|
|
||||||
uint8_t more;
|
|
||||||
uint32_t rem, proposed_m;
|
|
||||||
|
|
||||||
// 计算 proposed_m = floor(2^(floor_log_2_d + 31) / absD)
|
|
||||||
proposed_m = div_64_32((uint32_t)1 << (floor_log_2_d - 1), 0, absD, &rem);
|
|
||||||
const uint32_t e = absD - rem;
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] proposed_m = " << proposed_m << ", rem = " << rem << ", e = " << e << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确定是否需要"加法"版本
|
|
||||||
const bool branchfree = false; // 使用分支版本
|
|
||||||
|
|
||||||
if (!branchfree && e < ((uint32_t)1 << floor_log_2_d)) {
|
|
||||||
// 这个幂次有效
|
|
||||||
more = (uint8_t)(floor_log_2_d - 1);
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Using basic algorithm, shift = " << (int)more << std::endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 我们需要上升一个等级
|
|
||||||
proposed_m += proposed_m;
|
|
||||||
const uint32_t twice_rem = rem + rem;
|
|
||||||
if (twice_rem >= absD || twice_rem < rem) {
|
|
||||||
proposed_m += 1;
|
|
||||||
}
|
|
||||||
more = (uint8_t)(floor_log_2_d | LIBDIVIDE_ADD_MARKER);
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Using add algorithm, proposed_m = " << proposed_m << ", more = " << (int)more << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proposed_m += 1;
|
|
||||||
int32_t magic = (int32_t)proposed_m;
|
|
||||||
|
|
||||||
// 处理负除数
|
|
||||||
if (d < 0) {
|
|
||||||
more |= LIBDIVIDE_NEGATIVE_DIVISOR;
|
|
||||||
if (!branchfree) {
|
|
||||||
magic = -magic;
|
|
||||||
}
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Negative divisor, magic = " << magic << ", more = " << (int)more << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 为我们的IR生成提取移位量和标志
|
|
||||||
int shift = more & 0x3F; // 移除标志,保留移位量(位0-5)
|
|
||||||
bool need_add = (more & LIBDIVIDE_ADD_MARKER) != 0;
|
|
||||||
bool is_negative = (more & LIBDIVIDE_NEGATIVE_DIVISOR) != 0;
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Final result: magic = " << magic << ", more = " << (int)more
|
|
||||||
<< " (0x" << std::hex << (int)more << std::dec << ")" << std::endl;
|
|
||||||
std::cout << "[SR] Shift = " << shift << ", need_add = " << need_add
|
|
||||||
<< ", is_negative = " << is_negative << std::endl;
|
|
||||||
|
|
||||||
// Test the magic number using the correct libdivide algorithm
|
|
||||||
std::cout << "[SR] Testing magic number (libdivide algorithm):" << std::endl;
|
|
||||||
int test_values[] = {1, 7, 37, 100, 999, -1, -7, -37, -100};
|
|
||||||
|
|
||||||
for (int test_val : test_values) {
|
|
||||||
int64_t quotient;
|
|
||||||
|
|
||||||
// 实现正确的libdivide算法
|
|
||||||
int64_t product = (int64_t)test_val * magic;
|
|
||||||
int64_t high_bits = product >> 32;
|
|
||||||
|
|
||||||
if (need_add) {
|
|
||||||
// ADD_MARKER情况:移位前加上被除数
|
|
||||||
// 这是libdivide的关键洞察!
|
|
||||||
high_bits += test_val;
|
|
||||||
quotient = high_bits >> shift;
|
|
||||||
} else {
|
|
||||||
// 正常情况:只是移位
|
|
||||||
quotient = high_bits >> shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 符号修正:这是libdivide有符号除法的关键部分!
|
|
||||||
// 如果被除数为负,商需要加1来匹配C语言的截断除法语义
|
|
||||||
if (test_val < 0) {
|
|
||||||
quotient += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int expected = test_val / divisor;
|
|
||||||
|
|
||||||
bool correct = (quotient == expected);
|
|
||||||
std::cout << "[SR] " << test_val << " / " << divisor << " = " << quotient
|
|
||||||
<< " (expected " << expected << ") " << (correct ? "✓" : "✗") << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "[SR] ===== End magic computation =====" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 返回魔数、移位量,并在移位中编码ADD_MARKER标志
|
|
||||||
// 我们将使用移位的第6位表示ADD_MARKER,第7位表示负数(如果需要)
|
|
||||||
int encoded_shift = shift;
|
|
||||||
if (need_add) {
|
|
||||||
encoded_shift |= 0x40; // 设置第6位表示ADD_MARKER
|
|
||||||
if (DEBUG) {
|
|
||||||
std::cout << "[SR] Encoding ADD_MARKER in shift: " << encoded_shift << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {magic, encoded_shift};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LoopStrengthReduction::runOnFunction(Function* F, AnalysisManager& AM) {
|
bool LoopStrengthReduction::runOnFunction(Function* F, AnalysisManager& AM) {
|
||||||
if (F->getBasicBlocks().empty()) {
|
if (F->getBasicBlocks().empty()) {
|
||||||
@@ -1018,7 +837,7 @@ Value* StrengthReductionContext::generateConstantDivisionReplacement(
|
|||||||
IRBuilder* builder
|
IRBuilder* builder
|
||||||
) const {
|
) const {
|
||||||
// 使用mulh指令优化任意常数除法
|
// 使用mulh指令优化任意常数除法
|
||||||
auto [magic, shift] = computeMulhMagicNumbers(candidate->multiplier);
|
auto [magic, shift] = SysYIROptUtils::computeMulhMagicNumbers(candidate->multiplier);
|
||||||
|
|
||||||
// 检查是否无法优化(magic == -1, shift == -1 表示失败)
|
// 检查是否无法优化(magic == -1, shift == -1 表示失败)
|
||||||
if (magic == -1 && shift == -1) {
|
if (magic == -1 && shift == -1) {
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR
|
|||||||
registerOptimizationPass<LICM>(builderIR);
|
registerOptimizationPass<LICM>(builderIR);
|
||||||
registerOptimizationPass<LoopStrengthReduction>(builderIR);
|
registerOptimizationPass<LoopStrengthReduction>(builderIR);
|
||||||
registerOptimizationPass<InductionVariableElimination>();
|
registerOptimizationPass<InductionVariableElimination>();
|
||||||
|
|
||||||
|
registerOptimizationPass<GlobalStrengthReduction>(builderIR);
|
||||||
registerOptimizationPass<Reg2Mem>(builderIR);
|
registerOptimizationPass<Reg2Mem>(builderIR);
|
||||||
|
|
||||||
registerOptimizationPass<SCCP>(builderIR);
|
registerOptimizationPass<SCCP>(builderIR);
|
||||||
|
|||||||
Reference in New Issue
Block a user