<div dir="ltr"><div><div><div><div><div><div><div>Here's our testcase:<br><span style="font-family:monospace,monospace"><br>#include <stdio.h><br><br>struct flags {<br>    unsigned frog: 1;<br>    unsigned foo : 1;<br>    unsigned bar : 1;<br>    unsigned bat : 1;<br>    unsigned baz : 1;<br>    unsigned bam : 1;<br>};<br><br>int main() {<br>    struct flags flags;<br>    flags.bar = 1;<br>    flags.foo = 1;<br>    if (flags.foo == 1) {<br>        printf("Pass\n");<br>        return 0;<br>    } else {<br>        printf("FAIL\n");<br>        return 1;<br>    }  <br>}</span><br><br></div>when we compile this using LLVM 3.9 we get the "FAIL" message. However, when we compile in LLVM 3.6 it passes. (this is only an issue with -O0, higher levels of optimization work fine)<br><br></div>After some investigation we discovered the problem, here's the relevant part of our assembly generated by LVM 3.9:<br><span style="font-family:monospace,monospace"><br>    load          r0, r510, 24, 8<br>    slr           r0, r0, 1, 8<br>    cmpimm        r0, r0, 1, 0, 8, SNE<br>    bitop1        r0, r0, 1<<0, AND, 64<br>    jct          .LBB0_2, r0, 0, N<br>    jrel         .LBB0_1</span><br><br></div>Notice the slr (shift logical right) instruction there is shifting to the right 1 position in order to get  flags.foo into bit 0 of r0.  But the problem is that the compare(cmpimm) is comparing not just the single bit but the whole value in r0 (an 8-bit value) against 1. If we insert a logical AND with '1' to mask r0 just prior to the compare it works fine.<br><br></div>And as it turns out, we see that <b><span style="font-family:monospace,monospace">and</span></b> in the LLVM IR generated using -O0 and -emit-llvm has the AND included:<br> ...<br><span style="font-family:monospace,monospace">  %bf.lshr = lshr i8 %bf.load4, 1<br><b>  %bf.clear5 = and i8 %bf.lshr, 1</b><br>  %bf.cast = zext i8 %bf.clear5 to i32<br>  %cmp = icmp eq i32 %bf.cast, 1<br>  br i1 %cmp, label %if.then, label %if.else</span><br><br></div>(compiled with:  clang -O0 -emit-llvm -S failing.c -o failing.ll )<br><br></div>I reran passing -debug to llc to see what's happening at various stages of DAG optimization:<br><br><span style="font-family:monospace,monospace">clang -O0 -mllvm -debug -S failing.c -o failing.s</span> <br><br></div>The initial selection DAG has the AND op node:<br><span style="font-family:monospace,monospace"><br>            t22: i8 = srl t19, Constant:i64<1><br><b>            t23: i8 = and t22, Constant:i8<1></b><br>          t24: i32 = zero_extend t23<br>        t27: i1 = setcc t24, Constant:i32<1>, seteq:ch<br>      t29: i1 = xor t27, Constant:i1<-1><br>    t31: ch = brcond t18, t29, BasicBlock:ch<if.else 0xa5f8d48><br>  t33: ch = br t31, BasicBlock:ch<if.then 0xa5f8c98></span><br><br><div><div><div><div>The Optimized lowered selection DAG does not contain the<b> AND</b> node, but it does have a truncate which would seem to stand in for it given the result is only 1bit wide and the xor following it is operating on 1-bit wide values:<br><br><span style="font-family:monospace,monospace">         t22: i8 = srl t19, Constant:i64<1><br>        t35: i1 = truncate t22<br>      t29: i1 = xor t35, Constant:i1<-1><br>    t31: ch = brcond t18, t29, BasicBlock:ch<if.else 0xa5f8d48><br>  t33: ch = br t31, BasicBlock:ch<if.then 0xa5f8c98><br><br></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">Next we get to the Type-legalized selection DAG:<br><br></font>        t22: i8 = srl t19, Constant:i64<1><br>      t40: i8 = xor t22, Constant:i8<1><br>    t31: ch = brcond t18, t40, BasicBlock:ch<if.else 0xa5f8d48><br>  t33: ch = br t31, BasicBlock:ch<if.then 0xa5f8c98><font face="arial,helvetica,sans-serif"><br><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif"> The</font> truncate<font face="arial,helvetica,sans-serif"> is now gone.<br><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">Next we have the Optimzied type-legalized DAG:<br><br></font>        t22: i8 = srl t19, Constant:i64<1><br>      t43: i8 = setcc t22, Constant:i8<1>, setne:ch<br>    t31: ch = brcond t18, t43, BasicBlock:ch<if.else 0xa5f8d48><br>  t33: ch = br t31, BasicBlock:ch<if.then 0xa5f8c98><font face="arial,helvetica,sans-serif"><br><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">The<b> </b></font><b>xor</b><font face="arial,helvetica,sans-serif"> has been replaced with a </font><b>setcc</b><font face="arial,helvetica,sans-serif">. The legalized selection DAG is essentially the same. As is the optimized legalized selection DAG. <br><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">So if t19 contains</font> 0b00000110<font face="arial,helvetica,sans-serif"> then<br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">t22 contains </font>0b00000011<font face="arial,helvetica,sans-serif"> <br></font>setcc<font face="arial,helvetica,sans-serif"> then compares </font>t22<font face="arial,helvetica,sans-serif"> with a constant 1 and since they're not equal (</font>setne<font face="arial,helvetica,sans-serif">) it sets bit 0 of t43. <br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">brcond will then test bit 0 of t43 and since it's set it branches to the else branch (prints FAIL in this case)<br><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">If instead t22 contained 0b00000001 (as would be the case if the mask was still there) the </font>setcc <font face="arial,helvetica,sans-serif">would find both values to compare equal and since </font>setne <font face="arial,helvetica,sans-serif">is specified the branch in </font>brcond<font face="arial,helvetica,sans-serif"> will not be taken (the correct behavior)<br><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">Things seem to have gone wrong when the </font></span><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">Type-legalized selection DAG was optimized and the </font><b>xor </b><font face="arial,helvetica,sans-serif">node was changed to a </font><b>setcc </b><font face="arial,helvetica,sans-serif">(and actually, the </font><b>xor</b><font face="arial,helvetica,sans-serif"> seems like it was more optimal than the </font><b>setcc </b><font face="arial,helvetica,sans-serif">anyway)</font><b>. </b><font face="arial,helvetica,sans-serif"><br><br> Any ideas about why this is happening?<br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif"><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">[in 3.6 we don't see this issue, but then again, in 3.6 the assembly is a bit different: no srl is used to get at the foo field fo the struct]<br><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif">Phil<br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif"><br></font></span></div><div><span style="font-family:monospace,monospace"><font face="arial,helvetica,sans-serif"><br></font></span></div><div><br><br></div><div><div><div><br></div></div></div></div></div></div></div>