From patchwork Wed Mar 13 21:55:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Diego Novillo X-Patchwork-Id: 227356 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id DA2352C0082 for ; Thu, 14 Mar 2013 08:55:39 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1363816540; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID: MIME-Version:Content-Type:Content-Disposition:User-Agent: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=f2sb7mhQrwlW2JOw9Hfs 8q9r8Us=; b=LJfy8PgMNtIYlBVEcd/Fy2vv3gUDIhBFvCOgJXrKRDZbJ1WAPodK X1+/OYypcusnUam6njpk2v6zKx46YCm2hi4OLH1baXXTz/rW1koPirmF17f94yYf y66h2krMR9wVWowkRzmWJZtMnM8yNjP/8p9ttUlUujBwsl6qGOuuNos= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:X-Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type:Content-Disposition:User-Agent:X-Gm-Message-State:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=BCjZol6l35f3jsGbWGLQRb8fNdzE3wW4HNFWvvDh8AQmXfpUupWKbNYM3vJr4m cGywD+9hoj7dRLHK+7+NtSkZaySy8iUMYZ0jyd3ijOg6WZ+cHZnIK4OL5/nCRMFA BMMqL6jlqq3OOwD1eTUlUJfQHkuuHCtT2UXhAwitrdVD0=; Received: (qmail 11855 invoked by alias); 13 Mar 2013 21:55:29 -0000 Received: (qmail 11847 invoked by uid 22791); 13 Mar 2013 21:55:27 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, KHOP_RCVD_TRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RP_MATCHES_RCVD, TW_CX, TW_TM X-Spam-Check-By: sourceware.org Received: from mail-qe0-f73.google.com (HELO mail-qe0-f73.google.com) (209.85.128.73) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 13 Mar 2013 21:55:20 +0000 Received: by mail-qe0-f73.google.com with SMTP id a11so157233qen.4 for ; Wed, 13 Mar 2013 14:55:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:date:from:to:cc:subject:message-id:mime-version :content-type:content-disposition:organization:user-agent :x-gm-message-state; bh=urEc4hCfLcnbhGVnyyrv2tG9rgsGWyx6JF7zBQzwXP0=; b=XLp/KAKfEggX99QH54dEA7BvFssryne1cKdtBAueGhEGYXSwdj1c6XSaqM8SAX4NOp q6lesR0SIVHLUQf5txA/gGSbHbDBOcDtv7oqctP6dBbfduYvNTC/u4mbz7An1eSwVg4P 2LqSb2WRCQuHozjyKhI31ZxLYsiKgasyhh/WDpgk2UdN5b+sVgU0MDl9yWfWPe97BgDf 7Cw6hO3GLF7bJJucqTpTrlcY7WiYgx6jHnPwaVtkVqsZFgdRTMFDKA3xVyuDUfdr+8jm 9DapFfzDQsT4fANJrtnp7CHjCcbrgF12e9CgUrW7ybU2CKgDaQyielnDh41yjsujZ3/e KmiA== X-Received: by 10.236.103.72 with SMTP id e48mr13262974yhg.36.1363211719259; Wed, 13 Mar 2013 14:55:19 -0700 (PDT) Received: from corp2gmr1-2.hot.corp.google.com (corp2gmr1-2.hot.corp.google.com [172.24.189.93]) by gmr-mx.google.com with ESMTPS id u21si10560yhj.0.2013.03.13.14.55.19 (version=TLSv1.1 cipher=AES128-SHA bits=128/128); Wed, 13 Mar 2013 14:55:19 -0700 (PDT) Received: from torture.tor.corp.google.com (torture.tor.corp.google.com [172.30.222.16]) by corp2gmr1-2.hot.corp.google.com (Postfix) with ESMTP id 0E1925A4217; Wed, 13 Mar 2013 14:55:19 -0700 (PDT) Received: by torture.tor.corp.google.com (Postfix, from userid 54752) id E7A11C07B2; Wed, 13 Mar 2013 17:55:17 -0400 (EDT) Date: Wed, 13 Mar 2013 17:55:17 -0400 From: Diego Novillo To: gcc-patches@gcc.gnu.org Cc: Lawrence Crowl , David Li , Richard Biener Subject: [cxx-conversion] RFC - Helper types for building GIMPLE Message-ID: <20130313215516.GA29289@google.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Gm-Message-State: ALoCoQnkrI34IWMqzPKWy+AzgH7pU2bHA+sFAQzf9O1SEJKnd4KX2o60m34RR2wr6/tNTb46NPpLmO5Ab65pnv5e6e2oWZaiYbJ35zFdmfY9XFBRyP2K8oxYwwZngGMPc/enofsk8LIUoQ8HONypT/ET/lkZcQ9WynGu9pVzxbDa7wgWFG2IHkTO7HheQ3c0dNSauIFJR3kwDubrGBY8ubNcbBFX1LIXODV7aGQUGqVlTOTgHq0E93Q= X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch adds an initial implementation for a new helper type for generating GIMPLE statements. The type is called gimple_builder. There are two main variants: gimple_builder_normal and gimple_builder_ssa. The difference between the two is the temporaries they create. The 'normal' builder creates temporaries in normal form (i.e., VAR_DECLs). The 'ssa' builder creates SSA names. The basic functionality is described in http://gcc.gnu.org/wiki/cxx-conversion/gimple-generation. I expect it to evolve as I address feedback on this initial implementation. The patch implements the initial builder. It has enough functionality to simplify the generation of 3 address assignments (the bulk of all generated code). To use the builder: 1- Declare an instance 'gb' of gimple_builder_normal or gimple_builder_ssa. E.g., gimple_builder_ssa gb; 2- Use gb.add_* to add a new statement to it. This returns an SSA name or VAR_DECL with the value of the added statement. 3- Call gb.insert_*() to insert the sequence of statements in the builder into a statement iterator. For instance, in asan.c we generate the expression: (shadow != 0) & (base_addr & 7) + (size_in_bytes - 1)) >= shadow). with the following code: ----------------------------------------------------------------------------- gimple_builder_ssa gb(location); t = gb.add (NE_EXPR, shadow, 0); tree t1 = gb.add (BIT_AND_EXPR, base_addr, 7); t1 = gb.add_type_cast (shadow_type, t1); if (size_in_bytes > 1) t1 = gb.add (PLUS_EXPR, t1, size_in_bytes - 1); t1 = gb.add (GE_EXPR, t1, shadow); t = gb.add (BIT_AND_EXPR, t, t1); gb.insert_after (&gsi, GSI_NEW_STMT); ----------------------------------------------------------------------------- In contrast, the original code needed to generate the same expression is significantly longer: ----------------------------------------------------------------------------- g = gimple_build_assign_with_ops (NE_EXPR, make_ssa_name (boolean_type_node, NULL), shadow, build_int_cst (shadow_type, 0)); gimple_set_location (g, location); gsi_insert_after (&gsi, g, GSI_NEW_STMT); t = gimple_assign_lhs (g); g = gimple_build_assign_with_ops (BIT_AND_EXPR, make_ssa_name (uintptr_type, NULL), base_addr, build_int_cst (uintptr_type, 7)); gimple_set_location (g, location); gsi_insert_after (&gsi, g, GSI_NEW_STMT); g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (shadow_type, NULL), gimple_assign_lhs (g), NULL_TREE); gimple_set_location (g, location); gsi_insert_after (&gsi, g, GSI_NEW_STMT); if (size_in_bytes > 1) { g = gimple_build_assign_with_ops (PLUS_EXPR, make_ssa_name (shadow_type, NULL), gimple_assign_lhs (g), build_int_cst (shadow_type, size_in_bytes - 1)); gimple_set_location (g, location); gsi_insert_after (&gsi, g, GSI_NEW_STMT); } g = gimple_build_assign_with_ops (GE_EXPR, make_ssa_name (boolean_type_node, NULL), gimple_assign_lhs (g), shadow); gimple_set_location (g, location); gsi_insert_after (&gsi, g, GSI_NEW_STMT); g = gimple_build_assign_with_ops (BIT_AND_EXPR, make_ssa_name (boolean_type_node, NULL), t, gimple_assign_lhs (g)); gimple_set_location (g, location); gsi_insert_after (&gsi, g, GSI_NEW_STMT); t = gimple_assign_lhs (g); ----------------------------------------------------------------------------- I expect to add more facilities to the builder. Mainly, generation of control flow altering statements which will automatically reflect on the CFG. I do not think the helper should replace all code generation, but it should serve as a shorter/simpler way of generating GIMPLE IL in the common cases. Feedback welcome. I would like to consider adding this facility when stage 1 opens. In the meantime, I've committed the patch to the cxx-conversion branch. Thanks. Diego. diff --git a/gcc/asan.c b/gcc/asan.c index af9c01e..571882a 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1379,57 +1379,15 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter, /* Slow path for 1, 2 and 4 byte accesses. Test (shadow != 0) & ((base_addr & 7) + (size_in_bytes - 1)) >= shadow). */ - g = gimple_build_assign_with_ops (NE_EXPR, - make_ssa_name (boolean_type_node, - NULL), - shadow, - build_int_cst (shadow_type, 0)); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - t = gimple_assign_lhs (g); - - g = gimple_build_assign_with_ops (BIT_AND_EXPR, - make_ssa_name (uintptr_type, - NULL), - base_addr, - build_int_cst (uintptr_type, 7)); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - - g = gimple_build_assign_with_ops (NOP_EXPR, - make_ssa_name (shadow_type, - NULL), - gimple_assign_lhs (g), NULL_TREE); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - + gimple_builder_ssa gb(location); + t = gb.add (NE_EXPR, shadow, 0); + tree t1 = gb.add (BIT_AND_EXPR, base_addr, 7); + t1 = gb.add_type_cast (shadow_type, t1); if (size_in_bytes > 1) - { - g = gimple_build_assign_with_ops (PLUS_EXPR, - make_ssa_name (shadow_type, - NULL), - gimple_assign_lhs (g), - build_int_cst (shadow_type, - size_in_bytes - 1)); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - } - - g = gimple_build_assign_with_ops (GE_EXPR, - make_ssa_name (boolean_type_node, - NULL), - gimple_assign_lhs (g), - shadow); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - - g = gimple_build_assign_with_ops (BIT_AND_EXPR, - make_ssa_name (boolean_type_node, - NULL), - t, gimple_assign_lhs (g)); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - t = gimple_assign_lhs (g); + t1 = gb.add (PLUS_EXPR, t1, size_in_bytes - 1); + t1 = gb.add (GE_EXPR, t1, shadow); + t = gb.add (BIT_AND_EXPR, t, t1); + gb.insert_after (&gsi, GSI_NEW_STMT); } else t = shadow; diff --git a/gcc/gimple.c b/gcc/gimple.c index 785c2f0..c4687df 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -4210,4 +4210,115 @@ gimple_asm_clobbers_memory_p (const_gimple stmt) return false; } + + +/* Return the expression type to use based on the CODE and type of + the given operand OP. If the expression CODE is a comparison, + the returned type is boolean_type_node. Otherwise, it returns + the type of OP. */ + +tree +gimple_builder_base::get_expr_type (enum tree_code code, tree op) +{ + return (TREE_CODE_CLASS (code) == tcc_comparison) + ? boolean_type_node + : TREE_TYPE (op); +} + + +/* Add a new assignment to this GIMPLE sequence. The assignment has + the form: GIMPLE_ASSIGN . Returns LHS. */ + +tree +gimple_builder_base::add (enum tree_code code, tree lhs, tree op1, tree op2) +{ + gimple s = gimple_build_assign_with_ops (code, lhs, op1, op2); + gimple_seq_add_stmt (&seq_, s); + return lhs; +} + + +/* Add a new assignment to this GIMPLE sequence. The new assignment will + have the opcode CODE and operands OP1 and OP2. The type of the + expression on the RHS is inferred to be the type of OP1. + + The LHS of the statement will be an SSA name or a GIMPLE temporary + in normal form depending on the type of builder invoking this + function. */ + +tree +gimple_builder_base::add (enum tree_code code, tree op1, tree op2) +{ + tree lhs = create_lhs_for_assignment (get_expr_type (code, op1)); + return add (code, lhs, op1, op2); +} + + +/* Add a new assignment to this GIMPLE sequence. The new + assignment will have the opcode CODE and operands OP1 and VAL. + VAL is converted into a an INTEGER_CST of the same type as OP1. + + The LHS of the statement will be an SSA name or a GIMPLE temporary + in normal form depending on the type of builder invoking this + function. */ + +tree +gimple_builder_base::add (enum tree_code code, tree op1, int val) +{ + tree type = get_expr_type (code, op1); + tree op2 = build_int_cst (TREE_TYPE (op1), val); + tree lhs = create_lhs_for_assignment (type); + return add (code, lhs, op1, op2); +} + + +/* Add a type cast assignment to this GIMPLE sequence. This creates a NOP_EXPR + that converts OP to TO_TYPE. Return the LHS of the generated assignment. */ + +tree +gimple_builder_base::add_type_cast (tree to_type, tree op) +{ + tree lhs = create_lhs_for_assignment (to_type); + return add (NOP_EXPR, lhs, op, NULL_TREE); +} + + +/* Insert this sequence after the statement pointed-to by iterator I. + MODE is an is gs_insert_after. Scan the statements in SEQ for new + operands. */ + +void +gimple_builder_base::insert_after (gimple_stmt_iterator *i, + enum gsi_iterator_update mode) +{ + /* Since we are inserting a sequence, the semantics for GSI_NEW_STMT + are not quite what the caller is expecting. GSI_NEW_STMT will + leave the iterator pointing to the *first* statement of this + sequence. Rather, we want the iterator to point to the *last* + statement in the sequence. Therefore, we use + GSI_CONTINUE_LINKING when GSI_NEW_STMT is requested. */ + if (mode == GSI_NEW_STMT) + mode = GSI_CONTINUE_LINKING; + gsi_insert_seq_after (i, seq_, mode); +} + + +/* Create a GIMPLE temporary type TYPE to be used as the LHS of an + assignment. */ + +tree +gimple_builder_normal::create_lhs_for_assignment (tree type) +{ + return create_tmp_var (type, NULL); +} + + +/* Create an SSA name of type TYPE to be used as the LHS of an assignment. */ + +tree +gimple_builder_ssa::create_lhs_for_assignment (tree type) +{ + return make_ssa_name (type, NULL); +} + #include "gt-gimple.h" diff --git a/gcc/gimple.h b/gcc/gimple.h index 204c3c9..7b5e741 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -5393,4 +5393,57 @@ extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree, enum tree_code, tree, tree); bool gimple_val_nonnegative_real_p (tree); + + +/* GIMPLE builder class. This type provides a simplified interface + for generating new GIMPLE statements. */ + +class gimple_builder_base +{ +public: + tree add (enum tree_code, tree, tree); + tree add (enum tree_code, tree, int); + tree add (enum tree_code, tree, tree, tree); + tree add_type_cast (tree, tree); + void insert_after (gimple_stmt_iterator *, enum gsi_iterator_update); + +protected: + gimple_builder_base() : seq_(NULL), loc_(UNKNOWN_LOCATION) {} + gimple_builder_base(location_t l) : seq_(NULL), loc_(l) {} + tree get_expr_type (enum tree_code code, tree op); + virtual tree create_lhs_for_assignment (tree) = 0; + +private: + gimple_seq seq_; + location_t loc_; +}; + + +/* GIMPLE builder class for statements in normal form. Statements generated + by instances of this class will produce non-SSA temporaries. */ + +class gimple_builder_normal : public gimple_builder_base +{ +public: + gimple_builder_normal() : gimple_builder_base() {} + gimple_builder_normal(location_t l) : gimple_builder_base(l) {} + +protected: + virtual tree create_lhs_for_assignment (tree); +}; + + +/* GIMPLE builder class for statements in normal form. Statements generated + by instances of this class will produce SSA names. */ + +class gimple_builder_ssa : public gimple_builder_base +{ +public: + gimple_builder_ssa() : gimple_builder_base() {} + gimple_builder_ssa(location_t l) : gimple_builder_base(l) {} + +protected: + virtual tree create_lhs_for_assignment (tree); +}; + #endif /* GCC_GIMPLE_H */