llvm.org GIT mirror llvm / 6165e87
Reapply r112176 without removing the other CMN patterns (that was unintentional). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@112206 91177308-0d34-0410-b5e6-96231b3b80d8 Bill Wendling 10 years ago
1 changed file(s) with 46 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
22962296
22972297 defm CMP : AI1_cmp_irs<0b1010, "cmp",
22982298 BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>;
2299 //FIXME: Disable CMN, as CCodes are backwards from compare expectations
2300 // Compare-to-zero still works out, just not the relationals
2299
2300 // FIXME: There seems to be a (potential) hardware bug with the CMN instruction
2301 // and comparison with 0. These two pieces of code should give identical
2302 // results:
2303 //
2304 // rsbs r1, r1, 0
2305 // cmp r0, r1
2306 // mov r0, #0
2307 // it ls
2308 // mov r0, #1
2309 //
2310 // and:
2311 //
2312 // cmn r0, r1
2313 // mov r0, #0
2314 // it ls
2315 // mov r0, #1
2316 //
2317 // However, the CMN gives the *opposite* result when r1 is 0. This is because
2318 // the carry flag is set in the CMP case but not in the CMN case. In short, the
2319 // CMP instruction doesn't perform a truncate of the (logical) NOT of 0 plus the
2320 // value of r0 and the carry bit (because the "carry bit" parameter to
2321 // AddWithCarry is defined as 1 in this case, the carry flag will always be set
2322 // when r0 >= 0). The CMN instruction doesn't perform a NOT of 0 so there is
2323 // never a "carry" when this AddWithCarry is performed (because the "carry bit"
2324 // parameter to AddWithCarry is defined as 0).
2325 //
2326 // The AddWithCarry in the CMP case seems to be relying upon the identity:
2327 //
2328 // ~x + 1 = -x
2329 //
2330 // However when x is 0 and unsigned, this doesn't hold:
2331 //
2332 // x = 0
2333 // ~x = 0xFFFF FFFF
2334 // ~x + 1 = 0x1 0000 0000
2335 // (-x = 0) != (0x1 0000 0000 = ~x + 1)
2336 //
2337 // Therefore, we should disable *all* versions of CMN, especially when comparing
2338 // against zero, until we can limit when the CMN instruction is used (when we
2339 // know that the RHS is not 0) or when we have a hardware fix for this.
2340 //
2341 // (See the ARM docs for the "AddWithCarry" pseudo-code.)
2342 //
2343 // This is related to .
2344 //
23012345 //defm CMN : AI1_cmp_irs<0b1011, "cmn",
23022346 // BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>;
23032347