NeHuang created this revision.
NeHuang added reviewers: nemanjai, stefanp, PowerPC.
NeHuang added projects: LLVM, clang.
Herald added subscribers: shchenz, kbarton.
NeHuang requested review of this revision.
Herald added a subscriber: cfe-commits.
This patch is in a series of patches to provide builtins for compatibility
with the XL compiler. This patch adds the builtins and emit target independent
code for rotate related operations.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D104744
Files:
clang/include/clang/Basic/BuiltinsPPC.def
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Basic/Targets/PPC.cpp
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/Sema/SemaChecking.cpp
clang/test/CodeGen/builtins-ppc-xlcompat-error.c
clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c
Index: clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \
+// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \
+// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc-unknown-aix \
+// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix \
+// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s
+
+extern unsigned int ui;
+extern unsigned long long ull;
+
+void test_builtin_ppc_rldimi() {
+ // CHECK-LABEL: test_builtin_ppc_rldimi
+ // CHECK: %res = alloca i64, align 8
+ // CHECK-NEXT: [[RA:%[0-9]+]] = load i64, i64* @ull, align 8
+ // CHECK-NEXT: [[RB:%[0-9]+]] = load i64, i64* @ull, align 8
+ // CHECK-NEXT: [[RC:%[0-9]+]] = call i64 @llvm.fshl.i64(i64 [[RA]], i64 [[RA]], i64 63)
+ // CHECK-NEXT: [[RD:%[0-9]+]] = and i64 [[RC]], 72057593769492480
+ // CHECK-NEXT: [[RE:%[0-9]+]] = and i64 [[RB]], -72057593769492481
+ // CHECK-NEXT: [[RF:%[0-9]+]] = or i64 [[RD]], [[RE]]
+ // CHECK-NEXT: store i64 [[RF]], i64* %res, align 8
+ // CHECK-NEXT: ret void
+
+ /*shift = 63, mask = 0x00FFFFFFF0000000 = 72057593769492480, ~mask = 0xFF0000000FFFFFFF = -72057593769492481*/
+ unsigned long long res = __builtin_ppc_rldimi(ull, ull, 63, 0x00FFFFFFF0000000);
+}
+
+void test_builtin_ppc_rlwimi() {
+ // CHECK-LABEL: test_builtin_ppc_rlwimi
+ // CHECK: %res = alloca i32, align 4
+ // CHECK-NEXT: [[RA:%[0-9]+]] = load i32, i32* @ui, align 4
+ // CHECK-NEXT: [[RB:%[0-9]+]] = load i32, i32* @ui, align 4
+ // CHECK-NEXT: [[RC:%[0-9]+]] = call i32 @llvm.fshl.i32(i32 [[RA]], i32 [[RA]], i32 31)
+ // CHECK-NEXT: [[RD:%[0-9]+]] = and i32 [[RC]], 16776960
+ // CHECK-NEXT: [[RE:%[0-9]+]] = and i32 [[RB]], -16776961
+ // CHECK-NEXT: [[RF:%[0-9]+]] = or i32 [[RD]], [[RE]]
+ // CHECK-NEXT: store i32 [[RF]], i32* %res, align 4
+ // CHECK-NEXT: ret void
+
+ /*shift = 31, mask = 0xFFFF00 = 16776960, ~mask = 0xFFFFFFFFFF0000FF = -16776961*/
+ unsigned int res = __builtin_ppc_rlwimi(ui, ui, 31, 0xFFFF00);
+}
+
+void test_builtin_ppc_rlwnm() {
+ // CHECK-LABEL: test_builtin_ppc_rlwnm
+ // CHECK: %res = alloca i32, align 4
+ // CHECK-NEXT: [[RA:%[0-9]+]] = load i32, i32* @ui, align 4
+ // CHECK-NEXT: [[RB:%[0-9]+]] = call i32 @llvm.fshl.i32(i32 [[RA]], i32 [[RA]], i32 31)
+ // CHECK-NEXT: [[RC:%[0-9]+]] = and i32 [[RB]], 511
+ // CHECK-NEXT: store i32 [[RC]], i32* %res, align 4
+ // CHECK-NEXT: ret void
+
+ /*shift = 31, mask = 0x1FF = 511*/
+ unsigned int res = __builtin_ppc_rlwnm(ui, 31, 0x1FF);
+}
Index: clang/test/CodeGen/builtins-ppc-xlcompat-error.c
===================================================================
--- clang/test/CodeGen/builtins-ppc-xlcompat-error.c
+++ clang/test/CodeGen/builtins-ppc-xlcompat-error.c
@@ -10,9 +10,32 @@
// RUN: -Wall -Werror -verify %s
extern unsigned int ui;
+extern unsigned long long ull;
void test_builtin_ppc_cmprb() {
int res = __builtin_ppc_cmprb(3, ui, ui); //expected-error {{argument value 3 is outside the valid range [0, 1]}}
}
+void test_builtin_ppc_rldimi() {
+ unsigned int shift;
+ unsigned long long mask;
+ unsigned long long res = __builtin_ppc_rldimi(ull, ull, shift, 7); // expected-error {{argument to '__builtin_ppc_rldimi' must be a constant integer}}
+ res = __builtin_ppc_rldimi(ull, ull, 63, mask); // expected-error {{argument to '__builtin_ppc_rldimi' must be a constant integer}}
+ res = __builtin_ppc_rldimi(ull, ull, 63, 0xFFFF000000000F00); // expected-error {{argument 3 value should represent a contiguous bit field}}
+}
+
+void test_builtin_ppc_rlwimi() {
+ unsigned int shift;
+ unsigned int mask;
+ unsigned int res = __builtin_ppc_rlwimi(ui, ui, shift, 7); // expected-error {{argument to '__builtin_ppc_rlwimi' must be a constant integer}}
+ res = __builtin_ppc_rlwimi(ui, ui, 31, mask); // expected-error {{argument to '__builtin_ppc_rlwimi' must be a constant integer}}
+ res = __builtin_ppc_rlwimi(ui, ui, 31, 0xFFFF0F00); // expected-error {{argument 3 value should represent a contiguous bit field}}
+}
+void test_builtin_ppc_rlwnm() {
+ unsigned int shift;
+ unsigned int mask;
+ unsigned int res = __builtin_ppc_rlwnm(ui, shift, 7); // expected-error {{argument to '__builtin_ppc_rlwnm' must be a constant integer}}
+ res = __builtin_ppc_rlwnm(ui, 31, mask); // expected-error {{argument to '__builtin_ppc_rlwnm' must be a constant integer}}
+ res = __builtin_ppc_rlwnm(ui, 31, 0xFF0F0F00); // expected-error {{argument 2 value should represent a contiguous bit field}}
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -3255,6 +3255,72 @@
}
}
+/// Returns true if Val consists of one contiguous run of 1s with any number of
+/// 0s on either side. The 1s are allowed to wrap from LSB to MSB, so
+/// 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is not,
+/// since all 1s are not contiguous.
+bool Sema::CheckPPCisRunOfOnes(CallExpr *TheCall, unsigned ArgNum) {
+ llvm::APSInt Result;
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check constant-ness first.
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
+ return true;
+
+ unsigned Val = Result.getExtValue();
+ if (!Val)
+ return Diag(TheCall->getBeginLoc(),
+ diag::err_argument_not_contiguous_bit_field)
+ << ArgNum << Arg->getSourceRange();
+
+ if (llvm::isShiftedMask_32(Val)) {
+ return false;
+ } else {
+ Val = ~Val; // invert mask
+ if (llvm::isShiftedMask_32(Val)) {
+ return false;
+ }
+ }
+ // no run present
+ return Diag(TheCall->getBeginLoc(),
+ diag::err_argument_not_contiguous_bit_field)
+ << ArgNum << Arg->getSourceRange();
+}
+
+bool Sema::CheckPPC64isRunOfOnes(CallExpr *TheCall, unsigned ArgNum) {
+ llvm::APSInt Result;
+ // We can't check the value of a dependent argument.
+ Expr *Arg = TheCall->getArg(ArgNum);
+ if (Arg->isTypeDependent() || Arg->isValueDependent())
+ return false;
+
+ // Check constant-ness first.
+ if (SemaBuiltinConstantArg(TheCall, ArgNum, Result))
+ return true;
+
+ unsigned long long Val = Result.getExtValue();
+ if (!Val)
+ return Diag(TheCall->getBeginLoc(),
+ diag::err_argument_not_contiguous_bit_field)
+ << ArgNum << Arg->getSourceRange();
+
+ if (llvm::isShiftedMask_64(Val)) {
+ return false;
+ } else {
+ Val = ~Val; // invert mask
+ if (llvm::isShiftedMask_64(Val)) {
+ return false;
+ }
+ }
+ // no run present
+ return Diag(TheCall->getBeginLoc(),
+ diag::err_argument_not_contiguous_bit_field)
+ << ArgNum << Arg->getSourceRange();
+}
+
bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
CallExpr *TheCall) {
unsigned i = 0, l = 0, u = 0;
@@ -3274,6 +3340,7 @@
BuiltinID == PPC::BI__builtin_divde ||
BuiltinID == PPC::BI__builtin_divdeu;
+ llvm::APSInt Result;
if (Is64BitBltin && !IsTarget64Bit)
return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
<< TheCall->getSourceRange();
@@ -3340,6 +3407,15 @@
return SemaBuiltinConstantArgRange(TheCall, 3, 0, 7);
case PPC::BI__builtin_ppc_cmprb:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 1);
+ case PPC::BI__builtin_ppc_rlwnm:
+ return SemaBuiltinConstantArg(TheCall, 1, Result) ||
+ CheckPPCisRunOfOnes(TheCall, 2);
+ case PPC::BI__builtin_ppc_rlwimi:
+ return SemaBuiltinConstantArg(TheCall, 2, Result) ||
+ CheckPPCisRunOfOnes(TheCall, 3);
+ case PPC::BI__builtin_ppc_rldimi:
+ return SemaBuiltinConstantArg(TheCall, 2, Result) ||
+ CheckPPC64isRunOfOnes(TheCall, 3);
#define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
case PPC::BI__builtin_##Name: \
return SemaBuiltinPPCMMACall(TheCall, Types);
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -15050,6 +15050,23 @@
else
return Builder.CreateSub(Ops[0], Ops[1], "vsubuqm");
}
+ case PPC::BI__builtin_ppc_rldimi:
+ case PPC::BI__builtin_ppc_rlwimi: {
+ llvm::Type *Ty = Ops[0]->getType();
+ Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
+ if (BuiltinID == PPC::BI__builtin_ppc_rldimi)
+ Ops[2] = Builder.CreateZExt(Ops[2], Int64Ty);
+ Value *shift = Builder.CreateCall(F, {Ops[0], Ops[0], Ops[2]});
+ Value *X = Builder.CreateAnd(shift, Ops[3]);
+ Value *Y = Builder.CreateAnd(Ops[1], Builder.CreateNot(Ops[3]));
+ return Builder.CreateOr(X, Y);
+ }
+ case PPC::BI__builtin_ppc_rlwnm: {
+ llvm::Type *Ty = Ops[0]->getType();
+ Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
+ Value *shift = Builder.CreateCall(F, {Ops[0], Ops[0], Ops[1]});
+ return Builder.CreateAnd(shift, Ops[2]);
+ }
// Copy sign
case PPC::BI__builtin_vsx_xvcpsgnsp:
case PPC::BI__builtin_vsx_xvcpsgndp: {
Index: clang/lib/Basic/Targets/PPC.cpp
===================================================================
--- clang/lib/Basic/Targets/PPC.cpp
+++ clang/lib/Basic/Targets/PPC.cpp
@@ -107,6 +107,9 @@
Builder.defineMacro("__maddhd", "__builtin_ppc_maddhd");
Builder.defineMacro("__maddhdu", "__builtin_ppc_maddhdu");
Builder.defineMacro("__maddld", "__builtin_ppc_maddld");
+ Builder.defineMacro("__rlwnm", "__builtin_ppc_rlwnm");
+ Builder.defineMacro("__rlwimi", "__builtin_ppc_rlwimi");
+ Builder.defineMacro("__rldimi", "__builtin_ppc_rldimi");
}
/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -12519,6 +12519,8 @@
bool SemaBuiltinComplex(CallExpr *TheCall);
bool SemaBuiltinVSX(CallExpr *TheCall);
bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
+ bool CheckPPCisRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
+ bool CheckPPC64isRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
public:
// Used by C++ template instantiation.
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9689,6 +9689,8 @@
"argument should be an 8-bit value shifted by a multiple of 8 bits">;
def err_argument_not_shifted_byte_or_xxff : Error<
"argument should be an 8-bit value shifted by a multiple of 8 bits, or in the form 0x??FF">;
+def err_argument_not_contiguous_bit_field : Error<
+ "argument %0 value should represent a contiguous bit field">;
def err_rotation_argument_to_cadd
: Error<"argument should be the value 90 or 270">;
def err_rotation_argument_to_cmla
Index: clang/include/clang/Basic/BuiltinsPPC.def
===================================================================
--- clang/include/clang/Basic/BuiltinsPPC.def
+++ clang/include/clang/Basic/BuiltinsPPC.def
@@ -57,6 +57,10 @@
BUILTIN(__builtin_ppc_maddhd, "LLiLLiLLiLLi", "")
BUILTIN(__builtin_ppc_maddhdu, "ULLiULLiULLiULLi", "")
BUILTIN(__builtin_ppc_maddld, "LLiLLiLLiLLi", "")
+// Rotate
+BUILTIN(__builtin_ppc_rlwnm, "UiUiUiUi", "")
+BUILTIN(__builtin_ppc_rlwimi, "UiUiUiUiUi", "")
+BUILTIN(__builtin_ppc_rldimi, "ULLiULLiULLiUiULLi", "")
BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits