KeyExistsQ[] but for functions?

DownValues aren't the only method for caching previously computed results. For instance you can use an association,

ClearAll[fdata, f]
fdata = <||>;
f[x_] := Lookup[fdata, x, fdata[x] = x^2]

Now when you compute a value it is stored in fdata,

In[21]:= f /@ Range[3]

Out[21]= {1, 4, 9}

In[22]:= KeyExistsQ[fdata, #] & /@ Range[4]

Out[22]= {True, True, True, False}

Here's a simple method for checking if any of the down values of a function matches f[5] literally. It's a good use case for Verbatim:

KeyExistsForFunctionsQ[fun_, arg_] := AnyTrue[
  Keys[DownValues[fun]],
  MatchQ[#, Verbatim[HoldPattern[fun[arg]]]] &
]

This method can be extended to checking other types of down values of functions as well. For example:

ValueQWithoutEval[fun_, arg_] := AnyTrue[
  Keys[DownValues[fun]],
  MatchQ[Hold[fun[arg]], Hold[#]] &
]

This will check if any of the down values of a function will match fun[arg] without actually trying to evaluate it (because it might be expensive, for example). Note that this will not work for assignments that use Condition in the r.h.s. of := like

f[x_] := With[{y = 2 x + 1}, y /; PrimeQ[y]]

For functions like that, you can't avoid evaluating the function at least partially to find out if the argument matches.