[clang] [clang] Implement constexpr support for __builtin_{clzg, ctzg} (PR #86577)

Nick Desaulniers via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 25 14:53:47 PDT 2024


================
@@ -12367,8 +12368,17 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
                            BuiltinOp != Builtin::BI__lzcnt &&
                            BuiltinOp != Builtin::BI__lzcnt64;
 
-    if (ZeroIsUndefined && !Val)
-      return Error(E);
+    if (!Val) {
----------------
nickdesaulniers wrote:

https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fclzg

> Similar to __builtin_clz, except the argument is type-generic unsigned integer (standard, extended or bit-precise) and there is optional second argument with int type. No integral argument promotions are performed on the first argument. If two arguments are specified, and first argument is 0, the result is the second argument. If only one argument is specified and it is 0, the result is undefined.

The code as written is doing:
1. evaluate arg 0.
2. if evaluation is 0 and the builtin is clzg and num args > 1
3. evaluate arg 1

Consider that it may be cheaper to evaluate the number of args than the full subexpression (at least when the sub expression itself is more than just a literal iteger).

The code can be rewritten as:

```suggestion
  case Builtin::BI__builtin_clzg:
  case Builtin::BI__builtin_ctzg: {
    unsigned ArgToEval = E->getNumArgs() > 1 ? 1 : 0;
    APSInt Val;
     if (!EvaluateInteger(E->getArg(0), Val, Info))
      return false;
     if (E->getNumArgs() == 1 && !Val)
       return Error(E);
     return Success(...
```

https://github.com/llvm/llvm-project/pull/86577


More information about the cfe-commits mailing list