[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