Replace usage of fractions.gcd with a conditional that uses math.gcd if
it is available and which falls back to fractions.gcd if it is not. This
allows the code to work in Python 3.9+ where the deprecated
fractions.gcd function was removed.

If support for versions of Python older than 3.5 is dropped then this
code could be simplified to just use math.gcd.
diff --git a/compiler/front_end/expression_bounds.py b/compiler/front_end/expression_bounds.py
index 7191ada..5d37e1c 100644
--- a/compiler/front_end/expression_bounds.py
+++ b/compiler/front_end/expression_bounds.py
@@ -14,6 +14,7 @@
 
 """Functions for proving mathematical properties of expressions."""
 
+import math
 import fractions
 import operator
 
@@ -22,6 +23,14 @@
 from compiler.util import traverse_ir
 
 
+# Create a local alias for math.gcd with a fallback to fractions.gcd if it is
+# not available. This can be dropped if pre-3.5 Python support is dropped.
+if hasattr(math, 'gcd'):
+  _math_gcd = math.gcd
+else:
+  _math_gcd = fractions.gcd
+
+
 def compute_constraints_of_expression(expression, ir):
   """Adds appropriate bounding constraints to the given expression."""
   if ir_util.is_constant_type(expression.type):
@@ -691,7 +700,7 @@
   if b == 0: return a
   if a == "infinity": return b
   if b == "infinity": return a
-  return fractions.gcd(a, b)
+  return _math_gcd(a, b)
 
 
 def compute_constants(ir):