Index: include/clang/Basic/Builtins.def =================================================================== --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -404,6 +404,10 @@ BUILTIN(__builtin_bswap32, "UiUi", "nc") BUILTIN(__builtin_bswap64, "ULLiULLi", "nc") +BUILTIN(__builtin_bitreverse16, "UsUs", "nc") +BUILTIN(__builtin_bitreverse32, "UiUi", "nc") +BUILTIN(__builtin_bitreverse64, "ULLiULLi", "nc") + // Random GCC builtins BUILTIN(__builtin_constant_p, "i.", "nctu") BUILTIN(__builtin_classify_type, "i.", "nctu") Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -288,6 +288,40 @@ return CGF.Builder.CreateExtractValue(Tmp, 0); } +// Emit a simple mangled intrinsic that has 1 argument and a return type +// matching the argument type. +static Value *emitUnaryBuiltin(CodeGenFunction &CGF, + const CallExpr *E, + unsigned IntrinsicID) { + llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); + + Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); + return CGF.Builder.CreateCall(F, Src0); +} + +// Emit an intrinsic that has 3 float or double operands. +static Value *emitTernaryFPBuiltin(CodeGenFunction &CGF, + const CallExpr *E, + unsigned IntrinsicID) { + llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); + llvm::Value *Src2 = CGF.EmitScalarExpr(E->getArg(2)); + + Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); + return CGF.Builder.CreateCall(F, {Src0, Src1, Src2}); +} + +// Emit an intrinsic that has 1 float or double operand, and 1 integer. +static Value *emitFPIntBuiltin(CodeGenFunction &CGF, + const CallExpr *E, + unsigned IntrinsicID) { + llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); + + Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); + return CGF.Builder.CreateCall(F, {Src0, Src1}); +} + namespace { struct WidthAndSignedness { unsigned Width; @@ -645,10 +679,12 @@ case Builtin::BI__builtin_bswap16: case Builtin::BI__builtin_bswap32: case Builtin::BI__builtin_bswap64: { - Value *ArgValue = EmitScalarExpr(E->getArg(0)); - llvm::Type *ArgType = ArgValue->getType(); - Value *F = CGM.getIntrinsic(Intrinsic::bswap, ArgType); - return RValue::get(Builder.CreateCall(F, ArgValue)); + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::bswap)); + } + case Builtin::BI__builtin_bitreverse16: + case Builtin::BI__builtin_bitreverse32: + case Builtin::BI__builtin_bitreverse64: { + return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::bitreverse)); } case Builtin::BI__builtin_object_size: { unsigned Type = @@ -6851,39 +6887,6 @@ } } -// Emit an intrinsic that has 1 float or double. -static Value *emitUnaryFPBuiltin(CodeGenFunction &CGF, - const CallExpr *E, - unsigned IntrinsicID) { - llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); - - Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); - return CGF.Builder.CreateCall(F, Src0); -} - -// Emit an intrinsic that has 3 float or double operands. -static Value *emitTernaryFPBuiltin(CodeGenFunction &CGF, - const CallExpr *E, - unsigned IntrinsicID) { - llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); - llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); - llvm::Value *Src2 = CGF.EmitScalarExpr(E->getArg(2)); - - Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); - return CGF.Builder.CreateCall(F, {Src0, Src1, Src2}); -} - -// Emit an intrinsic that has 1 float or double operand, and 1 integer. -static Value *emitFPIntBuiltin(CodeGenFunction &CGF, - const CallExpr *E, - unsigned IntrinsicID) { - llvm::Value *Src0 = CGF.EmitScalarExpr(E->getArg(0)); - llvm::Value *Src1 = CGF.EmitScalarExpr(E->getArg(1)); - - Value *F = CGF.CGM.getIntrinsic(IntrinsicID, Src0->getType()); - return CGF.Builder.CreateCall(F, {Src0, Src1}); -} - Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { switch (BuiltinID) { @@ -6933,13 +6936,13 @@ return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_trig_preop); case AMDGPU::BI__builtin_amdgcn_rcp: case AMDGPU::BI__builtin_amdgcn_rcpf: - return emitUnaryFPBuiltin(*this, E, Intrinsic::amdgcn_rcp); + return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rcp); case AMDGPU::BI__builtin_amdgcn_rsq: case AMDGPU::BI__builtin_amdgcn_rsqf: - return emitUnaryFPBuiltin(*this, E, Intrinsic::amdgcn_rsq); + return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rsq); case AMDGPU::BI__builtin_amdgcn_rsq_clamped: case AMDGPU::BI__builtin_amdgcn_rsq_clampedf: - return emitUnaryFPBuiltin(*this, E, Intrinsic::amdgcn_rsq_clamped); + return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rsq_clamped); case AMDGPU::BI__builtin_amdgcn_ldexp: case AMDGPU::BI__builtin_amdgcn_ldexpf: return emitFPIntBuiltin(*this, E, Intrinsic::amdgcn_ldexp); @@ -6951,8 +6954,8 @@ case AMDGPU::BI__builtin_amdgpu_rsq: case AMDGPU::BI__builtin_amdgpu_rsqf: { if (getTarget().getTriple().getArch() == Triple::amdgcn) - return emitUnaryFPBuiltin(*this, E, Intrinsic::amdgcn_rsq); - return emitUnaryFPBuiltin(*this, E, Intrinsic::r600_rsq); + return emitUnaryBuiltin(*this, E, Intrinsic::amdgcn_rsq); + return emitUnaryBuiltin(*this, E, Intrinsic::r600_rsq); } case AMDGPU::BI__builtin_amdgpu_ldexp: case AMDGPU::BI__builtin_amdgpu_ldexpf: { Index: test/CodeGen/builtins.c =================================================================== --- test/CodeGen/builtins.c +++ test/CodeGen/builtins.c @@ -116,6 +116,14 @@ P(bswap16, (N)); P(bswap32, (N)); P(bswap64, (N)); + + // CHECK: @llvm.bitreverse.i16 + // CHECK: @llvm.bitreverse.i32 + // CHECK: @llvm.bitreverse.i64 + P(bitreverse16, (N)); + P(bitreverse32, (N)); + P(bitreverse64, (N)); + // FIXME // V(clear_cache, (&N, &N+1)); V(trap, ());