Now you've disallowed using a constructor to create an instance of a Test object with a different x value, but gcc/clang still aren't optimizing.
It may be legal to use char* or memcpy to create an object-representation of a Test object with a different x value, without violating the strict-aliasing rule.  That would make the optimization illegal.
Update, see discussion in comments; in the ISO standard 6.8.4 basic.type.qualifier "A const object is an object of type const T" and doesn't rule out it being a sub-object, and getting at it via a pointer to the struct probably just counts as a non-const access path to a const object.  (Any attempt to modify a const object during its lifetime results in undefined behavior doesn't leave room for loopholes since this is an object, not a reference to an object).  So the char* and memcpy methods look to be UB, and even placement-new probably can't help: Placement new and assignment of class with const member - reuse is allowed only if "the type of the original object is not const-qualified".
(That language about not reusing the storage of a const object changed in C++20; it now leaves the door open for using placement-new on a whole struct/class object that's non-const, even if it contains const members.)
Manufacturing a brand new Test object with arbitrary x value via std::bit_cast<Test>( int ) still appears to be fully legal even in ISO C++.  It is Trivially Copyable.  Also, it appears that real implementations such as GCC and clang define the behaviour for all these cases, at least de-facto; I didn't check their official docs to see if it's mentioned as a GNU extension.  As far as optimizer limits, that's what matters.
This section hinges on some flimsy arguments / wishful thinking
   Test foo;
   *(char*)&foo = 3;  // change first byte of the object-representation
                      // which is where foo.x's value lives
In reference contexts in C++, const means you can't modify this object through this reference.  I don't know how that applies for a const member of a non-const object.
This is a Standard Layout type, so it should be binary compatible with an equivalent C struct, and also safe to write/read to a file and back without UB.  It's a POD type (or I think the C++20 replacement for the concept of POD).  It's even trivially copyable with or without a Test(const Test&) = default; copy-constructor, although that's probably not relevant.
If it's legal to write it out to a file and read it back, it should still be well-defined even if the file is modified in between.  Or if we memcpy it to an array, modify the array, and copy back:
   Test foo;
   char buf[sizeof(foo)];
   memcpy(buf, &foo, sizeof(foo));
   buf[0] = 3;         // on a little-endian system like x86, this is buf.x = 3;  - the upper bytes stay 0
   memcpy(&foo, buf, sizeof(foo));
The only questionable step is the final memcpy back into foo; this is what creates a Test object with an x value the constructor couldn't produce.
@Klauss raised a concern about overwriting the whole object without destructing it and doing a placement-new of the new one.  I thought that was allowed for Standard Layout POD types, but I haven't checked the standard.  That should be allowed for a struct or class whose members are all non-const; that's the point of Standard Layout and POD / TrivialType.  In any case, the char* version avoids doing that, not rewriting the whole object.
Does merely having a const member break the ability to write/read the object representation to a file?  I don't think so; having a const member doesn't disqualify a type from being Standard Layout, Trivial, and even Trivially Copyable.  (This point is the biggest stretch; but I still think it's legal unless someone can show me in the standard where it isn't legal to poke around in the object-representation of a non-const class object.)
It would be extremely weird if having or not-having a constructor that allowed different initializers for the const int x member was the difference between it being UB or not to write/read this object to a file and modify it.  The inability to create a Test object with a different x value the "normal" way is a red herring as far as whether it's legal to poke around in the bytes of the object representation.  (Although that is still a valid question for a class with a const member.)
And now we're back to non-hand-wavy stuff I think is still fully correct
@Tobias also commented with an example (https://godbolt.org/z/3abaEqWdM) that uses C++20 std::bit_cast to manufacture a Test object with x == 2 that's constexpr-safe and evaluates correctly even inside a static_assert.  std::bit_cast
We can also see from this example that GCC and clang leave room for non-inline function calls to modify that member of an already-constructed Test object:
void ext(void*);  // might do anything to the pointed-to memory
int test() {
    Test foo;    // construct with x=1
    ext (&foo);
    return foo.x;   // with ext() commented out,  mov eax, 1
}
Godbolt
# GCC11.2 -O3.  clang is basically equivalent.
test():
        sub     rsp, 24             # stack alignment + wasted 16 bytes
        lea     rdi, [rsp+12]
        mov     DWORD PTR [rsp+12], 1      # construct with x=1
        call    ext(void*)
        mov     eax, DWORD PTR [rsp+12]    # reload from memory, not mov eax, 1
        add     rsp, 24
        ret
It may or may not be a missed optimization.  Many missed-optimizations are things compilers don't look for because it would be computationally expensive (even an ahead-of-time compiler can't use exponential-time algorithms carelessly on potentially-large functions).
This doesn't seem too expensive to look for, though, just checking if a constructor default has no way to be overridden. Although it seems lowish in value in terms of making faster / smaller code since hopefully most code won't do this.
It's certainly a sub-optimal way to write code, because you're wasting space in each instance of the class holding this constant.  So hopefully it doesn't appear often in real code-bases.  static constexpr is idiomatic and much better than a const per-instance member object if you intentionally have a per-class constant.
However, constant-propagation can be very valuable, so even if it only happens rarely, it can open up major optimizations in the cases it does.