XC8 is not GCC because at the time HiTech made the best compiler for 8bit PIC
XC8 is not GCC because there is no gcc for 8bit PICs, and essentially CAN NOT be a gcc for 8 bit PICS because the PIC architecture is too far away from what GCC thinks a CPU should look like.
There isn't a GCC for 8-bit targets AFAIK, except one: avr-gcc. It is GCC-based and officially supported by the GCC team. https://gcc.gnu.org/wiki/avr-gcc
So I guess some people used to AVR are probably wondering why the hell Microchip didn't go the same route. Now, I admit not knowing much about avr-gcc, but I'm pretty sure this was hard work and hard to maintain, so I don't blame whoever wouldn't want to go through this same mess. As to architecture, I admit I don't know the AVR architecture enough to judge how much easier it was than with the PIC, but certainly all the oddities of the 8-bit PICs were much more severe.
AVR is, for the most part: 32 CPU registers, flat address space, memory-mapped IO registers, reasonably orthogonal load-store (RISC) architecture, hardware multiply, and most instructions single cycle. Stack is traditional (stack pointer into RAM, PUSH and POP instructions).
Oddities include: Harvard architecture (Flash constants accessible by LPM instruction, using PROGMEM and related macros in C); some CPU registers in IO space (flags, stack pointer, some other things); paged memory when extended (effectively, CPU registers have an extra up-to-8 bits section located in IO space, e.g. X pointer (actually r27:r26) extended by RAMPX; this only matters on the larger Flash or RAM devices, or the A-series (fully loaded) devices with external bus interface); interrupts only push address and since flags are in IO there's a whole dance to PUSH it and other important registers (this isn't so unusual really, but different from some that do automatically like x86); and probably more things that aren't immediately coming to mind. Inorthogonal instructions are mainly the more extended instructions that therefore have fewer operands available, e.g. FMULS and stuff (fixed-point multiply, one for each combination of signs, plus the regular MULs). Some operands are implicit, e.g. MULs return output in r1:r0, or the DES crypto instruction using r0-r15; there is a 16-bit reg-reg move which only works on even alignments of course; and most immediate operands only work with r16-r31 destinations. Oh, and instructions are up to 2 arguments, Intel style.
So, overall, pretty easy to compile for. Most of the quirks are handled by instruction assignment (a less efficient alternative may be used depending on register allocations) and linker scripts (memory spaces, because of course EEPROM, Flash and RAM all start at their own respective zeroes*).
*On XMEGA and AVR0 (new ATmegas), EEPROM can be memory-mapped at a fixed offset. Though I don't know if the libraries make use of this, or the old method (through the NVM controller).
The main downside is, generated code has gotten
worse since GCC 4 or so. The optimizer seems to be a bit neglected. I found about a 2x improvement going from -O3 functions to assembler functions on my reverb effect project (at least as of GCC 8.1.0), enough savings that the effect went from a barely usable 2 reverb taps and 1 biquad filter, to 6 taps and 2 filters with about two taps worth of CPU to spare.
But as capability goes, that's a full software DSP effect at 25kS/s, using a simplified mechanism (single delay line with taps, not a proper all-pass), internal 12-bit ADC, external 12-bit DAC, and external RAM (bit-banged). Not bad for an 8-bit machine running at 32MHz.
Tim