Esempio n. 1
0
 def transform_unary_minus_expr(self,
                                unary_minus: ir.UnaryMinusExpr) -> ir.Expr:
     expr = self.transform_expr(unary_minus.inner_expr)
     # -(3) => -3
     if isinstance(expr, ir.Literal):
         assert isinstance(expr.value, int)
         return ir.Literal(-expr.value)
     # -(x - y) => y - x
     if isinstance(expr, ir.Int64BinaryOpExpr) and expr.op == '-':
         return ir.Int64BinaryOpExpr(lhs=expr.rhs, rhs=expr.lhs, op='-')
     return ir.UnaryMinusExpr(expr)
Esempio n. 2
0
    def transform_int64_binary_op_expr(
            self, binary_op: ir.Int64BinaryOpExpr) -> ir.Expr:
        lhs = binary_op.lhs
        rhs = binary_op.rhs
        op = binary_op.op
        # (x - y) => (x + -y)
        # This pushes down the minus, so that e.g. (x - (-y)) => (x + y).
        if op == '-':
            rhs = ir.UnaryMinusExpr(rhs)
            op = '+'

        lhs = self.transform_expr(lhs)
        rhs = self.transform_expr(rhs)

        if op == '+' and isinstance(rhs, ir.UnaryMinusExpr):
            # We could not push down the minus, so switch back to a subtraction.
            op = '-'
            rhs = rhs.inner_expr

        if op == '+':
            # 3 + 5 => 8
            if isinstance(lhs, ir.Literal) and isinstance(rhs, ir.Literal):
                return ir.Literal(lhs.value + rhs.value)
            # 0 + x => x
            if isinstance(lhs, ir.Literal) and lhs.value == 0:
                return rhs
            # x + 0 => x
            if isinstance(rhs, ir.Literal) and rhs.value == 0:
                return lhs

        if op == '-':
            # 8 - 5 => 3
            if isinstance(lhs, ir.Literal) and isinstance(rhs, ir.Literal):
                return ir.Literal(lhs.value - rhs.value)
            # 0 - x => -x
            if isinstance(lhs, ir.Literal) and lhs.value == 0:
                return ir.UnaryMinusExpr(rhs)
            # x - 0 => x
            if isinstance(rhs, ir.Literal) and rhs.value == 0:
                return lhs

        if op == '*':
            # 3 * 5 => 15
            if isinstance(lhs, ir.Literal) and isinstance(rhs, ir.Literal):
                return ir.Literal(lhs.value * rhs.value)
            # 0 * x => 0
            if isinstance(lhs, ir.Literal) and lhs.value == 0:
                if self._can_remove_subexpression(rhs):
                    return ir.Literal(0)
            # x * 0 => 0
            if isinstance(rhs, ir.Literal) and rhs.value == 0:
                if self._can_remove_subexpression(lhs):
                    return ir.Literal(0)
            # 1 * x => x
            if isinstance(lhs, ir.Literal) and lhs.value == 1:
                return rhs
            # x * 1 => x
            if isinstance(rhs, ir.Literal) and rhs.value == 1:
                return lhs

        if op == '/':
            # 16 / 3 => 5
            if isinstance(lhs, ir.Literal) and isinstance(rhs, ir.Literal):
                return ir.Literal(lhs.value // rhs.value)
            # x / 1 => x
            if isinstance(rhs, ir.Literal) and rhs.value == 1:
                return lhs

        if op == '%':
            # 16 % 3 => 1
            if isinstance(lhs, ir.Literal) and isinstance(rhs, ir.Literal):
                return ir.Literal(lhs.value % rhs.value)
            # x % 1 => 0
            if isinstance(rhs, ir.Literal) and rhs.value == 1:
                return ir.Literal(0)

        return ir.Int64BinaryOpExpr(lhs, rhs, op)
Esempio n. 3
0
 def transform_int64_binary_op_expr(
         self, binary_op: ir.Int64BinaryOpExpr) -> ir.Expr:
     lhs, rhs = self.transform_exprs([binary_op.lhs, binary_op.rhs],
                                     binary_op)
     return ir.Int64BinaryOpExpr(lhs=lhs, rhs=rhs, op=binary_op.op)