Your code is broken for a=0 - single step through it in your head, or in a debugger, to see what happens.
Given this specific condition, it's equivalent to (unsigned)a <= 1U (because negative integer convert to huge unsigned values).  You can do a single cmp and movls / movhi.  Compilers already spot this optimization; here's how to ask a compiler to make asm for you so you can learn the tricks clever humans programmed into them:
int foo(int a) {
    if(a == 0 || a == 1){
       a = 1;
    }
    else{
       a = 2;
    }
    return a;
}
With ARM GCC10 -O3 -marm on the Godbolt compiler explorer:
foo:
        cmp     r0, #1
        movls   r0, #1
        movhi   r0, #2
        bx      lr
See How to remove "noise" from GCC/clang assembly output? for more about making functions that will have useful asm output.  In this case, r0 is the first arg-passing register in the calling convention, and also the return-value register.
I also included another C version using if (a <= 1U) to show that it compiles to the same asm.  (1U is an unsigned constant, so C integer promotion rules implicitly convert a to unsigned so the types match for the <= operator.  You don't need to explicitly do (unsigned)a <= 1U.)
General case: not a single range
For a case like a==0 || a==3 that isn't a single range-check, you can predicate a 2nd cmp.  (Godbolt)
foo:
        cmp     r0, #3             # sets Z if a was 3
        cmpne   r0, #0             # leaves Z unmodified if it was already set, else sets it according to a == 0
        moveq   r0, #1
        movne   r0, #2
        bx      lr
You can similarly chain && like a==3 && b==4, or for checks like a >= 3 && a <= 7 you can sub / cmp, using the same unsigned-compare trick as the 0 or 1 range check after sub maps a values into the 0..n range.  See the Godbolt link for that.