The intrinsics builtin_arm_get_fpscr and builtin_arm_set_fpscr read from and write to the fpscr (Floating-Point Status and Control Register) register.
A translation fault occurs if there is a read then write then read from this register:
void foo(int *p) { p[0] = __builtin_arm_get_fpscr(); __builtin_arm_set_fpscr(1); p[1] = __builtin_arm_get_fpscr(); }
The generated code for the above example only has one read and one write the second read is common sub-expression eliminated into the first read. This is obviously wrong. I think the reason this is happening is due to the intrinsic definition in IntrinsicsARM.td for arm_get_fpscr which has IntrNoMem:
def int_arm_get_fpscr : GCCBuiltin<"__builtin_arm_get_fpscr">, Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>;
the definition for IntrNoMem is:
// IntrNoMem - The intrinsic does not access memory or have any other // side effects. It may be CSE'd deleted if dead, etc. def IntrNoMem : IntrinsicProperty;
The problem is that LLVM doesn't realize it's reading the register that __builtin_arm_set_fpscr wrote. So a potential fix for this problem could be to treat a read of fpscr as a memory access the same way as a write is treated as a memory access.