diff --git a/.gitignore b/.gitignore index 94c67f9..6775166 100644 --- a/.gitignore +++ b/.gitignore @@ -28,9 +28,15 @@ test-data/personal .idea *.iml +# Vscode Projects +.vscode + # Test script log ssyc.log ssyc.*.log # Personal data -.vscode/java.code-snippets \ No newline at end of file +.vscode/java.code-snippets + +# MacOS +.DS_store \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 5c7420a..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "recommendations": [ - "redhat.java", - - // ANTLR4 support - "mike-lischke.vscode-antlr4", - - // ARM assemble syntax highlight - "dan-c-underwood.arm" - ] -} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 4537721..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // 使用 IntelliSense 了解相关属性。 - // 悬停以查看现有属性的描述。 - // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "java", - "name": "Debug (Attach)", - "request": "attach", - "hostName": "localhost", - "port": 5005, - "preLaunchTask": "debug" - } - ] -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 3f066a5..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "files.associations": { - "*.g4": "antlr", - "m": "shellscript", - "*.sy": "c", - "*.s": "arm", - "*.llvm": "llvm", - }, - - "files.exclude": { - "bin": true, - "lib": true, - "_trash": true, - "target": true, - "**/.antlr": true, - "test-data/**/*.exec": true, - "test-data/**/*.c": true, - }, - - "explorer.fileNesting.enabled": true, - "explorer.fileNesting.patterns": { - "SysY.g4": "SysY*", - "Instruction.java": "*Inst.java", - "IRType.java": "*IRTy.java" - }, - - "workbench.editor.enablePreview": true, - "explorer.compactFolders": true, - - "editor.rulers": [ - 120 - ], - "files.trimTrailingWhitespace": true, - - "java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx16G -Xms512m", - "java.completion.filteredTypes": [ - "java.awt.*", - "com.sun.*", - "sun.*", - "jdk.*", - "org.graalvm.*", - "io.micrometer.shaded.*", - // Add javax - "javax.*", - ], - "java.project.referencedLibraries": [ - "lib/**/*.jar", - ] -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index cf25283..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "type": "shell", - "command": "${workspaceFolder}/m", - "args": ["build"], - "group": "build", - }, - { - "label": "debug", - "dependsOn": "build", - "type": "shell", - "command": "java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 -cp \"lib/*:target\" FunctionalDebug", - "isBackground": true, - "problemMatcher": [{ - "pattern": [{ - "regexp": "\\b\\B", - "file": 1, - "location": 2, - "message": 3 - }], - "background": { - "activeOnStart": true, - "beginsPattern": "^.*Listening for", - "endsPattern": "^.*transport dt_socket at address.*" - } - }] - } - ] -} \ No newline at end of file diff --git a/docs/backend.md b/docs/backend.md index 7507e6c..2d12216 100644 --- a/docs/backend.md +++ b/docs/backend.md @@ -52,7 +52,7 @@ Operand cond: Any, Ge, Gt, Eq, Ne, Le, Lt > 表示改指令在什么情况下执行(目前只有Branch跳转指令、MOV指令和BranchToCond优化涉及) -> (对于比赛用例的中, 出现了浮点数Nan的比较, 因而应该将Le改用Ls,Lt改用Mi, 目前本项目还是保留为Le, Lt) +> (对于比赛用例的中, 出现了浮点数Nan的比较, 因而应该将Le改用Ls,Lt改用Mi,而Ge改用Pl,Gt改用Hi不需要添加) operands:表示该指令所拥有的操作数 > 并不是所有的指令都拥有操作数 比如Return和Branch指令 每个指令所拥有的操作数个数也不一定相同,比如Binary就有三个操作数 而Ternay则有四个操作数 @@ -60,70 +60,6 @@ operands:表示该指令所拥有的操作数 Shift: Arm汇编中的第2个操作数 > 表示的是对于,用于在计算时实现移位操作 -### 指令接口 - -对于指令的构造函数而言,如果第一次参数时ArmBlock则表示将该指令自动插入到该ArmBlock的尾部 - -对于每个指令而言,可以通过 - -```java -getRegUse() -``` -获得使用寄存器 - -```java -getRegDef() -``` -获得定值寄存器 - -使用寄存器和定值寄存器保证是一个寄存器类型,而不会是一个立即数或者是地址,这个概念来源于Live Interval计算(活跃区间计算) - -对于未进行寄存器分配时的操作数,也有可能是物理寄存器,这是因为在函数传参和返回时会涉及到固定的物理寄存器 - -对于每个指令而言,有三个接口可以替换操作数 - -```java -replaceOperand(Operand oldOp, Operand op) -``` -将指令中所有的操作数为操作数oladOp替换为操作数op - -```java -replaceDefOperand(Operand oldOp, Operand op) -``` -将指令中所有的使用操作数为操作数oladOp替换为操作数op - -```java -replaceUseOperand(Operand oldOp, Operand op) -``` -将指令中所有的定值操作数为操作数oladOp替换为操作数op - -因为替换是把所有同类型的操作数都进行替换(可能会出现指令ADD VR1 VR2 VR2,为相同的虚拟寄存器的情况),因此如果不希望全部替换则可以只替换使用操作数的部分和定值操作数的部分(理论上对于使用操作数为同一个操作数时,同时替换肯定是最优解?) - -### 寄存器接口 - -对于创建一个物理寄存器 可以直接通过 -```java -IPhyReg.R(0), IPhyReg.SP, new IPhyReg(0), new IPhyReg(13) -``` -其中第一个和第三个等价 第二个和第四个等价 - -目前可以使用的寄存器: - -通用寄存器: r0-r12 r14(lr) - -向量寄存器: s0-s31 - -IVirtualReg 应该分配通用寄存器 -FVirtualReg 应该分配向量寄存器 - -对于寄存器有接口: -```java -Set getInstSet() -``` -其可以返回该寄存器在哪些指令当中使用了,每次该寄存器被替换了则会在这个Set中自动删除 - -但实际上这个只对虚拟寄存器是有效的,因为逻辑上相同的虚拟寄存器也是同一个实例,但对于物理寄存器而言,逻辑上相同的物理寄存器并不一定是同一个实例。 - ### 栈结构 对于在 Linux ARM 上, 栈向低地址方向增长, 高地址是栈顶 @@ -252,6 +188,12 @@ StackAddr用于表示一个基址或者一个CAlloc的在栈上的地址,当 $$\mid x \mid = 2^x \pm 2^y / 0 \quad (x \geq y)$$ +对于立即数模,只会对`2^n`和`0`的特殊情况进行优化 + +立即数模其本身等价于 x % y == x - (x / y) * y + +其中模转换成的乘法和除法也可以继续使用立即数乘除法优化 + ### 窥孔优化 目前采用的策略包括: diff --git a/local-test/find_exit_code.py b/local-test/find_exit_code.py deleted file mode 100755 index 7b44bab..0000000 --- a/local-test/find_exit_code.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/python -from typing import Iterable -import os -import os.path as op - -def find(path: str) -> Iterable[str]: - for filename in os.listdir(path): - file_path = op.join(path, filename) - if op.isdir(file_path): - yield from find(file_path) - else: - yield file_path - - -def lines(file_name: str) -> Iterable[tuple[int, str]]: - with open(file_name, 'r') as f: - for no, line in enumerate(f.readlines()): - yield no + 1, line - -if __name__ == '__main__': - try: - import sys - _, lineNoStr = sys.argv - except: - print('Usage: find_exit_code ') - exit(1) - - lineNo = int(lineNoStr) - - def is_log_ensure(no: int, line: str) -> bool: - return no % 128 == lineNo and line.find('Log.ensure') != -1 - - def is_ir_verify(no: int, line: str) -> bool: - return 128 + (no % 128) == lineNo \ - and (line.find('IRVerifyException') != -1 or line.find('ensure') != -1) \ - and line.find('Log') == -1 - - pred = is_log_ensure if lineNo < 128 else is_ir_verify - - for file in find('src'): - for no, line in lines(file): - if pred(no, line): - print(f'Found on {file}:{no} : {line}') \ No newline at end of file diff --git a/local-test/test.py b/local-test/test.py index 639c780..f21c2a9 100644 --- a/local-test/test.py +++ b/local-test/test.py @@ -6,31 +6,39 @@ console = Console() + def rel(*subs: str) -> str: return os.path.join(os.curdir, *subs) + exists = os.path.exists echo = console.log + def exit_with(message: str): console.log(f'[red bold]{message}') exit(1) + def sh(command: str): if (ret := os.system(command)) != 0: exit_with(f'Command fail: {command} (return {ret})') + def fill_front_zero(num: int, target_length: int) -> str: return '0' * (target_length - len(str(num))) + str(num) + def fill_end_space(raw: str, target_length: int) -> str: return raw + ' ' * (target_length - len(raw)) -def one_pass(status_message: str, from_suffix: str, to_suffix: str, show: bool=True): + +def one_pass(status_message: str, from_suffix: str, to_suffix: str, show: bool = True): def decorator(func: Callable[[str, str], None]): def do(subdir: str): console.print(f"[cyan bold]================= begin: {status_message} =================") - with console.status(f'[bold green]{status_message} on {subdir} ({from_suffix} -> {to_suffix})...') as status: + with console.status( + f'[bold green]{status_message} on {subdir} ({from_suffix} -> {to_suffix})...') as status: files = os.listdir(rel('test-data', subdir)) sources = sorted([s for s in files if s.endswith(from_suffix)]) source_cnt = len(sources) @@ -42,11 +50,12 @@ def do(subdir: str): func(full_src, full_dst) if show: - console.log(f'Finish ({fill_front_zero(idx, total_len)}/{source_cnt}) {filename}') + console.log(f'Finish ({fill_front_zero(idx + 1, total_len)}/{source_cnt}) {filename}') # console.clear() do.type = (from_suffix, to_suffix) return do + return decorator @@ -68,18 +77,35 @@ def do(src: str, dst: str): print(line, end='') console.log(f'[red bold]Compiler failed on {src}') exit(1) + + return do + + +def ssyc_O2(option: str) -> Callable[[str, str], None]: + def do(src: str, dst: str): + result = os.system(f'java -cp "lib/*:target" Main {option} {src} {dst} -O2 2> ssyc.log') + if result != 0: + with open('ssyc.log', 'r') as f: + for line in f.readlines(): + print(line, end='') + console.log(f'[red bold]Compiler failed on {src}') + exit(1) + return do + ssyc_llvm = one_pass('ssyc', '.sy', '.llvm')(ssyc('llvm')) # Check that: https://stackoverflow.com/questions/62436694/why-cant-gcc-compile-assembly-produced-by-clang clang_cmd = 'clang -I/usr/arm-linux-gnueabihf/include -no-integrated-as -target armv7-linux-gnueabihf -static -g0' + @one_pass('clang-emit-llvm', '.sy', '.llvm') def clang_llvm(src: str, dst: str): new_src = pre_include(src) sh(f'{clang_cmd} -emit-llvm -S {new_src} -o {dst}') + @one_pass('llc', '.llvm', '.s') def llc(src: str, dst: str): bc = src.removesuffix('.llvm') + '.bc' @@ -91,6 +117,8 @@ def llc(src: str, dst: str): ssyc_asm = one_pass('ssyc', '.sy', '.s')(ssyc('asm')) +ssyc_asm_O2 = one_pass('ssyc', '.sy', '.s')(ssyc_O2('asm')) + def pre_include(source: str) -> str: lines = [] @@ -109,6 +137,7 @@ def pre_include(source: str) -> str: return dst + # @one_pass('gcc', '.sy', '.s') # def gcc(src: str, dst: str): # new_src = pre_include(src) @@ -119,17 +148,18 @@ def clang(src: str, dst: str): new_src = pre_include(src) sh(f'{clang_cmd} -S {new_src} -o {dst} 2> /dev/null') + @one_pass('clang-O2', '.sy', '.s', show=False) def clang_O2(src: str, dst: str): new_src = pre_include(src) sh(f'{clang_cmd} -O2 -S {new_src} -o {dst} 2> /dev/null') - @one_pass('gcc-as', '.s', '.exec', show=False) def gcc_as(src: str, dst: str): sh(f'arm-linux-gnueabihf-gcc -march=armv7-a -static -g {src} {rel("util", "libsysy.a")} -o {dst}') + @one_pass('generate-stdout', '.exec', '.out') def generate_stdout(src: str, dst: str): base_name = src.removesuffix('.exec') @@ -182,7 +212,6 @@ def run(exec: str, result_file: str): with open(result_file, 'wb') as f: f.writelines(lines) - nick_name = fill_end_space(os.path.split(base_name)[-1], 40) if os.system(f'diff {output_file} {result_file} > /dev/null') != 0: sh(f'difft {result_file} {output_file}') @@ -197,6 +226,8 @@ def run(exec: str, result_file: str): fail_list = [] + + @one_pass('run-for-long-time', '.exec', '.res', show=False) def run_for_long_time(exec: str, result_file: str): base_name = exec.removesuffix('.exec') @@ -223,7 +254,6 @@ def run_for_long_time(exec: str, result_file: str): with open(result_file, 'wb') as f: f.writelines(lines) - nick_name = fill_end_space(os.path.split(base_name)[-1], 40) if os.system(f'diff {output_file} {result_file} > /dev/null') != 0: prompt = f'[red bold]Fail [cyan]{nick_name} [red bold]: Wrong Answer, check [cyan]{result_file} [red bold]for details.' @@ -238,13 +268,16 @@ def run_for_long_time(exec: str, result_file: str): os.remove(pgm_return) os.remove(pgm_stderr) + def print_fail(subdir: str): for prompt in fail_list: console.log(prompt) + def link_run_on_rpi(): pass + def clear_up(): with console.status('[green bold]Clearing...') as status: for subdir in sorted(os.listdir(rel('test-data'))): @@ -270,13 +303,16 @@ def check_funcs(funcs): if last_type != '.s': exit_with('Last pass should return a .s file') + if __name__ == '__main__': test_items = { 'ssyc_llvm': [build, ssyc_llvm, llc, gcc_as, run], 'ssyc_asm': [build, ssyc_asm, gcc_as, run], + 'ssyc_asm_O2': [build, ssyc_asm_O2, gcc_as, run], 'ssyc_llvm_long': [build, ssyc_llvm, llc, gcc_as, run_for_long_time, print_fail], 'ssyc_asm_long': [build, ssyc_asm, llc, gcc_as, run_for_long_time, print_fail], + 'ssyc_asm_O2_long': [build, ssyc_asm_O2, llc, gcc_as, run_for_long_time, print_fail], 'clang': [clang, gcc_as, run], 'clang_O2': [clang_O2, gcc_as, run], @@ -298,4 +334,4 @@ def check_funcs(funcs): console.print('[white bold]Usage: ./m test ') console.print(f' : {sorted(os.listdir(rel("test-data")))}') console.print(f' : {list(test_items.keys())}') - console.print(f'Passed: {sys.argv}') \ No newline at end of file + console.print(f'Passed: {sys.argv}') diff --git a/src/Compiler.java b/src/Compiler.java index 357b1d9..d5a83f9 100644 --- a/src/Compiler.java +++ b/src/Compiler.java @@ -2,25 +2,35 @@ import utils.Log; import utils.LogFailException; +import java.util.Objects; + public class Compiler { - public static void main(String[] args) { + public static void main(String[] args) { // 功能测试:compiler -S -o testcase.s testcase.sy // 性能测试:compiler -S -o testcase.s testcase.sy -O2 try { final var outputFileName = args[2]; final var inputFileName = args[3]; - final var needOptimize = args.length == 5; + var needOptimize = false; + var needLog = false; + for (var arg : args) { + if (arg.equalsIgnoreCase("-o2")) { + needOptimize = true; + } + if (arg.equalsIgnoreCase("-log")) { + needLog = true; + } + } - Log.inOnlineJudge(); + if (!needLog) { + Log.inOnlineJudge(); + } Main.needOptimize = needOptimize; Main.runWithLargeStack("asm", inputFileName, outputFileName); - } catch (LogFailException e) { - e.printStackTrace(); - System.exit(e.getLineNo() % 128); - } catch (IRVerifyException e) { + } catch (LogFailException | IRVerifyException e) { e.printStackTrace(); - System.exit(e.getLineNo() % 128 + 128); + System.exit(-1); } catch (Exception e) { throw new RuntimeException("Fail at arg: [" + String.join(", ", args) + "]", e); } diff --git a/src/FunctionalDebug.java b/src/FunctionalDebug.java deleted file mode 100644 index 68b3247..0000000 --- a/src/FunctionalDebug.java +++ /dev/null @@ -1,14 +0,0 @@ -public class FunctionalDebug { - public static void main(String[] args) { - // final var basePath = "./test-data/functional/"; - // final var file_name = "21_if_test2"; - // final var basePath = "./test-data/functional/"; - final var basePath = "./test-data/personal/"; - final var file_name = "05-induction"; - - final var input = basePath + file_name + ".sy"; - final var output = basePath + file_name + ".llvm"; - - Main.runWithLargeStack("llvm", input, output); - } -} diff --git a/src/FunctionalProfile.java b/src/FunctionalProfile.java deleted file mode 100644 index 991acbc..0000000 --- a/src/FunctionalProfile.java +++ /dev/null @@ -1,14 +0,0 @@ -import utils.Log; - -public class FunctionalProfile { - public static void main(String[] args) { - final var basePath = "./test-data/hidden_functional/"; - final var file_name = "29_long_line"; - - final var input = basePath + file_name + ".sy"; - final var output = basePath + file_name + ".llvm"; - - Log.inOnlineJudge(); - Main.runWithLargeStack("asm", input, output); - } -} diff --git a/src/Main.java b/src/Main.java index 62b17b5..81fcc81 100644 --- a/src/Main.java +++ b/src/Main.java @@ -17,11 +17,29 @@ public class Main { public static boolean needOptimize = true; public static void main(String[] args) { - if (args.length != 3) { + var needOptimize = false; + var needLog = false; + var flagCnt = 0; + for (var arg : args) { + if (arg.equalsIgnoreCase("-o2")) { + needOptimize = true; + flagCnt++; + } + if (arg.equalsIgnoreCase("--log")) { + needLog = true; + flagCnt++; + } + } + + if (args.length - flagCnt < 3) { System.out.println("Usage: ssyc "); throw new RuntimeException("Argument error: [" + String.join(" ", args) + "]"); } + Main.needOptimize = needOptimize; + if (!needLog) { + Log.inOnlineJudge(); + } runWithLargeStack(args[0], args[1], args[2]); } @@ -82,7 +100,6 @@ public static void runNormal(String target, String inputFileName, String outputF final var parser = new SysYParser(tokens); final var ruleContext = parser.compUnit(); - Log.inOnlineJudge(); switch (target) { case "ast" -> { writer.write(DebugTools.toDebugTreeString(ruleContext).toString()); diff --git a/src/backend/codegen/ToAsmManager.java b/src/backend/codegen/ToAsmManager.java index 997daf7..689f15a 100644 --- a/src/backend/codegen/ToAsmManager.java +++ b/src/backend/codegen/ToAsmManager.java @@ -1,6 +1,5 @@ package backend.codegen; -import backend.ImmUtils; import backend.lir.ArmFunction; import backend.lir.ArmModule; import backend.lir.inst.ArmInst.ArmCondType; @@ -13,6 +12,7 @@ import ir.constant.ArrayConst.ZeroArrayConst; import ir.visitor.ConstantVisitor; import utils.Log; +import utils.ImmUtils; import java.util.HashMap; import java.util.List; @@ -265,7 +265,8 @@ private void codeGenRegPopAtFuncEnd(ArmCondType cond, ArmFunction func) { if (!usedRegs.iRegs.isEmpty()) { // 如果有保存 lr 的话, 直接把 lr 的值恢复到 pc 里去, 省条 bx lr 指令 // 可以看 InstToAsm#visitArmInstReturn 里的对应处理 - // FIXME: 这样 caller 会不会得到一个保存着任意值的 LR 寄存器? + // 这样 caller 会得到一个保存着任意值的 lr 寄存器 + // 但是因为在使用跳转指令的时候,lr 寄存器就会认为已经被使用了,所以 lr 寄存器不会对于 caller 而言不会保存有意义的值 usedRegs.iRegs.replaceAll(reg -> reg.equals(IPhyReg.LR) ? IPhyReg.PC : reg); asm.instruction("pop").cond(cond) .group(usedRegs.iRegs.toArray(Operand[]::new)) diff --git a/src/backend/codegen/ToLIRManager.java b/src/backend/codegen/ToLIRManager.java index e293485..afcfcb7 100644 --- a/src/backend/codegen/ToLIRManager.java +++ b/src/backend/codegen/ToLIRManager.java @@ -1,6 +1,6 @@ package backend.codegen; -import backend.ImmUtils; +import utils.ImmUtils; import backend.lir.ArmBlock; import backend.lir.ArmFunction; import backend.lir.ArmModule; @@ -36,8 +36,8 @@ *
  • 一些简单的优化, 比如乘加融合
  • *
  • 一些强度削减, 比如特定乘除法换成位移和加法
  • * - * - * TODO: 考虑拆分转换代码, 拆成最简单的 SSA -> TAC 转换 (只做 Phi Destruction 和映射) 和若干个优化与底层相关转换 pass 的形式 + * 考虑拆分转换代码, 拆成最简单的 SSA -> TAC 转换 (只做 Phi Destruction 和映射) 和若干个优化与底层相关转换 pass 的形式 + *

    */ public class ToLIRManager { private final Map valMap = new HashMap<>(); @@ -57,8 +57,8 @@ public class ToLIRManager { put(InstKind.FCmpNe, ArmCondType.Ne); put(InstKind.FCmpGt, ArmCondType.Gt); put(InstKind.FCmpGe, ArmCondType.Ge); - put(InstKind.FCmpLt, ArmCondType.Lt); - put(InstKind.FCmpLe, ArmCondType.Le); + put(InstKind.FCmpLt, ArmCondType.Mi); + put(InstKind.FCmpLe, ArmCondType.Ls); } }; @@ -70,6 +70,7 @@ public ToLIRManager(Module irModule) { public ArmModule codeGenLIR() { int acCnt = 0; + // 数组初始化信息 for (var val : irModule.getArrayConstants()) { armModule.getArrayConstants().put("meminit_array_" + acCnt, val); valMap.put(val, new Addr("meminit_array_" + acCnt++)); @@ -192,8 +193,13 @@ public ArmModule codeGenLIR() { block.forEach(visitor::visit); } - // Phi 处理, 相当于在每个基本块最后都添加一条MOVE指令 将incoming基本块里面的Value Move到当前基本块的Value - // MOVE Phi Incoming.Value + // phi 处理 + // 相当于在每个基本块最后都添加一条move指令 将incoming基本块里面的value move到一个临时的寄存器 + // 然后在phi所在的基本块将这个临时寄存器move到phi中 + // in incoming block: + // move temp value + // in phi block: + // move phi temp final var firstBranch = new HashMap(); for (var block : func) { var armBlock = blockMap.get(block); @@ -248,10 +254,11 @@ class InstructionResolver implements InstructionVisitor { switch (inst.getKind()) { case IAdd -> { - // 这里其实可以加一个判断逻辑 如果 -imm是合法条件 是不是可以变成减法 从而减少一个MOV32 var instKind = ArmInstKind.IAdd; + // 如果 lhs 是一个立即数的话,则交换立即数 if (lhs instanceof IntConst) { int imm = ((IntConst) lhs).getValue(); + // 如果 -imm 是合法条件 变成减法 从而减少一个 mov32 if (ImmUtils.checkEncodeImm(-imm)) { rhsReg = resolveIImm(-imm, block, func); instKind = ArmInstKind.ISub; @@ -260,6 +267,7 @@ class InstructionResolver implements InstructionVisitor { } lhsReg = resolveLhsOperand(rhs, block, func); } else { + // 如果 -imm 是合法条件 变成减法 从而减少一个 mov32 if (rhs instanceof IntConst && ImmUtils.checkEncodeImm(-((IntConst) rhs).getValue())) { rhsReg = resolveIImm(-((IntConst) rhs).getValue(), block, func); instKind = ArmInstKind.ISub; @@ -269,7 +277,7 @@ class InstructionResolver implements InstructionVisitor { lhsReg = resolveLhsOperand(lhs, block, func); } dstReg = resolveOperand(inst, block, func); - // ADD inst inst.getLHS() inst.getRHS() + // add inst inst.lhs inst.rhs new ArmInstBinary(block, instKind, dstReg, lhsReg, rhsReg); } case ISub -> { @@ -278,10 +286,11 @@ class InstructionResolver implements InstructionVisitor { lhsReg = resolveLhsOperand(rhs, block, func); rhsReg = resolveOperand(lhs, block, func); dstReg = resolveOperand(inst, block, func); - // RSB inst inst.getRHS() inst.getLHS() + // rsb inst inst.rhs inst.lhs new ArmInstBinary(block, ArmInstKind.IRsb, dstReg, lhsReg, rhsReg); } else { var instKind = ArmInstKind.ISub; + // 如果 -imm 是合法条件 变成加法 从而减少一个 mov32 if (rhs instanceof IntConst && ImmUtils.checkEncodeImm(-((IntConst) rhs).getValue())) { rhsReg = resolveIImm(-((IntConst) rhs).getValue(), block, func); instKind = ArmInstKind.IAdd; @@ -308,13 +317,16 @@ class InstructionResolver implements InstructionVisitor { imm = ((IntConst) rhs).getValue(); } if (src != null) { + // 乘法优化 + // 只会优化以下的情况 + // |x| = 2^x +- 2^y / 0 (x >= y) resolveConstMuL(dstReg, src, imm, block); break; } } lhsReg = resolveLhsOperand(lhs, block, func); rhsReg = resolveLhsOperand(rhs, block, func); - // MUL inst inst.getLHS() inst.getRHS() + // mul inst inst.lhs inst.rhs new ArmInstBinary(block, ArmInstKind.IMul, dstReg, lhsReg, rhsReg); } case IDiv -> { @@ -326,25 +338,39 @@ class InstructionResolver implements InstructionVisitor { resolveConstDiv(dstReg, lhsReg, imm, block, func); } else { rhsReg = resolveLhsOperand(rhs, block, func); // sdiv 不允许立即数 - // SDIV inst inst.getLHS() inst.getRHS() + // sdiv inst inst.lhs inst.rhs new ArmInstBinary(block, ArmInstKind.IDiv, dstReg, lhsReg, rhsReg); } } case IMod -> { - // x % y == x - (x / y) *y - // % 0 % 1 % 2^n 特殊判断 + // x % y == x - (x / y) * y + // %0 %1 %2^n 特殊判断 if (rhs instanceof IntConst) { var imm = ((IntConst) rhs).getValue(); if (imm == 0) { + // %0 特殊判断 dstReg = resolveOperand(inst, block, func); lhsReg = resolveOperand(lhs, block, func); + // mov inst inst.lhs new ArmInstMove(block, dstReg, lhsReg); break; } else if (Math.abs(imm) == 1) { + // %1 特殊判断 dstReg = resolveOperand(inst, block, func); + // mov inst 0 new ArmInstMove(block, dstReg, new IImm(0)); break; } else if (ImmUtils.is2Power(Math.abs(imm))) { + // %2^n 特殊判断 + // %2 + // add vr, lhs, lhs, lsr #31 + // bic vr2, vr, #1 + // sub inst, lhs, vr2 + // %2^n (n >= 2) + // asr vr, lhs, #31 + // add vr2, lhs, vr, lsr #(32 - n) + // bic vr3, vr, #2^n - 1 + // sub inst, lhs, vr3 int abs = Math.abs(imm); int l = ImmUtils.countTailingZeros(abs); dstReg = resolveOperand(inst, block, func); @@ -368,23 +394,23 @@ class InstructionResolver implements InstructionVisitor { lhsReg = resolveLhsOperand(lhs, block, func); dstReg = resolveOperand(inst, block, func); var vr = new IVirtualReg(); - // SDIV VR inst.getLHS() inst.getRHS() + // sdiv vr inst.lhs inst.rhs if (rhs instanceof IntConst) { var imm = ((IntConst) rhs).getValue(); resolveConstDiv(vr, lhsReg, imm, block, func); } else { - rhsReg = resolveLhsOperand(rhs, block, func); // 实际上rhs 也会再Ternay变成 lhs + rhsReg = resolveLhsOperand(rhs, block, func); // 实际上rhs 也会在 Ternay 指令中 变成 lhs new ArmInstBinary(block, ArmInstKind.IDiv, vr, lhsReg, rhsReg); } - // MLS inst VR inst.getRHS() inst.getLHS() - // inst = inst.getLHS() - VR * inst.getRHS() + // mls inst vr inst.rhs inst.lhs + // inst = inst.lhs - vr * inst.rhs if (rhs instanceof IntConst && ImmUtils.canOptimizeMul(((IntConst) rhs).getValue())) { var imm = ((IntConst) rhs).getValue(); var vr2 = new IVirtualReg(); resolveConstMuL(vr2, vr, imm, block); new ArmInstBinary(block, ArmInstKind.ISub, dstReg, lhsReg, vr2); } else { - rhsReg = resolveLhsOperand(rhs, block, func); // 实际上rhs 也会再Ternay变成 lhs + rhsReg = resolveLhsOperand(rhs, block, func); // 实际上rhs 也会在 Ternay 指令中 变成 lhs new ArmInstTernary(block, ArmInstKind.IMulSub, dstReg, vr, rhsReg, lhsReg); } } @@ -397,14 +423,14 @@ class InstructionResolver implements InstructionVisitor { rhsReg = resolveOperand(rhs, block, func); } dstReg = resolveOperand(inst, block, func); - // VADD.F32 inst inst.getLHS() inst.getRHS() + // vadd.f32 inst inst.lhs inst.rhs new ArmInstBinary(block, ArmInstKind.FAdd, dstReg, lhsReg, rhsReg); } case FSub -> { lhsReg = resolveLhsOperand(lhs, block, func); rhsReg = resolveOperand(rhs, block, func); dstReg = resolveOperand(inst, block, func); - // VSUB.F32 inst inst.getLHS() inst.getRHS() + // vsub.f32 inst inst.lhs inst.rhs new ArmInstBinary(block, ArmInstKind.FSub, dstReg, lhsReg, rhsReg); } case FMul -> { @@ -416,14 +442,14 @@ class InstructionResolver implements InstructionVisitor { rhsReg = resolveOperand(rhs, block, func); } dstReg = resolveOperand(inst, block, func); - // VMUL.F32 inst inst.getLHS() inst.getRHS() + // vmul.f32 inst inst.lhs inst.rhs new ArmInstBinary(block, ArmInstKind.FMul, dstReg, lhsReg, rhsReg); } case FDiv -> { lhsReg = resolveLhsOperand(lhs, block, func); rhsReg = resolveOperand(rhs, block, func); dstReg = resolveOperand(inst, block, func); - // VDIV.F32 inst inst.getLHS() inst.getRHS() + // vdiv.f32 inst inst.lhs inst.rhs new ArmInstBinary(block, ArmInstKind.FDiv, dstReg, lhsReg, rhsReg); } default -> Log.ensure(false, "binary inst not implement"); @@ -437,11 +463,10 @@ class InstructionResolver implements InstructionVisitor { var dstReg = resolveLhsOperand(inst, block, func); if (inst.getKind() == InstKind.INeg) { - // new ArmInstBinary(block, ArmInstKind.IRsb, dstReg, srcReg, new IImm(0)); - // NEG inst inst.getArg() + // neg inst inst.arg new ArmInstUnary(block, ArmInstKind.INeg, dstReg, srcReg); } else if (inst.getKind() == InstKind.FNeg) { - // VNEG.F32 inst inst.getArg() + // vneg.f32 inst inst.arg new ArmInstUnary(block, ArmInstKind.FNeg, dstReg, srcReg); } return null; @@ -457,7 +482,7 @@ class InstructionResolver implements InstructionVisitor { } else { addrReg = resolveOperand(addr, block, func); } - // LDR inst inst.getPtr() + // ldr inst inst.ptr var load = new ArmInstLoad(block, dstReg, addrReg); if (addr instanceof GlobalVar && inst.getType().isPtr()) { func.getAddrLoadMap().put(dstReg, load); @@ -471,14 +496,14 @@ class InstructionResolver implements InstructionVisitor { var varReg = resolveLhsOperand(var, block, func); var addrReg = resolveOperand(addr, block, func); - // STR inst.getVal() inst.getPtr() + // str inst.val inst.ptr new ArmInstStore(block, varReg, addrReg); return null; } @Override public Void visitCAllocInst(CAllocInst inst) { var dst = resolveOperand(inst, block, func); - // ADD inst [SP, 之前已用的栈大小] + // add inst [sp, 之前已用的栈大小] var alloc = new ArmInstStackAddr(block, dst, new IImm(func.getStackSize())); alloc.setCAlloc(true); func.getStackAddrMap().put(dst, alloc); @@ -490,13 +515,13 @@ class InstructionResolver implements InstructionVisitor { @Override public Void visitGEPInst(GEPInst inst) { var p = ((PointerIRTy) inst.getPtr().getType()).getBaseType(); var indices = inst.getIndices(); - ArrayList dim = new ArrayList<>(); + List dim = new ArrayList<>(); while (p.isArray()) { dim.add(p.getSize()); p = ((ArrayIRTy) p).getElementType(); } - // 加上最后一个基础类型 INT FLOAT的SIZE + // 加上最后一个基础类型 int/float的size dim.add(p.getSize()); // 原基地址 @@ -511,11 +536,11 @@ class InstructionResolver implements InstructionVisitor { tot += offsetImm.getImm() * length; if (i == indices.size() - 1) { if (tot == 0) { - // MOVR inst 当前地址 + // mov inst 当前地址 new ArmInstMove(block, ret, arr); } else { var imm = resolveIImm(tot, block, func); - // ADD inst 当前地址 + 偏移量 + // add inst 当前地址 + 偏移量 new ArmInstBinary(block, ArmInstKind.IAdd, ret, arr, imm); } } @@ -523,8 +548,8 @@ class InstructionResolver implements InstructionVisitor { if (tot != 0) { var imm = resolveIImm(tot, block, func); var vr = new IVirtualReg(); - // ADD VR 当前地址 + 偏移量 - // 当前地址 = VR + // add vr 当前地址 + 偏移量 + // 当前地址 = vr new ArmInstBinary(block, ArmInstKind.IAdd, vr, arr, imm); tot = 0; arr = vr; @@ -539,8 +564,8 @@ class InstructionResolver implements InstructionVisitor { new ArmInstBinary(block, ArmInstKind.IAdd, dst, arr, vr); } else { var imm = resolveIImmInReg(length, block, func); - // MLA inst dim.get(i) indices.get(i) 当前地址 - // inst = dim.get(i)*indices.get(i) + 当前地址 + // mla inst dim[i] indices[i] 当前地址 + // inst = dim[i] * indices[i] + 当前地址 new ArmInstTernary(block, ArmInstKind.IMulAdd, dst, offset, imm, arr); } @@ -557,6 +582,7 @@ class InstructionResolver implements InstructionVisitor { List finalArg = new ArrayList<>(); int fcnt = 0, icnt = 0; var args = inst.getArgList(); + // 找到前4个整型的参数 for (int i = 0; i < args.size(); i++) { var arg = args.get(i); if (!arg.getType().isFloat()) { @@ -568,6 +594,7 @@ class InstructionResolver implements InstructionVisitor { break; } } + // 找到前16个浮点型的参数 for (int i = 0; i < args.size(); i++) { var arg = args.get(i); if (arg.getType().isFloat()) { @@ -579,6 +606,7 @@ class InstructionResolver implements InstructionVisitor { break; } } + // 计算得到 for (int i = 0; i < args.size(); i++) { var arg = args.get(i); if (argsIdx.contains(i)) { @@ -593,10 +621,12 @@ class InstructionResolver implements InstructionVisitor { var src = resolveLhsOperand(arg, block, func); int nowOffset = -offset + (i - icnt - fcnt) * 4; int finalOffset = nowOffset; - // STR inst.args.get(i) [SP, -(inst.args.size()-i)*4] + // str inst.args[i] [sp, -(inst.args.size-i)*4] // 越后面的参数越靠近栈顶 Operand addr = IPhyReg.SP; + // 如果offset不符合范围 if (!ImmUtils.checkOffsetRange(nowOffset, src)) { + // 先寻找一个stack addr 指令 for (var entry : stackAddrSet) { var op = entry.key; var instOffset = entry.value.getIntOffset(); @@ -606,6 +636,7 @@ class InstructionResolver implements InstructionVisitor { break; } } + // 如果没找到,则创建一个新的stack addr指令 if (addr.equals(IPhyReg.SP)) { int instOffset = nowOffset / 1024 * 1024;// 负值 因此是往更大的方向 var vr = new IVirtualReg(); @@ -613,7 +644,7 @@ class InstructionResolver implements InstructionVisitor { stackAddr.setFix(true); addr = vr; finalOffset = nowOffset - instOffset; - Log.ensure(ImmUtils.checkOffsetRange(finalOffset, src), "chang offset is illegal"); + Log.ensure(ImmUtils.checkOffsetRange(finalOffset, src), "check offset is illegal"); stackAddrSet.add(new Pair<>(vr, stackAddr)); func.getStackAddrMap().put(vr, stackAddr); } @@ -638,24 +669,24 @@ class InstructionResolver implements InstructionVisitor { new ArmInstMove(block, IPhyReg.R(i), argOp.get(i)); } if (finalArg.size() > icnt + fcnt) { - // SUB SP SP (inst.args.size() - 4) * 4 + // sub sp sp (inst.args.size - 4) * 4 new ArmInstBinary(block, ArmInstKind.ISub, IPhyReg.SP, IPhyReg.SP, offsetOp); } new ArmInstCall(block, funcMap.get(inst.getCallee())); if (finalArg.size() > icnt + fcnt) { - // ADD SP SP (inst.args.size() - 4) * 4 + // add sp sp (inst.args.size - 4) * 4 new ArmInstBinary(block, ArmInstKind.IAdd, IPhyReg.SP, IPhyReg.SP, offsetOp); } if (!inst.getType().isVoid()) { var dst = resolveLhsOperand(inst, block, func); if (inst.getType().isFloat()) { // 如果结果是一个浮点数 则直接用s0来保存数据 - // VMOV inst S0 + // vmov inst s0 // atpcs 规范 new ArmInstMove(block, dst, FPhyReg.S(0)); } else if (inst.getType().isInt()) { // 否则用r0来保存数据 - // MOV inst R0 + // mov inst r0 new ArmInstMove(block, dst, IPhyReg.R(0)); } } @@ -669,10 +700,10 @@ class InstructionResolver implements InstructionVisitor { var srcReg = resolveOperand(src, block, func); if (src.getType().isFloat()) { // atpcs 规范 - // VMOV S0 inst.getReturnValue() + // vmov S0 inst.getReturnValue() new ArmInstMove(block, FPhyReg.S(0), srcReg); } else { - // VMOV R0 inst.getReturnValue() + // vmov R0 inst.getReturnValue() new ArmInstMove(block, IPhyReg.R(0), srcReg); } @@ -689,9 +720,9 @@ class InstructionResolver implements InstructionVisitor { var vr = new FVirtualReg(); var src = resolveOperand(inst.getFrom(), block, func); var dst = resolveOperand(inst, block, func); - // VMOV VR inst.getFrom() + // vmov vr inst.getFrom() new ArmInstMove(block, vr, src); - // VCVT.F32.S32 inst VR + // vcvt.f32.s32 inst vr new ArmInstIntToFloat(block, dst, vr); return null; } @@ -701,9 +732,9 @@ class InstructionResolver implements InstructionVisitor { var vr = new FVirtualReg(); var src = resolveOperand(inst.getFrom(), block, func); var dst = resolveOperand(inst, block, func); - // VCVT.F32.S32 inst VR + // vcvt.f32.s32 inst vr new ArmInstFloatToInt(block, vr, src); - // VMOV VR inst.getFrom() + // vmov vr inst.getFrom() new ArmInstMove(block, dst, vr); return null; } @@ -743,12 +774,14 @@ class InstructionResolver implements InstructionVisitor { var ac = inst.getInit(); int size = inst.getInit().getType().getSize(); if (ac instanceof ZeroArrayConst) { + // 如果是全0数组 直接调用memset var imm = resolveIImm(size, block, func); new ArmInstMove(block, IPhyReg.R(0), dst); new ArmInstMove(block, IPhyReg.R(1), new IImm(0)); new ArmInstMove(block, IPhyReg.R(2), imm); new ArmInstCall(block, "memset", 3, 0); } else { + // 否则调用memcpy var src = resolveOperand(ac, block, func); var imm = resolveIImm(size, block, func); new ArmInstMove(block, IPhyReg.R(0), dst); @@ -816,8 +849,8 @@ private Operand resolveParameter(Parameter val, ArmFunction func) { for (int i = 0; i < params.size(); i++) { if (params.get(i).equals(val)) { if (i < icnt) { - // MOVE VR Ri - // R0 - R3 在后续的基本块中会修改 因此需要在最前面的块当中就读取出来 + // mov vr ri + // r0 - r3 在后续的基本块中会修改 因此需要在最前面的块当中就读取出来 // 加到最前面防止后续load修改了r0 - r3 var move = new ArmInstMove(vr, IPhyReg.R(i)); func.getPrologue().add(0, move); @@ -825,8 +858,8 @@ private Operand resolveParameter(Parameter val, ArmFunction func) { var move = new ArmInstMove(vr, FPhyReg.S(i - icnt)); func.getPrologue().add(0, move); } else { - // LDR VR [SP, (i-4)*4] - // 寄存器分配后修改为 LDR VR [SP, (i-4)*4 + stackSize + push的大小] + // ldr vr [sp, (i-4)*4] + // 寄存器分配后修改为 ldr vr [sp, (i-4)*4 + stackSize + push的大小] var load = new ArmInstParamLoad(func.getPrologue(), vr, new IImm((i - icnt - fcnt) * 4)); func.getParamLoadMap().put(vr, load); } @@ -861,7 +894,6 @@ private Operand resolvePhiOperand(Value val, ArmBlock block, ArmFunction func) { private Operand resolveGlobalVar(GlobalVar val, ArmBlock block, ArmFunction func) { // 全局变量应该事先处理 - // 后续可以加一个优化, 在一个基本块内一定的虚拟寄存器序号内直接返回虚拟寄存器 if (globalMap.containsKey(val)) { return globalMap.get(val); } @@ -895,15 +927,14 @@ private ArmCondType resolveCmpInst(CmpInst inst, ArmBlock block, ArmFunction fun var cond = condMap.get(inst.getKind()); for (var ch : Arrays.asList(lhs, rhs)) { + // 将Bool比较的结果转换为Int if (ch instanceof BoolToIntInst) { resolveBoolToIntInst((BoolToIntInst) ch, block, func); } - // if(ch instanceof IntToFloatInst){ - // resolveIntToFloatInst((IntToFloatInst) ch, block, func); - // } } Operand lhsReg, rhsReg; + // 是否和负值比较 boolean isCmn = false; if (lhs instanceof Constant) { if (lhs instanceof IntConst ic) { @@ -937,8 +968,8 @@ private ArmCondType resolveCmpInst(CmpInst inst, ArmBlock block, ArmFunction fun lhsReg = resolveLhsOperand(lhs, block, func); } - // CMP( VCMP.F32 ) inst.getLHS() inst.getRHS() (可能交换LHS/RHS) - // VMRS APSR_nzcv fpscr + // cmp( vcmp.f32 ) inst.getLHS() inst.getRHS() (可能交换LHS/RHS) + // vmrs APSR_nzcv fpscr var cmp = new ArmInstCmp(block, lhsReg, rhsReg, cond); cmp.setCmn(isCmn); return cond; @@ -949,17 +980,17 @@ private void resolveBoolToIntInst(BoolToIntInst inst, ArmBlock block, ArmFunctio var dstReg = resolveOperand(inst, block, func); if (src instanceof BoolConst bc) { if (bc.getValue()) { - // MOV inst #1 + // mov inst #1 new ArmInstMove(block, dstReg, new IImm(1)); } else { - // MOV inst #0 + // mov inst #0 new ArmInstMove(block, dstReg, new IImm(0)); } } else if (src instanceof CmpInst) { var cond = resolveCmpInst((CmpInst) src, block, func); - // MOV.{cond} inst #1 + // mov.{cond} inst #1 new ArmInstMove(block, dstReg, new IImm(1), cond); - // MOV.{OppCond} inst #0 + // mov.{OppCond} inst #0 new ArmInstMove(block, dstReg, new IImm(0), cond.getOppCondType()); } else { Log.ensure(false); @@ -980,6 +1011,13 @@ private void resolveConstDiv(Operand dst, Operand src, int imm, ArmBlock block, } return; } else if (ImmUtils.is2Power(abs)) { + // 如果不除2 + // asr vr, src, #31 + // add vr2, vr2, vr, lsr #32 - ctz(imm) + // asr dst, vr2, ctz(imm) + // 如果除2 + // add vr, vr, src, lsr #32 - ctz(imm) + // asr dst, vr, ctz(imm) int l = ImmUtils.countTailingZeros(abs); var vr = src; var vr2 = new IVirtualReg(); @@ -1033,15 +1071,23 @@ private void resolveConstMuL(Operand dst, Operand src, int imm, ArmBlock block) } } else if (ImmUtils.is2Power(abs)) { if (imm > 0) { + // lsl dst, src, #ctz(imm) var move = new ArmInstMove(block, dst, src); move.setShift(new ArmShift(ArmShift.ShiftType.Lsl, l)); } else { + // mov vr, #0 + // sub dst, vr, src, lsl #ctz(imm) var vr = new IVirtualReg(); new ArmInstMove(block, vr, new IImm(0)); var sub = new ArmInstBinary(block, ArmInstKind.ISub, dst, vr, src); sub.setShift(new ArmShift(ArmShift.ShiftType.Lsl, l)); } } else if (ImmUtils.is2Power(abs - 1)) { + // imm > 0 + // add dst, src, src, lsl #ctz(abs-1) + // imm < 0 + // add vr, src, src, lsl #ctz(abs-1) + // rsb dst, vr, #0 l = ImmUtils.countTailingZeros(abs - 1); var dst2 = dst; if (imm < 0) { @@ -1054,6 +1100,10 @@ private void resolveConstMuL(Operand dst, Operand src, int imm, ArmBlock block) } } else if (ImmUtils.is2Power(abs + 1)) { l = ImmUtils.countTailingZeros(abs + 1); + // imm > 0 + // rsb dst, src, src, lsl #ctz(abs+1) + // imm < 0 + // sub dst, src, src, lsl #ctz(abs+1) if (imm > 0) { var rsb = new ArmInstBinary(block, ArmInstKind.IRsb, dst, src, src); rsb.setShift(new ArmShift(ArmShift.ShiftType.Lsl, l)); @@ -1076,6 +1126,19 @@ private void resolveConstMuL(Operand dst, Operand src, int imm, ArmBlock block) } } l = ImmUtils.countTailingZeros(nowAbs); + // imm = (1< p) + // add vr, src, src, lsl #l-p + // lsl dst, vr. #p + // imm = (1< p) + // rsb vr, src, src, lsl #l-p + // lsl dst, vr. #p + // imm = -((1< p) + // add vr, src, src, lsl #l-p + // lsl vr2, vr. #p + // rsb dst, vr2, #0 + // imm = -((1< p) + // sub vr, src, src, lsl #l-p + // lsl dst, vr. #p var vr = new IVirtualReg(); if (IsAdd) { if (imm > 0) { diff --git a/src/backend/lir/inst/ArmInst.java b/src/backend/lir/inst/ArmInst.java index d2823e8..5783c80 100644 --- a/src/backend/lir/inst/ArmInst.java +++ b/src/backend/lir/inst/ArmInst.java @@ -107,7 +107,9 @@ public enum ArmInstKind { public enum ArmCondType { Any, - Ge, Gt, Eq, Ne, Le, Lt; + Ge, Gt, Eq, Ne, Le, Lt, + // 浮点数使用 用于比较NaN + Hi, Pl, Ls, Mi; @Override public String toString() { @@ -126,7 +128,11 @@ public ArmCondType getOppCondType() { case Lt -> Ge; case Eq -> Ne; case Ne -> Eq; - default -> throw new RuntimeException("Unknown cond: " + this); + case Ls -> Hi; + case Hi -> Ls; + case Mi -> Pl; + case Pl -> Mi; + default -> this; }; } @@ -136,7 +142,11 @@ public ArmCondType getEqualOppCondType() { case Ge -> Le; case Gt -> Lt; case Lt -> Gt; - default -> throw new RuntimeException("Unknown cond: " + this); + case Ls -> Pl; + case Pl -> Ls; + case Mi -> Hi; + case Hi -> Mi; + default -> this; }; } } diff --git a/src/backend/lir/inst/ArmInstAddr.java b/src/backend/lir/inst/ArmInstAddr.java new file mode 100644 index 0000000..312d479 --- /dev/null +++ b/src/backend/lir/inst/ArmInstAddr.java @@ -0,0 +1,20 @@ +package backend.lir.inst; + +import backend.lir.operand.IImm; +import backend.lir.operand.Operand; + +public abstract class ArmInstAddr extends ArmInst { + protected ArmInstAddr(ArmInstKind kind) { + super(kind); + } + + abstract public Operand getDst(); + + abstract public IImm getOffset(); + + abstract public Operand getAddr(); + + abstract public void setTrueOffset(IImm trueOffset); + + abstract public void replaceAddr(Operand addr); +} diff --git a/src/backend/lir/inst/ArmInstParamLoad.java b/src/backend/lir/inst/ArmInstParamLoad.java index 445e136..235456d 100644 --- a/src/backend/lir/inst/ArmInstParamLoad.java +++ b/src/backend/lir/inst/ArmInstParamLoad.java @@ -5,7 +5,7 @@ import backend.lir.operand.IPhyReg; import backend.lir.operand.Operand; -public class ArmInstParamLoad extends ArmInst { +public class ArmInstParamLoad extends ArmInstAddr { private IImm trueOffset; public ArmInstParamLoad(ArmBlock block, Operand dst, IImm offset) { diff --git a/src/backend/lir/inst/ArmInstStackLoad.java b/src/backend/lir/inst/ArmInstStackLoad.java index c00bd4e..0facc2d 100644 --- a/src/backend/lir/inst/ArmInstStackLoad.java +++ b/src/backend/lir/inst/ArmInstStackLoad.java @@ -4,7 +4,7 @@ import backend.lir.operand.IPhyReg; import backend.lir.operand.Operand; -public class ArmInstStackLoad extends ArmInst { +public class ArmInstStackLoad extends ArmInstAddr { private IImm trueOffset; public ArmInstStackLoad(Operand dst, IImm offset) { diff --git a/src/backend/lir/inst/ArmInstStackStore.java b/src/backend/lir/inst/ArmInstStackStore.java index ef883cd..58182b1 100644 --- a/src/backend/lir/inst/ArmInstStackStore.java +++ b/src/backend/lir/inst/ArmInstStackStore.java @@ -4,7 +4,7 @@ import backend.lir.operand.IPhyReg; import backend.lir.operand.Operand; -public class ArmInstStackStore extends ArmInst { +public class ArmInstStackStore extends ArmInstAddr { private IImm trueOffset; public ArmInstStackStore(Operand dst, IImm offset) { diff --git a/src/backend/regallocator/RegAllocManager.java b/src/backend/regallocator/RegAllocManager.java index 445c243..3d4b073 100644 --- a/src/backend/regallocator/RegAllocManager.java +++ b/src/backend/regallocator/RegAllocManager.java @@ -1,6 +1,6 @@ package backend.regallocator; -import backend.ImmUtils; +import utils.ImmUtils; import backend.lir.ArmFunction; import backend.lir.ArmModule; import backend.lir.inst.*; @@ -8,6 +8,7 @@ import utils.Log; import java.util.*; +import java.util.function.BiFunction; /** * 去除 LIR 中的所有虚拟寄存器 @@ -61,8 +62,7 @@ public void regAllocate() { for (var op : inst.getOperands()) { assert op instanceof Reg; if (op.isVirtual()) { - Log.ensure(allocatorMap.containsKey(op), - "virtual reg:" + op.print() + " not exist in allocator map"); + Log.ensure(allocatorMap.containsKey(op), "virtual reg:" + op.print() + " not exist in allocator map"); inst.replaceOperand(op, allocatorMap.get(op)); } } @@ -76,12 +76,14 @@ public void regAllocate() { private boolean fixStack(ArmFunction func) { boolean isFix = false; int regCnt = func.getFUsedRegs().size() + func.getIUsedRegs().size(); + // 栈的位置要与8对齐 int stackSize = (func.getStackSize() + 4 * regCnt + 4) / 8 * 8 - 4 * regCnt; func.setFinalStackSize(stackSize); stackSize = stackSize - func.getStackSize(); Map stackMap = new HashMap<>(); var stackObject = func.getStackObject(); var stackObjectOffset = func.getStackObjectOffset(); + // 反向构建栈的位置信息 for (int i = stackObjectOffset.size() - 1; i >= 0; i--) { stackMap.put(stackObjectOffset.get(i), stackSize); stackSize += stackObject.get(i); @@ -89,9 +91,56 @@ private boolean fixStack(ArmFunction func) { Map stackAddrMap = new HashMap<>(); Map addrStackMap = new HashMap<>(); Log.ensure(stackSize == func.getFinalStackSize(), "stack size error"); + + int finalStackSize = stackSize; + // 修复ArmInstAddr的寻址 + BiFunction fixArmInstAddr = (inst, trueOffset) -> { + boolean isInstFix = false; + if (!ImmUtils.checkOffsetRange(trueOffset, inst.getDst())) { + if (inst.getAddr().equals(IPhyReg.SP)) { + isInstFix = true; + for (var entry : stackAddrMap.entrySet()) { + var offset = entry.getKey(); + var op = entry.getValue(); + if (offset <= trueOffset && ImmUtils.checkOffsetRange(trueOffset - offset, inst.getDst())) { + inst.replaceAddr(op); + inst.setTrueOffset(new IImm(trueOffset - offset)); + func.getSpillNodes().remove(op); + // 相当于当前节点改变了生命周期 + break; + } + } + if (inst.getAddr().equals(IPhyReg.SP)) { + int addrTrueOffset = trueOffset / 1024 * 1024; + var vr = new IVirtualReg(); + int instOffset = finalStackSize - addrTrueOffset; + var stackAddr = new ArmInstStackAddr(vr, new IImm(instOffset)); + stackAddr.setTrueOffset(new IImm(addrTrueOffset)); + inst.insertBeforeCO(stackAddr); + inst.replaceAddr(vr); + Log.ensure(trueOffset >= addrTrueOffset, "check offset is illegal"); + Log.ensure(ImmUtils.checkOffsetRange(trueOffset - addrTrueOffset, inst.getDst()), "check offset is illegal"); + inst.setTrueOffset(new IImm(trueOffset - addrTrueOffset)); + stackAddrMap.put(addrTrueOffset, vr); + addrStackMap.put(vr, addrTrueOffset); + func.getStackAddrMap().put(vr, stackAddr); + } + } else { + var addrTrueOffset = addrStackMap.get(inst.getAddr()); + var nowTrueOffset = trueOffset - addrTrueOffset; + Log.ensure(ImmUtils.checkOffsetRange(nowTrueOffset, inst.getDst()), "check offset is illegal"); + inst.setTrueOffset(new IImm(nowTrueOffset)); + } + } else { + inst.setTrueOffset(new IImm(trueOffset)); + } + return isInstFix; + }; + for (var block : func) { for (var inst : block) { if (inst instanceof ArmInstStackAddr stackAddr) { + // 修复基准地址 if (stackAddr.isCAlloc()) { Log.ensure(stackMap.containsKey(stackAddr.getOffset().getImm()), "stack offset not present"); stackAddr.setTrueOffset(new IImm(stackMap.get(stackAddr.getOffset().getImm()))); @@ -107,130 +156,15 @@ private boolean fixStack(ArmFunction func) { } } else if (inst instanceof ArmInstParamLoad paramLoad) { int trueOffset = paramLoad.getOffset().getImm() + stackSize + 4 * regCnt; - if (!ImmUtils.checkOffsetRange(trueOffset, paramLoad.getDst())) { - if (paramLoad.getAddr().equals(IPhyReg.SP)) { - isFix = true; - for (var entry : stackAddrMap.entrySet()) { - var offset = entry.getKey(); - var op = entry.getValue(); - if (offset <= trueOffset && ImmUtils.checkOffsetRange(trueOffset - offset, paramLoad.getDst())) { - paramLoad.replaceAddr(op); - paramLoad.setTrueOffset(new IImm(trueOffset - offset)); - func.getSpillNodes().remove(op); - // 相当于当前节点改变了生命周期 - break; - } - } - if (paramLoad.getAddr().equals(IPhyReg.SP)) { - int addrTrueOffset = trueOffset / 1024 * 1024; - var vr = new IVirtualReg(); - int instOffset = stackSize - addrTrueOffset; - var stackAddr = new ArmInstStackAddr(vr, new IImm(instOffset)); - stackAddr.setTrueOffset(new IImm(addrTrueOffset)); - paramLoad.insertBeforeCO(stackAddr); - paramLoad.replaceAddr(vr); - Log.ensure(trueOffset >= addrTrueOffset, "chang offset is illegal"); - Log.ensure(ImmUtils.checkOffsetRange(trueOffset - addrTrueOffset, paramLoad.getDst()), - "chang offset is illegal"); - paramLoad.setTrueOffset(new IImm(trueOffset - addrTrueOffset)); - stackAddrMap.put(addrTrueOffset, vr); - addrStackMap.put(vr, addrTrueOffset); - func.getStackAddrMap().put(vr, stackAddr); - } - } else { - var addrTrueOffset = addrStackMap.get(paramLoad.getAddr()); - var nowTrueOffset = trueOffset - addrTrueOffset; - Log.ensure(ImmUtils.checkOffsetRange(nowTrueOffset, paramLoad.getDst()), "chang offset is illegal"); - paramLoad.setTrueOffset(new IImm(nowTrueOffset)); - } - } else { - paramLoad.setTrueOffset(new IImm(trueOffset)); - } + isFix |= fixArmInstAddr.apply(paramLoad, trueOffset); } else if (inst instanceof ArmInstStackLoad stackLoad) { Log.ensure(stackMap.containsKey(stackLoad.getOffset().getImm()), "stack offset not present"); int trueOffset = stackMap.get(stackLoad.getOffset().getImm()); - if (!ImmUtils.checkOffsetRange(trueOffset, stackLoad.getDst())) { - if (stackLoad.getAddr().equals(IPhyReg.SP)) { - isFix = true; - for (var entry : stackAddrMap.entrySet()) { - var offset = entry.getKey(); - var op = entry.getValue(); - if (offset <= trueOffset && ImmUtils.checkOffsetRange(trueOffset - offset, stackLoad.getDst())) { - stackLoad.replaceAddr(op); - stackLoad.setTrueOffset(new IImm(trueOffset - offset)); - func.getSpillNodes().remove(op); - // 相当于当前节点改变了生命周期 - break; - } - } - if (stackLoad.getAddr().equals(IPhyReg.SP)) { - int addrTrueOffset = trueOffset / 1024 * 1024; - var vr = new IVirtualReg(); - int instOffset = stackSize - addrTrueOffset; - var stackAddr = new ArmInstStackAddr(vr, new IImm(instOffset)); - stackAddr.setTrueOffset(new IImm(addrTrueOffset)); - stackLoad.insertBeforeCO(stackAddr); - stackLoad.replaceAddr(vr); - Log.ensure(trueOffset >= addrTrueOffset, "chang offset is illegal"); - Log.ensure(ImmUtils.checkOffsetRange(trueOffset - addrTrueOffset, stackLoad.getDst()), - "chang offset is illegal"); - stackLoad.setTrueOffset(new IImm(trueOffset - addrTrueOffset)); - stackAddrMap.put(addrTrueOffset, vr); - addrStackMap.put(vr, addrTrueOffset); - func.getStackAddrMap().put(vr, stackAddr); - } - } else { - var addrTrueOffset = addrStackMap.get(stackLoad.getAddr()); - var nowTrueOffset = trueOffset - addrTrueOffset; - Log.ensure(ImmUtils.checkOffsetRange(nowTrueOffset, stackLoad.getDst()), "chang offset is illegal"); - stackLoad.setTrueOffset(new IImm(nowTrueOffset)); - } - } else { - stackLoad.setTrueOffset(new IImm(trueOffset)); - } + isFix |= fixArmInstAddr.apply(stackLoad, trueOffset); } else if (inst instanceof ArmInstStackStore stackStore) { Log.ensure(stackMap.containsKey(stackStore.getOffset().getImm()), "stack offset not present"); int trueOffset = stackMap.get(stackStore.getOffset().getImm()); - if (!ImmUtils.checkOffsetRange(trueOffset, stackStore.getDst())) { - if (stackStore.getAddr().equals(IPhyReg.SP)) { - isFix = true; - for (var entry : stackAddrMap.entrySet()) { - var offset = entry.getKey(); - var op = entry.getValue(); - if (offset <= trueOffset - && ImmUtils.checkOffsetRange(trueOffset - offset, stackStore.getDst())) { - stackStore.replaceAddr(op); - stackStore.setTrueOffset(new IImm(trueOffset - offset)); - func.getSpillNodes().remove(op); - // 相当于当前节点改变了生命周期 - break; - } - } - if (stackStore.getAddr().equals(IPhyReg.SP)) { - int addrTrueOffset = trueOffset / 1024 * 1024; - var vr = new IVirtualReg(); - int instOffset = stackSize - addrTrueOffset; - var stackAddr = new ArmInstStackAddr(vr, new IImm(instOffset)); - stackAddr.setTrueOffset(new IImm(addrTrueOffset)); - stackStore.insertBeforeCO(stackAddr); - stackStore.replaceAddr(vr); - Log.ensure(trueOffset >= addrTrueOffset, "chang offset is illegal"); - Log.ensure(ImmUtils.checkOffsetRange(trueOffset - addrTrueOffset, stackStore.getDst()), - "chang offset is illegal"); - stackStore.setTrueOffset(new IImm(trueOffset - addrTrueOffset)); - stackAddrMap.put(addrTrueOffset, vr); - addrStackMap.put(vr, addrTrueOffset); - func.getStackAddrMap().put(vr, stackAddr); - } - } else { - var addrTrueOffset = addrStackMap.get(stackStore.getAddr()); - var nowTrueOffset = trueOffset - addrTrueOffset; - Log.ensure(ImmUtils.checkOffsetRange(nowTrueOffset, stackStore.getDst()), "chang offset is illegal"); - stackStore.setTrueOffset(new IImm(nowTrueOffset)); - } - } else { - stackStore.setTrueOffset(new IImm(trueOffset)); - } + isFix |= fixArmInstAddr.apply(stackStore, trueOffset); } } } @@ -253,6 +187,7 @@ private boolean recoverRegAllocate(ArmFunction func) { var haveRecoverStackLoad = block.getHaveRecoverStackLoad(); for (var inst : block) { if (inst instanceof ArmInstStackAddr stackAddr) { + // 恢复一个基本块内的基准地址 var offset = stackAddr.getOffset(); if (!stackAddr.getDst().isVirtual()) { continue; @@ -268,6 +203,7 @@ private boolean recoverRegAllocate(ArmFunction func) { } } if (inst instanceof ArmInstLoad load) { + // 恢复一个基本块内的Load指令 if (!(load.getAddr() instanceof Addr addr)) { continue; } @@ -285,6 +221,7 @@ private boolean recoverRegAllocate(ArmFunction func) { } } if (inst instanceof ArmInstParamLoad load) { + // 恢复一个基本块内的ParamLoad指令 if (!load.getAddr().equals(IPhyReg.SP)) { continue; } @@ -303,6 +240,7 @@ private boolean recoverRegAllocate(ArmFunction func) { } } if (inst instanceof ArmInstMove move) { + // 恢复一个基本块内的立即数赋值 if (!move.getDst().isVirtual()) { continue; } @@ -321,6 +259,7 @@ private boolean recoverRegAllocate(ArmFunction func) { } } if (inst instanceof ArmInstStackLoad load) { + // 恢复一个基本块内的寄存器分裂的Load if (!load.getAddr().equals(IPhyReg.SP)) { continue; } @@ -339,6 +278,8 @@ private boolean recoverRegAllocate(ArmFunction func) { } } if (inst instanceof ArmInstStackStore store) { + // 这样利用Store的寄存器也可以给Load继续使用 + // 理论上可以删除只保留最后一个,但不方便恢复 if (!store.getAddr().equals(IPhyReg.SP)) { continue; } diff --git a/src/backend/regallocator/RegAllocator.java b/src/backend/regallocator/RegAllocator.java index 4249983..53bc444 100644 --- a/src/backend/regallocator/RegAllocator.java +++ b/src/backend/regallocator/RegAllocator.java @@ -6,7 +6,6 @@ import java.util.Map; public interface RegAllocator { - // 原本打算实现几种寄存器分配算法, 所以抽了一个接口, 但是由于时间关系, 最终只实现了一种 String getName(); Map run(ArmFunction func); diff --git a/src/backend/regallocator/SimpleGraphColoring.java b/src/backend/regallocator/SimpleGraphColoring.java index dc2561a..bf01aec 100644 --- a/src/backend/regallocator/SimpleGraphColoring.java +++ b/src/backend/regallocator/SimpleGraphColoring.java @@ -56,9 +56,9 @@ public Set getRegs() { return regs; } - public boolean canSimolify() { + public boolean canSimplify() { return icnt <= IPhyReg.getIntAllocatableRegs().size() - && fcnt <= FPhyReg.getFloatAllocatableRegs().size(); + && fcnt <= FPhyReg.getFloatAllocatableRegs().size(); } public void clear() { @@ -100,6 +100,7 @@ public Map run(ArmFunction func) { } public Map runTurn(ArmFunction func) { + // 建立冲突图 buildGraph(func); for (var ent : adj.entrySet()) { var reg = ent.getKey(); @@ -107,14 +108,16 @@ public Map runTurn(ArmFunction func) { continue; } remainNodes.add(reg); - if (ent.getValue().canSimolify()) { + if (ent.getValue().canSimplify()) { simplifyQueue.add(reg); haveSimplify.add(reg); } } + // h简化 simplify(); + // 溢出 if (!remainNodes.isEmpty()) { - List spillNodes = new ArrayList<>(); + Set spillNodes = new HashSet<>(); while (!remainNodes.isEmpty()) { spillNodes.add(chooseSpillNode(func)); simplify(); @@ -124,6 +127,7 @@ public Map runTurn(ArmFunction func) { } Map ans = new HashMap<>(); Set used = Reg.getAllAllocatableRegs().stream().filter(adj::containsKey).collect(Collectors.toSet()); + // 寄存器分配 for (int i = simplifyWorkLists.size() - 1; i >= 0; i--) { var workList = simplifyWorkLists.get(i); var reg = workList.getKey(); @@ -156,6 +160,7 @@ public Map runTurn(ArmFunction func) { } private void buildGraph(ArmFunction func) { + // 构建冲突图 simplifyWorkLists = new ArrayList<>(); remainNodes = new HashSet<>(); simplifyQueue = new ArrayDeque<>(); @@ -167,7 +172,6 @@ private void buildGraph(ArmFunction func) { LivenessAnalysis.funcLivenessAnalysis(func); for (var block : func) { var live = new HashSet<>(block.getBlockLiveInfo().getLiveOut()); - var instsInReverse = new ArrayList<>(block); Collections.reverse(instsInReverse); for (final var inst : instsInReverse) { @@ -199,7 +203,7 @@ private void remove(Reg reg) { Log.ensure(reg.isVirtual(), "remove reg must be a virtual reg"); for (var u : adj.get(reg).getRegs()) { adj.get(u).remove(reg); - if (adj.get(u).canSimolify() && !haveSimplify.contains(u) && u.isVirtual()) { + if (adj.get(u).canSimplify() && !haveSimplify.contains(u) && u.isVirtual()) { simplifyQueue.add(u); haveSimplify.add(u); } @@ -242,7 +246,7 @@ private Reg chooseSpillNode(ArmFunction func) { return spillNode; } - private void spill(ArmFunction func, List spillNodes) { + private void spill(ArmFunction func, Set spillNodes) { Map offsetMap = new HashMap<>(); Set specialNode = new HashSet<>(); for (var spill : spillNodes) { @@ -251,6 +255,7 @@ private void spill(ArmFunction func, List spillNodes) { || (func.getStackLoadMap().containsKey(spill) && !func.getStackStoreSet().contains(spill)) || func.getImmMap().containsKey(spill) || func.getStackAddrMap().containsKey(spill)) { + // 需要跳过处理的 spill node specialNode.add(spill); } else if (!func.getStackStoreSet().contains(spill)) { int offset = func.getStackSize(); @@ -272,77 +277,85 @@ private void spill(ArmFunction func, List spillNodes) { if (nxt) { continue; } - for (var spill : spillNodes) { - if (inst.getOperands().contains(spill)) { - if (func.getImmMap().containsKey(spill)) { - Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); - Reg vr = spill.isInt() ? new IVirtualReg() : new FVirtualReg(); - var oldMove = func.getImmMap().get(spill); - var newMove = new ArmInstMove(vr, oldMove.getSrc()); - inst.insertBeforeCO(newMove); - inst.replaceOperand(spill, vr); - func.getImmMap().put(vr, newMove); - func.getSpillNodes().add(vr); - } else if (func.getAddrLoadMap().containsKey(spill)) { - Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); - var vr = new IVirtualReg(); - var oldLoad = func.getAddrLoadMap().get(spill); - var newLoad = new ArmInstLoad(vr, oldLoad.getAddr()); - inst.insertBeforeCO(newLoad); - inst.replaceOperand(spill, vr); - func.getAddrLoadMap().put(vr, newLoad); - func.getSpillNodes().add(vr); - } else if (func.getStackAddrMap().containsKey(spill)) { - Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); - var vr = new IVirtualReg(); - var oldStackAddr = func.getStackAddrMap().get(spill); - var newStackAddr = new ArmInstStackAddr(vr, oldStackAddr.getOffset()); - newStackAddr.setFix(oldStackAddr.isFix()); - newStackAddr.setCAlloc(oldStackAddr.isCAlloc()); - newStackAddr.setTrueOffset(oldStackAddr.getTrueOffset()); - inst.insertBeforeCO(newStackAddr); - inst.replaceOperand(spill, vr); - func.getStackAddrMap().put(vr, newStackAddr); - func.getSpillNodes().add(vr); - } else if (func.getParamLoadMap().containsKey(spill)) { - Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); - Reg vr = spill.isInt() ? new IVirtualReg() : new FVirtualReg(); - var oldParamLoad = func.getParamLoadMap().get(spill); - var newParamLoad = new ArmInstParamLoad(vr, oldParamLoad.getOffset()); - // newParamLoad.replaceAddr(oldParamLoad.getAddr()); - // newParamLoad.setTrueOffset(oldParamLoad.getTrueOffset()); - // 对于param load 恢复到最初的状态 即从sp中获取数据 再去找addr - inst.insertBeforeCO(newParamLoad); - inst.replaceOperand(spill, vr); - func.getParamLoadMap().put(vr, newParamLoad); - func.getSpillNodes().add(vr); - } else if (func.getStackLoadMap().containsKey(spill) && !(inst instanceof ArmInstStackStore) - && !inst.getRegDef().contains(spill)) { - Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); - Reg vr = spill.isInt() ? new IVirtualReg() : new FVirtualReg(); - var oldStackLoad = func.getStackLoadMap().get(spill); - var newStackLoad = new ArmInstStackLoad(vr, oldStackLoad.getOffset()); - newStackLoad.replaceAddr(oldStackLoad.getAddr()); - inst.insertBeforeCO(newStackLoad); - inst.replaceOperand(spill, vr); - func.getStackLoadMap().put(vr, newStackLoad); - func.getSpillNodes().add(vr); - } else if (!func.getStackStoreSet().contains(spill)) { - Reg vr = spill.isInt() ? new IVirtualReg() : new FVirtualReg(); - int offset = offsetMap.get(spill); - if (inst.getRegUse().contains(spill)) { - var stackLoad = new ArmInstStackLoad(vr, new IImm(offset)); - inst.insertBeforeCO(stackLoad); - func.getStackLoadMap().put(vr, stackLoad); - } - if (inst.getRegDef().contains(spill)) { - inst.insertAfterCO(new ArmInstStackStore(vr, new IImm(offset))); - func.getStackStoreSet().add(vr); + for (var op : inst.getOperands()) { + if (op instanceof Reg spill) { + if (spillNodes.contains(spill)) { + if (func.getImmMap().containsKey(spill)) { + // 直接替换立即数 + Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); + Reg vr = spill.isInt() ? new IVirtualReg() : new FVirtualReg(); + var oldMove = func.getImmMap().get(spill); + var newMove = new ArmInstMove(vr, oldMove.getSrc()); + inst.insertBeforeCO(newMove); + inst.replaceOperand(spill, vr); + func.getImmMap().put(vr, newMove); + func.getSpillNodes().add(vr); + } else if (func.getAddrLoadMap().containsKey(spill)) { + // 直接替换 addr + Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); + var vr = new IVirtualReg(); + var oldLoad = func.getAddrLoadMap().get(spill); + var newLoad = new ArmInstLoad(vr, oldLoad.getAddr()); + inst.insertBeforeCO(newLoad); + inst.replaceOperand(spill, vr); + func.getAddrLoadMap().put(vr, newLoad); + func.getSpillNodes().add(vr); + } else if (func.getStackAddrMap().containsKey(spill)) { + // 直接替换 stack addr + Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); + var vr = new IVirtualReg(); + var oldStackAddr = func.getStackAddrMap().get(spill); + var newStackAddr = new ArmInstStackAddr(vr, oldStackAddr.getOffset()); + newStackAddr.setFix(oldStackAddr.isFix()); + newStackAddr.setCAlloc(oldStackAddr.isCAlloc()); + newStackAddr.setTrueOffset(oldStackAddr.getTrueOffset()); + inst.insertBeforeCO(newStackAddr); + inst.replaceOperand(spill, vr); + func.getStackAddrMap().put(vr, newStackAddr); + func.getSpillNodes().add(vr); + } else if (func.getParamLoadMap().containsKey(spill)) { + // 直接替换 param load + Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); + Reg vr = spill.isInt() ? new IVirtualReg() : new FVirtualReg(); + var oldParamLoad = func.getParamLoadMap().get(spill); + var newParamLoad = new ArmInstParamLoad(vr, oldParamLoad.getOffset()); + // newParamLoad.replaceAddr(oldParamLoad.getAddr()); + // newParamLoad.setTrueOffset(oldParamLoad.getTrueOffset()); + // 对于param load 恢复到最初的状态 即从sp中获取数据 再去找addr + inst.insertBeforeCO(newParamLoad); + inst.replaceOperand(spill, vr); + func.getParamLoadMap().put(vr, newParamLoad); + func.getSpillNodes().add(vr); + } else if (func.getStackLoadMap().containsKey(spill) && !(inst instanceof ArmInstStackStore) + && !inst.getRegDef().contains(spill)) { + // 把一个基本块内合并的StackLoad又重新分裂 + Log.ensure(!inst.getRegDef().contains(spill), "def reg contains special node"); + Reg vr = spill.isInt() ? new IVirtualReg() : new FVirtualReg(); + var oldStackLoad = func.getStackLoadMap().get(spill); + var newStackLoad = new ArmInstStackLoad(vr, oldStackLoad.getOffset()); + newStackLoad.replaceAddr(oldStackLoad.getAddr()); + inst.insertBeforeCO(newStackLoad); + inst.replaceOperand(spill, vr); + func.getStackLoadMap().put(vr, newStackLoad); + func.getSpillNodes().add(vr); + } else if (!func.getStackStoreSet().contains(spill)) { + // 直接分裂 + Reg vr = spill.isInt() ? new IVirtualReg() : new FVirtualReg(); + int offset = offsetMap.get(spill); + if (inst.getRegUse().contains(spill)) { + var stackLoad = new ArmInstStackLoad(vr, new IImm(offset)); + inst.insertBeforeCO(stackLoad); + func.getStackLoadMap().put(vr, stackLoad); + } + if (inst.getRegDef().contains(spill)) { + inst.insertAfterCO(new ArmInstStackStore(vr, new IImm(offset))); + func.getStackStoreSet().add(vr); + } + inst.replaceOperand(spill, vr); + func.getSpillNodes().add(vr); } - inst.replaceOperand(spill, vr); - func.getSpillNodes().add(vr); + func.getSpillNodes().add(spill); } - func.getSpillNodes().add(spill); } } } diff --git a/src/pass/backend/Peephole.java b/src/pass/backend/Peephole.java index c92a78b..2d0cc97 100644 --- a/src/pass/backend/Peephole.java +++ b/src/pass/backend/Peephole.java @@ -1,6 +1,6 @@ package pass.backend; -import backend.ImmUtils; +import utils.ImmUtils; import backend.lir.*; import backend.lir.inst.ArmInst.ArmInstKind; import backend.lir.inst.*; diff --git a/src/backend/ImmUtils.java b/src/utils/ImmUtils.java similarity index 99% rename from src/backend/ImmUtils.java rename to src/utils/ImmUtils.java index 26e5559..6bb6fee 100644 --- a/src/backend/ImmUtils.java +++ b/src/utils/ImmUtils.java @@ -1,4 +1,4 @@ -package backend; +package utils; import backend.lir.operand.Operand;