[llvm] r294028 - [TLI] Robustize SDAG LibFunc proto checking by merging it into TLI.

Ahmed Bougacha via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 3 11:11:20 PST 2017


Author: ab
Date: Fri Feb  3 13:11:19 2017
New Revision: 294028

URL: http://llvm.org/viewvc/llvm-project?rev=294028&view=rev
Log:
[TLI] Robustize SDAG LibFunc proto checking by merging it into TLI.

This re-applies commit r292189, reverted in r292191.

SelectionDAGBuilder recognizes libfuncs using some homegrown
parameter type-checking.

Use TLI instead, removing another heap of redundant code.

This isn't strictly NFC, as the SDAG code was too lax.
Concretely, this means changes are required to a few tests:
- calling a non-variadic function via a variadic prototype isn't OK;
  it just happens to work on x86_64 (but not on, e.g., aarch64).
- mempcpy has a size_t parameter;  the SDAG code accepts any integer
  type, which meant using i32 on x86_64 worked.
- a handful of SystemZ tests check the SDAG support for lax prototype
  checking: Ulrich agrees on removing them.

I don't think it's worth supporting any of these (IMO) invalid
testcases.  Instead, fix them to be more meaningful.

Added:
    llvm/trunk/test/CodeGen/X86/mempcpy-32.ll
Removed:
    llvm/trunk/test/CodeGen/SystemZ/memchr-02.ll
    llvm/trunk/test/CodeGen/SystemZ/memcmp-02.ll
    llvm/trunk/test/CodeGen/SystemZ/strcmp-02.ll
    llvm/trunk/test/CodeGen/SystemZ/strlen-02.ll
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/trunk/test/CodeGen/SystemZ/memchr-01.ll
    llvm/trunk/test/CodeGen/X86/memcmp.ll
    llvm/trunk/test/CodeGen/X86/mempcpy.ll

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=294028&r1=294027&r2=294028&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Fri Feb  3 13:11:19 2017
@@ -6054,20 +6054,13 @@ void SelectionDAGBuilder::processInteger
   setValue(&I, Value);
 }
 
-/// visitMemCmpCall - See if we can lower a call to memcmp in an optimized form.
-/// If so, return true and lower it, otherwise return false and it will be
-/// lowered like a normal call.
+/// See if we can lower a memcmp call into an optimized form.  If so, return
+/// true and lower it, otherwise return false and it will be lowered like a
+/// normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitMemCmpCall(const CallInst &I) {
-  // Verify that the prototype makes sense.  int memcmp(void*,void*,size_t)
-  if (I.getNumArgOperands() != 3)
-    return false;
-
   const Value *LHS = I.getArgOperand(0), *RHS = I.getArgOperand(1);
-  if (!LHS->getType()->isPointerTy() || !RHS->getType()->isPointerTy() ||
-      !I.getArgOperand(2)->getType()->isIntegerTy() ||
-      !I.getType()->isIntegerTy())
-    return false;
-
   const Value *Size = I.getArgOperand(2);
   const ConstantInt *CSize = dyn_cast<ConstantInt>(Size);
   if (CSize && CSize->getZExtValue() == 0) {
@@ -6157,22 +6150,15 @@ bool SelectionDAGBuilder::visitMemCmpCal
   return false;
 }
 
-/// visitMemChrCall -- See if we can lower a memchr call into an optimized
-/// form.  If so, return true and lower it, otherwise return false and it
-/// will be lowered like a normal call.
+/// See if we can lower a memchr call into an optimized form.  If so, return
+/// true and lower it, otherwise return false and it will be lowered like a
+/// normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitMemChrCall(const CallInst &I) {
-  // Verify that the prototype makes sense.  void *memchr(void *, int, size_t)
-  if (I.getNumArgOperands() != 3)
-    return false;
-
   const Value *Src = I.getArgOperand(0);
   const Value *Char = I.getArgOperand(1);
   const Value *Length = I.getArgOperand(2);
-  if (!Src->getType()->isPointerTy() ||
-      !Char->getType()->isIntegerTy() ||
-      !Length->getType()->isIntegerTy() ||
-      !I.getType()->isPointerTy())
-    return false;
 
   const SelectionDAGTargetInfo &TSI = DAG.getSelectionDAGInfo();
   std::pair<SDValue, SDValue> Res =
@@ -6188,15 +6174,12 @@ bool SelectionDAGBuilder::visitMemChrCal
   return false;
 }
 
-///
-/// visitMemPCpyCall -- lower a mempcpy call as a memcpy followed by code to
-/// to adjust the dst pointer by the size of the copied memory.
+/// See if we can lower a mempcpy call into an optimized form.  If so, return
+/// true and lower it, otherwise return false and it will be lowered like a
+/// normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitMemPCpyCall(const CallInst &I) {
-
-  // Verify argument count: void *mempcpy(void *, const void *, size_t)
-  if (I.getNumArgOperands() != 3)
-    return false;
-
   SDValue Dst = getValue(I.getArgOperand(0));
   SDValue Src = getValue(I.getArgOperand(1));
   SDValue Size = getValue(I.getArgOperand(2));
@@ -6231,19 +6214,13 @@ bool SelectionDAGBuilder::visitMemPCpyCa
   return true;
 }
 
-/// visitStrCpyCall -- See if we can lower a strcpy or stpcpy call into an
-/// optimized form.  If so, return true and lower it, otherwise return false
-/// and it will be lowered like a normal call.
+/// See if we can lower a strcpy call into an optimized form.  If so, return
+/// true and lower it, otherwise return false and it will be lowered like a
+/// normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitStrCpyCall(const CallInst &I, bool isStpcpy) {
-  // Verify that the prototype makes sense.  char *strcpy(char *, char *)
-  if (I.getNumArgOperands() != 2)
-    return false;
-
   const Value *Arg0 = I.getArgOperand(0), *Arg1 = I.getArgOperand(1);
-  if (!Arg0->getType()->isPointerTy() ||
-      !Arg1->getType()->isPointerTy() ||
-      !I.getType()->isPointerTy())
-    return false;
 
   const SelectionDAGTargetInfo &TSI = DAG.getSelectionDAGInfo();
   std::pair<SDValue, SDValue> Res =
@@ -6260,19 +6237,13 @@ bool SelectionDAGBuilder::visitStrCpyCal
   return false;
 }
 
-/// visitStrCmpCall - See if we can lower a call to strcmp in an optimized form.
-/// If so, return true and lower it, otherwise return false and it will be
-/// lowered like a normal call.
+/// See if we can lower a strcmp call into an optimized form.  If so, return
+/// true and lower it, otherwise return false and it will be lowered like a
+/// normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitStrCmpCall(const CallInst &I) {
-  // Verify that the prototype makes sense.  int strcmp(void*,void*)
-  if (I.getNumArgOperands() != 2)
-    return false;
-
   const Value *Arg0 = I.getArgOperand(0), *Arg1 = I.getArgOperand(1);
-  if (!Arg0->getType()->isPointerTy() ||
-      !Arg1->getType()->isPointerTy() ||
-      !I.getType()->isIntegerTy())
-    return false;
 
   const SelectionDAGTargetInfo &TSI = DAG.getSelectionDAGInfo();
   std::pair<SDValue, SDValue> Res =
@@ -6289,17 +6260,13 @@ bool SelectionDAGBuilder::visitStrCmpCal
   return false;
 }
 
-/// visitStrLenCall -- See if we can lower a strlen call into an optimized
-/// form.  If so, return true and lower it, otherwise return false and it
-/// will be lowered like a normal call.
+/// See if we can lower a strlen call into an optimized form.  If so, return
+/// true and lower it, otherwise return false and it will be lowered like a
+/// normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitStrLenCall(const CallInst &I) {
-  // Verify that the prototype makes sense.  size_t strlen(char *)
-  if (I.getNumArgOperands() != 1)
-    return false;
-
   const Value *Arg0 = I.getArgOperand(0);
-  if (!Arg0->getType()->isPointerTy() || !I.getType()->isIntegerTy())
-    return false;
 
   const SelectionDAGTargetInfo &TSI = DAG.getSelectionDAGInfo();
   std::pair<SDValue, SDValue> Res =
@@ -6314,19 +6281,13 @@ bool SelectionDAGBuilder::visitStrLenCal
   return false;
 }
 
-/// visitStrNLenCall -- See if we can lower a strnlen call into an optimized
-/// form.  If so, return true and lower it, otherwise return false and it
-/// will be lowered like a normal call.
+/// See if we can lower a strnlen call into an optimized form.  If so, return
+/// true and lower it, otherwise return false and it will be lowered like a
+/// normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitStrNLenCall(const CallInst &I) {
-  // Verify that the prototype makes sense.  size_t strnlen(char *, size_t)
-  if (I.getNumArgOperands() != 2)
-    return false;
-
   const Value *Arg0 = I.getArgOperand(0), *Arg1 = I.getArgOperand(1);
-  if (!Arg0->getType()->isPointerTy() ||
-      !Arg1->getType()->isIntegerTy() ||
-      !I.getType()->isIntegerTy())
-    return false;
 
   const SelectionDAGTargetInfo &TSI = DAG.getSelectionDAGInfo();
   std::pair<SDValue, SDValue> Res =
@@ -6342,16 +6303,15 @@ bool SelectionDAGBuilder::visitStrNLenCa
   return false;
 }
 
-/// visitUnaryFloatCall - If a call instruction is a unary floating-point
-/// operation (as expected), translate it to an SDNode with the specified opcode
-/// and return true.
+/// See if we can lower a unary floating-point operation into an SDNode with
+/// the specified Opcode.  If so, return true and lower it, otherwise return
+/// false and it will be lowered like a normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitUnaryFloatCall(const CallInst &I,
                                               unsigned Opcode) {
-  // Sanity check that it really is a unary floating-point call.
-  if (I.getNumArgOperands() != 1 ||
-      !I.getArgOperand(0)->getType()->isFloatingPointTy() ||
-      I.getType() != I.getArgOperand(0)->getType() ||
-      !I.onlyReadsMemory())
+  // We already checked this call's prototype; verify it doesn't modify errno.
+  if (!I.onlyReadsMemory())
     return false;
 
   SDValue Tmp = getValue(I.getArgOperand(0));
@@ -6359,17 +6319,15 @@ bool SelectionDAGBuilder::visitUnaryFloa
   return true;
 }
 
-/// visitBinaryFloatCall - If a call instruction is a binary floating-point
-/// operation (as expected), translate it to an SDNode with the specified opcode
-/// and return true.
+/// See if we can lower a binary floating-point operation into an SDNode with
+/// the specified Opcode.  If so, return true and lower it, otherwise return
+/// false and it will be lowered like a normal call.
+/// The caller already checked that \p I calls the appropriate LibFunc with a
+/// correct prototype.
 bool SelectionDAGBuilder::visitBinaryFloatCall(const CallInst &I,
                                                unsigned Opcode) {
-  // Sanity check that it really is a binary floating-point call.
-  if (I.getNumArgOperands() != 2 ||
-      !I.getArgOperand(0)->getType()->isFloatingPointTy() ||
-      I.getType() != I.getArgOperand(0)->getType() ||
-      I.getType() != I.getArgOperand(1)->getType() ||
-      !I.onlyReadsMemory())
+  // We already checked this call's prototype; verify it doesn't modify errno.
+  if (!I.onlyReadsMemory())
     return false;
 
   SDValue Tmp0 = getValue(I.getArgOperand(0));
@@ -6411,18 +6369,16 @@ void SelectionDAGBuilder::visitCall(cons
     // some reason.
     LibFunc Func;
     if (!I.isNoBuiltin() && !F->hasLocalLinkage() && F->hasName() &&
-        LibInfo->getLibFunc(F->getName(), Func) &&
+        LibInfo->getLibFunc(*F, Func) &&
         LibInfo->hasOptimizedCodeGen(Func)) {
       switch (Func) {
       default: break;
       case LibFunc_copysign:
       case LibFunc_copysignf:
       case LibFunc_copysignl:
-        if (I.getNumArgOperands() == 2 &&   // Basic sanity checks.
-            I.getArgOperand(0)->getType()->isFloatingPointTy() &&
-            I.getType() == I.getArgOperand(0)->getType() &&
-            I.getType() == I.getArgOperand(1)->getType() &&
-            I.onlyReadsMemory()) {
+        // We already checked this call's prototype; verify it doesn't modify
+        // errno.
+        if (I.onlyReadsMemory()) {
           SDValue LHS = getValue(I.getArgOperand(0));
           SDValue RHS = getValue(I.getArgOperand(1));
           setValue(&I, DAG.getNode(ISD::FCOPYSIGN, getCurSDLoc(),

Modified: llvm/trunk/test/CodeGen/SystemZ/memchr-01.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/memchr-01.ll?rev=294028&r1=294027&r2=294028&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/memchr-01.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/memchr-01.ll Fri Feb  3 13:11:19 2017
@@ -1,21 +1,57 @@
-; Test memchr using SRST, with a weird but usable prototype.
+; Test memchr using SRST, with the correct prototype.
 ;
-; RUN: llc < %s -mtriple=s390x-linux-gnu -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=s390x-linux-gnu -no-integrated-as | FileCheck %s
 
-declare i8 *@memchr(i8 *%src, i16 %char, i32 %len)
+declare i8 *@memchr(i8 *%src, i32 %char, i64 %len)
 
 ; Test a simple forwarded call.
-define i8 *@f1(i8 *%src, i16 %char, i32 %len) {
+define i8 *@f1(i64 %len, i8 *%src, i32 %char) {
 ; CHECK-LABEL: f1:
-; CHECK-DAG: lgr [[REG:%r[1-5]]], %r2
-; CHECK-DAG: algfr %r2, %r4
-; CHECK-DAG: llcr %r0, %r3
+; CHECK-DAG: agr %r2, %r3
+; CHECK-DAG: llcr %r0, %r4
 ; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK: srst %r2, [[REG]]
+; CHECK: srst %r2, %r3
 ; CHECK-NEXT: jo [[LABEL]]
 ; CHECK: blr %r14
 ; CHECK: lghi %r2, 0
 ; CHECK: br %r14
-  %res = call i8 *@memchr(i8 *%src, i16 %char, i32 %len)
+  %res = call i8 *@memchr(i8 *%src, i32 %char, i64 %len)
   ret i8 *%res
 }
+
+; Test a doubled call with no use of %r0 in between.  There should be a
+; single load of %r0.
+define i8 *@f2(i8 *%src, i8 *%charptr, i64 %len) {
+; CHECK-LABEL: f2:
+; CHECK: llc %r0, 0(%r3)
+; CHECK-NOT: %r0
+; CHECK: srst [[RES1:%r[1-5]]], %r2
+; CHECK-NOT: %r0
+; CHECK: srst %r2, [[RES1]]
+; CHECK: br %r14
+  %char = load volatile i8 , i8 *%charptr
+  %charext = zext i8 %char to i32
+  %res1 = call i8 *@memchr(i8 *%src, i32 %charext, i64 %len)
+  %res2 = call i8 *@memchr(i8 *%res1, i32 %charext, i64 %len)
+  ret i8 *%res2
+}
+
+; Test a doubled call with a use of %r0 in between.  %r0 must be loaded
+; for each loop.
+define i8 *@f3(i8 *%src, i8 *%charptr, i64 %len) {
+; CHECK-LABEL: f3:
+; CHECK: llc [[CHAR:%r[1-5]]], 0(%r3)
+; CHECK: lr %r0, [[CHAR]]
+; CHECK: srst [[RES1:%r[1-5]]], %r2
+; CHECK: lhi %r0, 0
+; CHECK: blah %r0
+; CHECK: lr %r0, [[CHAR]]
+; CHECK: srst %r2, [[RES1]]
+; CHECK: br %r14
+  %char = load volatile i8 , i8 *%charptr
+  %charext = zext i8 %char to i32
+  %res1 = call i8 *@memchr(i8 *%src, i32 %charext, i64 %len)
+  call void asm sideeffect "blah $0", "{r0}" (i32 0)
+  %res2 = call i8 *@memchr(i8 *%res1, i32 %charext, i64 %len)
+  ret i8 *%res2
+}

Removed: llvm/trunk/test/CodeGen/SystemZ/memchr-02.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/memchr-02.ll?rev=294027&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/memchr-02.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/memchr-02.ll (removed)
@@ -1,57 +0,0 @@
-; Test memchr using SRST, with the correct prototype.
-;
-; RUN: llc < %s -mtriple=s390x-linux-gnu -no-integrated-as | FileCheck %s
-
-declare i8 *@memchr(i8 *%src, i32 %char, i64 %len)
-
-; Test a simple forwarded call.
-define i8 *@f1(i64 %len, i8 *%src, i32 %char) {
-; CHECK-LABEL: f1:
-; CHECK-DAG: agr %r2, %r3
-; CHECK-DAG: llcr %r0, %r4
-; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK: srst %r2, %r3
-; CHECK-NEXT: jo [[LABEL]]
-; CHECK: blr %r14
-; CHECK: lghi %r2, 0
-; CHECK: br %r14
-  %res = call i8 *@memchr(i8 *%src, i32 %char, i64 %len)
-  ret i8 *%res
-}
-
-; Test a doubled call with no use of %r0 in between.  There should be a
-; single load of %r0.
-define i8 *@f2(i8 *%src, i8 *%charptr, i64 %len) {
-; CHECK-LABEL: f2:
-; CHECK: llc %r0, 0(%r3)
-; CHECK-NOT: %r0
-; CHECK: srst [[RES1:%r[1-5]]], %r2
-; CHECK-NOT: %r0
-; CHECK: srst %r2, [[RES1]]
-; CHECK: br %r14
-  %char = load volatile i8 , i8 *%charptr
-  %charext = zext i8 %char to i32
-  %res1 = call i8 *@memchr(i8 *%src, i32 %charext, i64 %len)
-  %res2 = call i8 *@memchr(i8 *%res1, i32 %charext, i64 %len)
-  ret i8 *%res2
-}
-
-; Test a doubled call with a use of %r0 in between.  %r0 must be loaded
-; for each loop.
-define i8 *@f3(i8 *%src, i8 *%charptr, i64 %len) {
-; CHECK-LABEL: f3:
-; CHECK: llc [[CHAR:%r[1-5]]], 0(%r3)
-; CHECK: lr %r0, [[CHAR]]
-; CHECK: srst [[RES1:%r[1-5]]], %r2
-; CHECK: lhi %r0, 0
-; CHECK: blah %r0
-; CHECK: lr %r0, [[CHAR]]
-; CHECK: srst %r2, [[RES1]]
-; CHECK: br %r14
-  %char = load volatile i8 , i8 *%charptr
-  %charext = zext i8 %char to i32
-  %res1 = call i8 *@memchr(i8 *%src, i32 %charext, i64 %len)
-  call void asm sideeffect "blah $0", "{r0}" (i32 0)
-  %res2 = call i8 *@memchr(i8 *%res1, i32 %charext, i64 %len)
-  ret i8 *%res2
-}

Removed: llvm/trunk/test/CodeGen/SystemZ/memcmp-02.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/memcmp-02.ll?rev=294027&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/memcmp-02.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/memcmp-02.ll (removed)
@@ -1,139 +0,0 @@
-; Test memcmp using CLC, with i64 results.
-;
-; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
-
-declare i64 @memcmp(i8 *%src1, i8 *%src2, i64 %size)
-
-; Zero-length comparisons should be optimized away.
-define i64 @f1(i8 *%src1, i8 *%src2) {
-; CHECK-LABEL: f1:
-; CHECK: lghi %r2, 0
-; CHECK: br %r14
-  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 0)
-  ret i64 %res
-}
-
-; Check a case where the result is used as an integer.
-define i64 @f2(i8 *%src1, i8 *%src2) {
-; CHECK-LABEL: f2:
-; CHECK: clc 0(2,%r2), 0(%r3)
-; CHECK: ipm [[REG:%r[0-5]]]
-; CHECK: srl [[REG]], 28
-; CHECK: rll [[REG]], [[REG]], 31
-; CHECK: lgfr %r2, [[REG]]
-; CHECK: br %r14
-  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 2)
-  ret i64 %res
-}
-
-; Check a case where the result is tested for equality.
-define void @f3(i8 *%src1, i8 *%src2, i64 *%dest) {
-; CHECK-LABEL: f3:
-; CHECK: clc 0(3,%r2), 0(%r3)
-; CHECK-NEXT: ber %r14
-; CHECK: br %r14
-  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 3)
-  %cmp = icmp eq i64 %res, 0
-  br i1 %cmp, label %exit, label %store
-
-store:
-  store i64 0, i64 *%dest
-  br label %exit
-
-exit:
-  ret void
-}
-
-; Check a case where the result is tested for inequality.
-define void @f4(i8 *%src1, i8 *%src2, i64 *%dest) {
-; CHECK-LABEL: f4:
-; CHECK: clc 0(4,%r2), 0(%r3)
-; CHECK-NEXT: blhr %r14
-; CHECK: br %r14
-entry:
-  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 4)
-  %cmp = icmp ne i64 %res, 0
-  br i1 %cmp, label %exit, label %store
-
-store:
-  store i64 0, i64 *%dest
-  br label %exit
-
-exit:
-  ret void
-}
-
-; Check a case where the result is tested via slt.
-define void @f5(i8 *%src1, i8 *%src2, i64 *%dest) {
-; CHECK-LABEL: f5:
-; CHECK: clc 0(5,%r2), 0(%r3)
-; CHECK-NEXT: blr %r14
-; CHECK: br %r14
-entry:
-  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 5)
-  %cmp = icmp slt i64 %res, 0
-  br i1 %cmp, label %exit, label %store
-
-store:
-  store i64 0, i64 *%dest
-  br label %exit
-
-exit:
-  ret void
-}
-
-; Check a case where the result is tested for sgt.
-define void @f6(i8 *%src1, i8 *%src2, i64 *%dest) {
-; CHECK-LABEL: f6:
-; CHECK: clc 0(6,%r2), 0(%r3)
-; CHECK-NEXT: bhr %r14
-; CHECK: br %r14
-entry:
-  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 6)
-  %cmp = icmp sgt i64 %res, 0
-  br i1 %cmp, label %exit, label %store
-
-store:
-  store i64 0, i64 *%dest
-  br label %exit
-
-exit:
-  ret void
-}
-
-; Check the upper end of the CLC range.  Here the result is used both as
-; an integer and for branching.
-define i64 @f7(i8 *%src1, i8 *%src2, i64 *%dest) {
-; CHECK-LABEL: f7:
-; CHECK: clc 0(256,%r2), 0(%r3)
-; CHECK: ipm [[REG:%r[0-5]]]
-; CHECK: srl [[REG]], 28
-; CHECK: rll [[REG]], [[REG]], 31
-; CHECK: lgfr %r2, [[REG]]
-; CHECK: blr %r14
-; CHECK: br %r14
-entry:
-  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 256)
-  %cmp = icmp slt i64 %res, 0
-  br i1 %cmp, label %exit, label %store
-
-store:
-  store i64 0, i64 *%dest
-  br label %exit
-
-exit:
-  ret i64 %res
-}
-
-; 257 bytes needs two CLCs.
-define i64 @f8(i8 *%src1, i8 *%src2) {
-; CHECK-LABEL: f8:
-; CHECK: clc 0(256,%r2), 0(%r3)
-; CHECK: jlh [[LABEL:\..*]]
-; CHECK: clc 256(1,%r2), 256(%r3)
-; CHECK: [[LABEL]]:
-; CHECK: ipm [[REG:%r[0-5]]]
-; CHECK: br %r14
-  %res = call i64 @memcmp(i8 *%src1, i8 *%src2, i64 257)
-  ret i64 %res
-}

Removed: llvm/trunk/test/CodeGen/SystemZ/strcmp-02.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/strcmp-02.ll?rev=294027&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/strcmp-02.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/strcmp-02.ll (removed)
@@ -1,72 +0,0 @@
-; Test strcmp using CLST, i64 version.
-;
-; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
-
-declare i64 @strcmp(i8 *%src1, i8 *%src2)
-
-; Check a case where the result is used as an integer.
-define i64 @f1(i8 *%src1, i8 *%src2) {
-; CHECK-LABEL: f1:
-; CHECK: lhi %r0, 0
-; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK: clst %r2, %r3
-; CHECK-NEXT: jo [[LABEL]]
-; CHECK-NEXT: BB#{{[0-9]+}}
-; CHECK-NEXT: ipm [[REG:%r[0-5]]]
-; CHECK: srl [[REG]], 28
-; CHECK: rll [[REG]], [[REG]], 31
-; CHECK: lgfr %r2, [[REG]]
-; CHECK: br %r14
-  %res = call i64 @strcmp(i8 *%src1, i8 *%src2)
-  ret i64 %res
-}
-
-; Check a case where the result is tested for equality.
-define void @f2(i8 *%src1, i8 *%src2, i64 *%dest) {
-; CHECK-LABEL: f2:
-; CHECK: lhi %r0, 0
-; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK: clst %r2, %r3
-; CHECK-NEXT: jo [[LABEL]]
-; CHECK-NEXT: BB#{{[0-9]+}}
-; CHECK-NEXT: ber %r14
-; CHECK: br %r14
-  %res = call i64 @strcmp(i8 *%src1, i8 *%src2)
-  %cmp = icmp eq i64 %res, 0
-  br i1 %cmp, label %exit, label %store
-
-store:
-  store i64 0, i64 *%dest
-  br label %exit
-
-exit:
-  ret void
-}
-
-; Test a case where the result is used both as an integer and for
-; branching.
-define i64 @f3(i8 *%src1, i8 *%src2, i64 *%dest) {
-; CHECK-LABEL: f3:
-; CHECK: lhi %r0, 0
-; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK: clst %r2, %r3
-; CHECK-NEXT: jo [[LABEL]]
-; CHECK-NEXT: BB#{{[0-9]+}}
-; CHECK-NEXT: ipm [[REG:%r[0-5]]]
-; CHECK: srl [[REG]], 28
-; CHECK: rll [[REG]], [[REG]], 31
-; CHECK: lgfr %r2, [[REG]]
-; CHECK: blr %r14
-; CHECK: br %r14
-entry:
-  %res = call i64 @strcmp(i8 *%src1, i8 *%src2)
-  %cmp = icmp slt i64 %res, 0
-  br i1 %cmp, label %exit, label %store
-
-store:
-  store i64 0, i64 *%dest
-  br label %exit
-
-exit:
-  ret i64 %res
-}

Removed: llvm/trunk/test/CodeGen/SystemZ/strlen-02.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SystemZ/strlen-02.ll?rev=294027&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/SystemZ/strlen-02.ll (original)
+++ llvm/trunk/test/CodeGen/SystemZ/strlen-02.ll (removed)
@@ -1,39 +0,0 @@
-; Test strlen using SRST, i32 version.
-;
-; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
-
-declare i32 @strlen(i8 *%src)
-declare i32 @strnlen(i8 *%src, i32 %len)
-
-; Test strlen with an i32-based prototype.  It would also be valid for
-; the uses of %r3 and REG after the LGR to be swapped.
-define i32 @f1(i32 %dummy, i8 *%src) {
-; CHECK-LABEL: f1:
-; CHECK-DAG: lhi %r0, 0
-; CHECK-DAG: lghi %r2, 0
-; CHECK-DAG: lgr [[REG:%r[145]]], %r3
-; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK-NEXT: srst %r2, [[REG]]
-; CHECK-NEXT: jo [[LABEL]]
-; CHECK-NEXT: BB#{{[0-9]+}}
-; CHECK-NEXT: sgr %r2, %r3
-; CHECK: br %r14
-  %res = call i32 @strlen(i8 *%src)
-  ret i32 %res
-}
-
-; Test strnlen with an i32-based prototype.
-define i32 @f2(i32 zeroext %len, i8 *%src) {
-; CHECK-LABEL: f2:
-; CHECK-DAG: agr %r2, %r3
-; CHECK-DAG: lhi %r0, 0
-; CHECK-DAG: lgr [[REG:%r[145]]], %r3
-; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK-NEXT: srst %r2, [[REG]]
-; CHECK-NEXT: jo [[LABEL]]
-; CHECK-NEXT: BB#{{[0-9]+}}
-; CHECK-NEXT: sgr %r2, %r3
-; CHECK: br %r14
-  %res = call i32 @strnlen(i8 *%src, i32 %len)
-  ret i32 %res
-}

Modified: llvm/trunk/test/CodeGen/X86/memcmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/memcmp.ll?rev=294028&r1=294027&r2=294028&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/memcmp.ll (original)
+++ llvm/trunk/test/CodeGen/X86/memcmp.ll Fri Feb  3 13:11:19 2017
@@ -7,11 +7,11 @@
 
 @.str = private constant [23 x i8] c"fooooooooooooooooooooo\00", align 1 ; <[23 x i8]*> [#uses=1]
 
-declare i32 @memcmp(...)
+declare i32 @memcmp(i8*, i8*, i64)
 
 define void @memcmp2(i8* %X, i8* %Y, i32* nocapture %P) nounwind {
 entry:
-  %0 = tail call i32 (...) @memcmp(i8* %X, i8* %Y, i32 2) nounwind ; <i32> [#uses=1]
+  %0 = tail call i32 @memcmp(i8* %X, i8* %Y, i64 2) nounwind ; <i32> [#uses=1]
   %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
   br i1 %1, label %return, label %bb
 
@@ -30,7 +30,7 @@ return:
 
 define void @memcmp2a(i8* %X, i32* nocapture %P) nounwind {
 entry:
-  %0 = tail call i32 (...) @memcmp(i8* %X, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 1), i32 2) nounwind ; <i32> [#uses=1]
+  %0 = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 1), i64 2) nounwind ; <i32> [#uses=1]
   %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
   br i1 %1, label %return, label %bb
 
@@ -47,7 +47,7 @@ return:
 
 define void @memcmp2nb(i8* %X, i8* %Y, i32* nocapture %P) nounwind {
 entry:
-  %0 = tail call i32 (...) @memcmp(i8* %X, i8* %Y, i32 2) nounwind nobuiltin ; <i32> [#uses=1]
+  %0 = tail call i32 @memcmp(i8* %X, i8* %Y, i64 2) nounwind nobuiltin ; <i32> [#uses=1]
   %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
   br i1 %1, label %return, label %bb
 
@@ -63,7 +63,7 @@ return:
 
 define void @memcmp4(i8* %X, i8* %Y, i32* nocapture %P) nounwind {
 entry:
-  %0 = tail call i32 (...) @memcmp(i8* %X, i8* %Y, i32 4) nounwind ; <i32> [#uses=1]
+  %0 = tail call i32 @memcmp(i8* %X, i8* %Y, i64 4) nounwind ; <i32> [#uses=1]
   %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
   br i1 %1, label %return, label %bb
 
@@ -80,7 +80,7 @@ return:
 
 define void @memcmp4a(i8* %X, i32* nocapture %P) nounwind {
 entry:
-  %0 = tail call i32 (...) @memcmp(i8* %X, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 1), i32 4) nounwind ; <i32> [#uses=1]
+  %0 = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 1), i64 4) nounwind ; <i32> [#uses=1]
   %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
   br i1 %1, label %return, label %bb
 
@@ -96,7 +96,7 @@ return:
 
 define void @memcmp8(i8* %X, i8* %Y, i32* nocapture %P) nounwind {
 entry:
-  %0 = tail call i32 (...) @memcmp(i8* %X, i8* %Y, i32 8) nounwind ; <i32> [#uses=1]
+  %0 = tail call i32 @memcmp(i8* %X, i8* %Y, i64 8) nounwind ; <i32> [#uses=1]
   %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
   br i1 %1, label %return, label %bb
 
@@ -113,7 +113,7 @@ return:
 
 define void @memcmp8a(i8* %X, i32* nocapture %P) nounwind {
 entry:
-  %0 = tail call i32 (...) @memcmp(i8* %X, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0), i32 8) nounwind ; <i32> [#uses=1]
+  %0 = tail call i32 @memcmp(i8* %X, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0), i64 8) nounwind ; <i32> [#uses=1]
   %1 = icmp eq i32 %0, 0                          ; <i1> [#uses=1]
   br i1 %1, label %return, label %bb
 

Added: llvm/trunk/test/CodeGen/X86/mempcpy-32.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mempcpy-32.ll?rev=294028&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/mempcpy-32.ll (added)
+++ llvm/trunk/test/CodeGen/X86/mempcpy-32.ll Fri Feb  3 13:11:19 2017
@@ -0,0 +1,20 @@
+;  RUN: llc < %s -mtriple=i686-unknown-linux -O2 | FileCheck %s
+
+; This tests the i686 lowering of mempcpy.
+; Also see mempcpy.ll
+
+ at G = common global i8* null, align 8
+
+; CHECK-LABEL: RET_MEMPCPY:
+; CHECK: movl [[REG:%e[a-z0-9]+]], {{.*}}G
+; CHECK: calll {{.*}}memcpy
+; CHECK: movl [[REG]], %eax
+;
+define i8* @RET_MEMPCPY(i8* %DST, i8* %SRC, i32 %N) {
+  %add.ptr = getelementptr inbounds i8, i8* %DST, i32 %N
+  store i8* %add.ptr, i8** @G, align 8
+  %call = tail call i8* @mempcpy(i8* %DST, i8* %SRC, i32 %N)
+  ret i8* %call
+}
+
+declare i8* @mempcpy(i8*, i8*, i32)

Modified: llvm/trunk/test/CodeGen/X86/mempcpy.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mempcpy.ll?rev=294028&r1=294027&r2=294028&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/mempcpy.ll (original)
+++ llvm/trunk/test/CodeGen/X86/mempcpy.ll Fri Feb  3 13:11:19 2017
@@ -1,5 +1,4 @@
 ;  RUN: llc < %s -mtriple=x86_64-unknown-linux -O2 | FileCheck %s
-;  RUN: llc < %s -mtriple=i686-unknown-linux -O2 | FileCheck %s
 
 ; This test checks that:
 ; (1)  mempcpy is lowered as memcpy, and 
@@ -11,12 +10,15 @@
 ; the first instance to be reused as the return value. This allows the check for
 ; (2) to be expressed as verifying that the MOV to store DST+N to G and
 ; the MOV to copy DST+N to %rax use the same source register.
+
+; Also see mempcpy-32.ll
+
 @G = common global i8* null, align 8
 
 ; CHECK-LABEL: RET_MEMPCPY:
-; CHECK: mov{{.*}} [[REG:%[er][a-z0-9]+]], {{.*}}G
-; CHECK: call{{.*}} {{.*}}memcpy
-; CHECK: mov{{.*}} [[REG]], %{{[er]}}ax
+; CHECK: movq [[REG:%r[a-z0-9]+]], {{.*}}G
+; CHECK: callq {{.*}}memcpy
+; CHECK: movq [[REG]], %rax
 ;
 define i8* @RET_MEMPCPY(i8* %DST, i8* %SRC, i64 %N) {
   %add.ptr = getelementptr inbounds i8, i8* %DST, i64 %N




More information about the llvm-commits mailing list