Interesting point because learning the backend code structure is not trivial and each target is implemented in a different subfolder under the Target
with several .cpp, .h, and .td files.
Since following is mentioned in your provided link:
"Also write code in XXXISelLowering.cpp to replace or remove operations and data types that are not supported natively in a SelectionDAG."
Let's take this forward. I would answer with a bigger picture showing basic steps
prior to instruction selection, starting with the LLVM IR
step that is to the top-left and then citing Getting Started with LLVM
Core Libraries: 
First, a SelectionDAGBuilder instance (see SelectionDAGISel.cpp for details)
visits every function and creates a SelectionDAG object for each basic block. During
this process, some special IR instructions such as call and ret already need targetspecific
idioms—for instance, how to pass call arguments and how to return from
a function—to be transformed into SelectionDAG nodes. To solve this issue, the
algorithms in the TargetLowering class are used for the first time. This class is an
abstract interface that each target must implement, but also has plenty of common
functionality used throughout all backends.
To implement this abstract interface, each target declares a TargetLowering
subclass named <Target>TargetLowering. Each target also overloads methods
that implement how a specific target-independent, high-level node should be lowered
to a level closer to the one of this machine. As expected, only a small subset of
nodes must be lowered in this way, while the majority of the others are matched
and replaced at instruction selection. For instance, in SelectionDAG from sum. bc, the X86TargetLowering::LowerReturn() method (see lib/Target/X86/ X86ISelLowering.cpp) is used to lower the IR ret instruction. While doing this,
it generates the X86ISD::RET_FLAG node, which copies the function result to EAX—a
target-specific way to handle the function return.