From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate.crashing.org (gate.crashing.org [63.228.1.57]) by sourceware.org (Postfix) with ESMTP id B77FD3851AA3 for ; Thu, 7 Jul 2022 22:39:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B77FD3851AA3 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=kernel.crashing.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=kernel.crashing.org Received: from gate.crashing.org (localhost.localdomain [127.0.0.1]) by gate.crashing.org (8.14.1/8.14.1) with ESMTP id 267McYpa020322; Thu, 7 Jul 2022 17:38:34 -0500 Received: (from segher@localhost) by gate.crashing.org (8.14.1/8.14.1/Submit) id 267McXcx020321; Thu, 7 Jul 2022 17:38:33 -0500 X-Authentication-Warning: gate.crashing.org: segher set sender to segher@kernel.crashing.org using -f Date: Thu, 7 Jul 2022 17:38:33 -0500 From: Segher Boessenkool To: Roger Sayle Cc: gcc-patches@gcc.gnu.org Subject: Re: [PATCH] Be careful with MODE_CC in simplify_const_relational_operation. Message-ID: <20220707223833.GA25951@gate.crashing.org> References: <003601d89245$a86f8830$f94e9890$@nextmovesoftware.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <003601d89245$a86f8830$f94e9890$@nextmovesoftware.com> User-Agent: Mutt/1.4.2.3i X-Spam-Status: No, score=-3.2 required=5.0 tests=BAYES_00, JMQ_SPF_NEUTRAL, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Jul 2022 22:39:36 -0000 Hi! On Thu, Jul 07, 2022 at 10:08:04PM +0100, Roger Sayle wrote: > I think it's fair to describe RTL's representation of condition flags > using MODE_CC as a little counter-intuitive. "A little challenging", and you should see that as a good thing, as a puzzle to crack :-) > For example, the i386 > backend represents the carry flag (in adc instructions) using RTL of > the form "(ltu:SI (reg:CCC) (const_int 0))", where great care needs > to be taken not to treat this like a normal RTX expression, after all > LTU (less-than-unsigned) against const0_rtx would normally always be > false. A comparison of a MODE_CC thing against 0 means the result of a *previous* comparison (or other cc setter) is looked at. Usually it simply looks at some condition bits in a flags register. It does not do any actual comparison: that has been done before (if at all even). > Hence, MODE_CC comparisons need to be treated with caution, > and simplify_const_relational_operation returns early (to avoid > problems) when GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC. Not just to avoid problems: there simply isn't enough information to do a correct job. > However, consider the (currently) hypothetical situation, where the > RTL optimizers determine that a previous instruction unconditionally > sets or clears the carry flag, and this gets propagated by combine into > the above expression, we'd end up with something that looks like > (ltu:SI (const_int 1) (const_int 0)), which doesn't mean what it says. > Fortunately, simplify_const_relational_operation is passed the > original mode of the comparison (cmp_mode, the original mode of op0) > which can be checked for MODE_CC, even when op0 is now VOIDmode > (const_int) after the substitution. Defending against this is clearly the > right thing to do. > > More controversially, rather than just abort simplification/optimization > in this case, we can use the comparison operator to infer/select the > semantics of the CC_MODE flag. Hopefully, whenever a backend uses LTU, > it represents the (set) carry flag (and behaves like i386.md), in which > case the result of the simplified expression is the first operand. > [If there's no standardization of semantics across backends, then > we should always just return 0; but then miss potential optimizations]. On PowerPC, ltu means the result of an unsigned comparison (we have instructions for that, cmpl[wd][i] mainly) was "smaller than". It does not mean anything is unsigned smaller than zero. It also has nothing to do with carries, which are done via a different register (the XER). > + /* Handle MODE_CC comparisons that have been simplified to > + constants. */ > + if (GET_MODE_CLASS (mode) == MODE_CC > + && op1 == const0_rtx > + && CONST_INT_P (op0)) > + { > + /* LTU represents the carry flag. */ > + if (code == LTU) > + return op0 == const0_rtx ? const0_rtx : const_true_rtx; > + return 0; > + } > + > /* We can't simplify MODE_CC values since we don't know what the > actual comparison is. */ ^^^ This comment is 100% true. We cannot simplify any MODE_CC comparison without having more context. The combiner does have that context when it tries to combine the CC setter with the CC consumer, for example. Do you have some piece of motivating example code? Segher