带有 Rust 的窥视孔装配说明模式匹配窗口的更好方式?

问题描述 投票:0回答:2

所以我试图在我从

Vec<LLStackInstruction> -> Vec<LLStackInstruction>
出发的地方实施窥视孔优化,其中返回的列表被优化。 (
LL
低级别) 我们的编译器被建模为一个抽象堆栈机器,对于 init/assign,我们将 RHS 压入堆栈,将 LHS 的 addr 压入堆栈,然后弹出和 STR,但试图将其简化为压入 RHS,然后直接通过地址存储到地址中specififer 但我得到了一个非常丑陋的匹配:(并且具有可变性)

pub fn peephole_optimiser(instrs: Vec<LLStackInstruction>) -> Vec<LLStackInstruction> {
    let mut optimized_instructions: Vec<LLStackInstruction> = Vec::new();

    let mut iter = instrs.iter().peekable();

    while let Some(instruction) = iter.next() {
        let window_iter = iter.clone();
        let window: Vec<_> = [vec![instruction], window_iter.take(10).collect()].concat();
        
        if let Some(LLStackInstruction::Push(Register::FP)) = window.get(0) {
            if let Some(LLStackInstruction::Mov(Condition::None, r1, ArgType::Imm(n))) = window.get(1) {
                if let Some(LLStackInstruction::Push(r2)) = window.get(2) {
                    if let Some(LLStackInstruction::Pop(_)) = window.get(3) {
                        if let Some(LLStackInstruction::Pop(_)) = window.get(4) {
                            if let Some(LLStackInstruction::Sub(..)) = window.get(5) {
                                if let Some(LLStackInstruction::Branch(..)) = window.get(6) {
                                    if let Some(LLStackInstruction::Push(_)) = window.get(7) {
                                        if let Some(LLStackInstruction::Pop(_)) = window.get(8) {
                                            if let Some(LLStackInstruction::Pop(_)) = window.get(9) {
                                                if let Some(LLStackInstruction::Str(..)) = window.get(10) {
                                                    if r1 == r2 {
                                                        optimized_instructions.push(LLStackInstruction::Pop(Register::R4));
                                                        optimized_instructions.push(LLStackInstruction::Str(Register::R4, AddressSpecifier::ImmediateOffset(Register::FP, -n)));
                                                        iter.nth(9);
                                                        continue;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        optimized_instructions.push(instruction.clone());
    }
    optimized_instructions
}

我怎样才能让它变得更好

此优化的示例

            // Compact init/assign statements
            // push {fp}
            // mov r1, #88
            // push {r1}
            // pop {r0}
            // pop {r1}
            // subs r0, r1, r0
            // bvs _overflow_err
            // push {r0}
            // pop {r3}
            // pop {r4}
            // str r4, [r3]

            // INTO
            // pop {r4}
            // str r4, [fp, #-88]

我唯一能想到的是,如果我可以将其表达为更小窗口的多个步骤并进行多次优化(或者在优化窗口后,从结果开始重新运行直到结果不变)

assembly rust compiler-construction compiler-optimization peephole-optimization
2个回答
0
投票

每晚都有if-let链功能:

#![feature(let_chains)]

if let a = b && let c = d && e == f { ... }

稳定后,您可以使用

if_chain
箱:

if_chain::if_chain! {
    if let a = b;
    if let c = d;
    if e == f;
    then { ... }
}

0
投票

你可以直接匹配你的窗口而不是嵌套的

if let
语句。 Rust 支持切片的模式解构:

match window[..11] {
    [
        LLStackInstruction::Push(Register::FP), 
        LLStackInstruction::Push(r2), 
        LLStackInstruction::Pop(_), 
        LLStackInstruction::Pop(_), 
        LLStackInstruction::Sub(..), 
        LLStackInstruction::Branch(..), 
        LLStackInstruction::Push(_), 
        LLStackInstruction::Pop(_), 
        LLStackInstruction::Pop(_), 
        LLStackInstruction::Str(..)
    ] if r1 == r2 => {
        optimized_instructions.push(LLStackInstruction::Pop(Register::R4));
        optimized_instructions.push(LLStackInstruction::Str(
            Register::R4,
            AddressSpecifier::ImmediateOffset(Register::FP, -n),
        ));
        iter.nth(9);
        continue;
    }
    _ => {}
}
© www.soinside.com 2019 - 2024. All rights reserved.