From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id D4B9C3858C54 for ; Wed, 8 Mar 2023 08:57:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D4B9C3858C54 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1678265840; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZT6l5meDTIBoiRv96k3clNmTv/N24H+eJTv4E9IIFdk=; b=eZPeuqsEwJuCVB15WCqizMX2sUtz8puIBFVMzdo6ToZR7T5D0j/+lynN3BFIRHV9MCo+wp B/OZjYzHJrJos1ZAiHCFDv3w5KmcRKVZpQclAiJHHMiUupe4omichYTW08ExMBGp83BbN/ YOV/C2/CNzfMaxGfyg/VrDNAFRWvan0= Received: from mail-ed1-f69.google.com (mail-ed1-f69.google.com [209.85.208.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-522-ROLlrMqvNg2GGeGVDwGCaQ-1; Wed, 08 Mar 2023 03:57:19 -0500 X-MC-Unique: ROLlrMqvNg2GGeGVDwGCaQ-1 Received: by mail-ed1-f69.google.com with SMTP id u10-20020a056402064a00b004c689813557so22638934edx.10 for ; Wed, 08 Mar 2023 00:57:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678265838; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZT6l5meDTIBoiRv96k3clNmTv/N24H+eJTv4E9IIFdk=; b=aLwblTfMowXJ3uDZP5ERhdKyfrzOSOYtFJZtIFZ2/VWKH3nVQTgAzJoZQiGVov4y92 SupFprtVGpNnknQLtOEcwMCPgkNDjWOXp6CAosDAqawTwh4N30ONRf/orP2cgqTNKSqj Z6dfNrYeCJdv8uaqKeKws7bncQC2oBQCVgPV3xg3gOTFXD8aYzGYe6Oj6fCij/S/qKXF Cmi48zD71/l5K1C4BL7Ch50IIBytGmkKhaYsz1pyX+zSJYb14Ir1VLpPUl8p40yD0GU5 P7oOBUdbMI8FPyt3RNOkla7DpGQSW38RDAYVq6JfT246010fs8kq6+EyUSKXC7NI6k98 vVTA== X-Gm-Message-State: AO0yUKU/tRocCL1i3iZjp5/hcBcJwCMIl/ZZqorgYcp+7NWLHlYrm5K/ +ykGFFb90SQFXMc9vwr3xSY8MeJqLjyANuR/OSbb3Mj1iQYbz8c78qPabm/Smkk7vOoC1Fsv3gu FI6FNKXXRx4V+3DLiurR24zyg1Vvy9hunUw== X-Received: by 2002:a17:906:9143:b0:8ad:d366:54c4 with SMTP id y3-20020a170906914300b008add36654c4mr12178840ejw.4.1678265838174; Wed, 08 Mar 2023 00:57:18 -0800 (PST) X-Google-Smtp-Source: AK7set/Z/m/mWp8Kthqb/fMex6PfWCyVn0FLH4LHX6GXMwiDT/BMyDUlyt+tG/DaNxUNBK/gjSfGEmJH/SsYewpY7Ag= X-Received: by 2002:a17:906:9143:b0:8ad:d366:54c4 with SMTP id y3-20020a170906914300b008add36654c4mr12178832ejw.4.1678265837867; Wed, 08 Mar 2023 00:57:17 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Aldy Hernandez Date: Wed, 8 Mar 2023 09:57:06 +0100 Message-ID: Subject: Re: [PATCH 2/4][ranger]: Add range-ops for widen addition and widen multiplication [PR108583] To: Tamar Christina Cc: "gcc-patches@gcc.gnu.org" , nd , "amacleod@redhat.com" X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_LOTSOFHASH,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: As Andrew has been advising on this one, I'd prefer for him to review it. However, he's on vacation this week. FYI... Aldy On Mon, Mar 6, 2023 at 12:22=E2=80=AFPM Tamar Christina wrote: > > Ping. > > And updated the patch to reject cases that we don't expect or can handle = cleanly for now. > > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues. > > Ok for master? > > Thanks, > Tamar > > gcc/ChangeLog: > > PR target/108583 > * gimple-range-op.h (gimple_range_op_handler): Add maybe_non_stan= dard. > * gimple-range-op.cc (gimple_range_op_handler::gimple_range_op_ha= ndler): > Use it. > (gimple_range_op_handler::maybe_non_standard): New. > * range-op.cc (class operator_widen_plus_signed, > operator_widen_plus_signed::wi_fold, class operator_widen_plus_un= signed, > operator_widen_plus_unsigned::wi_fold, class operator_widen_mult_= signed, > operator_widen_mult_signed::wi_fold, class operator_widen_mult_un= signed, > operator_widen_mult_unsigned::wi_fold, > ptr_op_widen_mult_signed, ptr_op_widen_mult_unsigned, > ptr_op_widen_plus_signed, ptr_op_widen_plus_unsigned): New. > * range-op.h (ptr_op_widen_mult_signed, ptr_op_widen_mult_unsigne= d, > ptr_op_widen_plus_signed, ptr_op_widen_plus_unsigned): New > > Co-Authored-By: Andrew MacLeod > > --- Inline copy of patch --- > > diff --git a/gcc/gimple-range-op.h b/gcc/gimple-range-op.h > index 743b858126e333ea9590c0f175aacb476260c048..1bf63c5ce6f5db924a1f5907a= b4539e376281bd0 100644 > --- a/gcc/gimple-range-op.h > +++ b/gcc/gimple-range-op.h > @@ -41,6 +41,7 @@ public: > relation_trio =3D TRIO_VARYING); > private: > void maybe_builtin_call (); > + void maybe_non_standard (); > gimple *m_stmt; > tree m_op1, m_op2; > }; > diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc > index d9dfdc56939bb62ade72726b15c3d5e87e4ddcd1..a5d625387e712c170e1e68f6a= 7d494027f6ef0d0 100644 > --- a/gcc/gimple-range-op.cc > +++ b/gcc/gimple-range-op.cc > @@ -179,6 +179,8 @@ gimple_range_op_handler::gimple_range_op_handler (gim= ple *s) > // statements. > if (is_a (m_stmt)) > maybe_builtin_call (); > + else > + maybe_non_standard (); > } > > // Calculate what we can determine of the range of this unary > @@ -764,6 +766,57 @@ public: > } > } op_cfn_parity; > > +// Set up a gimple_range_op_handler for any nonstandard function which c= an be > +// supported via range-ops. > + > +void > +gimple_range_op_handler::maybe_non_standard () > +{ > + range_operator *signed_op =3D ptr_op_widen_mult_signed; > + range_operator *unsigned_op =3D ptr_op_widen_mult_unsigned; > + if (gimple_code (m_stmt) =3D=3D GIMPLE_ASSIGN) > + switch (gimple_assign_rhs_code (m_stmt)) > + { > + case WIDEN_PLUS_EXPR: > + { > + signed_op =3D ptr_op_widen_plus_signed; > + unsigned_op =3D ptr_op_widen_plus_unsigned; > + } > + gcc_fallthrough (); > + case WIDEN_MULT_EXPR: > + { > + m_valid =3D false; > + m_op1 =3D gimple_assign_rhs1 (m_stmt); > + m_op2 =3D gimple_assign_rhs2 (m_stmt); > + tree ret =3D gimple_assign_lhs (m_stmt); > + bool signed1 =3D TYPE_SIGN (TREE_TYPE (m_op1)) =3D=3D SIGNED; > + bool signed2 =3D TYPE_SIGN (TREE_TYPE (m_op2)) =3D=3D SIGNED; > + bool signed_ret =3D TYPE_SIGN (TREE_TYPE (ret)) =3D=3D SIGNED; > + > + /* Normally these operands should all have the same sign, but > + some passes and violate this by taking mismatched sign args.= At > + the moment the only one that's possible is mismatch inputs a= nd > + unsigned output. Once ranger supports signs for the operand= s we > + can properly fix it, for now only accept the case we can do > + correctly. */ > + if ((signed1 ^ signed2) && signed_ret) > + return; > + > + m_valid =3D true; > + if (signed2 && !signed1) > + std::swap (m_op1, m_op2); > + > + if (signed1 || signed2) > + m_int =3D signed_op; > + else > + m_int =3D unsigned_op; > + break; > + } > + default: > + break; > + } > +} > + > // Set up a gimple_range_op_handler for any built in function which can = be > // supported via range-ops. > > diff --git a/gcc/range-op.h b/gcc/range-op.h > index f00b747f08a1fa8404c63bfe5a931b4048008b03..b1eeac70df81f2bdf228af7ad= ff5399e7ac5e5d6 100644 > --- a/gcc/range-op.h > +++ b/gcc/range-op.h > @@ -311,4 +311,8 @@ private: > // This holds the range op table for floating point operations. > extern floating_op_table *floating_tree_table; > > +extern range_operator *ptr_op_widen_mult_signed; > +extern range_operator *ptr_op_widen_mult_unsigned; > +extern range_operator *ptr_op_widen_plus_signed; > +extern range_operator *ptr_op_widen_plus_unsigned; > #endif // GCC_RANGE_OP_H > diff --git a/gcc/range-op.cc b/gcc/range-op.cc > index 5c67bce6d3aab81ad3186b902e09d6a96878d9bb..718ccb6f074e1a2a9ef1b7a5d= 4e879898d4a7fc3 100644 > --- a/gcc/range-op.cc > +++ b/gcc/range-op.cc > @@ -1556,6 +1556,73 @@ operator_plus::op2_range (irange &r, tree type, > return op1_range (r, type, lhs, op1, rel.swap_op1_op2 ()); > } > > +class operator_widen_plus_signed : public range_operator > +{ > +public: > + virtual void wi_fold (irange &r, tree type, > + const wide_int &lh_lb, > + const wide_int &lh_ub, > + const wide_int &rh_lb, > + const wide_int &rh_ub) const; > +} op_widen_plus_signed; > +range_operator *ptr_op_widen_plus_signed =3D &op_widen_plus_signed; > + > +void > +operator_widen_plus_signed::wi_fold (irange &r, tree type, > + const wide_int &lh_lb, > + const wide_int &lh_ub, > + const wide_int &rh_lb, > + const wide_int &rh_ub) const > +{ > + wi::overflow_type ov_lb, ov_ub; > + signop s =3D TYPE_SIGN (type); > + > + wide_int lh_wlb > + =3D wide_int::from (lh_lb, wi::get_precision (lh_lb) * 2, SIGNED); > + wide_int lh_wub > + =3D wide_int::from (lh_ub, wi::get_precision (lh_ub) * 2, SIGNED); > + wide_int rh_wlb =3D wide_int::from (rh_lb, wi::get_precision (rh_lb) = * 2, s); > + wide_int rh_wub =3D wide_int::from (rh_ub, wi::get_precision (rh_ub) = * 2, s); > + > + wide_int new_lb =3D wi::add (lh_wlb, rh_wlb, s, &ov_lb); > + wide_int new_ub =3D wi::add (lh_wub, rh_wub, s, &ov_ub); > + > + r =3D int_range<2> (type, new_lb, new_ub); > +} > + > +class operator_widen_plus_unsigned : public range_operator > +{ > +public: > + virtual void wi_fold (irange &r, tree type, > + const wide_int &lh_lb, > + const wide_int &lh_ub, > + const wide_int &rh_lb, > + const wide_int &rh_ub) const; > +} op_widen_plus_unsigned; > +range_operator *ptr_op_widen_plus_unsigned =3D &op_widen_plus_unsigned; > + > +void > +operator_widen_plus_unsigned::wi_fold (irange &r, tree type, > + const wide_int &lh_lb, > + const wide_int &lh_ub, > + const wide_int &rh_lb, > + const wide_int &rh_ub) const > +{ > + wi::overflow_type ov_lb, ov_ub; > + signop s =3D TYPE_SIGN (type); > + > + wide_int lh_wlb > + =3D wide_int::from (lh_lb, wi::get_precision (lh_lb) * 2, UNSIGNED)= ; > + wide_int lh_wub > + =3D wide_int::from (lh_ub, wi::get_precision (lh_ub) * 2, UNSIGNED)= ; > + wide_int rh_wlb =3D wide_int::from (rh_lb, wi::get_precision (rh_lb) = * 2, s); > + wide_int rh_wub =3D wide_int::from (rh_ub, wi::get_precision (rh_ub) = * 2, s); > + > + wide_int new_lb =3D wi::add (lh_wlb, rh_wlb, s, &ov_lb); > + wide_int new_ub =3D wi::add (lh_wub, rh_wub, s, &ov_ub); > + > + r =3D int_range<2> (type, new_lb, new_ub); > +} > > class operator_minus : public range_operator > { > @@ -2031,6 +2098,70 @@ operator_mult::wi_fold (irange &r, tree type, > } > } > > +class operator_widen_mult_signed : public range_operator > +{ > +public: > + virtual void wi_fold (irange &r, tree type, > + const wide_int &lh_lb, > + const wide_int &lh_ub, > + const wide_int &rh_lb, > + const wide_int &rh_ub) > + const; > +} op_widen_mult_signed; > +range_operator *ptr_op_widen_mult_signed =3D &op_widen_mult_signed; > + > +void > +operator_widen_mult_signed::wi_fold (irange &r, tree type, > + const wide_int &lh_lb, > + const wide_int &lh_ub, > + const wide_int &rh_lb, > + const wide_int &rh_ub) const > +{ > + signop s =3D TYPE_SIGN (type); > + > + wide_int lh_wlb =3D wide_int::from (lh_lb, wi::get_precision (lh_lb) *= 2, SIGNED); > + wide_int lh_wub =3D wide_int::from (lh_ub, wi::get_precision (lh_ub) *= 2, SIGNED); > + wide_int rh_wlb =3D wide_int::from (rh_lb, wi::get_precision (rh_lb) *= 2, s); > + wide_int rh_wub =3D wide_int::from (rh_ub, wi::get_precision (rh_ub) *= 2, s); > + > + /* We don't expect a widening multiplication to be able to overflow bu= t range > + calculations for multiplications are complicated. After widening t= he > + operands lets call the base class. */ > + return op_mult.wi_fold (r, type, lh_wlb, lh_wub, rh_wlb, rh_wub); > +} > + > + > +class operator_widen_mult_unsigned : public range_operator > +{ > +public: > + virtual void wi_fold (irange &r, tree type, > + const wide_int &lh_lb, > + const wide_int &lh_ub, > + const wide_int &rh_lb, > + const wide_int &rh_ub) > + const; > +} op_widen_mult_unsigned; > +range_operator *ptr_op_widen_mult_unsigned =3D &op_widen_mult_unsigned; > + > +void > +operator_widen_mult_unsigned::wi_fold (irange &r, tree type, > + const wide_int &lh_lb, > + const wide_int &lh_ub, > + const wide_int &rh_lb, > + const wide_int &rh_ub) const > +{ > + signop s =3D TYPE_SIGN (type); > + > + wide_int lh_wlb =3D wide_int::from (lh_lb, wi::get_precision (lh_lb) *= 2, UNSIGNED); > + wide_int lh_wub =3D wide_int::from (lh_ub, wi::get_precision (lh_ub) *= 2, UNSIGNED); > + wide_int rh_wlb =3D wide_int::from (rh_lb, wi::get_precision (rh_lb) *= 2, s); > + wide_int rh_wub =3D wide_int::from (rh_ub, wi::get_precision (rh_ub) *= 2, s); > + > + /* We don't expect a widening multiplication to be able to overflow bu= t range > + calculations for multiplications are complicated. After widening t= he > + operands lets call the base class. */ > + return op_mult.wi_fold (r, type, lh_wlb, lh_wub, rh_wlb, rh_wub); > +} > > class operator_div : public cross_product_operator > { >