예제 #1
0
파일: cfs_opt.cpp 프로젝트: clear-wing/xoc
//Control flow struct optimizations.
//Transform follow struct to do-while loop
//
//    LABEL:
//    IR-List
//    IF DET
//       GOTO LABEL
//       ...(DEAD CODE)
//    ELSE
//       FALSE-PART
//    ENDIF
//
//is replace by
//
//    DO {
//        IR-List
//    } WHILE DET
//    FALSE-PART
bool IR_CFS_OPT::transformToDoWhile(IR ** head, IR * ir)
{
    ASSERT(head != NULL && *head != NULL, ("invalid parameter"));
    if (!ir->is_lab()) { return false; }

    for (IR * t = ir; t != NULL; t = t->get_next()) {
        if (!t->is_if()) { continue; }

        if (IF_truebody(t) != NULL &&
            IF_truebody(t)->is_goto() &&
            isSameLabel(LAB_lab(ir), GOTO_lab(IF_truebody(t)))) {

            //Start transform.
            IR * dowhile = m_ru->allocIR(IR_DO_WHILE);
            LOOP_det(dowhile) = m_ru->dupIRTree(LOOP_det(t));

            IR * if_stmt = t;
            t = ir->get_next();
            while (t != NULL && t != if_stmt) {
                IR * c = t;
                t = t->get_next();
                xcom::remove(head, c);
                xcom::add_next(&LOOP_body(dowhile), c);
            }

            ASSERT(t == if_stmt, ("illegal IR layout"));

            xcom::remove(head, if_stmt);
            if (IF_falsebody(if_stmt)) {
                xcom::add_next(&dowhile, IF_falsebody(if_stmt));
                IF_falsebody(if_stmt) = NULL;
            }
            xcom::insertafter(&ir, dowhile);
            m_ru->freeIRTree(if_stmt); //free IF
            xcom::remove(head, ir);
            m_ru->freeIRTree(ir); //free LABEL
            return true;
        }
    }

    return false;
}
예제 #2
0
파일: cfs_opt.cpp 프로젝트: Grainspring/xoc
/*
Control flow struct optimizations.
Transform follow struct to do-while loop

	LABEL:
	IR-LIST
	IF DET
	   GOTO LABEL
	   ...(DEAD CODE)
	ELSE
	   FALSE-PART
	ENDIF

is replace by

	DO {
		IR-LIST
	} WHILE DET
	FALSE-PART
*/
bool IR_CFS_OPT::trans_to_do_while_loop(IR ** head, IR * ir)
{
	IS_TRUE(head != NULL && *head != NULL, ("invalid parameter"));
	if (ir->is_lab()) {
		IR * t = ir;
		LABEL_INFO * li = LAB_lab(ir);
		while (t != NULL) {
			if (IR_type(t) == IR_IF) {
				if (IF_truebody(t) != NULL &&
					IR_type(IF_truebody(t)) == IR_GOTO &&
					is_same_label(LAB_lab(ir), GOTO_lab(IF_truebody(t)))) {

					//start transform...
					IR * dowhile = m_ru->new_ir(IR_DO_WHILE);
					LOOP_det(dowhile) = m_ru->dup_irs(LOOP_det(t));

					IR * if_stmt = t;
					t = IR_next(ir);
					while (t != NULL && t != if_stmt) {
						IR * c = t;
						t = IR_next(t);
						remove(head, c);
						add_next(&LOOP_body(dowhile), c);
					}
					IS_TRUE(t == if_stmt, ("???"));
					remove(head, if_stmt);
					if (IF_falsebody(if_stmt)) {
						add_next(&dowhile, IF_falsebody(if_stmt));
						IF_falsebody(if_stmt) = NULL;
					}
					insertafter(&ir, dowhile);
					m_ru->free_irs(if_stmt); //free IF
					remove(head, ir);
					m_ru->free_irs(ir); //free LABEL
					return true;
				}
			}
			t = IR_next(t);
		}
	}
	return false;
}
예제 #3
0
파일: cfs_opt.cpp 프로젝트: clear-wing/xoc
//The followed forms
//   if (cond) {
//
//   } else {
//       IR-list
//   }
//
//is replaced by
//
//   if (!cond) {
//       IR-list
//   }
bool IR_CFS_OPT::transformIf2(IR ** head, IR * ir)
{
    ASSERT(head && *head, ("invalid parameter"));
    if (ir == NULL || !ir->is_if()) { return false; }

    //Check true part
    if (IF_truebody(ir) == NULL) {
        if (IF_falsebody(ir) == NULL) {
            xcom::remove(head, ir);
            m_ru->freeIRTree(ir);
            return true;
        }
        m_ru->invertCondition(&IF_det(ir));
        IF_truebody(ir) = IF_falsebody(ir);
        IF_falsebody(ir) = NULL;
        return true;
    }

    return false;
}
예제 #4
0
파일: cfs_opt.cpp 프로젝트: Grainspring/xoc
/* The followed forms

	if (cond) {

	} else {
		IR-list
	}

is replaced by

	if (!cond) {
		IR-list
	} */
bool IR_CFS_OPT::trans_if2(IR ** head, IR * ir)
{
	IS_TRUE(head && *head, ("invalid parameter"));
	if (ir == NULL || IR_type(ir) != IR_IF) { return false; }

	//Check true part
	if (!IF_truebody(ir)) {
		if (IF_falsebody(ir) == NULL) {
			remove(head, ir);
			m_ru->free_irs(ir);
			return true;
		}
		m_ru->invert_cond(&IF_det(ir));
		IF_truebody(ir) = IF_falsebody(ir);
		IF_falsebody(ir) = NULL;
		return true;
	}

	return false;
}
예제 #5
0
파일: cfs_opt.cpp 프로젝트: clear-wing/xoc
bool IR_CFS_OPT::CfsOpt(
        IN OUT IR ** ir_list,
        SimpCtx const& sc)
{
    bool change = false;

    for (IR * ir = *ir_list; ir != NULL;) {
        if (transformToDoWhile(ir_list, ir)) {
            change = true;
            ir = *ir_list;
            continue;
        }

        if (ir->is_if() && transformIf1(ir_list, ir)) {
            change = true;
            ir = *ir_list;
            continue;
        }

        if (ir->is_if() && transformIf2(ir_list, ir)) {
            change = true;
            ir = *ir_list;
            continue;
        }

        if (ir->is_if() && transformIf3(ir_list, ir)) {
            change = true;
            ir = *ir_list;
            continue;
        }

        switch (ir->get_code()) {
        case IR_IF:
            if (hoistIf(ir_list, ir)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            if (CfsOpt(&IF_truebody(ir), sc)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            if (CfsOpt(&IF_falsebody(ir), sc)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            break;
        case IR_DO_WHILE:
        case IR_WHILE_DO:
        case IR_DO_LOOP:
            if (hoistLoop(ir_list, ir)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            if (CfsOpt(&LOOP_body(ir), sc)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            break;
        case IR_SWITCH:
            if (CfsOpt(&SWITCH_body(ir), sc)) {
                change = true;
                ir = *ir_list;
                continue;
            }
            break;
        default:;
        } //end switch

         ir = ir->get_next();
    }
    return change;
}
예제 #6
0
파일: cfs_opt.cpp 프로젝트: clear-wing/xoc
//The followed forms
// x is signed
//     IF(x > 0x7FFFFFFF) {a=1} ELSE {b=1}   =>  b=1
//     IF(x < 0x80000000) {a=1} ELSE {b=1}   =>  b=1
//
// x is unsigned
//     IF(x > 0xFFFFFFFF){a=1} ELSE {b=1}   =>  b=1
//     IF(x < 0x0) {a=1} ELSE {b=1}         =>  b=1
bool IR_CFS_OPT::transformIf3(IR ** head, IR * ir)
{
    ASSERT(head && *head, ("invalid parameter"));
    if (ir == NULL || !ir->is_if()) { return false; }

    IR * det = IF_det(ir);
    if (det->is_gt()) {
        IR * opnd0 = BIN_opnd0(det);
        IR * opnd1 = BIN_opnd1(det);
        if (opnd0->is_ld() &&
            opnd0->is_int() &&
            opnd1->is_const() &&
            opnd1->is_int() &&
            m_ru->getIntegerInDataTypeValueRange(opnd1) ==
              m_ru->getMaxInteger(m_tm->get_dtype_bitsize(
                TY_dtype(opnd1->get_type())), opnd1->is_signed())) {
            //e.g:
            //x is unsigned, if(x>0xFFFFFFFF) {a=1} else {b=1} => b=1
            //x is signed, if(x>0x7FFFFFFF) {a=1} else {b=1} =>  b=1
            IR * allocIR = NULL;
            if (IF_falsebody(ir) != NULL) {
                allocIR = m_ru->dupIRTree(IF_falsebody(ir));
            }

            xcom::replace(head, ir, allocIR);

            if (allocIR != NULL) {
                IR_parent(allocIR) = IR_parent(ir);
            }

            m_ru->freeIRTree(ir);
            return true;
        }
    } else if (det->is_lt()) {
        IR * opnd0 = BIN_opnd0(det);
        IR * opnd1 = BIN_opnd1(det);
        if (opnd0->is_ld() &&
            opnd0->is_int() &&
            opnd1->is_const() &&
            opnd1->is_int() &&
            m_ru->getIntegerInDataTypeValueRange(opnd1) ==
              m_ru->getMinInteger(m_tm->get_dtype_bitsize(
                TY_dtype(opnd1->get_type())), opnd1->is_signed())) {
            //x is signed, IF(x < 0x80000000) {a=1} ELSE {b=1}  =>  b=1
            IR * allocIR = NULL;
            if (IF_falsebody(ir) != NULL) {
                allocIR = m_ru->dupIRTree(IF_falsebody(ir));
            }

            xcom::replace(head, ir, allocIR);

            if (allocIR != NULL) {
                IR_parent(allocIR) = IR_parent(ir);
            }

            m_ru->freeIRTree(ir);
            return true;
        } else if (opnd0->is_ld() &&
                   opnd1->is_const() &&
                   opnd0->is_uint() &&
                   CONST_int_val(opnd1) == 0) {
            //x is unsigned, if(x<0) {a=1} else {b=1}  =>  b=1
            IR * allocIR = NULL;
            if (IF_falsebody(ir) != NULL) {
                allocIR = m_ru->dupIRTree(IF_falsebody(ir));
            }

            xcom::replace(head, ir, allocIR);

            if (allocIR != NULL) {
                IR_parent(allocIR) = IR_parent(ir);
            }

            m_ru->freeIRTree(ir);
            return true;
        }
    }

    return false;
}
예제 #7
0
파일: cfs_opt.cpp 프로젝트: Grainspring/xoc
bool IR_CFS_OPT::perform_cfs_optimization(IN OUT IR ** ir_list,
										  IN SIMP_CTX const& sc)
{
	bool change = false;

	for (IR * ir = *ir_list; ir != NULL;) {
		if (trans_to_do_while_loop(ir_list, ir)) {
			change = true;
			ir = *ir_list;
			continue;
		}

		if (IR_type(ir) == IR_IF && trans_if1(ir_list, ir)) {
			change = true;
			ir = *ir_list;
			continue;
		}

		if (IR_type(ir) == IR_IF && trans_if2(ir_list, ir)) {
			change = true;
			ir = *ir_list;
			continue;
		}

		if (IR_type(ir) == IR_IF && trans_if3(ir_list, ir)) {
			change = true;
			ir = *ir_list;
			continue;
		}

		switch (IR_type(ir)) {
		case IR_IF:
			if (hoist_if(ir_list, ir)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			if (perform_cfs_optimization(&IF_truebody(ir), sc)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			if (perform_cfs_optimization(&IF_falsebody(ir), sc)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			break;
		case IR_DO_WHILE:
		case IR_WHILE_DO:
		case IR_DO_LOOP:
			if (hoist_loop(ir_list, ir)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			if (perform_cfs_optimization(&LOOP_body(ir), sc)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			break;
		case IR_SWITCH:
			if (perform_cfs_optimization(&SWITCH_body(ir), sc)) {
				change = true;
				ir = *ir_list;
				continue;
			}
			break;
		default:;
		} //end switch

		 ir = IR_next(ir);
	}
	return change;
}
예제 #8
0
파일: cfs_opt.cpp 프로젝트: Grainspring/xoc
/* The followed forms
	x is signed
		IF(x > 0x7FFFFFFF) {a=1} ELSE {b=1}   =>  b=1
		IF(x < 0x80000000) {a=1} ELSE {b=1}   =>  b=1

	x is unsigned
		IF(x > 0xFFFFFFFF){a=1} ELSE {b=1}   =>  b=1
		IF(x < 0x0) {a=1} ELSE {b=1}         =>  b=1 */
bool IR_CFS_OPT::trans_if3(IR ** head, IR * ir)
{
	IS_TRUE(head && *head, ("invalid parameter"));
	if (ir == NULL || IR_type(ir) != IR_IF) { return false; }

	IR * det = IF_det(ir);
	if (IR_type(det) == IR_GT) {
		IR * opnd0 = BIN_opnd0(det);
		IR * opnd1 = BIN_opnd1(det);
		DTD const* op0_rty = opnd0->get_dtd(m_dm);
		DTD const* op1_rty = opnd1->get_dtd(m_dm);

		if (IR_type(opnd0) == IR_LD &&
			opnd1->is_const() &&
			opnd0->is_int(m_dm) &&
			CONST_int_val(opnd1) == MAX_INT_VALUE) {
			//x is signed, if(x>0x7FFFFFFF) {a=1} else {b=1} =>  b=1
			IR * new_ir = NULL;
			if (IF_falsebody(ir)) {
				new_ir = m_ru->dup_irs(IF_falsebody(ir));
			}
			replace(head, ir, new_ir);

			//Revise IR_parent.
			IR_parent(new_ir) = IR_parent(ir);

			m_ru->free_irs(ir);
			return true;
		} else if (IR_type(opnd0) == IR_LD &&
				   IR_is_const(opnd1) &&
				   opnd0->is_uint(m_dm) &&
				   CONST_int_val(opnd1) == MAX_UINT_VALUE) {
			//x is unsigned, if(x>0xFFFFFFFF) {a=1} else {b=1} => b=1
			IR * new_ir = NULL;
			if (IF_falsebody(ir)) {
				new_ir = m_ru->dup_irs(IF_falsebody(ir));
			}

			replace(head, ir, new_ir);

			//Revise IR_parent.
			IR_parent(new_ir) = IR_parent(ir);

			m_ru->free_irs(ir);
			return true;
		}
	} else if (IR_type(det) == IR_LT) {
		IR * opnd0 = BIN_opnd0(det);
		IR * opnd1 = BIN_opnd1(det);
		DTD const* op0_rty = opnd0->get_dtd(m_dm);
		DTD const* op1_rty = opnd1->get_dtd(m_dm);
		if (IR_type(opnd0) == IR_LD &&
			IR_is_const(opnd1) &&
			opnd0->is_int(m_dm) &&
			CONST_int_val(opnd1) == MIN_INT_VALUE) {
			//x is signed, IF(x < 0x80000000) {a=1} ELSE {b=1}  =>  b=1
			IR * new_ir = NULL;
			if (IF_falsebody(ir)) {
				new_ir = m_ru->dup_irs(IF_falsebody(ir));
			}
			replace(head, ir, new_ir);
			m_ru->free_irs(ir);
			return true;
		} else if (IR_type(opnd0) == IR_LD &&
					IR_is_const(opnd1) &&
					opnd0->is_uint(m_dm) &&
					CONST_int_val(opnd1) == 0) {
			//x is unsigned, if(x<0) {a=1} else {b=1}  =>  b=1
			IR * new_ir = NULL;
			if (IF_falsebody(ir)) {
				new_ir = m_ru->dup_irs(IF_falsebody(ir));
			}
			replace(head, ir, new_ir);

			//Revise IR_parent.
			IR_parent(new_ir) = IR_parent(ir);

			m_ru->free_irs(ir);
			return true;
		}
	}

	return false;
}