Revert "[TLI] Robustize SDAG proto checking by merging it into TLI."

This reverts commit r292189, as it causes issues on SystemZ bots.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292191 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ahmed Bougacha 2017-01-17 03:31:00 +00:00
parent f42a59313b
commit ce7126af56
4 changed files with 82 additions and 42 deletions

View File

@ -5976,7 +5976,16 @@ void SelectionDAGBuilder::processIntegerCallValue(const Instruction &I,
/// If so, return true and lower it, otherwise return false and it will be
/// lowered like a normal call.
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) {
@ -6070,9 +6079,18 @@ bool SelectionDAGBuilder::visitMemCmpCall(const CallInst &I) {
/// form. If so, return true and lower it, otherwise return false and it
/// will be lowered like a normal call.
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 =
@ -6092,6 +6110,11 @@ bool SelectionDAGBuilder::visitMemChrCall(const CallInst &I) {
/// visitMemPCpyCall -- lower a mempcpy call as a memcpy followed by code to
/// to adjust the dst pointer by the size of the copied memory.
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));
@ -6130,7 +6153,15 @@ bool SelectionDAGBuilder::visitMemPCpyCall(const CallInst &I) {
/// optimized form. If so, return true and lower it, otherwise return false
/// and it will be lowered like a normal call.
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 =
@ -6151,7 +6182,15 @@ bool SelectionDAGBuilder::visitStrCpyCall(const CallInst &I, bool isStpcpy) {
/// If so, return true and lower it, otherwise return false and it will be
/// lowered like a normal call.
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 =
@ -6172,7 +6211,13 @@ bool SelectionDAGBuilder::visitStrCmpCall(const CallInst &I) {
/// form. If so, return true and lower it, otherwise return false and it
/// will be lowered like a normal call.
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 =
@ -6191,7 +6236,15 @@ bool SelectionDAGBuilder::visitStrLenCall(const CallInst &I) {
/// form. If so, return true and lower it, otherwise return false and it
/// will be lowered like a normal call.
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 =
@ -6212,8 +6265,11 @@ bool SelectionDAGBuilder::visitStrNLenCall(const CallInst &I) {
/// and return true.
bool SelectionDAGBuilder::visitUnaryFloatCall(const CallInst &I,
unsigned Opcode) {
// We already checked this call's prototype; verify it doesn't modify errno.
if (!I.onlyReadsMemory())
// 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())
return false;
SDValue Tmp = getValue(I.getArgOperand(0));
@ -6226,8 +6282,12 @@ bool SelectionDAGBuilder::visitUnaryFloatCall(const CallInst &I,
/// and return true.
bool SelectionDAGBuilder::visitBinaryFloatCall(const CallInst &I,
unsigned Opcode) {
// We already checked this call's prototype; verify it doesn't modify errno.
if (!I.onlyReadsMemory())
// 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())
return false;
SDValue Tmp0 = getValue(I.getArgOperand(0));
@ -6269,16 +6329,18 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
// some reason.
LibFunc::Func Func;
if (!I.isNoBuiltin() && !F->hasLocalLinkage() && F->hasName() &&
LibInfo->getLibFunc(*F, Func) &&
LibInfo->getLibFunc(F->getName(), Func) &&
LibInfo->hasOptimizedCodeGen(Func)) {
switch (Func) {
default: break;
case LibFunc::copysign:
case LibFunc::copysignf:
case LibFunc::copysignl:
// We already checked this call's prototype; verify it doesn't modify
// errno.
if (I.onlyReadsMemory()) {
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()) {
SDValue LHS = getValue(I.getArgOperand(0));
SDValue RHS = getValue(I.getArgOperand(1));
setValue(&I, DAG.getNode(ISD::FCOPYSIGN, getCurSDLoc(),

View File

@ -7,11 +7,11 @@
@.str = private constant [23 x i8] c"fooooooooooooooooooooo\00", align 1 ; <[23 x i8]*> [#uses=1]
declare i32 @memcmp(i8*, i8*, i64)
declare i32 @memcmp(...)
define void @memcmp2(i8* %X, i8* %Y, i32* nocapture %P) nounwind {
entry:
%0 = tail call i32 @memcmp(i8* %X, i8* %Y, i64 2) nounwind ; <i32> [#uses=1]
%0 = tail call i32 (...) @memcmp(i8* %X, i8* %Y, i32 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: ; preds = %entry
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), i64 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), i32 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: ; preds = %entry
define void @memcmp2nb(i8* %X, i8* %Y, i32* nocapture %P) nounwind {
entry:
%0 = tail call i32 @memcmp(i8* %X, i8* %Y, i64 2) nounwind nobuiltin ; <i32> [#uses=1]
%0 = tail call i32 (...) @memcmp(i8* %X, i8* %Y, i32 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: ; preds = %entry
define void @memcmp4(i8* %X, i8* %Y, i32* nocapture %P) nounwind {
entry:
%0 = tail call i32 @memcmp(i8* %X, i8* %Y, i64 4) nounwind ; <i32> [#uses=1]
%0 = tail call i32 (...) @memcmp(i8* %X, i8* %Y, i32 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: ; preds = %entry
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), i64 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), i32 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: ; preds = %entry
define void @memcmp8(i8* %X, i8* %Y, i32* nocapture %P) nounwind {
entry:
%0 = tail call i32 @memcmp(i8* %X, i8* %Y, i64 8) nounwind ; <i32> [#uses=1]
%0 = tail call i32 (...) @memcmp(i8* %X, i8* %Y, i32 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: ; preds = %entry
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), i64 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), i32 8) nounwind ; <i32> [#uses=1]
%1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]
br i1 %1, label %return, label %bb

View File

@ -1,20 +0,0 @@
; RUN: llc < %s -mtriple=i686-unknown-linux -O2 | FileCheck %s
; This tests the i686 lowering of mempcpy.
; Also see mempcpy.ll
@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)

View File

@ -1,4 +1,5 @@
; 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
@ -10,15 +11,12 @@
; 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: movq [[REG:%r[a-z0-9]+]], {{.*}}G
; CHECK: callq {{.*}}memcpy
; CHECK: movq [[REG]], %rax
; CHECK: mov{{.*}} [[REG:%[er][a-z0-9]+]], {{.*}}G
; CHECK: call{{.*}} {{.*}}memcpy
; CHECK: mov{{.*}} [[REG]], %{{[er]}}ax
;
define i8* @RET_MEMPCPY(i8* %DST, i8* %SRC, i64 %N) {
%add.ptr = getelementptr inbounds i8, i8* %DST, i64 %N