public static StrideConstraint FromExpr(GPUVerifier verifier, Implementation impl, Expr e)
        {
            if (e is LiteralExpr)
            {
                return(new EqStrideConstraint(e));
            }

            var ee = e as BvExtractExpr;

            if (ee != null)
            {
                var sc    = FromExpr(verifier, impl, ee.Bitvector);
                var modsc = sc as ModStrideConstraint;
                if (modsc != null)
                {
                    modsc.mod        = new BvExtractExpr(Token.NoToken, modsc.mod, ee.End, ee.Start);
                    modsc.mod.Type   = e.Type;
                    modsc.modEq      = new BvExtractExpr(Token.NoToken, modsc.modEq, ee.End, ee.Start);
                    modsc.modEq.Type = e.Type;
                    return(modsc);
                }
                else
                {
                    return(sc);
                }
            }

            var ie = e as IdentifierExpr;

            if (ie != null)
            {
                if (GPUVerifier.IsConstantInCurrentRegion(ie))
                {
                    return(new EqStrideConstraint(e));
                }

                var rsa = verifier.reducedStrengthAnalysesRegion[impl];
                var sc  = rsa.GetStrideConstraint(ie.Decl.Name);
                if (sc == null)
                {
                    return(Bottom(verifier, e));
                }
                return(sc);
            }

            Expr lhs, rhs;

            if (verifier.IntRep.IsAdd(e, out lhs, out rhs))
            {
                var lhsc = FromExpr(verifier, impl, lhs);
                var rhsc = FromExpr(verifier, impl, rhs);
                return(BuildAddStrideConstraint(verifier, e, lhsc, rhsc));
            }

            if (verifier.IntRep.IsMul(e, out lhs, out rhs))
            {
                var lhsc = FromExpr(verifier, impl, lhs);
                var rhsc = FromExpr(verifier, impl, rhs);
                return(BuildMulStrideConstraint(verifier, e, lhsc, rhsc));
            }

            return(Bottom(verifier, e));
        }
        public static StrideConstraint FromExpr(GPUVerifier verifier, Implementation impl, Expr e)
        {
            if (e is LiteralExpr)
            {
                return(new EqStrideConstraint(e));
            }

            var ee = e as BvExtractExpr;

            if (ee != null)
            {
                var sc = FromExpr(verifier, impl, ee.Bitvector);

                if (sc is ModStrideConstraint)
                {
                    var modsc = (ModStrideConstraint)sc;
                    modsc = new ModStrideConstraint(
                        new BvExtractExpr(Token.NoToken, modsc.Mod, ee.End, ee.Start),
                        new BvExtractExpr(Token.NoToken, modsc.ModEq, ee.End, ee.Start));
                    modsc.Mod.Type   = e.Type;
                    modsc.ModEq.Type = e.Type;
                    return(modsc);
                }
                else if (sc is EqStrideConstraint)
                {
                    var eqsc = (EqStrideConstraint)sc;
                    eqsc = new EqStrideConstraint(
                        new BvExtractExpr(Token.NoToken, eqsc.Eq, ee.End, ee.Start));
                    eqsc.Eq.Type = e.Type;
                    return(eqsc);
                }
                else
                {
                    throw new NotSupportedException("Stride constraint not supported");
                }
            }

            var ie = e as IdentifierExpr;

            if (ie != null)
            {
                if (GPUVerifier.IsConstantInCurrentRegion(ie))
                {
                    return(new EqStrideConstraint(e));
                }

                var rsa = verifier.ReducedStrengthAnalysesRegion[impl];
                var sc  = rsa.GetStrideConstraint(ie.Decl.Name);

                if (sc == null)
                {
                    return(Bottom(verifier, e));
                }

                return(sc);
            }

            Expr subExpr;

            if (verifier.IntRep.IsSext(e, out subExpr))
            {
                var sc = FromExpr(verifier, impl, subExpr);

                if (sc is ModStrideConstraint)
                {
                    var modsc = (ModStrideConstraint)sc;
                    modsc = new ModStrideConstraint(
                        verifier.IntRep.MakeSext(modsc.Mod, e.Type),
                        verifier.IntRep.MakeSext(modsc.ModEq, e.Type));
                    return(modsc);
                }
                else if (sc is EqStrideConstraint)
                {
                    var eqsc = (EqStrideConstraint)sc;
                    eqsc = new EqStrideConstraint(
                        verifier.IntRep.MakeSext(eqsc.Eq, e.Type));
                    return(eqsc);
                }
                else
                {
                    throw new NotSupportedException("Stride constraint not supported");
                }
            }

            Expr lhs, rhs;

            if (verifier.IntRep.IsAdd(e, out lhs, out rhs))
            {
                var lhsc = FromExpr(verifier, impl, lhs);
                var rhsc = FromExpr(verifier, impl, rhs);
                return(BuildAddStrideConstraint(verifier, e, lhsc, rhsc));
            }

            if (verifier.IntRep.IsMul(e, out lhs, out rhs))
            {
                var lhsc = FromExpr(verifier, impl, lhs);
                var rhsc = FromExpr(verifier, impl, rhs);
                return(BuildMulStrideConstraint(verifier, e, lhsc, rhsc));
            }

            return(Bottom(verifier, e));
        }