From 5c34cbc7b871b30eb1f2a960286c4c098f8933b9 Mon Sep 17 00:00:00 2001 From: rain2133 <1370973498@qq.com> Date: Mon, 18 Aug 2025 20:37:20 +0800 Subject: [PATCH] =?UTF-8?q?[midend-GSR]=E5=B0=86=E9=AD=94=E6=95=B0?= =?UTF-8?q?=E6=B1=82=E8=A7=A3=E7=A7=BB=E5=8A=A8=E5=88=B0utils=E7=9A=84?= =?UTF-8?q?=E9=9D=99=E6=80=81=E6=96=B9=E6=B3=95=E4=B8=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pass/Optimize/GlobalStrengthReduction.h | 2 +- .../Pass/Optimize/LoopStrengthReduction.h | 7 - .../midend/Pass/Optimize/SysYIROptUtils.h | 184 ++++++++++ .../Pass/Optimize/GlobalStrengthReduction.cpp | 341 +++++------------- .../Pass/Optimize/LoopStrengthReduction.cpp | 183 +--------- src/midend/Pass/Pass.cpp | 2 + 6 files changed, 279 insertions(+), 440 deletions(-) diff --git a/src/include/midend/Pass/Optimize/GlobalStrengthReduction.h b/src/include/midend/Pass/Optimize/GlobalStrengthReduction.h index 574494c..43c75fb 100644 --- a/src/include/midend/Pass/Optimize/GlobalStrengthReduction.h +++ b/src/include/midend/Pass/Optimize/GlobalStrengthReduction.h @@ -68,7 +68,7 @@ private: MagicNumber computeMagicNumber(uint32_t divisor); std::pair computeMulhMagicNumbers(int divisor); Value* createMagicDivision(BinaryInst* divInst, uint32_t divisor, const MagicNumber& magic); - Value* createMagicDivisionLibdivide(BinaryInst* divInst, int divisor, const std::pair& magicPair); + Value* createMagicDivisionLibdivide(BinaryInst* divInst, int divisor); bool isPowerOfTwo(uint32_t n); int log2OfPowerOfTwo(uint32_t n); diff --git a/src/include/midend/Pass/Optimize/LoopStrengthReduction.h b/src/include/midend/Pass/Optimize/LoopStrengthReduction.h index ecf96dd..a6bc8cd 100644 --- a/src/include/midend/Pass/Optimize/LoopStrengthReduction.h +++ b/src/include/midend/Pass/Optimize/LoopStrengthReduction.h @@ -127,13 +127,6 @@ private: */ bool analyzeInductionVariableRange(const InductionVarInfo* ivInfo, Loop* loop) const; - /** - * 计算用于除法优化的魔数和移位量 - * @param divisor 除数 - * @return {魔数, 移位量} - */ - std::pair computeMulhMagicNumbers(int divisor) const; - /** * 生成除法替换代码 * @param candidate 优化候选项 diff --git a/src/include/midend/Pass/Optimize/SysYIROptUtils.h b/src/include/midend/Pass/Optimize/SysYIROptUtils.h index 00a4db5..48d2f26 100644 --- a/src/include/midend/Pass/Optimize/SysYIROptUtils.h +++ b/src/include/midend/Pass/Optimize/SysYIROptUtils.h @@ -107,6 +107,190 @@ public: // 所以当AllocaInst的basetype是PointerType时(一维数组)或者是指向ArrayType的PointerType(多位数组)时,返回true return aval && (baseType->isPointer() || baseType->as()->getBaseType()->isArray()); } + + + //该实现参考了libdivide的算法 + static std::pair 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 \ No newline at end of file diff --git a/src/midend/Pass/Optimize/GlobalStrengthReduction.cpp b/src/midend/Pass/Optimize/GlobalStrengthReduction.cpp index 118b793..e15a9c5 100644 --- a/src/midend/Pass/Optimize/GlobalStrengthReduction.cpp +++ b/src/midend/Pass/Optimize/GlobalStrengthReduction.cpp @@ -123,25 +123,24 @@ bool GlobalStrengthReductionContext::processBasicBlock(BasicBlock *bb) { } bool GlobalStrengthReductionContext::processInstruction(Instruction *inst) { - bool changed = false; - if (DEBUG >= 2) { + if (DEBUG) { std::cout << " Processing instruction: " << inst->getName() << std::endl; } // 先尝试代数优化 if (tryAlgebraicOptimization(inst)) { - changed = true; algebraicOptCount++; + return true; } // 再尝试强度削弱 if (tryStrengthReduction(inst)) { - changed = true; strengthReductionCount++; + return true; } - return changed; + return false; } // ====================================================================== @@ -638,7 +637,9 @@ bool GlobalStrengthReductionContext::reduceDivision(BinaryInst *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); strengthReductionCount++; return true; @@ -646,18 +647,11 @@ bool GlobalStrengthReductionContext::reduceDivision(BinaryInst *inst) { // x / c = x * magic_number (魔数乘法优化 - 使用libdivide算法) if (isConstantInt(rhs, constVal) && constVal > 1 && constVal != (uint32_t)(-1)) { - auto magicPair = computeMulhMagicNumbers(static_cast(constVal)); - if (magicPair.first != -1) { // 有效的魔数 - if (DEBUG) { - std::cout << " StrengthReduction: " << inst->getName() - << " = x / " << constVal << " -> libdivide magic multiplication" << std::endl; - } - - Value* magicResult = createMagicDivisionLibdivide(inst, static_cast(constVal), magicPair); - replaceWithOptimized(inst, magicResult); - divisionOptCount++; - return true; - } + // auto magicPair = computeMulhMagicNumbers(static_cast(constVal)); + Value* magicResult = createMagicDivisionLibdivide(inst, static_cast(constVal)); + replaceWithOptimized(inst, magicResult); + divisionOptCount++; + return true; } return false; @@ -709,251 +703,98 @@ bool GlobalStrengthReductionContext::reducePower(CallInst *inst) { return false; } -// ====================================================================== -// 魔数乘法相关方法 -// ====================================================================== - -// 该实现参考了libdivide的算法 -std::pair 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) { +Value* GlobalStrengthReductionContext::createMagicDivisionLibdivide(BinaryInst* divInst, int divisor) { builder->setPosition(divInst->getParent(), divInst->getParent()->findInstIterator(divInst)); + // 使用mulh指令优化任意常数除法 + auto [magic, shift] = SysYIROptUtils::computeMulhMagicNumbers(divisor); - Value* dividend = divInst->getLhs(); - - // 创建魔数常量 - Value* magicConst = getConstantInt(static_cast(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& 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; - + // 检查是否无法优化(magic == -1, shift == -1 表示失败) + if (magic == -1 && shift == -1) { if (DEBUG) { - std::cout << "[SR] Power of 2 division: shift=" << shift - << ", negative=" << is_negative << std::endl; + std::cout << "[SR] Cannot optimize division by " << divisor + << ", keeping original division" << std::endl; } - - Value* result = dividend; - 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; + // 返回 nullptr 表示无法优化,调用方应该保持原始除法 + return nullptr; } - // 非2的幂除法,使用魔数乘法 - int shift = encoded_shift & 0x3F; // 获取移位量(位0-5) - bool need_add = (encoded_shift & 0x40) != 0; // 检查ADD_MARKER标志(位6) - - if (DEBUG) { - std::cout << "[SR] Magic multiplication: shift=" << shift - << ", need_add=" << need_add << std::endl; + // 2的幂次方除法可以用移位优化(但这不是魔数法的情况)这种情况应该不会被分类到这里但是还是做一个保护措施 + if ((divisor & (divisor - 1)) == 0 && divisor > 0) { + // 是2的幂次方,可以用移位 + int shift_amount = 0; + int temp = divisor; + while (temp > 1) { + 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); - - // 执行高位乘法:mulh(dividend, magic) - // 由于我们的IR可能没有直接的mulh指令,我们使用64位乘法然后取高32位 - // 这里需要根据实际的IR指令集进行调整 - Value* tmp = builder->createMulInst(dividend, magicConst); - - if (need_add) { - // ADD算法:(mulh(dividend, magic) + dividend) >> shift - tmp = builder->createAddInst(tmp, dividend); + // 检查魔数是否能放入32位,如果不能,则不进行优化 + if (magic > INT32_MAX || magic < INT32_MIN) { + if (DEBUG) { + std::cout << "[SR] Magic number " << magic << " exceeds 32-bit range, skipping optimization" << std::endl; + } + return nullptr; // 无法优化,保持原始除法 } - if (shift > 0) { - Value* shiftConst = getConstantInt(shift); - tmp = builder->createBinaryInst(Instruction::kSra, Type::getIntType(), tmp, shiftConst); + Value* magicConstant = ConstantInteger::get((int32_t)magic); + + // 检查是否需要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) { - if (DEBUG >= 2) { + if (DEBUG) { std::cout << " Replacing " << original->getName() << " with " << replacement->getName() << std::endl; } diff --git a/src/midend/Pass/Optimize/LoopStrengthReduction.cpp b/src/midend/Pass/Optimize/LoopStrengthReduction.cpp index 973a053..0edbed4 100644 --- a/src/midend/Pass/Optimize/LoopStrengthReduction.cpp +++ b/src/midend/Pass/Optimize/LoopStrengthReduction.cpp @@ -106,187 +106,6 @@ bool StrengthReductionContext::analyzeInductionVariableRange( return hasNegativePotential; } -//该实现参考了libdivide的算法 -std::pair 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) { if (F->getBasicBlocks().empty()) { @@ -1018,7 +837,7 @@ Value* StrengthReductionContext::generateConstantDivisionReplacement( IRBuilder* builder ) const { // 使用mulh指令优化任意常数除法 - auto [magic, shift] = computeMulhMagicNumbers(candidate->multiplier); + auto [magic, shift] = SysYIROptUtils::computeMulhMagicNumbers(candidate->multiplier); // 检查是否无法优化(magic == -1, shift == -1 表示失败) if (magic == -1 && shift == -1) { diff --git a/src/midend/Pass/Pass.cpp b/src/midend/Pass/Pass.cpp index c834e30..aee29b0 100644 --- a/src/midend/Pass/Pass.cpp +++ b/src/midend/Pass/Pass.cpp @@ -78,6 +78,8 @@ void PassManager::runOptimizationPipeline(Module* moduleIR, IRBuilder* builderIR registerOptimizationPass(builderIR); registerOptimizationPass(builderIR); registerOptimizationPass(); + + registerOptimizationPass(builderIR); registerOptimizationPass(builderIR); registerOptimizationPass(builderIR);