anchor.diff:              | ER     = 0 
               | PER_lt = 1
               | PER_gt = 2
  -            
  +
               type GenericComparer(comparerType:ComparerType) = 
                   interface System.Collections.IComparer 
                   member  c.ComparerType = comparerType
  
positive.code:                  when 'T : decimal     = System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #))
  
  
              /// Generic comparison. Implements ER mode (where "0" is returned when NaNs are compared)
              //
              // The compiler optimizer is aware of this function  (see use of generic_comparison_inner_vref in opt.fs)
              // and devirtualizes calls to it based on "T".
              let GenericComparisonIntrinsic<'T> (x:'T) (y:'T) : int = 
                  GenericComparisonWithComparerIntrinsic (fsComparerER :> IComparer) x y
  
  
              /// Generic less-than. Uses comparison implementation in PER mode but catches 
              /// the local exception that is thrown when NaN's are compared.
              let GenericLessThanIntrinsic (x:'T) (y:'T) = 
                  (# "clt" (GenericComparisonWithComparerIntrinsic fsComparerPER_lt x y) 0 : bool #)
              
              /// Generic greater-than. Uses comparison implementation in PER mode but catches 
              /// the local exception that is thrown when NaN's are compared.
              let GenericGreaterThanIntrinsic (x:'T) (y:'T) = 
                  (# "cgt" (GenericComparisonWithComparerIntrinsic fsComparerPER_gt x y) 0 : bool #)
               
              /// Generic greater-than-or-equal. Uses comparison implementation in PER mode but catches 
              /// the local exception that is thrown when NaN's are compared.
              let GenericGreaterOrEqualIntrinsic (x:'T) (y:'T) = 
                  (# "cgt" (GenericComparisonWithComparerIntrinsic fsComparerPER_gt x y) (-1) : bool #)
              
              /// Generic less-than-or-equal. Uses comparison implementation in PER mode but catches 
              /// the local exception that is thrown when NaN's are compared.
              let GenericLessOrEqualIntrinsic (x:'T) (y:'T) = 
                  (# "clt" (GenericComparisonWithComparerIntrinsic fsComparerPER_lt x y) 1 : bool #)
  
  
              /// Compare two values of the same generic type, in ER mode, with static optimizations 
  
negative.code:             /// The unique object for comparing values in ER mode (where "0" is returned when NaNs are compared)
              let fsComparerER = GenericComparer ComparerType.ER
  
              // eliminate_tail_call_xxx are to elimate tail calls which are a problem with value types > 64 bits
              // and the 64-bit JIT due to the amd64 calling convention which needs to do some magic.
              let inline eliminate_tail_call_int x = 0 + x
              let inline eliminate_tail_call_bool x =
                  // previously: not (not (x))
                  // but found that the following also removes tail calls, although this could obviously
                  // change if the fsharp optimizer is changed...
                  match x with
                  | true -> true
                  | false -> false
  
  #if FX_ATLEAST_40 // should probably create some compilation flag for this stuff
              type private EquivalenceRelation = class end
              type private PartialEquivalenceRelation = class end
  
              module GenericSpecializeCompareTo =
                  let standardTypes (t:Type) : obj =
                      if   t.Equals typeof<bool>       then box (Func<IComparer,bool      ,bool      ,int>(fun _ x y -> if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)))
                      elif t.Equals typeof<sbyte>      then box (Func<IComparer,sbyte     ,sbyte     ,int>(fun _ x y -> if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)))
                      elif t.Equals typeof<int16>      then box (Func<IComparer,int16     ,int16     ,int>(fun _ x y -> if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)))
                      elif t.Equals typeof<int32>      then box (Func<IComparer,int32     ,int32     ,int>(fun _ x y -> if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)))
                      elif t.Equals typeof<int64>      then box (Func<IComparer,int64     ,int64     ,int>(fun _ x y -> if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)))
                      elif t.Equals typeof<nativeint>  then box (Func<IComparer,nativeint ,nativeint ,int>(fun _ x y -> if (# "clt" x y : bool #) then (-1) else (# "cgt" x y : int #)))
                      elif t.Equals typeof<byte>       then box (Func<IComparer,byte      ,byte      ,int>(fun _ x y -> if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)))
                      elif t.Equals typeof<uint16>     then box (Func<IComparer,uint16    ,uint16    ,int>(fun _ x y -> if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)))
                      elif t.Equals typeof<uint32>     then box (Func<IComparer,uint32    ,uint32    ,int>(fun _ x y -> if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)))
                      elif t.Equals typeof<uint64>     then box (Func<IComparer,uint64    ,uint64    ,int>(fun _ x y -> if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)))
                      elif t.Equals typeof<unativeint> then box (Func<IComparer,unativeint,unativeint,int>(fun _ x y -> if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)))
                      elif t.Equals typeof<char>       then box (Func<IComparer,char      ,char      ,int>(fun _ x y -> if (# "clt.un" x y : bool #) then (-1) else (# "cgt.un" x y : int #)))
                      elif t.Equals typeof<string>     then box (Func<IComparer,string    ,string    ,int>(fun _ x y -> System.String.CompareOrdinal((# "" x : string #) ,(# "" y : string #))))
                      elif t.Equals typeof<decimal>    then box (Func<IComparer,decimal   ,decimal   ,int>(fun _ x y -> System.Decimal.Compare((# "" x:decimal #), (# "" y:decimal #))))
                      else null
  
                  let makeComparableType ty =
                      let comparableTypedef = typedefof<IComparable<_>>
                      comparableTypedef.MakeGenericType [|ty|]
  
                  let makeReturnType ty =
                      let func4Typedef = typedefof<Func<_,_,_,_>>
                      func4Typedef.MakeGenericType [| typeof<IComparer>; ty; ty; typeof<int> |]
  
                  let makeCompareDelegate (ty:Type) (ct:Type) (def:Type) : obj =
                      let concrete = def.MakeGenericType [|ct|]
                      let instance = Activator.CreateInstance concrete
                      upcast Delegate.CreateDelegate (makeReturnType ty, instance, "Compare")
  
                  type GenericComparerObj<'a>() =
                      member __.Compare (comp:IComparer, x:'a, y:'a) = comp.Compare (box x, box y)
  
                  let withRelation (_tyRelation:Type) (ty:Type) : obj =
                      let pass0 : obj =
                          standardTypes ty
  
                      match pass0 with
                      | null -> makeCompareDelegate ty ty typedefof<GenericComparerObj<_>>
                      | f -> f
  
                  type Function<'relation, 'a>() =
                      static let func : Func<IComparer,'a, 'a, int> =
                          match withRelation typeof<'relation> typeof<'a> with
                          | null -> raise (Exception "invalid logic")
                          | f -> unboxPrim f
  
                      static member Func = func
  
              /// Compare two values of the same generic type, using "comp".
              //
              // "comp" is assumed to be either fsComparerPER or fsComparerER (and hence 'Compare' is implemented via 'GenericCompare').
  