From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9930 invoked by alias); 5 Aug 2013 21:04:21 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 9844 invoked by uid 48); 5 Aug 2013 21:04:18 -0000 From: "rearnsha at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug target/54829] bad optimization: sub followed by cmp w/ zero (x86 & ARM) Date: Mon, 05 Aug 2013 21:04:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: target X-Bugzilla-Version: 4.7.1 X-Bugzilla-Keywords: missed-optimization X-Bugzilla-Severity: enhancement X-Bugzilla-Who: rearnsha at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2013-08/txt/msg00317.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54829 --- Comment #8 from Richard Earnshaw --- (In reply to Daniel Santos from comment #7) > First off, I apologize for my late response here. > > (In reply to comment #5) > I'm going to respond a little backwards.. > > > In fact, on ARM there is no branch instruction that can be used for "> 0" as a > > side effect of a subtract. To get the desired effect the code would have to be > > completely re-arranged to factor out the "< 0" (bmi) and then "== 0" (beq) > > cases first. > > I'm not an ARM programmer, but I'm looking at my reference book and it would > appear that BGT would perform a branch of greater than for signed comparison > and and BHI for unsigned comparison. Again, convert the subtraction into a > comparison (subtract, but discard the result) and branch based upon the > flags (for signed numbers): > > cmp r0, r1 > bgt .L1 > bne .L2 > ;handle equality here > Unfortunately, computers don't to infinite precision arithmetic by default. That would perform a different comparison in that it checks that r0 > r1, not whether r0 - r1 > 0. The difference, for signed comparisons, is when overflow occurs. Consider the case where (in your original code) a has the value INT_MIN (ie -2147483648) and b has the value 1. Now clearly a < b and by the normal rules of arithmetic (infinite precision) we would expect a - b to be less than zero. However, INT_MIN - 1 cannot be represented in a 32-bit long value and becomes INT_MAX due to overflow; the result is that for these values a - b > 0! On ARM and x86, the flag setting that results from a subtract operation is, in effect a comparison of the original operands, rather than a comparison of the result; that is on ARM subs rd, rn, rm is equivalent to cmp rn, rm except that the register rd is not written by the comparison. Power PC is different: it's subtract and compare instruction really does use the result of the subtraction to form the comparison.