Fixed
Created: Sep 2, 2014
Updated: Dec 3, 2018
Resolved Date: Oct 14, 2014
Found In Version: 6.0.0.10
Fix Version: 6.0.0.13
Severity: Standard
Applicable for: Wind River Linux 6
Component/s: Toolchain
Architecture: ARM
this is on wrl 600.10 and the following options:
cc1 -fpreprocessed -quiet -mcpu=cortex-a15 -mfpu=vfpv3-d16 -mthumb -mtls-dialect=gnu -auxbase obfuscated-org -g -O3 -Werror=implicit-function-declaration -Wno-write-strings -fdump-rtl-all -fdump-tree-all -fno-omit-frame-pointer -dAp obfuscated-org.c
We have some code like this, part of a huge piece of code that we've failed to reduce substantially (if we change anything gcc chooses to
generate different, and correct, code). Unfortunately we can not share the complete code due to it's sensitivity. I'd be happy to go through and show parts of it in live online.
Compiling the code below doesn't generate the provided assembly, but tries to demonstrate the problem. A (potential ?) fix is provided in the end.
struct a {
unsigned int a:27;
unsigned int b:1;
unsigned int c:4;
unsigned int d;
};
struct b {
struct a a;
};
union u {
struct a a;
struct b b;
};
/* Below u->a.b and u->b.a.b is the same bit
*/
void func(union u* u, long* p) {
if(u->a.b != 0) {
p[2] = 1;
}
else {
err("An error", 43);
}
if(u->b.a.b != 0) {
/* do stuff */
}
else
err("An error", 42);
}
--- 8< ---
The compiler generates code;
lsls r2, r3, #28 @ 1149 *shiftsi3_compare0_scratch [length = 4]
itt mi
movmi r2, #1 @ 13 *p *thumb2_movsi_insn/2 [length = 6]
strmi r2, [r7, #8] @ 1050 *p *thumb2_movsi_insn/7 [length = 6]
bpl .L168 @ 1150 arm_cond_branch [length = 4]
...
.L168:
beq .L106 @ 255 arm_cond_branch [length = 2]
...
The first block is the first test (if) and is correct, but the beq is not correct (and unnecessary).
The fix could be (but my understanding of gcc/md is limited).
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index ed8b83a..7fdbaea 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -12071,7 +12071,7 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
/* An operation (on Thumb) where we want to test for a single bit.
This is done by shifting that bit up into the top bit of a
scratch register; we can then branch on the sign bit. */
- if (TARGET_THUMB1
+ if ((TARGET_THUMB1 || TARGET_THUMB2)
&& GET_MODE (x) == SImode
&& (op == EQ || op == NE)
&& GET_CODE (x) == ZERO_EXTRACT