"r" means you are specifying %0 to be a register (as an input).  (val) means you are specifying that the register should contain the value of val.  So the compiler will allocate a register and make sure it contains val.  For x86_64 the first argument for the function will be in %edi/%rdi, and that is what %0 will expand to.
I stand corrected...
...if the function is not inlined, val will be passed in edi/rdi but might be shuffled around before the asm, but the "r" will cause the compiler to arrange for it to be in some register for the asm.  (See the effect of -O0, below).
Also a function which is not declared/defined to be inline may be inlined, at higher levels of optimization.
I note that it is only possible to read/write CR0 to/from a general purpose register and then only at privilege level 0.  @PeterCordes notes that a "memory" clobber would probably a Good Idea.  Clearly, changing CR0 can have really exciting side effects !
When I tried this at -O0 I found that a simple inline was ignored, and the function compiled for x86_64 to:
   lcr0:
        pushq   %rbp
        movq    %rsp, %rbp
        movl    %edi, -4(%rbp)
        movl    -4(%rbp), %eax
        movl %eax,%cr0
        nop
        popq    %rbp
        ret
I guess that gcc_inline may include __attribute__((__always_inline__)), in which case even at -O0 lcr0 is inlined -- but with lots of lovely stack business.  This time for x86:
  main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $16, %esp
        movl    12(%ebp), %eax
        movl    (%eax), %eax
        movl    (%eax), %eax
        movl    %eax, -4(%ebp)
        movl    -4(%ebp), %eax
        movl    %eax, -8(%ebp)
        movl    -8(%ebp), %eax
        movl %eax,%cr0
        nop
        movl    $0, %eax
        leave
        ret