Compile following code with options -Os -march=armv5te -mthumb, class A { public: int ah; unsigned field : 2; }; void foo(A* p) { p->ah = 1; p->field = 1; } We can get: mov r3, #1 // A str r3, [r0] ldrb r3, [r0, #4] mov r2, #3 bic r3, r3, r2 mov r2, #1 // B orr r3, r3, r2 strb r3, [r0, #4] @ sp needed for prologue bx lr Both instruction A and B load a constant 1 into register. We can load 1 into r1 in instruction A and use r1 when constant 1 is required. So instruction B can be removed. cse pass doesn't find this opportunity is because it needs all expressions to be of the same mode. But in rtl level the first 1 is in mode SI and the second 1 is in mode QI. Arm doesn't has any physical register of QI mode, so all of them are put into 32 bit physical register and causes redundant load of constant 1.
Created attachment 18662 [details] test case
confirmed - FYI, the problem doesn't arise with !-mthumb.