Using the following in the F# interactive console, it ran in less than a second:
let rec f i l = 
  match i with 
  | i when i < l -> f (i+1) l
  | _ -> l
f 0 100000000;;
I then tried a straight translation i.e.
let rec g i l = if i < l then g (i+1) l else l
g 0 100000000;;
Same outcome but different compilation. 
This is what f looks like in when translated to C#:
int f(int i, int l)
{
  while(true)
  {
    int num = i;
    if(num >= l)
      return l;
    int i = num;
    l = l;
    i = i + 1;
  }
}
g, however is translated to this:
int g(int i, int l)
{
  while(i < l)
  {
    l = l;
    i++;
  }
  return l;
}
It is interesting that two functions that are fundamentally the same are rendered differently by the F# compiler. It also shows that the F# compiler has tail-recursive optimization. Thus this should loop until i reaches the limit for 32-bit integers.