From patchwork Thu May 11 23:37:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luc Van Oostenryck X-Patchwork-Id: 9723261 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E92E360364 for ; Thu, 11 May 2017 23:39:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E41ED28745 for ; Thu, 11 May 2017 23:39:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D888228747; Thu, 11 May 2017 23:39:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C609D28745 for ; Thu, 11 May 2017 23:39:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932307AbdEKXjz (ORCPT ); Thu, 11 May 2017 19:39:55 -0400 Received: from mail-wr0-f195.google.com ([209.85.128.195]:33422 "EHLO mail-wr0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932267AbdEKXjz (ORCPT ); Thu, 11 May 2017 19:39:55 -0400 Received: by mail-wr0-f195.google.com with SMTP id w50so5519181wrc.0 for ; Thu, 11 May 2017 16:39:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=ZdNkPc/NgJVqe/d0HKgfzb2jWE2FiXfIBoRteYrFVZ4=; b=M9Oea0EGyosNTJiJcrhR19Fb+h+AXMYE54ksGDdm38gOGjC1sgG1I7yGKmrLKeGpoi kU/dxDdy/NG9BIQIuttwBZBpzOUv4qBS63HvuMU+sFB36CfpaCetGRih9d54V9QkM+gd UIMfvCfOVJDZNeA7ETRa8L0tztdXXngN//d4KZ1hkbDGqVmxZmXQIhkO2IjBNP2K6NnK ks+1OOiqvadbwiu2RV4JpNb4Td2i3G9DLpaS+0yJW+uUjuBW4EUXkvpyXULd9C+yUHbg xM/rgG/VQGhwdMRjfzr+aFIhSGSbdy8SMszri+/rE/13dWW+tHq+qgOeGnZ5TJ/IWP4X VewQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=ZdNkPc/NgJVqe/d0HKgfzb2jWE2FiXfIBoRteYrFVZ4=; b=D8h68nj0tCr7Y6SEiHSMLVhjJgrWGYZx7imVOZz/SRtmmv5+YNAdBg9vesF/euvV0W Sev5+ZPoNnbYK3B7rOJJVcjcyZEGfWD0sF+4mL5Sw/uq4nTj7HQbhzxUw9ov0fDor43j dgBEq8jMobiY+xeSzR+bbdUshe5xo+erGWKiuxbqVKF7rJ9p9A+9yfLm3GBCkfjYyMyt VjboMrM6Kufa0n3v+Fyh6vfNNIhGB6Vl4ydLfCnVm9QOpm2pKtkK/ni56lDEKAG2vuE0 kOi2DhKqZVGoIF6U+e7wGlnO5j+N4rzH0qQ6N9DsjPGOMq+4DEcQM413gdJXEQFQFuNY UB9A== X-Gm-Message-State: AODbwcAtddyS1lvFje6XJveT/apT5YRd5L5owxHsWxjAvwzShJV9gXgb VsEDm1TW3PiQLQ== X-Received: by 10.223.164.148 with SMTP id g20mr666208wrb.89.1494545993383; Thu, 11 May 2017 16:39:53 -0700 (PDT) Received: from localhost.localdomain ([2a02:a03f:8a9:3a00:fdd7:bb97:1eb8:845e]) by smtp.gmail.com with ESMTPSA id a24sm1674200wra.17.2017.05.11.16.39.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 May 2017 16:39:52 -0700 (PDT) From: Luc Van Oostenryck To: linux-sparse@vger.kernel.org Cc: Christopher Li , Luc Van Oostenryck Subject: [PATCH] fix boolean context for OP_AND_BOOL & OP_OR_BOOL Date: Fri, 12 May 2017 01:37:49 +0200 Message-Id: <20170511233749.9500-1-luc.vanoostenryck@gmail.com> X-Mailer: git-send-email 2.12.2 Sender: linux-sparse-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sparse@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Current simplifications of 'x && 1 --> x' and its dual 'x || 0 --> x' are wrong because the '||' and '&&' operators demand that their operands are first compared against zero which then always give a boolean valued result. For example: '3 && 1' is not equal to '3' but to '1' (or 'true'). The correct simplification is thus 'x && 1 --> x != 0' and 'x || 0 --> x != 0'. Fix this by always first doing the comparison against zero before generating the OP_AND_BOOL and OP_OR_BOOL instructions. Note: of course, we could decide that the semantic of OP_AND_BOOL and OP_OR_BOOL is that these ops take care themselves of making a boolean context (which was, I think, why these ops were created) but then these simplifications cannot be done (or when they are done, we need to add the comparison against zero). Fixes: b85ec4bb7f5b1c522d7c71782dbd9cf1c4c49b2f Fixes: a0886db12307d2633b04ec44342099a2955794a5 Signed-off-by: Luc Van Oostenryck --- Note: this patch is essentially a respin of a previous patch but stripped of its dependences on all the LLVM, floating point & optimization changes which will be upstreamed later. linearize.c | 37 +++++++++++++++++++++++++++++++++++-- validation/optim/bool-context.c | 12 ++++++++++++ validation/optim/bool-simplify.c | 8 ++++++-- 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 validation/optim/bool-context.c diff --git a/linearize.c b/linearize.c index a9f36b823..236d37a31 100644 --- a/linearize.c +++ b/linearize.c @@ -1156,6 +1156,26 @@ static int opcode_sign(int opcode, struct symbol *ctype) return opcode; } +static inline pseudo_t add_convert_to_bool(struct entrypoint *ep, pseudo_t src, struct symbol *type) +{ + pseudo_t zero; + int op; + + if (is_bool_type(type)) + return src; + zero = value_pseudo(0); + op = OP_SET_NE; + return add_binary_op(ep, &bool_ctype, op, src, zero); +} + +static pseudo_t linearize_expression_to_bool(struct entrypoint *ep, struct expression *expr) +{ + pseudo_t dst; + dst = linearize_expression(ep, expr); + dst = add_convert_to_bool(ep, dst, expr->ctype); + return dst; +} + static pseudo_t linearize_assignment(struct entrypoint *ep, struct expression *expr) { struct access_data ad = { NULL, }; @@ -1276,6 +1296,19 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi return retval; } +static pseudo_t linearize_binop_bool(struct entrypoint *ep, struct expression *expr) +{ + pseudo_t src1, src2, dst; + int op = (expr->op == SPECIAL_LOGICAL_OR) ? OP_OR_BOOL : OP_AND_BOOL; + + src1 = linearize_expression_to_bool(ep, expr->left); + src2 = linearize_expression_to_bool(ep, expr->right); + dst = add_binary_op(ep, &bool_ctype, op, src1, src2); + if (expr->ctype != &bool_ctype) + dst = cast_pseudo(ep, dst, &bool_ctype, expr->ctype); + return dst; +} + static pseudo_t linearize_binop(struct entrypoint *ep, struct expression *expr) { pseudo_t src1, src2, dst; @@ -1286,8 +1319,6 @@ static pseudo_t linearize_binop(struct entrypoint *ep, struct expression *expr) ['|'] = OP_OR, ['^'] = OP_XOR, [SPECIAL_LEFTSHIFT] = OP_SHL, [SPECIAL_RIGHTSHIFT] = OP_LSR, - [SPECIAL_LOGICAL_AND] = OP_AND_BOOL, - [SPECIAL_LOGICAL_OR] = OP_OR_BOOL, }; int op; @@ -1570,6 +1601,8 @@ pseudo_t linearize_expression(struct entrypoint *ep, struct expression *expr) return linearize_call_expression(ep, expr); case EXPR_BINOP: + if (expr->op == SPECIAL_LOGICAL_AND || expr->op == SPECIAL_LOGICAL_OR) + return linearize_binop_bool(ep, expr); return linearize_binop(ep, expr); case EXPR_LOGICAL: diff --git a/validation/optim/bool-context.c b/validation/optim/bool-context.c new file mode 100644 index 000000000..11326d391 --- /dev/null +++ b/validation/optim/bool-context.c @@ -0,0 +1,12 @@ +#define bool _Bool + +bool bool_ior(int a, int b) { return a || b; } +bool bool_and(int a, int b) { return a && b; } + +/* + * check-name: bool-context + * check-command: test-linearize -Wno-decl $file + * check-output-ignore + * + * check-output-pattern-4-times: setne\\..* %arg[12] + */ diff --git a/validation/optim/bool-simplify.c b/validation/optim/bool-simplify.c index e0ff1c2d4..05be11497 100644 --- a/validation/optim/bool-simplify.c +++ b/validation/optim/bool-simplify.c @@ -32,13 +32,17 @@ and_0: and_1: .L2: - ret.32 %arg1 + setne.1 %r8 <- %arg1, $0 + cast.32 %r11 <- (1) %r8 + ret.32 %r11 or_0: .L4: - ret.32 %arg1 + setne.1 %r14 <- %arg1, $0 + cast.32 %r17 <- (1) %r14 + ret.32 %r17 or_1: