Skip to content

Latest commit

 

History

History
463 lines (366 loc) · 8.72 KB

289.md

File metadata and controls

463 lines (366 loc) · 8.72 KB
Info

Example

/*
divide_by_32_no_assume(int):
        lea     eax, [rdi + 31]
        test    edi, edi
        cmovns  eax, edi
        sar     eax, 5
        ret
*/
auto divide_by_32_no_assume(int x) {
    return x / 32;
}


/*
divide_by_32_assume(int):
        mov     eax, edi
        shr     eax, 5
        ret
*/
auto divide_by_32_assume(int x) {
    __builtin_assume(x >= 0);
    return x / 32;
}

https://godbolt.org/z/EY43Moa4z

Puzzle

  • Can you modify given examples by adding assume attribute so that sum_impl/g1/g2 functions will be optimized?

    • Note: Expected optimized assembly is provided above the functions
/* TODO - modify sum_impl by adding assume attribute so that sum_impl will be optimized */
auto sum(auto... ts) {
    return sum_impl(ts...);
}

/*
  sum_impl(int, int, int):
        imul    esi, edx
        lea     eax, [rsi + rdi]
        ret
 */
auto sum_impl(int src, int n, int s) {
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}



/* TODO - modify smart_ptr by adding assume attribute so that g1/g2 will be optimized */
struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

/*
  g1(smart_ptr):
        mov     eax, dword ptr [rdi]
        ret
*/
auto g1(smart_ptr p) { return p.counter(); }

/*
  g2(smart_ptr):
        mov     eax, dword ptr [rdi]
        inc     eax
        ret
*/
auto g2(smart_ptr p) { return g1(p); }

https://godbolt.org/z/r5P4jYdnd

Solutions

auto sum_impl(int src, int n, int s) {

   auto i = 0;
   __builtin_assume(i < n);
   for (; i < n ; ++i) {
       src += s;
   }

   return src;
}

struct smart_ptr final {
   constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
       __builtin_assume(counter_ >= 1);
       ++counter_;
   }

   ~smart_ptr() {
       if (--counter_ == 0) {
           destroy();
       }
   }

   [[nodiscard]] auto counter() const { return counter_; }

  private:
   void destroy();
   int counter_{};
};

https://godbolt.org/z/h79ncYKWM

auto sum_impl(int src, int n, int s) {
    __builtin_assume(n > 0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        __builtin_assume(r.counter_ >= 1);
        ++counter_;
    }

    ~smart_ptr() {
        __builtin_assume(counter_ > 0);
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://cpp_tip_of_the_week.godbolt.org/z/vooc977sW

auto sum_impl(int src, int n, int s) {
  __builtin_assume(n >= 0);
  for (auto i = 0; i < n; ++i) {
    src += s;
  }
  return src;
}

struct smart_ptr final {
  constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
    __builtin_assume(counter_ > 0);
    ++counter_;
  }

  ~smart_ptr() {
    if (--counter_ == 0) destroy();
  }

  [[nodiscard]] auto counter() const { return counter_; }

private:
  void destroy();
  int counter_{};
};

https://godbolt.org/z/Wzx6zWEfb

auto sum_impl(int src, int n, int s) {
    __builtin_assume(n >= 0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        __builtin_assume(counter_ >= 1);
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://godbolt.org/z/6dWMTjh5o

auto sum_impl(int src, int n, int s) {
    __builtin_assume(n >= 0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        __builtin_assume(counter_ > 0);
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://godbolt.org/z/xs8T8M53Y

auto sum_impl(int src, int n, int s) {
  __builtin_assume(n >= 0);
  for (auto i = 0; i < n; ++i) {
    src += s;
  }
  return src;
}

struct smart_ptr final {
  constexpr explicit(false) smart_ptr(const smart_ptr& r)
      : counter_(r.counter_) {
    __builtin_assume(counter_ > 0);
    ++counter_;
  }

  ~smart_ptr() {
    if (--counter_ == 0) destroy();
  }

  [[nodiscard]] auto counter() const { return counter_; }

 private:
  void destroy();
  int counter_{};
};

https://godbolt.org/z/79c79r8b4

auto sum_impl(int src, int n, int s) {
    //src += n * s;
    __builtin_assume(n > 0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        __builtin_assume(counter_ >= 1);
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://godbolt.org/z/ocvnTrzrq

#if defined(__clang__)
#define ASSUME(expr) __builtin_assume(expr)
#elif defined(__GNUC__) && !defined(__ICC)
#define ASSUME(expr) if (expr) {} else { __builtin_unreachable(); }
#elif defined(_MSC_VER) || defined(__ICC)
#define ASSUME(expr) __assume(expr)
#endif

auto sum_impl(int src, int n, int s) {
    ASSUME(n > 0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        ASSUME(counter_ > 0);
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://godbolt.org/z/dqEr5nMxW

auto sum_impl(int src, int n, int s) {
    __builtin_assume(n >= 0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        __builtin_assume(counter_ > 0);
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://godbolt.org/z/jYoqM4sbo

auto sum_impl(int src, int n, int s) {
    __builtin_assume(n >= 0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        __builtin_assume(counter_ > 0);
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://godbolt.org/z/1ezTeK8o7

auto sum_impl(int src, int n, int s) {
    __builtin_assume(n >0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        __builtin_assume(r.counter_ > 0);
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://godbolt.org/z/hETMdvjKE

auto sum_impl(int src, int n, int s) {
    __builtin_assume(n >= 0);
    for (auto i = 0; i < n; ++i) {
        src += s;
    }
    return src;
}

struct smart_ptr final {
    constexpr explicit(false) smart_ptr(const smart_ptr& r) : counter_(r.counter_) {
        __builtin_assume(counter_ > 0);
        ++counter_;
    }

    ~smart_ptr() {
        if (--counter_ == 0) destroy();
    }

    [[nodiscard]] auto counter() const { return counter_; }

   private:
    void destroy();
    int counter_{};
};

https://godbolt.org/z/KdaEh9fKo