Compiler produces orr instead of bic using (O2 and Os)
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
GNU Arm Embedded Toolchain |
Invalid
|
Undecided
|
Unassigned |
Bug Description
The code is more or less form the SMT32 lib, I did some of the preprocesser-
I noticed this bug using 7-2018-q2 on windows, but research shows it's more wide spread.
Using -O2/-Os and up GCC 6.4 produces the expected bic, while gcc 7.3 and later produces an orr. -O1 seems to be fine:
#include <stdint.h>
typedef struct
{
volatile uint32_t DIFSEL;
} ADC_TypeDef;
#define WRITE_REG(REG, VAL) ((REG) = (VAL))
#define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK)))
static inline void LL_ADC_
{
(((
}
int test(ADC_TypeDef * testvar) {
LL_
(( (0x01U << (26U))) | (((uint32_
( (0x7FU << (0U)))
);
}
gcc-6.4 -Os:
test:
ldr r3, [r0]
bic r3, r3, #2
str r3, [r0]
bx lr
gcc-7.3 -Os:
test:
ldr r3, [r0]
orr r3, r3, #2
str r3, [r0]
bx lr
I suspect the issue is : 0x7FFFU<< (SingleDiff & ((0x20U << (0U))))
which is a shift by 32 , this is undefined so the compiler can do what it likes
If you change the 0x7FFFFU to 0x7FFFFLL you get what you would expect. I would suggest there are betters to code this function than using 0x7FFFFLL