From patchwork Wed Apr 12 19:33:39 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: 9678273 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 66010601C3 for ; Wed, 12 Apr 2017 19:33:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 546862861B for ; Wed, 12 Apr 2017 19:33:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 481C328644; Wed, 12 Apr 2017 19:33: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 B04B12861B for ; Wed, 12 Apr 2017 19:33:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755120AbdDLTd4 (ORCPT ); Wed, 12 Apr 2017 15:33:56 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:35129 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755092AbdDLTdy (ORCPT ); Wed, 12 Apr 2017 15:33:54 -0400 Received: by mail-wm0-f68.google.com with SMTP id d79so8562516wmi.2 for ; Wed, 12 Apr 2017 12:33:53 -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:in-reply-to:references; bh=GFzxPvbHTNebVK8S9Y1e0FBia0TXDMBYV7VhyB4DPW0=; b=GWdZGpio5meAy0NWgnG2REha44Elnt/avSBHQEvtI0l5LKlIZLyPR65upVDPdIFdLo KTVGftO08O3t0kHrzyPJAfDIMTykD+ZS5ZGSJdcxyTNrPoTInOaRCm0RdvxFGPM/lpe4 DApJ4GLyciUnJDXvVbwcZ0qX5hoFjsQddclg4exfu4YXDNl7ol5CEUA3h+9FxkPGHaDR TySqDxu+wGyRDIHlDs9bkXzD8jyW/MSf+cw2ij6q6k12ImT/F7Mst+xoJkbBnnOag0sG Jz0xmcuZnAdGgFPSBu+hYOMlaixcjkfbU51zKM66iq9hjxlOLRoyV3JjEJmaWeH8pMri QUKA== 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:in-reply-to :references; bh=GFzxPvbHTNebVK8S9Y1e0FBia0TXDMBYV7VhyB4DPW0=; b=XS4cO+s2X7PnkGtlFEo4BCqBfvDJRQh1hpuf2JScQyrKaV/zL2zt5T2ZGGHrUU98ev PFH9pyyjea6wKIyDoIOc2+XRYhefi5A+sVaX8QAHrMyHlbxhw8XM/O7KgxDNBih2Xv+E 1m0atAOGwG0/sq/ljxbkirx13gW2XARGhjr/+bZ5aXX9pBViY4Rp7SoynYXO8UqDrNL/ dinHMvJIol2ZtsqeR8owSh94VZjstPbHzYqhUq/Q3W7ltF6qvR1u2/STyrLC9oIwrWAD R4YNOC+PfJiDTbbm7O/zKdLvsHsUjxa9BPK2UkGeTOqZJKBGmHH5B5Clv/gZ1wBJaAiI x+yg== X-Gm-Message-State: AN3rC/5VxOtfeOuCjI1hEFTLnL0PTC5WSNy8drz8IU/G3QWVOSBehz2b 6qLpDZKoQhfo1w== X-Received: by 10.28.137.208 with SMTP id l199mr20468680wmd.65.1492025632907; Wed, 12 Apr 2017 12:33:52 -0700 (PDT) Received: from localhost.localdomain ([2a02:a03f:8b2:dc00:6c54:829e:388a:2472]) by smtp.gmail.com with ESMTPSA id h20sm7733401wmd.29.2017.04.12.12.33.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 12 Apr 2017 12:33:52 -0700 (PDT) From: Luc Van Oostenryck To: linux-sparse@vger.kernel.org Cc: Christopher Li , Luc Van Oostenryck Subject: [PATCH 1/6] fix boolean context for OP_AND_BOOL & OP_OR_BOOL Date: Wed, 12 Apr 2017 21:33:39 +0200 Message-Id: <20170412193344.95935-2-luc.vanoostenryck@gmail.com> X-Mailer: git-send-email 2.12.0 In-Reply-To: <20170412193344.95935-1-luc.vanoostenryck@gmail.com> References: <20170412193344.95935-1-luc.vanoostenryck@gmail.com> 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 simplification 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'. 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 I think was 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 --- linearize.c | 42 +++++++++++++++++++++++++++++++-- validation/optim/bool-context-fp.c | 48 ++++++++++++++++++++++++++++++++++++++ validation/optim/bool-context.c | 12 ++++++++++ validation/optim/bool-simplify.c | 8 +++++-- 4 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 validation/optim/bool-context.c diff --git a/linearize.c b/linearize.c index 9fda0a1ad..e730ab56f 100644 --- a/linearize.c +++ b/linearize.c @@ -1209,6 +1209,31 @@ static int map_opcode(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; + if (is_float_type(type)) { + zero = add_setfval(ep, type, 0.0); + op = map_opcode(OP_SET_NE, type); + } else { + 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, }; @@ -1351,6 +1376,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; @@ -1361,8 +1399,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; @@ -1647,6 +1683,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-fp.c b/validation/optim/bool-context-fp.c index ad075c56e..6b3e8d181 100644 --- a/validation/optim/bool-context-fp.c +++ b/validation/optim/bool-context-fp.c @@ -5,6 +5,10 @@ bool bfexp(float a) { return (bool)a; } bool bfnot(float a) { return !a; } int ifnot(float a) { return !a; } +bool bfior(float a, float b) { return a || b; } +int ifior(float a, float b) { return a || b; } +bool bfand(float a, float b) { return a && b; } +int ifand(float a, float b) { return a && b; } /* * check-name: bool context fp @@ -43,5 +47,49 @@ ifnot: ret.32 %r16 +bfior: +.L8: + + setfval.32 %r19 <- 0.000000 + fcmpune.1 %r20 <- %arg1, %r19 + fcmpune.1 %r23 <- %arg2, %r19 + or-bool.1 %r24 <- %r23, %r20 + setne.1 %r26 <- %r24, $0 + ret.1 %r26 + + +ifior: +.L10: + + setfval.32 %r29 <- 0.000000 + fcmpune.1 %r30 <- %arg1, %r29 + fcmpune.1 %r33 <- %arg2, %r29 + or-bool.1 %r34 <- %r33, %r30 + cast.32 %r35 <- (1) %r34 + ret.32 %r35 + + +bfand: +.L12: + + setfval.32 %r38 <- 0.000000 + fcmpune.1 %r39 <- %arg1, %r38 + fcmpune.1 %r42 <- %arg2, %r38 + and-bool.1 %r43 <- %r42, %r39 + setne.1 %r45 <- %r43, $0 + ret.1 %r45 + + +ifand: +.L14: + + setfval.32 %r48 <- 0.000000 + fcmpune.1 %r49 <- %arg1, %r48 + fcmpune.1 %r52 <- %arg2, %r48 + and-bool.1 %r53 <- %r52, %r49 + cast.32 %r54 <- (1) %r53 + ret.32 %r54 + + * check-output-end */ 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: