Skip to content

Commit de9c861

Browse files
committed
[MSVC, ARM64] Add _Copy* and _Count* intrinsics
1 parent 64573da commit de9c861

File tree

4 files changed

+228
-1
lines changed

4 files changed

+228
-1
lines changed

clang/include/clang/Basic/BuiltinsAArch64.def

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES,
259259

260260
TARGET_HEADER_BUILTIN(__break, "vi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
261261

262-
263262
TARGET_HEADER_BUILTIN(__writex18byte, "vUNiUc", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
264263
TARGET_HEADER_BUILTIN(__writex18word, "vUNiUs", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
265264
TARGET_HEADER_BUILTIN(__writex18dword, "vUNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
@@ -270,6 +269,20 @@ TARGET_HEADER_BUILTIN(__readx18word, "UsUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES,
270269
TARGET_HEADER_BUILTIN(__readx18dword, "UNiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
271270
TARGET_HEADER_BUILTIN(__readx18qword, "ULLiUNi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
272271

272+
TARGET_HEADER_BUILTIN(_CopyDoubleFromInt64, "dSLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
273+
TARGET_HEADER_BUILTIN(_CopyFloatFromInt32, "fSi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
274+
TARGET_HEADER_BUILTIN(_CopyInt32FromFloat, "Sif", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
275+
TARGET_HEADER_BUILTIN(_CopyInt64FromDouble, "SLLid", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
276+
277+
TARGET_HEADER_BUILTIN(_CountLeadingOnes, "UiULi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
278+
TARGET_HEADER_BUILTIN(_CountLeadingOnes64, "UiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
279+
TARGET_HEADER_BUILTIN(_CountLeadingSigns, "UiSLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
280+
TARGET_HEADER_BUILTIN(_CountLeadingSigns64, "UiSLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
281+
TARGET_HEADER_BUILTIN(_CountLeadingZeros, "UiULi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
282+
TARGET_HEADER_BUILTIN(_CountLeadingZeros64, "UiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
283+
TARGET_HEADER_BUILTIN(_CountOneBits, "UiULi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
284+
TARGET_HEADER_BUILTIN(_CountOneBits64, "UiULLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "")
285+
273286
#undef BUILTIN
274287
#undef LANGBUILTIN
275288
#undef TARGET_BUILTIN

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10779,6 +10779,68 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
1077910779
return Load;
1078010780
}
1078110781

10782+
if (BuiltinID == AArch64::BI_CopyDoubleFromInt64 ||
10783+
BuiltinID == AArch64::BI_CopyFloatFromInt32 ||
10784+
BuiltinID == AArch64::BI_CopyInt32FromFloat ||
10785+
BuiltinID == AArch64::BI_CopyInt64FromDouble) {
10786+
return EmitScalarExpr(E->getArg(0));
10787+
}
10788+
10789+
if (BuiltinID == AArch64::BI_CountLeadingOnes ||
10790+
BuiltinID == AArch64::BI_CountLeadingOnes64 ||
10791+
BuiltinID == AArch64::BI_CountLeadingZeros ||
10792+
BuiltinID == AArch64::BI_CountLeadingZeros64) {
10793+
Value *Arg = EmitScalarExpr(E->getArg(0));
10794+
llvm::Type *ArgType = Arg->getType();
10795+
10796+
if (BuiltinID == AArch64::BI_CountLeadingOnes ||
10797+
BuiltinID == AArch64::BI_CountLeadingOnes64)
10798+
Arg = Builder.CreateXor(Arg, Constant::getAllOnesValue(ArgType));
10799+
10800+
Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
10801+
Value *Result = Builder.CreateCall(F, {Arg, Builder.getInt1(false)});
10802+
10803+
if (BuiltinID == AArch64::BI_CountLeadingOnes64 ||
10804+
BuiltinID == AArch64::BI_CountLeadingZeros64)
10805+
Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10806+
return Result;
10807+
}
10808+
10809+
if (BuiltinID == AArch64::BI_CountLeadingSigns ||
10810+
BuiltinID == AArch64::BI_CountLeadingSigns64) {
10811+
Value *Arg = EmitScalarExpr(E->getArg(0));
10812+
llvm::Type *ArgType = Arg->getType();
10813+
10814+
Function *F;
10815+
if (BuiltinID == AArch64::BI_CountLeadingSigns) {
10816+
F = CGM.getIntrinsic(Intrinsic::aarch64_cls);
10817+
if (ArgType != Builder.getInt32Ty())
10818+
Arg =
10819+
Builder.CreateIntCast(Arg, Builder.getInt32Ty(), /*isSigned*/ true);
10820+
} else {
10821+
F = CGM.getIntrinsic(Intrinsic::aarch64_cls64);
10822+
if (ArgType != Builder.getInt64Ty())
10823+
Arg =
10824+
Builder.CreateIntCast(Arg, Builder.getInt64Ty(), /*isSigned*/ true);
10825+
}
10826+
Value *Result = Builder.CreateCall(F, Arg, "cls");
10827+
if (BuiltinID == AArch64::BI_CountLeadingSigns64)
10828+
Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10829+
return Result;
10830+
}
10831+
10832+
if (BuiltinID == AArch64::BI_CountOneBits ||
10833+
BuiltinID == AArch64::BI_CountOneBits64) {
10834+
Value *ArgValue = EmitScalarExpr(E->getArg(0));
10835+
llvm::Type *ArgType = ArgValue->getType();
10836+
Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
10837+
10838+
Value *Result = Builder.CreateCall(F, ArgValue);
10839+
if (BuiltinID == AArch64::BI_CountOneBits64)
10840+
Result = Builder.CreateTrunc(Result, Builder.getInt32Ty());
10841+
return Result;
10842+
}
10843+
1078210844
// Handle MSVC intrinsics before argument evaluation to prevent double
1078310845
// evaluation.
1078410846
if (std::optional<MSVCIntrin> MsvcIntId =

clang/lib/Headers/intrin.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,20 @@ unsigned char __readx18byte(unsigned long offset);
572572
unsigned short __readx18word(unsigned long offset);
573573
unsigned long __readx18dword(unsigned long offset);
574574
unsigned __int64 __readx18qword(unsigned long offset);
575+
576+
double _CopyDoubleFromInt64(__int64);
577+
float _CopyFloatFromInt32(__int32);
578+
__int32 _CopyInt32FromFloat(float);
579+
__int64 _CopyInt64FromDouble(double);
580+
581+
unsigned int _CountLeadingOnes(unsigned long);
582+
unsigned int _CountLeadingOnes64(unsigned __int64);
583+
unsigned int _CountLeadingSigns(long);
584+
unsigned int _CountLeadingSigns64(__int64);
585+
unsigned int _CountLeadingZeros(unsigned long);
586+
unsigned int _CountLeadingZeros64(unsigned _int64);
587+
unsigned int _CountOneBits(unsigned long);
588+
unsigned int _CountOneBits64(unsigned __int64);
575589
#endif
576590

577591
/*----------------------------------------------------------------------------*\

clang/test/CodeGen/arm64-microsoft-intrinsics.c

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,5 +265,143 @@ unsigned __int64 check__readx18qword(unsigned LONG offset) {
265265
// CHECK-MSCOMPAT: %[[RETVAL:.*]] = load i64, ptr %[[PTR]], align 1
266266
// CHECK-MSCOMPAT: ret i64 %[[RETVAL]]
267267

268+
double check__CopyDoubleFromInt64(__int64 arg1) {
269+
return _CopyDoubleFromInt64(arg1);
270+
}
271+
272+
// CHECK-MSCOMPAT: %[[RETVAL:.*]] = alloca double, align 8
273+
// CHECK-MSCOMPAT: %[[ARG:.*]].addr = alloca i64, align 8
274+
// CHECK-MSCOMPAT: store i64 %[[ARG]], ptr %[[ARG]].addr, align 8
275+
// CHECK-MSCOMPAT: %[[VAR0:.*]] = load i64, ptr %[[ARG]].addr, align 8
276+
// CHECK-MSCOMPAT: store i64 %[[VAR0]], ptr %[[RETVAL]], align 8
277+
// CHECK-MSCOMPAT: %[[VAR1:.*]] = load double, ptr %[[RETVAL]], align 8
278+
// CHECK-MSCOMPAT: ret double %[[VAR1]]
279+
// CHECK-LINUX: error: call to undeclared function '_CopyDoubleFromInt64'
280+
281+
float check__CopyFloatFromInt32(__int32 arg1) {
282+
return _CopyFloatFromInt32(arg1);
283+
}
284+
285+
// CHECK-MSCOMPAT: %[[RETVAL:.*]] = alloca float, align 4
286+
// CHECK-MSCOMPAT: %[[ARG:.*]].addr = alloca i32, align 4
287+
// CHECK-MSCOMPAT: store i32 %[[ARG]], ptr %[[ARG]].addr, align 4
288+
// CHECK-MSCOMPAT: %[[VAR0:.*]] = load i32, ptr %[[ARG]].addr, align 4
289+
// CHECK-MSCOMPAT: store i32 %[[VAR0]], ptr %[[RETVAL]], align 4
290+
// CHECK-MSCOMPAT: %[[VAR1:.*]] = load float, ptr %[[RETVAL]], align 4
291+
// CHECK-MSCOMPAT: ret float %[[VAR1]]
292+
// CHECK-LINUX: error: call to undeclared function '_CopyFloatFromInt32'
293+
294+
__int32 check__CopyInt32FromFloat(float arg1) {
295+
return _CopyInt32FromFloat(arg1);
296+
}
297+
298+
// CHECK-MSCOMPAT: %[[RETVAL:.*]] = alloca i32, align 4
299+
// CHECK-MSCOMPAT: %[[ARG:.*]].addr = alloca float, align 4
300+
// CHECK-MSCOMPAT: store float %[[ARG]], ptr %[[ARG]].addr, align 4
301+
// CHECK-MSCOMPAT: %[[VAR0:.*]] = load float, ptr %[[ARG]].addr, align 4
302+
// CHECK-MSCOMPAT: store float %[[VAR0]], ptr %[[RETVAL]], align 4
303+
// CHECK-MSCOMPAT: %[[VAR1:.*]] = load i32, ptr %[[RETVAL]], align 4
304+
// CHECK-MSCOMPAT: ret i32 %[[VAR1]]
305+
// CHECK-LINUX: error: call to undeclared function '_CopyInt32FromFloat'
306+
307+
__int64 check__CopyInt64FromDouble(double arg1) {
308+
return _CopyInt64FromDouble(arg1);
309+
}
310+
311+
// CHECK-MSCOMPAT: %[[RETVAL:.*]] = alloca i64, align 8
312+
// CHECK-MSCOMPAT: %[[ARG:.*]].addr = alloca double, align 8
313+
// CHECK-MSCOMPAT: store double %[[ARG]], ptr %[[ARG]].addr, align 8
314+
// CHECK-MSCOMPAT: %[[VAR0:.*]] = load double, ptr %[[ARG]].addr, align 8
315+
// CHECK-MSCOMPAT: store double %[[VAR0]], ptr %[[RETVAL]], align 8
316+
// CHECK-MSCOMPAT: %[[VAR1:.*]] = load i64, ptr %[[RETVAL]], align 8
317+
// CHECK-MSCOMPAT: ret i64 %[[VAR1]]
318+
// CHECK-LINUX: error: call to undeclared function '_CopyInt64FromDouble'
319+
320+
unsigned int check__CountLeadingOnes(unsigned LONG arg1) {
321+
return _CountLeadingOnes(arg1);
322+
}
323+
324+
// CHECK-MSVC: %[[ARG1:.*]].addr = alloca i32, align 4
325+
// CHECK-MSVC: store i32 %[[ARG1]], ptr %[[ARG1]].addr, align 4
326+
// CHECK-MSVC: %[[VAR0:.*]] = load i32, ptr %[[ARG1]].addr, align 4
327+
// CHECK-MSVC: %[[VAR1:.*]] = xor i32 %[[VAR0]], -1
328+
// CHECK-MSVC: %[[VAR2:.*]] = call i32 @llvm.ctlz.i32(i32 %1, i1 false)
329+
// CHECK-MSVC: ret i32 %[[VAR2]]
330+
331+
unsigned int check__CountLeadingOnes64(unsigned __int64 arg1) {
332+
return _CountLeadingOnes64(arg1);
333+
}
334+
335+
// CHECK-MSVC: %[[ARG1:.*]].addr = alloca i64, align 8
336+
// CHECK-MSVC: store i64 %[[ARG1]], ptr %[[ARG1]].addr, align 8
337+
// CHECK-MSVC: %[[VAR0:.*]] = load i64, ptr %[[ARG1]].addr, align 8
338+
// CHECK-MSVC: %[[VAR1:.*]] = xor i64 %[[VAR0]], -1
339+
// CHECK-MSVC: %[[VAR2:.*]] = call i64 @llvm.ctlz.i64(i64 %1, i1 false)
340+
// CHECK-MSVC: %[[VAR3:.*]] = trunc i64 %2 to i32
341+
// CHECK-MSVC: ret i32 %[[VAR3]]
342+
343+
unsigned int check__CountLeadingSigns(__int32 arg1) {
344+
return _CountLeadingSigns(arg1);
345+
}
346+
347+
// CHECK-MSVC: %[[ARG1:.*]].addr = alloca i32, align 4
348+
// CHECK-MSVC: store i32 %[[ARG1]], ptr %[[ARG1]].addr, align 4
349+
// CHECK-MSVC: %[[VAR0:.*]] = load i32, ptr %[[ARG1]].addr, align 4
350+
// CHECK-MSVC: %[[CLS:.*]] = call i32 @llvm.aarch64.cls(i32 %[[VAR0]])
351+
// CHECK-MSVC: ret i32 %[[CLS]]
352+
353+
unsigned int check__CountLeadingSigns64(__int64 arg1) {
354+
return _CountLeadingSigns64(arg1);
355+
}
356+
357+
// CHECK-MSVC: %[[ARG1:.*]].addr = alloca i64, align 8
358+
// CHECK-MSVC: store i64 %[[ARG1]], ptr %[[ARG1]].addr, align 8
359+
// CHECK-MSVC: %[[VAR0:.*]] = load i64, ptr %[[ARG1]].addr, align 8
360+
// CHECK-MSVC: %[[CLS:.*]] = call i32 @llvm.aarch64.cls64(i64 %[[VAR0]])
361+
// CHECK-MSVC: ret i32 %[[CLS]]
362+
363+
unsigned int check__CountLeadingZeros(__int32 arg1) {
364+
return _CountLeadingZeros(arg1);
365+
}
366+
367+
// CHECK-MSVC: %[[ARG1:.*]].addr = alloca i32, align 4
368+
// CHECK-MSVC: store i32 %[[ARG1]], ptr %[[ARG1]].addr, align 4
369+
// CHECK-MSVC: %[[VAR0:.*]] = load i32, ptr %[[ARG1]].addr, align 4
370+
// CHECK-MSVC: %[[VAR1:.*]] = call i32 @llvm.ctlz.i32(i32 %[[VAR0]], i1 false)
371+
// CHECK-MSVC: ret i32 %[[VAR1]]
372+
373+
unsigned int check__CountLeadingZeros64(__int64 arg1) {
374+
return _CountLeadingZeros64(arg1);
375+
}
376+
377+
// CHECK-MSVC: %[[ARG1:.*]].addr = alloca i64, align 8
378+
// CHECK-MSVC: store i64 %[[ARG1]], ptr %[[ARG1]].addr, align 8
379+
// CHECK-MSVC: %[[VAR0:.*]] = load i64, ptr %[[ARG1]].addr, align 8
380+
// CHECK-MSVC: %[[VAR1:.*]] = call i64 @llvm.ctlz.i64(i64 %[[VAR0]], i1 false)
381+
// CHECK-MSVC: %[[VAR2:.*]] = trunc i64 %[[VAR1]] to i32
382+
// CHECK-MSVC: ret i32 %[[VAR2]]
383+
384+
unsigned int check_CountOneBits(unsigned LONG arg1) {
385+
return _CountOneBits(arg1);
386+
}
387+
388+
// CHECK-MSVC: %[[ARG1:.*]].addr = alloca i32, align 4
389+
// CHECK-MSVC: store i32 %[[ARG1]], ptr %[[ARG1]].addr, align 4
390+
// CHECK-MSVC: %[[VAR0:.*]] = load i32, ptr %[[ARG1]].addr, align 4
391+
// CHECK-MSVC: %[[VAR1:.*]] = call i32 @llvm.ctpop.i32(i32 %0)
392+
// CHECK-MSVC: ret i32 %[[VAR1]]
393+
394+
unsigned int check_CountOneBits64(unsigned __int64 arg1) {
395+
return _CountOneBits64(arg1);
396+
}
397+
398+
// CHECK-MSVC: %[[ARG1:.*]].addr = alloca i64, align 8
399+
// CHECK-MSVC: store i64 %[[ARG1]], ptr %[[ARG1]].addr, align 8
400+
// CHECK-MSVC: %[[VAR0:.*]] = load i64, ptr %[[ARG1]].addr, align 8
401+
// CHECK-MSVC: %[[VAR1:.*]] = call i64 @llvm.ctpop.i64(i64 %0)
402+
// CHECK-MSVC: %[[VAR2:.*]] = trunc i64 %1 to i32
403+
// CHECK-MSVC: ret i32 %[[VAR2]]
404+
405+
268406
// CHECK-MSCOMPAT: ![[MD2]] = !{!"x18"}
269407
// CHECK-MSCOMPAT: ![[MD3]] = !{!"sp"}

0 commit comments

Comments
 (0)