Example #1
0
        /// <summary>
        /// Determine whether <paramref name="instr"/> is a match for
        /// the pattern that is a constant division
        /// </summary>
        /// <remarks>
        /// The pattern is:
        /// <code>
        /// hi:lo = r * const
        /// hi = slice(hi:lo) (alias)
        /// hi = hi >> shift  (optional)
        /// </code>
        /// This transformation must be carried out before value propagation
        /// pushes the shift inside other operations.
        /// </remarks>
        /// <param name="instr"></param>
        /// <returns></returns>
        public bool Match(Instruction instr)
        {
            Assignment       ass;
            SequenceStorage  dst;
            BinaryExpression bin;
            Constant         cRight;

            // Look for hi:lo = a * C
            if (!instr.As(out ass) ||
                !ass.Dst.Storage.As(out dst) ||
                !ass.Src.As(out bin) ||
                !(bin.Operator is IMulOperator) ||
                !bin.Right.As(out cRight) ||
                ass.Dst.DataType.Size <= bin.Left.DataType.Size)
            {
                return(false);
            }

            this.idOrig = ass.Dst;
            this.idDst  = FindAlias(ass.Dst, dst.Head);
            if (idDst == null)
            {
                return(false);
            }

            var best = FindBestRational(cRight.ToUInt32());

            // There may be a subsequent SAR / SHR to increase
            // the divisor.

            var      idSlice = idDst;
            Constant rShift  = null;

            if (idSlice != null)
            {
                rShift = FindShiftUse(idSlice);
                if (rShift != null)
                {
                    best = best / (1 << rShift.ToInt32());
                }
            }
            this.bestRational = best;

            this.dividend = bin.Left;
            return(true);
        }
        /// <summary>
        /// Determine whether <paramref name="instr"/> is a match for 
        /// the pattern that is a constant division
        /// </summary>
        /// <remarks>
        /// The pattern is:
        /// <code>
        /// hi:lo = r * const
        /// hi = slice(hi:lo) (alias)
        /// hi = hi >> shift  (optional)
        /// </code>
        /// This transformation must be carried out before value propagation
        /// pushes the shift inside other operations.
        /// </remarks>
        /// <param name="instr"></param>
        /// <returns></returns>
        public bool Match(Instruction instr)
        {
            Assignment ass;
            SequenceStorage dst;
            BinaryExpression bin;
            Constant cRight;

            // Look for hi:lo = a * C
            if (!instr.As(out ass) ||
                !ass.Dst.Storage.As(out dst) ||
                !ass.Src.As(out bin) ||
                !(bin.Operator is IMulOperator) ||
                !bin.Right.As(out cRight) ||
                ass.Dst.DataType.Size <= bin.Left.DataType.Size)
            {
                return false;
            }

            this.idOrig = ass.Dst;
            this.idDst = FindAlias(ass.Dst, dst.Head);
            if (idDst == null)
                return false;

            var best = FindBestRational(cRight.ToUInt32());

            // There may be a subsequent SAR / SHR to increase 
            // the divisor.

            var idSlice = idDst;
            Constant rShift = null;
            if (idSlice != null)
            {
                rShift = FindShiftUse(idSlice);
                if (rShift != null)
                {
                    best = best / (1 << rShift.ToInt32());
                }
            }
            this.bestRational = best;

            this.dividend = bin.Left;
            return true;
        }