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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to