The GHC documentation describes the UNPACK pragma as follows:
The UNPACK indicates to the compiler that it should unpack the contents of a constructor field into the constructor itself, removing a level of indirection.
How will datatype T be unpacked?
data T = T (P Int Int) corresponds to

Therefore, data T = T {-# UNPACK #-} !(P Int Int) corresponds to

In plain English, UNPACK has unpacked the contents of constructor P into the field of constructor T, removing one level of indirection and one constructor header (P).
data T = T {-# UNPACK #-} !(P Int Int) isn't as "compact" as data T'' = T'' Int# Int#:

What about
data U = U {-# UNPACK #-} !(P Int (P Int Int))
?
Similarly, data U = U (P Int (P Int Int)) corresponds to

and data U = U {-# UNPACK #-} !(P Int (P Int Int)) corresponds to

In plain English, UNPACK has unpacked the contents of constructor P into the field of constructor U, removing one level of indirection and one constructor header (P).
Resources