Skip to content

Latest commit

 

History

History
161 lines (131 loc) · 3.27 KB

312.md

File metadata and controls

161 lines (131 loc) · 3.27 KB
Info

  • Did you know that C++20 added support for Unevaluated asm-declaration in constexpr functions?

Example

constexpr auto get = [](auto value) {
  if consteval {
    return value;
  } else {
    auto result = 0;
    asm("movl $42, %%eax\n" : "=r" (result) );
    return result;
  }
};

static_assert(0 == get(0));
static_assert(4 == get(4));
static_assert(2 == get(2));

consteval auto fn() {
    return get(0);
}

int main(int argc, char**) {
  assert(42 == get(0));
  assert(42 == get(argc));
  return fn();
}

https://godbolt.org/z/z5jYdsa9P

Puzzle

Can you implement const_sub_or_asm_add which subtract given numbers using C++ operators if values can be constant evaluated and adds them using inline assembly otherwise?

constexpr auto const_sub_or_asm_add = [](auto lhs, auto rhs) {
  return 0; /*TODO*/
};

static_assert(1 == const_sub_or_asm_add(2, 1));
static_assert(-1 == const_sub_or_asm_add(3, 4));

int main(int argc, char**) {
  {
    constexpr auto c = const_sub_or_asm_add(1, 2);
    assert(-1 == c);
  }

  {
    auto c = const_sub_or_asm_add(1, 2);
    assert(3 == c);
  }

  {
    assert(3 == const_sub_or_asm_add(1, 2));
    assert(1 == const_sub_or_asm_add(argc, 0));
    assert(2 == const_sub_or_asm_add(argc, argc));
  }
}

https://godbolt.org/z/897a3fn8M

Solutions

constexpr auto const_sub_or_asm_add = [](auto lhs, auto rhs) {
    if consteval {
        return lhs - rhs;
    } else {
        auto result = 0;
        asm ("addl  %%ebx,%%eax"
            :"=a"(result)
            :"a"(lhs), "b"(rhs)
            );
        return result;
    }
};

https://godbolt.org/z/TdjMzKdaT

constexpr auto const_sub_or_asm_add = [](auto lhs, auto rhs) {
  if consteval {
    return lhs - rhs;
  } else {
    decltype(lhs + rhs) result;
    asm("leal (%1, %2), %0\n" : "=r"(result) : "r"(lhs), "r"(rhs));
    return result;
  }
};

https://godbolt.org/z/vrf35veev

constexpr auto const_sub_or_asm_add = [](auto lhs, auto rhs) {
  if consteval {
    return lhs - rhs;
  } else {
    auto result = 0;
    asm("add %%edx, %%eax\n" : "=r" (result) : "edx" (lhs), "eax" (rhs) );
    return result;
  }
};

https://godbolt.org/z/f34bsrj4o

constexpr auto const_sub_or_asm_add = [](auto lhs, auto rhs) {
    if consteval {
        return lhs - rhs;
    } else {
        auto result = 0;
        asm("movl %2, %0;"
            "addl %1, %0;"
            : "=&r"(result)
            : "r"(lhs), "r"(rhs));
        return result;
    }
};

https://godbolt.org/z/bz4z5Exdd

constexpr auto const_sub_or_asm_add = [](auto lhs, auto rhs) {
    if (std::is_constant_evaluated())
        return lhs - rhs;
    asm("addl %%ebx, %%eax;" : "=a" (lhs) : "a" (lhs) , "b" (rhs) );
    return lhs;
};

https://godbolt.org/z/af3vonrnW

constexpr auto const_sub_or_asm_add = [](auto lhs, auto rhs) {
  if consteval {
    return lhs - rhs;
  } else {
    auto add{0};
    asm("addl %%ebx, %%eax\n"
        : "=a" (add)
        : "a" (lhs), "b" (rhs) );
    return lhs + rhs;
  }
  return 0; /*TODO*/
};

https://godbolt.org/z/7zadcr6qx