Combining \ifxetex and \ifluatex with the logical OR operation

\usepackage{ifxetex,ifluatex}
\newif\ifxetexorluatex
\ifxetex
  \xetexorluatextrue
\else
  \ifluatex
    \xetexorluatextrue
  \else
    \xetexorluatexfalse
  \fi
\fi

Now \ifxetexorluatex will do what you want. For instance, for loading fontspec and setting input normalization:

\ifxetexorluatex
   \usepackage{fontspec}
   \setmainfont{TeX Gyre Pagella}
\else
   \usepackage[T1]{fontenc}
   \usepackage{tgpagella}
\fi

\ifxetex
  \XeTeXinputnormalization=1
\fi

A different implementation, just for fun, is

\newif\ifxetexorluatex
\begingroup\catcode94=7 \catcode0=9 % ASCII 94 is ^
\def\empty{}\def\next{^^^^0000}\expandafter\endgroup
\ifx\next\empty\xetexorluatextrue\else\xetexorluatexfalse\fi

It exploits the fact that the XeTeX and LuaTeX engines have the ^^^^ convention for inputting character with their Unicode point. If the engine is Unicode aware, ^^^^0000 counts as a unique token which, by the assignment \catcode0=9 is ignored, so that \next expands to nothing and is equivalent to \empty. In case an 8-bit engine is used, the expansion of \next would contain six tokens (^^^ counts as one, then ^0000) and \ifx will follow the "false" path.

Another way of doing it, without defining an \ifxetexorluatex conditional, is to say

\ifnum 0\ifxetex 1\fi\ifluatex 1\fi>0
   % code for XeTeX or LuaTeX
\else
   % code for pdfLaTeX
\fi

There must be no space between 0 and \ifxetex and between 1 and \fi. This exploits the fact that TeX expands tokens when looking for numbers. So if one of the two inner conditionals is true, the engine will see 01, which is greater than zero. If both are false it will see 0.

So a shorter way to set \ifxetexorluatex can be

\newif\ifxetexorluatex % a new conditional starts as false
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi>0
   \xetexorluatextrue
\fi

A much more general implementation using expl3.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\cs_new_eq:NN \pdftexengine \sys_if_engine_pdftex_p:
\cs_new_eq:NN \xetexengine  \sys_if_engine_xetex_p:
\cs_new_eq:NN \luatexengine \sys_if_engine_luatex_p:
\cs_new_eq:NN \ptexengine   \sys_if_engine_ptex_p:
\cs_new_eq:NN \uptexengine  \sys_if_engine_uptex_p:

\NewExpandableDocumentCommand{\ifengineTF}{mmm}
 {
  \bool_if:nTF { #1 } { #2 } { #3 }
 }
\ExplSyntaxOff

\begin{document}

\ifengineTF{\pdftexengine}
  {\typeout{pdf}}
  {\typeout{not pdf}}

\ifengineTF{\xetexengine || \luatexengine}
  {\typeout{either xe or lua}}
  {\typeout{neither xe nor lua}}

\ifengineTF{\pdftexengine || \xetexengine || \luatexengine}
 {\typeout{pdf or xe or lua}}
 {\typeout{ptex or uptex}}

\end{document}

Running from the shell the following commands

> pdflatex engines >> engines.out
> xelatex engines >> engines.out
> lualatex engines >> engines.out
> platex engines >> engines.out

results in the following engines.out file (edited to show only the relevant parts)

This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2018) (preloaded format=pdflatex)
 restricted \write18 enabled.
entering extended mode
(./engines.tex
[...]
pdf
neither xe nor lua
pdf or xe or lua
[...]

This is XeTeX, Version 3.14159265-2.6-0.99999 (TeX Live 2018) (preloaded format=xelatex)
 restricted \write18 enabled.
entering extended mode
(./engines.tex
[...]
not pdf
either xe or lua
pdf or xe or lua
[...]

This is LuaTeX, Version 1.07.0 (TeX Live 2018) 
 restricted system commands enabled.
(./engines.tex
[...]
not pdf
either xe or lua
pdf or xe or lua
[...]

This is e-pTeX, Version 3.14159265-p3.8.1-180226-2.6 (utf8.euc) (TeX Live 2018) (preloaded format=platex)
 restricted \write18 enabled.
entering extended mode
(./engines.tex
[...]
not pdf
neither xe nor lua
ptex or uptex
(./engines.aux) )
[...]

A different solution, with perhaps a better syntax, at the expense of expandability (until we will have e-expansion available).

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\ifengineTF}{mmm}
 {
  \bool_if:xTF
   {
    \clist_map_function:nN { #1 } \__egreg_predicate:f \c_true_bool
   }
   { #2 } { #3 }
 }
\cs_generate_variant:Nn \bool_if:nTF { x }

\cs_new:Nn \__egreg_predicate:n
 {
  \use:c { sys_if_engine_#1_p: } ||
 }
\cs_generate_variant:Nn \__egreg_predicate:n { f }
\ExplSyntaxOff

\begin{document}

\ifengineTF{pdftex}
  {\typeout{pdf}}
  {\typeout{not pdf}}

\ifengineTF{xetex,luatex}
  {\typeout{either xe or lua}}
  {\typeout{neither xe nor lua}}

\ifengineTF{pdftex,xetex,luatex}
 {\typeout{pdf or xe or lua}}
 {\typeout{ptex or uptex}}

\end{document}

The output is the same as before.


In such situations, the generic \ifboolexpr wrapper provided by the etoolbox package comes in handy:

\usepackage{etoolbox,ifxetex,ifluatex}

\ifboolexpr{bool{xetex} or bool{luatex}}{%
  <true-code>%
}{%
  <false-code>%
}

The bool operator that works with the \ifboolexpr syntax to perform boolean tests operates on all primitive style TeX conditionals. Note that it omits the \if prefix of the original \ifxetex and \ifluatex commands.


Sometimes this sort of issue is easier to solve by changing the order of checking things.

\documentclass{article}
\usepackage{ifpdf,ifluatex,ifxetex}
\begin{document}
\ifpdf
      I am in pdf
   \else
       common code for lualatex and xelatex
    \ifluatex  ...    \fi
    \ifxetex   ...    \fi
\fi
\end{document}