let rec reduce_expr exp = 
  let v = visit_expr reduce_expr in
  let body = 
    match exp.expr_t with
      CTTexpBinAssign(
      (CTTbinPlusPV | CTTbinMinusPV | CTTbinPostPlusPV | CTTbinPostMinusPVas binop,
      e_ptr,None,
      e_off) -> begin
        match calculate_magnitude exp.expr_type ~orig:exp with
          Some multiply ->
            let e_ptr = reduce_expr e_ptr in
            let e_off = reduce_expr e_off in
            let e2 =
              make_expr_t
                (CTTexpBinExpr (CTTbinTimes, e_off, multiply))
                (type_of e_off)
                ~orig:e_off
            in
            let e2 = fold_constants e2 in
            CTTexpBinAssign(binop,e_ptr,None,e2)
        | None -> (v exp).expr_t
      end
    | CTTexpBinExpr(
      (CTTbinPlusPV | CTTbinMinusPVas binop,
        e_ptr, e_off) -> begin
          match calculate_magnitude exp.expr_type ~orig:exp with
            Some multiply ->
              let e_ptr = reduce_expr e_ptr in
              let e_off = reduce_expr e_off in
              let e2 =
                make_expr_t
                  (CTTexpBinExpr (CTTbinTimes, e_off, multiply))
                  (type_of e_off)
                  ~orig:e_off
              in
              let e2 = fold_constants e2 in
              CTTexpBinExpr(binop,e_ptr,e2)
          | None ->
              (v exp).expr_t
        end
    | CTTexpCoerce(t,e1) ->
        let e1 = reduce_expr e1 in
        let new_t = convert_type t in
        if equal_type ~check_qual:qual_eq ~check_iqual:qual_eq new_t e1.expr_type then
          e1.expr_t 
        else
          CTTexpCoerce(convert_type t, e1)
    | _ -> (v exp).expr_t
  in
  let t = convert_type exp.expr_type in
  make_expr_t body t ~orig:exp