r333978 - Reimplement the bittest intrinsic family as builtins with inline asm

Martin Storsjö via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 5 02:32:57 PDT 2018


On Tue, 5 Jun 2018, Reid Kleckner via cfe-commits wrote:

> Author: rnk
> Date: Mon Jun  4 18:33:40 2018
> New Revision: 333978
>
> URL: http://llvm.org/viewvc/llvm-project?rev=333978&view=rev
> Log:
> Reimplement the bittest intrinsic family as builtins with inline asm
>
> We need to implement _interlockedbittestandset as a builtin for
> windows.h, so we might as well do the whole family. It reduces code
> duplication anyway.
>
> Fixes PR33188, a long standing bug in our bittest implementation
> encountered by Chakra.
>
> Added:
>    cfe/trunk/test/CodeGen/bittest-intrin.c
> Modified:
>    cfe/trunk/include/clang/Basic/Builtins.def
>    cfe/trunk/lib/CodeGen/CGBuiltin.cpp
>    cfe/trunk/lib/Headers/intrin.h
>    cfe/trunk/test/CodeGen/ms-intrinsics-other.c
>    cfe/trunk/test/CodeGen/ms-intrinsics.c
>
> Modified: cfe/trunk/include/clang/Basic/Builtins.def
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=333978&r1=333977&r2=333978&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Builtins.def (original)
> +++ cfe/trunk/include/clang/Basic/Builtins.def Mon Jun  4 18:33:40 2018
> @@ -744,6 +744,14 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn"
> LANGBUILTIN(_alloca,          "v*z", "n", ALL_MS_LANGUAGES)
> LANGBUILTIN(__annotation,     "wC*.","n", ALL_MS_LANGUAGES)
> LANGBUILTIN(__assume,         "vb",  "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_bittest,                "UcNiC*Ni", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_bittestandcomplement,   "UcNi*Ni", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_bittestandreset,        "UcNi*Ni", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_bittestandset,          "UcNi*Ni", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_bittest64,              "UcWiC*Wi", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_bittestandcomplement64, "UcWi*Wi", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_bittestandreset64,      "UcWi*Wi", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_bittestandset64,        "UcWi*Wi", "n", ALL_MS_LANGUAGES)
> LIBBUILTIN(_byteswap_ushort, "UsUs",     "fnc", "stdlib.h", ALL_MS_LANGUAGES)
> LIBBUILTIN(_byteswap_ulong,  "UNiUNi",   "fnc", "stdlib.h", ALL_MS_LANGUAGES)
> LIBBUILTIN(_byteswap_uint64, "ULLiULLi", "fnc", "stdlib.h", ALL_MS_LANGUAGES)
> @@ -783,7 +791,10 @@ LANGBUILTIN(_InterlockedOr,   "NiNiD*Ni"
> LANGBUILTIN(_InterlockedXor8,  "ccD*c",       "n", ALL_MS_LANGUAGES)
> LANGBUILTIN(_InterlockedXor16, "ssD*s",       "n", ALL_MS_LANGUAGES)
> LANGBUILTIN(_InterlockedXor,   "NiNiD*Ni",    "n", ALL_MS_LANGUAGES)
> -LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_interlockedbittestandreset,   "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_interlockedbittestandreset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_interlockedbittestandset,   "UcNiD*Ni", "n", ALL_MS_LANGUAGES)
> +LANGBUILTIN(_interlockedbittestandset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES)
> LANGBUILTIN(__noop,           "i.",  "n", ALL_MS_LANGUAGES)
> LANGBUILTIN(__popcnt16, "UsUs",     "nc", ALL_MS_LANGUAGES)
> LANGBUILTIN(__popcnt,   "UiUi",     "nc", ALL_MS_LANGUAGES)
>
> Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=333978&r1=333977&r2=333978&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Mon Jun  4 18:33:40 2018
> @@ -484,6 +484,37 @@ CodeGenFunction::emitBuiltinObjectSize(c
>   return Builder.CreateCall(F, {Ptr, Min, NullIsUnknown});
> }
> 
> +static RValue EmitBitTestIntrinsic(CodeGenFunction &CGF, const CallExpr *E,
> +                                   char TestAnd, char Size,
> +                                   bool Locked = false) {
> +  Value *BitBase = CGF.EmitScalarExpr(E->getArg(0));
> +  Value *BitPos = CGF.EmitScalarExpr(E->getArg(1));
> +
> +  // Build the assembly.
> +  SmallString<64> Asm;
> +  raw_svector_ostream AsmOS(Asm);
> +  if (Locked)
> +    AsmOS << "lock ";
> +  AsmOS << "bt";
> +  if (TestAnd)
> +    AsmOS << TestAnd;
> +  AsmOS << Size << " $2, ($1)\n\tsetc ${0:b}";
> +
> +  // Build the constraints. FIXME: We should support immediates when possible.
> +  std::string Constraints = "=r,r,r,~{cc},~{flags},~{memory},~{fpsr}";
> +  llvm::IntegerType *IntType = llvm::IntegerType::get(
> +      CGF.getLLVMContext(),
> +      CGF.getContext().getTypeSize(E->getArg(1)->getType()));
> +  llvm::Type *IntPtrType = IntType->getPointerTo();
> +  llvm::FunctionType *FTy =
> +      llvm::FunctionType::get(CGF.Int8Ty, {IntPtrType, IntType}, false);
> +
> +  llvm::InlineAsm *IA =
> +      llvm::InlineAsm::get(FTy, Asm, Constraints, /*SideEffects=*/true);
> +  CallSite CS = CGF.Builder.CreateCall(IA, {BitBase, BitPos});
> +  return RValue::get(CS.getInstruction());
> +}
> +
> // Many of MSVC builtins are on both x64 and ARM; to avoid repeating code, we
> // handle them here.

This doesn't seem thought through wrt non-x86 architectures. I'm not sure 
if there's any similar suitable instruction to use on ARM/AArch64, but we 
should at the very least fall back to doing whatever we did before this 
change for anything not x86.

// Martin


More information about the cfe-commits mailing list