编译原理实验六—代码优化

时间:2021-11-23 03:53:56

实验目的:

1. 通过上机实习,加深对代码优化的理解,掌握基本块优化、循环优化的方法。 

2.  掌握利用 DAG 进行基本块优化的技术。 



坑....闷头写了两天总算模拟出了个能跑得起来的差不多的代码,里面还有很多地方可以优化,函数和结构都有很多....先懒着这样吧

实现代码(待改进版)

#include<bits/stdc++.h>
#define PB push_back
using namespace std;
char opera[10]={'=','+','-','*','/','_'};
int n;
int cnt;
map<string,int> mp;
//该变量或常量所对应的结点编号
map<int,int> numbermp;
//该数字对应的结点编号

/*
Solved:
1.多变量对应同一常量
2.根据变量的值计算另一个变量的值

*/

struct Tac{
    string str;        //四元式的完整式子
    int id;            //序号
    int operation;    //操作
    string op1;        //操作数1
    int num1;        //若操作数1为数字
    string op2;        //操作数2
    int num2;        //若操作数2为数字
    string res;        //结果
    int ans;        //若结果为数字
}t[100];


struct node{
    int id;            //结点序号
    int operation;    //操作
                    
    int type;        //type=0:常量num,type=1:变量var
    int num;        //结点若代表常量
    vector<string> var;    
                    //若结点代表变量
    int lchild;        //左。右孩子序号
    int rchild;
    
    bool operator < (const node& y) const{
        return id<y.id;
    }
    
    node(){
        id = 0;
        operation = 0;
        type = 0;
        num = 0;
        var.clear();
        lchild = 0;
        rchild = 0;
    }
};
vector<node> Dag;


//vector<node> nd;

void debug(){
    for(int i = 1;i < n; i++){
        cout<<t[i].str<<' '<<t[i].id<<' '<<t[i].op1<<' '<<opera[t[i].operation]<<' '<<t[i].op2<<' '<<t[i].res<<endl;
    }
}
void superdebug(){
    for(int i = 0 ; i < Dag.size();i++){
        cout<<"id = "<<Dag[i].id<<" type = "<<Dag[i].type<<" num = "<<Dag[i].num;
        cout<<" var_num = "<<Dag[i].var.size()<<" first_var = "<<Dag[i].var[0];
        cout<<" lc = "<<Dag[i].lchild<<" rc = "<<Dag[i].rchild;
        cout<<" op "<<opera[Dag[i].operation]<<' '<<mp["T0"]<<endl;
    }
    
}

void process(Tac &stm){
    string s = stm.str;
    char op = s[1];
    for(int i=0;i<5;i++)
        if(op==opera[i]) stm.operation = i;
    int ptr = 3;
    while(s[ptr]==' ') ptr++;
    while(s[ptr]!=',') stm.op1+=s[ptr++];
    ptr++;
    while(s[ptr]==' ') ptr++;
    while(s[ptr]!=',') stm.op2+=s[ptr++];
    ptr++;
    while(s[ptr]==' ') ptr++;
    while(s[ptr]!=')') stm.res+=s[ptr++];
    
    if(stm.operation == 1 && stm.op2==" ") stm.operation = 5;
}

void read(){
    freopen("exp6_2.in","r",stdin);
    char s[100];
    n = 1;
    while(gets(s)){
        for(int i=0;i<strlen(s);i++){
            t[n].str += s[i];
        }            
        t[n].id = n;    
        process(t[n]);
        n++;
    }
    debug();
}


node & fiDag_node(int id){
    for(int i=0;i<Dag.size();i++){
        if(Dag[i].id == id) return Dag[i];
    }
}


//变量(常量)s是否已经存在,flag = 1存在
node new_node_var(string s,int &flag){
    if(mp[s]) {
        flag = 1;
        int id = mp[s];
        return fiDag_node(id);
    }    
    else{
        node tmp;    
        //cout<<"var = "<<s<<' '<<"cnt = "<<cnt<<endl;
        tmp.type = 1;
        tmp.var.push_back(s);
        mp[s] = cnt;
        tmp.id = cnt;
        flag = 0;
        cnt++;
        Dag.push_back(tmp);
        return tmp;
    }    
}


//变量(常量)s是否已经存在,flag = 1存在
node new_node_num(string str,int &flag){
    int s = 0;
    for(int i=0;i<str.length();i++) s = s*10+str[i]-'0';
    if(numbermp[s]) {
        flag = 1;
        int id = numbermp[s];
        return fiDag_node(id);
    }    
    else{
        node tmp;
        tmp.num = s;
        tmp.type = 0;
        //cout<<"num = "<<tmp.num<<' '<<"cnt = "<<cnt<<endl;
        numbermp[s] = cnt;
        tmp.id = cnt;
        flag = 0;
        cnt++;
        Dag.push_back(tmp);
        return tmp;
    }    
}




void pop_node(node &n1){
    Dag.pop_back();
    cnt--;
    if(n1.type)
        for(int i = 0;i<n1.var.size();i++) mp[n1.var[i]] = 0;
    else
        numbermp[n1.num] = 0;
}

void erase_node(string str){
    queue<node> q;
    for(int i = 0 ; i < Dag.size(); i++){
        if(!Dag[i].var.size() || Dag[i].var[0] != str) q.push(Dag[i]);
    }
    Dag.clear();
    while(!q.empty()){
        node temp = q.front();
        q.pop();
        Dag.PB(temp);         
    }    
}

void relocate_node(string str){    
    int id = mp[str];
    if(!id) return ;
    
    mp[str] = 0;
    int szflag = 0;//该结点只有它自己本身一个变量名
    int nodeloc = -1;
    int strloc = -1;
    for(int i = 0 ; i < Dag.size(); i++){
        int sz = Dag[i].var.size();
        for(int j = 0; j < sz; j++){
            if(Dag[i].var[j] == str){
                if(sz == 1){
                    szflag = 1;
                }
                nodeloc = i;
                strloc = j;
                break;
            }
        }
        if(nodeloc != -1) break;
    }
    if(nodeloc == -1) return ;
    //若当前结点只含有一个变量名
    if(szflag){
        for(int i = 0 ; i < Dag.size(); i++){
            //若当前是某个的子节点不能删除
            if(Dag[i].lchild == id || Dag[i].rchild == id){
            //    cout<<"是某个节点的子节点"<<' '<<id<<' '<<str<<endl;
                return ;
            }
        }
        //cout<<"非子节点"<<' '<<str<<endl;
        erase_node(str);
    }
    //从当前结点的多个变量中删除变量str
    else{
        queue<string> qq;
        for(int j = 0 ; j < strloc ; j++){
            string stemp = Dag[nodeloc].var[j];
            qq.push(stemp);
        }
        for(int j = strloc+1; j < Dag[nodeloc].var.size(); j++){
            string stemp = Dag[nodeloc].var[j];
            qq.push(stemp);
        }
        Dag[nodeloc].var.clear();
        while(!qq.empty()){
            string stemp = qq.front();
            qq.pop();
            Dag[nodeloc].var.PB(stemp);
        }
    }
}




int cal(int a,int b,int op){
    char opr = opera[op];
    if(opr == '+') return a+b;
    if(opr == '-') return a-b;
    if(opr == '*') return a*b;
    if(opr == '/') return a/b;
}

node new_node(string str,int &flag){
    int f = 0;
    node tmp;
    if(isdigit(str[0])) tmp = new_node_num(str,f);
    else tmp = new_node_var(str,f);
    flag = f;    
    return tmp;
}


void add_edge(Tac &stm){
    if(!stm.operation){//赋值
        int flag = 0;
        node n1 = new_node(stm.op1,flag);
        //考虑是否出现过,若出现过是否被引用
        relocate_node(stm.res);
        node &tmp = fiDag_node(n1.id);
        tmp.var.PB(stm.res);
        mp[stm.res] = tmp.id;    
    }    
    else{//运算
        int flag1 = 0;
        int flag2 = 0;
        node n1 = new_node(stm.op1,flag1);
        node n2 = new_node(stm.op2,flag2);
        
        //两个操作数都是数字或代表常量的变量
        if(!n1.type && !n2.type){
            //cout<<"All op are numbers"<<endl;
            int p = cal(n1.num,n2.num,stm.operation);
            if(!flag2) pop_node(n2);
            if(!flag1) pop_node(n1);
            if(!numbermp[p]) {
                int flag = 0;
                node ret = new_node(stm.res,flag);
                numbermp[p] = ret.id;
                ret.num = p;
                ret.type = 0;
                Dag.pop_back();
                Dag.PB(ret);    
            }
            else{
                int id = numbermp[p];
                node &temp = fiDag_node(id);
                temp.var.PB(stm.res);
                mp[stm.res] = id;
            }
        }
        //两个操作数不同时为数字
        else{
            //cout<<"Not all numbers Debugging"<<endl;
            int flag = 0;
            node ret = new_node(stm.res,flag);
            ret.lchild = n1.id;
            ret.rchild = n2.id;    
            ret.operation = stm.operation;
            //若结果非已存在结点
            if(!flag) {
                Dag.pop_back();
                int fouDag = -1;    
                //两个操作数是否已经进行过运算
                for(int i = 0; i < Dag.size();i++){
                    if(Dag[i].lchild && Dag[i].rchild
                       && Dag[i].lchild == ret.lchild && Dag[i].rchild == ret.rchild
                       && Dag[i].operation == ret.operation){
                        fouDag = i;
                        break;
                    }
                }
                if(fouDag != -1){
                    Dag[fouDag].var.PB(stm.res);
                    mp[stm.res] = Dag[fouDag].id;    
                }
                else{
                    Dag.push_back(ret);    
                }                
            }
            else{
                cout<<"TAT"<<endl;
                //结果已经存在 ,删除已有的结点,新建结点并连接左右孩子
                relocate_node(stm.res);
                int flag = 0;
                node freshnode = new_node(stm.res,flag);
                freshnode.lchild = n1.id;
                freshnode.rchild = n2.id;
                freshnode.operation = stm.operation;
                Dag.pop_back();
                Dag.PB(freshnode);
            }
        }    
    }
    //superdebug();
    //cout<<endl<<endl;
}



void solve(){
    for(int i = 1; i < n; i++){
        add_edge(t[i]);
    }
    cout<<endl<<"---ready to debug---"<<endl;
    superdebug();
    
    
    
    
    
}


void display(){
    for(int i = 0 ; i < Dag.size(); i++){
        if(!Dag[i].operation && !Dag[i].type){
            int sz = Dag[i].var.size();
            int num = Dag[i].num;
            for(int j = 0; j < sz; j++){
                cout<<"(=,"<<num<<", ,"<<Dag[i].var[j]<<")"<<endl;
            }
        }
        if(Dag[i].operation){
            int sz = Dag[i].var.size();
            string first_var = Dag[i].var[0];
            int lchild = Dag[i].lchild;
            int rchild = Dag[i].rchild;
            string lc = fiDag_node(lchild).var[0];
            string rc = fiDag_node(rchild).var[0];
            cout<<"("<<opera[Dag[i].operation]<<","<<lc<<","<<rc<<","<<first_var<<")"<<endl;
            for(int j = 1; j < sz;j++){
                string tmp_var = Dag[i].var[j];
                cout<<"(=,"<<first_var<<", ,"<<tmp_var<<")"<<endl;
            }
        }
    }        
}

int main(){
    cnt = 1;
    read();
    solve();
    display();
    
    
    
    
    
    
    
    return 0;
}
/*
(=,3, ,T0)
(*,2,T0,T1)
(+,R,r,T2)
(*,T1,T2,A)
(=,A, ,B)
(*,2,T0,T3)
(+,R,r,T4)
(*,T3,T4,T5)
(-,R,r,T6)
(*,T5,T6,B)

(*,A,B,T1)
(/,6,2,T2)
(-,T1,T2,T3)
(=,T3, ,X)
(=,5, ,C)
(*,A,B,T4)
(=,2,  ,C)
(+,18,C,T5)

(-,A,C,D)
(*,A,C,E)
(*,D,E,F)
(=,2, ,S)
(-,A,C,T)
(*,A,C,Q)
(*,2,S,G)
(*,T,Q,J)
(*,G,5,K)
(+,K,J,L)
(=,L, ,M)
*/