[clang] d40e809 - [PowerPC] Add PowerPC rotate related builtins and emit target independent code for XL compatibility
Victor Huang via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 15 08:26:35 PDT 2021
Author: Victor Huang
Date: 2021-07-15T10:23:54-05:00
New Revision: d40e8091bd1f48e8d3f64e4f99952f0139e9c27b
URL: https://github.com/llvm/llvm-project/commit/d40e8091bd1f48e8d3f64e4f99952f0139e9c27b
DIFF: https://github.com/llvm/llvm-project/commit/d40e8091bd1f48e8d3f64e4f99952f0139e9c27b.diff
LOG: [PowerPC] Add PowerPC rotate related builtins and emit target independent code for XL compatibility
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.
Reviewed By: nemanjai, #powerpc
Differential revision: https://reviews.llvm.org/D104744
Added:
clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c
Modified:
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
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def
index 09769b3f974eb..6bbd70c8368ec 100644
--- a/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/clang/include/clang/Basic/BuiltinsPPC.def
@@ -83,6 +83,10 @@ BUILTIN(__builtin_ppc_mulhwu, "UiUiUi", "")
BUILTIN(__builtin_ppc_maddhd, "LLiLLiLLiLLi", "")
BUILTIN(__builtin_ppc_maddhdu, "ULLiULLiULLiULLi", "")
BUILTIN(__builtin_ppc_maddld, "LLiLLiLLiLLi", "")
+// Rotate
+BUILTIN(__builtin_ppc_rlwnm, "UiUiIUiIUi", "")
+BUILTIN(__builtin_ppc_rlwimi, "UiUiUiIUiIUi", "")
+BUILTIN(__builtin_ppc_rldimi, "ULLiULLiULLiIUiIULLi", "")
BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f4c189a3d178f..779093977da8f 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9726,6 +9726,8 @@ def err_argument_not_shifted_byte : Error<
"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
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3435834fbf5b3..8201e61fa63d8 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12573,6 +12573,7 @@ class Sema final {
bool SemaBuiltinComplex(CallExpr *TheCall);
bool SemaBuiltinVSX(CallExpr *TheCall);
bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
+ bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
public:
// Used by C++ template instantiation.
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index b79b30d7a4cdb..947e8c945c887 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -140,6 +140,9 @@ static void defineXLCompatMacros(MacroBuilder &Builder) {
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
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 2819931664ba4..67f57015e49fd 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -15172,6 +15172,31 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
else
return Builder.CreateSub(Ops[0], Ops[1], "vsubuqm");
}
+ // Rotate and insert under mask operation.
+ // __rldimi(rs, is, shift, mask)
+ // (rotl64(rs, shift) & mask) | (is & ~mask)
+ // __rlwimi(rs, is, shift, mask)
+ // (rotl(rs, shift) & mask) | (is & ~mask)
+ 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);
+ }
+ // Rotate and insert under mask operation.
+ // __rlwnm(rs, shift, mask)
+ // rotl(rs, shift) & mask
+ 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: {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 6c6f284d1f6e5..e6098fcb451ba 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3296,10 +3296,35 @@ static bool SemaFeatureCheck(Sema &S, CallExpr *TheCall,
return true;
}
+/// Returns true if the argument 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, 0xFF0000FF, 0x0 are all runs. 0x0F0F0000 is not,
+/// since all 1s are not contiguous.
+bool Sema::SemaValueIsRunOfOnes(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;
+
+ // Check contiguous run of 1s, 0xFF0000FF is also a run of 1s.
+ if (Result.isShiftedMask() || (~Result).isShiftedMask())
+ return false;
+
+ 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;
bool IsTarget64Bit = TI.getTypeWidth(TI.getIntPtrType()) == 64;
+ llvm::APSInt Result;
if (isPPC_64Builtin(BuiltinID) && !IsTarget64Bit)
return Diag(TheCall->getBeginLoc(), diag::err_64_bit_builtin_32_bit_tgt)
@@ -3378,6 +3403,15 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
return SemaFeatureCheck(*this, TheCall, "isa-v30-instructions",
diag::err_ppc_builtin_only_on_arch, "9") ||
SemaBuiltinConstantArgRange(TheCall, 0, 0, 1);
+ // For __rlwnm, __rlwimi and __rldimi, the last parameter mask must
+ // be a constant that represents a contiguous bit field.
+ case PPC::BI__builtin_ppc_rlwnm:
+ return SemaBuiltinConstantArg(TheCall, 1, Result) ||
+ SemaValueIsRunOfOnes(TheCall, 2);
+ case PPC::BI__builtin_ppc_rlwimi:
+ case PPC::BI__builtin_ppc_rldimi:
+ return SemaBuiltinConstantArg(TheCall, 2, Result) ||
+ SemaValueIsRunOfOnes(TheCall, 3);
#define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
case PPC::BI__builtin_##Name: \
return SemaBuiltinPPCMMACall(TheCall, Types);
diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-error.c b/clang/test/CodeGen/builtins-ppc-xlcompat-error.c
index a4422299d7bee..721be4bf56c11 100644
--- a/clang/test/CodeGen/builtins-ppc-xlcompat-error.c
+++ b/clang/test/CodeGen/builtins-ppc-xlcompat-error.c
@@ -10,6 +10,8 @@
extern long long lla, llb;
extern int ia, ib;
+extern unsigned int ui;
+extern unsigned long long ull;
void test_trap(void) {
#ifdef __PPC64__
@@ -17,3 +19,27 @@ void test_trap(void) {
#endif
__tw(ia, ib, 50); //expected-error {{argument value 50 is outside the valid range [0, 31]}}
}
+
+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}}
+}
diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c b/clang/test/CodeGen/builtins-ppc-xlcompat-rotate.c
new file mode 100644
index 0000000000000..43f63b441c7ad
--- /dev/null
+++ b/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);
+}
More information about the cfe-commits
mailing list