NeHuang updated this revision to Diff 358761.
NeHuang marked 4 inline comments as done.
NeHuang added a comment.

Address review comments from Nemanja.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D104744/new/

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
===================================================================
--- /dev/null
+++ clang/test/CodeGen/builtins-ppc-xlcompat-error.c
@@ -0,0 +1,37 @@
+// REQUIRES: powerpc-registered-target
+
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -fsyntax-only \
+// RUN:   -Wall -Werror -verify %s
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -fsyntax-only \
+// RUN:   -Wall -Werror -verify %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -fsyntax-only \
+// RUN:   -Wall -Werror -verify %s
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -fsyntax-only \
+// RUN:   -Wall -Werror -verify %s
+
+extern unsigned int ui;
+extern unsigned long long ull;
+
+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
@@ -3280,10 +3280,35 @@
   return false;
 }
 
+/// 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)
@@ -3359,6 +3384,15 @@
     return SemaFeatureCheck(*this, TheCall, "power9-vector",
                             diag::err_ppc_builtin_only_on_pwr9) ||
            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);
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -15061,6 +15061,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
@@ -12556,6 +12556,7 @@
   bool SemaBuiltinComplex(CallExpr *TheCall);
   bool SemaBuiltinVSX(CallExpr *TheCall);
   bool SemaBuiltinOSLogFormat(CallExpr *TheCall);
+  bool SemaValueIsRunOfOnes(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
@@ -9721,6 +9721,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, "UiUiIUiIUi", "")
+BUILTIN(__builtin_ppc_rlwimi, "UiUiUiIUiIUi", "")
+BUILTIN(__builtin_ppc_rldimi, "ULLiULLiULLiIUiIULLi", "")
 
 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