Some basic concepts on pipes that will clear your doubts :
Fork() call is used to generate a child process, which by system procedure shares all stack data from parent (shared stack), hence open file descriptors (which basically are numbers...and nothing else).
We use fork with pipes because this way we can communicate between 2 processes, without any need for sending file descriptors explicitly.
We use execl() (process replacement) so as to read/write data from a different process (not real child, however related in hierarchy as same PID as child).
This time this new process has no access to the parent file descriptors, so we send them explicitly, but this allows us communication between processes that are different programs, however they have some common ancestor.
As asked above, if we don't use fork we will not be getting a child process for the parent process, moreover execl() would also be of no use in here as calling execl() in the parent process would hijack the process context of parent, thus losing access to the open file descriptors.
One reason for forking a child process is for using that process as a bait, so as to prevent process hijacking for the parent process.
Hence we would not be able to use pipes if we do execl() directly on parent process, if we dont have any child process.