An option would be to use a for loop.
for(i in c("x1", "x2")) df[[i]][is.na(df[[i]])] <- FALSE
Benchmark
set.seed(42)
df <- data.frame(
  id = c(rep(1:19),NA),
  x1 = sample(c(NA,TRUE), 20, replace = TRUE),
  x2 = sample(c(NA,TRUE), 20, replace = TRUE)
)
bench::mark(check=FALSE,
"Holger Brandl" = local(dplyr::mutate_each(df, dplyr::funs(replace(., is.na(.), F)), x1, x2)),
"mtelesha" = local(df <- tidyr::replace_na(df, list(x1 = FALSE, x2 = FALSE))),
Ramnath = local(df[,c('x1', 'x2')] <- gdata::NAToUnknown(df[,c('x1', 'x2')], unknown = 'FALSE')),
"Hong Ooi" = local(df[c("x1", "x2")][is.na(df[c("x1", "x2")])] <- FALSE),
GKi = local(for(i in c("x1", "x2")) df[[i]][is.na(df[[i]])] <- FALSE) )
#  expression         min   median `itr/sec` mem_al…¹ gc/se…² n_itr  n_gc total…³
#  <bch:expr>    <bch:tm> <bch:tm>     <dbl> <bch:by>   <dbl> <int> <dbl> <bch:t>
#1 Holger Brandl  16.93ms  17.33ms      57.6  34.43KB    19.2    21     7   365ms
#2 mtelesha        3.94ms   4.39ms     226.    8.15KB    13.1   103     6   456ms
#3 Ramnath       400.28µs 415.44µs    2381.    1.55KB    16.7  1142     8   480ms
#4 Hong Ooi      196.87µs 206.72µs    4755.      488B    18.8  2276     9   479ms
#5 GKi             61.8µs  66.16µs   14808.      280B    20.9  7076    10   478ms
The for-loop is about 3 times faster than Hong Ooi the second and uses the lowest amount of memory.