pengfei updated this revision to Diff 468486.
pengfei marked an inline comment as done.
pengfei added a comment.

Remove instruction write prefetch test from SystemZ.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136145

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins-arm.c
  clang/test/Sema/builtin-prefetch.c
  llvm/docs/LangRef.rst
  llvm/lib/IR/Verifier.cpp
  llvm/lib/Target/X86/X86Instr3DNow.td
  llvm/lib/Target/X86/X86InstrSSE.td
  llvm/test/CodeGen/SystemZ/prefetch-01.ll
  llvm/test/CodeGen/X86/prefetch.ll

Index: llvm/test/CodeGen/X86/prefetch.ll
===================================================================
--- llvm/test/CodeGen/X86/prefetch.ll
+++ llvm/test/CodeGen/X86/prefetch.ll
@@ -21,7 +21,7 @@
 
 ; rdar://10538297
 
-define void @t(ptr %ptr) nounwind  {
+define dso_local void @t(ptr %ptr) nounwind  {
 ; SSE-LABEL: t:
 ; SSE:       # %bb.0: # %entry
 ; SSE-NEXT:    movl {{[0-9]+}}(%esp), %eax
@@ -33,6 +33,10 @@
 ; SSE-NEXT:    prefetcht1 (%eax)
 ; SSE-NEXT:    prefetcht0 (%eax)
 ; SSE-NEXT:    prefetchnta (%eax)
+; SSE-NEXT:    prefetcht1 (%eax)
+; SSE-NEXT:    prefetcht0 (%eax)
+; SSE-NEXT:    prefetcht1 t
+; SSE-NEXT:    prefetcht0 ext
 ; SSE-NEXT:    retl
 ;
 ; PRFCHWSSE-LABEL: t:
@@ -46,6 +50,10 @@
 ; PRFCHWSSE-NEXT:    prefetchw (%eax)
 ; PRFCHWSSE-NEXT:    prefetchw (%eax)
 ; PRFCHWSSE-NEXT:    prefetchw (%eax)
+; PRFCHWSSE-NEXT:    prefetcht1 (%eax)
+; PRFCHWSSE-NEXT:    prefetcht0 (%eax)
+; PRFCHWSSE-NEXT:    prefetcht1 t
+; PRFCHWSSE-NEXT:    prefetcht0 ext
 ; PRFCHWSSE-NEXT:    retl
 ;
 ; PREFETCHWT1-LABEL: t:
@@ -59,6 +67,10 @@
 ; PREFETCHWT1-NEXT:    prefetchwt1 (%eax)
 ; PREFETCHWT1-NEXT:    prefetchw (%eax)
 ; PREFETCHWT1-NEXT:    prefetchwt1 (%eax)
+; PREFETCHWT1-NEXT:    prefetcht1 (%eax)
+; PREFETCHWT1-NEXT:    prefetcht0 (%eax)
+; PREFETCHWT1-NEXT:    prefetcht1 t
+; PREFETCHWT1-NEXT:    prefetcht0 ext
 ; PREFETCHWT1-NEXT:    retl
 ;
 ; 3DNOW-LABEL: t:
@@ -72,6 +84,10 @@
 ; 3DNOW-NEXT:    prefetchw (%eax)
 ; 3DNOW-NEXT:    prefetchw (%eax)
 ; 3DNOW-NEXT:    prefetchw (%eax)
+; 3DNOW-NEXT:    prefetch (%eax)
+; 3DNOW-NEXT:    prefetch (%eax)
+; 3DNOW-NEXT:    prefetch t
+; 3DNOW-NEXT:    prefetch ext
 ; 3DNOW-NEXT:    retl
 entry:
 	tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 1, i32 1 )
@@ -82,7 +98,12 @@
 	tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 2, i32 1 )
 	tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 3, i32 1 )
 	tail call void @llvm.prefetch( ptr %ptr, i32 1, i32 0, i32 1 )
+	tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 2, i32 0 )
+	tail call void @llvm.prefetch( ptr %ptr, i32 0, i32 3, i32 0 )
+	tail call void @llvm.prefetch( ptr @t,   i32 0, i32 2, i32 0 )
+	tail call void @llvm.prefetch( ptr @ext, i32 0, i32 3, i32 0 )
 	ret void
 }
 
+declare dso_local void @ext() nounwind
 declare void @llvm.prefetch(ptr, i32, i32, i32) nounwind
Index: llvm/test/CodeGen/SystemZ/prefetch-01.ll
===================================================================
--- llvm/test/CodeGen/SystemZ/prefetch-01.ll
+++ llvm/test/CodeGen/SystemZ/prefetch-01.ll
@@ -15,15 +15,6 @@
   ret void
 }
 
-; Check that instruction write prefetches are ignored.
-define dso_local void @f2(ptr %ptr) {
-; CHECK-LABEL: f2:
-; CHECK-NOT: %r2
-; CHECK: br %r14
-  call void @llvm.prefetch(ptr %ptr, i32 1, i32 0, i32 0)
-  ret void
-}
-
 ; Check data read prefetches.
 define dso_local void @f3(ptr %ptr) {
 ; CHECK-LABEL: f3:
Index: llvm/lib/Target/X86/X86InstrSSE.td
===================================================================
--- llvm/lib/Target/X86/X86InstrSSE.td
+++ llvm/lib/Target/X86/X86InstrSSE.td
@@ -3201,13 +3201,13 @@
 // Prefetch intrinsic.
 let Predicates = [HasSSEPrefetch], SchedRW = [WriteLoad] in {
 def PREFETCHT0   : I<0x18, MRM1m, (outs), (ins i8mem:$src),
-    "prefetcht0\t$src", [(prefetch addr:$src, imm, (i32 3), (i32 1))]>, TB;
+    "prefetcht0\t$src", [(prefetch addr:$src, imm, (i32 3), imm)]>, TB;
 def PREFETCHT1   : I<0x18, MRM2m, (outs), (ins i8mem:$src),
-    "prefetcht1\t$src", [(prefetch addr:$src, imm, (i32 2), (i32 1))]>, TB;
+    "prefetcht1\t$src", [(prefetch addr:$src, imm, (i32 2), imm)]>, TB;
 def PREFETCHT2   : I<0x18, MRM3m, (outs), (ins i8mem:$src),
-    "prefetcht2\t$src", [(prefetch addr:$src, imm, (i32 1), (i32 1))]>, TB;
+    "prefetcht2\t$src", [(prefetch addr:$src, imm, (i32 1), imm)]>, TB;
 def PREFETCHNTA  : I<0x18, MRM0m, (outs), (ins i8mem:$src),
-    "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0), (i32 1))]>, TB;
+    "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0), imm)]>, TB;
 }
 
 // FIXME: How should flush instruction be modeled?
Index: llvm/lib/Target/X86/X86Instr3DNow.td
===================================================================
--- llvm/lib/Target/X86/X86Instr3DNow.td
+++ llvm/lib/Target/X86/X86Instr3DNow.td
@@ -93,7 +93,7 @@
 let Predicates = [Has3DNow, NoSSEPrefetch] in
 def PREFETCH : I3DNow<0x0D, MRM0m, (outs), (ins i8mem:$addr),
                       "prefetch\t$addr",
-                      [(prefetch addr:$addr, imm, imm, (i32 1))]>, TB;
+                      [(prefetch addr:$addr, imm, imm, (i32 imm))]>, TB;
 
 def PREFETCHW : I<0x0D, MRM1m, (outs), (ins i8mem:$addr), "prefetchw\t$addr",
                   [(prefetch addr:$addr, (i32 1), (i32 PrefetchWLevel), (i32 1))]>,
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -5175,14 +5175,16 @@
           "llvm.init_trampoline parameter #2 must resolve to a function.",
           Call);
     break;
-  case Intrinsic::prefetch:
-    Check(cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2,
-          "rw argument to llvm.prefetch must be 0-1", Call);
-    Check(cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4,
-          "locality argument to llvm.prefetch must be 0-4", Call);
-    Check(cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue() < 2,
-          "cache type argument to llvm.prefetch must be 0-1", Call);
+  case Intrinsic::prefetch: {
+    int RW = cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue();
+    int Locality = cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue();
+    int Data = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue();
+    Check(RW < 2, "rw argument to llvm.prefetch must be 0-1", Call);
+    Check(Locality < 4, "locality argument to llvm.prefetch must be 0-4", Call);
+    Check(Data < 2, "cache type argument to llvm.prefetch must be 0-1", Call);
+    Check(Data != 0 || RW != 1, "instruction cache must be read only", Call);
     break;
+  }
   case Intrinsic::stackprotector:
     Check(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts()),
           "llvm.stackprotector parameter #2 must resolve to an alloca.", Call);
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -13163,8 +13163,9 @@
 ``locality`` is a temporal locality specifier ranging from (0) - no
 locality, to (3) - extremely local keep in cache. The ``cache type``
 specifies whether the prefetch is performed on the data (1) or
-instruction (0) cache. The ``rw``, ``locality`` and ``cache type``
-arguments must be constant integers.
+instruction (0) cache. When ``cache type`` is instruction, the ``rw``
+must be read. The ``rw``, ``locality`` and ``cache type`` arguments
+must be constant integers.
 
 Semantics:
 """"""""""
Index: clang/test/Sema/builtin-prefetch.c
===================================================================
--- clang/test/Sema/builtin-prefetch.c
+++ clang/test/Sema/builtin-prefetch.c
@@ -4,11 +4,13 @@
   int a;
   __builtin_prefetch(&a);
   __builtin_prefetch(&a, 1);
-  __builtin_prefetch(&a, 1, 2);
-  __builtin_prefetch(&a, 1, 9, 3); // expected-error{{too many arguments to function}}
+  __builtin_prefetch(&a, 0, 2, 1);
+  __builtin_prefetch(&a, 1, 2, 0); // expected-error{{instruction cache must be read only}}
+  __builtin_prefetch(&a, 1, 9, 8, 3); // expected-error{{too many arguments to function}}
   __builtin_prefetch(&a, "hello", 2); // expected-error{{argument to '__builtin_prefetch' must be a constant integer}}
   __builtin_prefetch(&a, a, 2); // expected-error{{argument to '__builtin_prefetch' must be a constant integer}}
   __builtin_prefetch(&a, 2); // expected-error{{argument value 2 is outside the valid range [0, 1]}}
   __builtin_prefetch(&a, 0, 4); // expected-error{{argument value 4 is outside the valid range [0, 3]}}
   __builtin_prefetch(&a, -1, 4); // expected-error{{argument value -1 is outside the valid range [0, 1]}}
+  __builtin_prefetch(&a, 1, 2, 3); // expected-error{{argument value 3 is outside the valid range [0, 1]}}
 }
Index: clang/test/CodeGen/builtins-arm.c
===================================================================
--- clang/test/CodeGen/builtins-arm.c
+++ clang/test/CodeGen/builtins-arm.c
@@ -97,8 +97,8 @@
   __builtin_arm_prefetch(&i, 1, 1);
   // CHECK: call {{.*}} @llvm.prefetch.p0(ptr %{{.*}}, i32 1, i32 3, i32 1)
 
-  __builtin_arm_prefetch(&i, 1, 0);
-  // CHECK: call {{.*}} @llvm.prefetch.p0(ptr %{{.*}}, i32 1, i32 3, i32 0)
+  __builtin_arm_prefetch(&i, 0, 0);
+  // CHECK: call {{.*}} @llvm.prefetch.p0(ptr %{{.*}}, i32 0, i32 3, i32 0)
 }
 
 void ldc(const void *i) {
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -7571,17 +7571,46 @@
 bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) {
   unsigned NumArgs = TheCall->getNumArgs();
 
-  if (NumArgs > 3)
+  if (NumArgs > 4)
     return Diag(TheCall->getEndLoc(),
                 diag::err_typecheck_call_too_many_args_at_most)
-           << 0 /*function call*/ << 3 << NumArgs << TheCall->getSourceRange();
+           << 0 /*function call*/ << 4 << NumArgs << TheCall->getSourceRange();
+
+  auto SemaBuiltinConstantArgRange =
+      [this, TheCall](int ArgNum, int Low, int High, int &Val) -> bool {
+    if (isConstantEvaluated())
+      return false;
+    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;
+
+    Val = Result.getSExtValue();
+    if (Val < Low || Val > High)
+      return Diag(TheCall->getBeginLoc(), diag::err_argument_invalid_range)
+             << Val << Low << High << Arg->getSourceRange();
+
+    return false;
+  };
 
   // Argument 0 is checked for us and the remaining arguments must be
   // constant integers.
+  int Vals[3] = {0, 0, 1};
   for (unsigned i = 1; i != NumArgs; ++i)
-    if (SemaBuiltinConstantArgRange(TheCall, i, 0, i == 1 ? 1 : 3))
+    if (SemaBuiltinConstantArgRange(i, 0, i == 2 ? 3 : 1, Vals[i - 1]))
       return true;
 
+  if (Vals[0] == 1 && Vals[2] == 0)
+    return Diag(TheCall->getEndLoc(),
+                diag::err_typecheck_call_inst_cache_must_read_only)
+           << TheCall->getSourceRange();
+
   return false;
 }
 
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -2917,13 +2917,14 @@
                                              /*EmittedE=*/nullptr, IsDynamic));
   }
   case Builtin::BI__builtin_prefetch: {
-    Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
+    Value *Locality, *RW, *Data, *Address = EmitScalarExpr(E->getArg(0));
     // FIXME: Technically these constants should of type 'int', yes?
     RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) :
       llvm::ConstantInt::get(Int32Ty, 0);
     Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) :
       llvm::ConstantInt::get(Int32Ty, 3);
-    Value *Data = llvm::ConstantInt::get(Int32Ty, 1);
+    Data = (E->getNumArgs() > 3) ? EmitScalarExpr(E->getArg(3)) :
+      llvm::ConstantInt::get(Int32Ty, 1);
     Function *F = CGM.getIntrinsic(Intrinsic::prefetch, Address->getType());
     return RValue::get(Builder.CreateCall(F, {Address, RW, Locality, Data}));
   }
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8432,6 +8432,8 @@
   "too many %select{|||execution configuration }0arguments to "
   "%select{function|block|method|kernel function}0 call, "
   "expected at most %1, have %2; did you mean %3?">;
+def err_typecheck_call_inst_cache_must_read_only : Error<
+  "instruction cache must be read only">;
 
 def err_arc_typecheck_convert_incompatible_pointer : Error<
   "incompatible pointer types passing retainable parameter of type %0"
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to