For example, if I use UInt8 constant for if condition then only one branch is evaluated:
```sql
SELECT if(1, 'success', throwIf(1, 'Executing FALSE branch'))

┌─'success'─┐
│ success   │
└───────────┘

1 rows in set. Elapsed: 0.003 sec.
```

But if I use some constant expression, then both branches are evaluated:
```sql
SELECT if(empty(''), 'success', throwIf(1, 'Executing FALSE branch'))

0 rows in set. Elapsed: 0.003 sec.

Received exception from server (version 21.12.2):
Code: 395. DB::Exception: Received from localhost:9000. DB::Exception: Executing FALSE branch: While processing if(empty(''), 'success', throwIf(1, 'Executing FALSE branch')). (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO)
```
struct MaskInfo
{
    bool has_ones;
    bool has_zeros;
};
MaskInfo extractMask(
    PaddedPODArray<UInt8> & mask,
    const ColumnPtr & column,
    UInt8 null_value = 0);
MaskInfo extractInvertedMask(
    PaddedPODArray<UInt8> & mask,
    const ColumnPtr & column,
    UInt8 null_value = 0);
MaskInfo extractMask(
    PaddedPODArray<UInt8> & mask,
    const ColumnPtr & column,
    PaddedPODArray<UInt8> * nulls,
    UInt8 null_value = 0);
MaskInfo extractInvertedMask(
    PaddedPODArray<UInt8> & mask,
    const ColumnPtr & column,
    PaddedPODArray<UInt8> * nulls,
    UInt8 null_value = 0);
void inverseMask(PaddedPODArray<UInt8> & mask, MaskInfo & mask_info);
void maskedExecute(ColumnWithTypeAndName & column, const PaddedPODArray<UInt8> & mask, const MaskInfo & mask_info);
void executeColumnIfNeeded(ColumnWithTypeAndName & column, bool empty = false);
int checkShirtCircuitArguments(const ColumnsWithTypeAndName & arguments);
void copyMask(const PaddedPODArray<UInt8> & from, PaddedPODArray<UInt8> & to);
}