This patch is mostly just refactoring a bunch of copy-and-pasted code, but
it also adds a check that the call instructions are readnone or readonly.
That check was already present for sin, cos, sqrt, log2, and exp2 calls, but
it was missing for the rest of the builtins being handled in this code.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161282
91177308-0d34-0410-b5e6-
96231b3b80d8
13 files changed:
+/// 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.
+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())
+ return false;
+
+ SDValue Tmp = getValue(I.getArgOperand(0));
+ setValue(&I, DAG.getNode(Opcode, getCurDebugLoc(), Tmp.getValueType(), Tmp));
+ return true;
+}
void SelectionDAGBuilder::visitCall(const CallInst &I) {
// Handle inline assembly differently.
void SelectionDAGBuilder::visitCall(const CallInst &I) {
// Handle inline assembly differently.
if (I.getNumArgOperands() == 2 && // Basic sanity checks.
I.getArgOperand(0)->getType()->isFloatingPointTy() &&
I.getType() == I.getArgOperand(0)->getType() &&
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.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, getCurDebugLoc(),
SDValue LHS = getValue(I.getArgOperand(0));
SDValue RHS = getValue(I.getArgOperand(1));
setValue(&I, DAG.getNode(ISD::FCOPYSIGN, getCurDebugLoc(),
case LibFunc::fabs:
case LibFunc::fabsf:
case LibFunc::fabsl:
case LibFunc::fabs:
case LibFunc::fabsf:
case LibFunc::fabsl:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FABS, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FABS))
break;
case LibFunc::sin:
case LibFunc::sinf:
case LibFunc::sinl:
break;
case LibFunc::sin:
case LibFunc::sinf:
case LibFunc::sinl:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType() &&
- I.onlyReadsMemory()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FSIN, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FSIN))
break;
case LibFunc::cos:
case LibFunc::cosf:
case LibFunc::cosl:
break;
case LibFunc::cos:
case LibFunc::cosf:
case LibFunc::cosl:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType() &&
- I.onlyReadsMemory()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FCOS, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FCOS))
break;
case LibFunc::sqrt:
case LibFunc::sqrtf:
case LibFunc::sqrtl:
break;
case LibFunc::sqrt:
case LibFunc::sqrtf:
case LibFunc::sqrtl:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType() &&
- I.onlyReadsMemory()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FSQRT, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FSQRT))
break;
case LibFunc::floor:
case LibFunc::floorf:
case LibFunc::floorl:
break;
case LibFunc::floor:
case LibFunc::floorf:
case LibFunc::floorl:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FFLOOR, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FFLOOR))
break;
case LibFunc::nearbyint:
case LibFunc::nearbyintf:
case LibFunc::nearbyintl:
break;
case LibFunc::nearbyint:
case LibFunc::nearbyintf:
case LibFunc::nearbyintl:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FNEARBYINT, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FNEARBYINT))
break;
case LibFunc::ceil:
case LibFunc::ceilf:
case LibFunc::ceill:
break;
case LibFunc::ceil:
case LibFunc::ceilf:
case LibFunc::ceill:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FCEIL, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FCEIL))
break;
case LibFunc::rint:
case LibFunc::rintf:
case LibFunc::rintl:
break;
case LibFunc::rint:
case LibFunc::rintf:
case LibFunc::rintl:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FRINT, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FRINT))
break;
case LibFunc::trunc:
case LibFunc::truncf:
case LibFunc::truncl:
break;
case LibFunc::trunc:
case LibFunc::truncf:
case LibFunc::truncl:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FTRUNC, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FTRUNC))
break;
case LibFunc::log2:
case LibFunc::log2f:
case LibFunc::log2l:
break;
case LibFunc::log2:
case LibFunc::log2f:
case LibFunc::log2l:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType() &&
- I.onlyReadsMemory()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FLOG2, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FLOG2))
break;
case LibFunc::exp2:
case LibFunc::exp2f:
case LibFunc::exp2l:
break;
case LibFunc::exp2:
case LibFunc::exp2f:
case LibFunc::exp2l:
- if (I.getNumArgOperands() == 1 && // Basic sanity checks.
- I.getArgOperand(0)->getType()->isFloatingPointTy() &&
- I.getType() == I.getArgOperand(0)->getType() &&
- I.onlyReadsMemory()) {
- SDValue Tmp = getValue(I.getArgOperand(0));
- setValue(&I, DAG.getNode(ISD::FEXP2, getCurDebugLoc(),
- Tmp.getValueType(), Tmp));
+ if (visitUnaryFloatCall(I, ISD::FEXP2))
break;
case LibFunc::memcmp:
if (visitMemCmpCall(I))
break;
case LibFunc::memcmp:
if (visitMemCmpCall(I))
void visitPHI(const PHINode &I);
void visitCall(const CallInst &I);
bool visitMemCmpCall(const CallInst &I);
void visitPHI(const PHINode &I);
void visitCall(const CallInst &I);
bool visitMemCmpCall(const CallInst &I);
+ bool visitUnaryFloatCall(const CallInst &I, unsigned Opcode);
void visitAtomicLoad(const LoadInst &I);
void visitAtomicStore(const StoreInst &I);
void visitAtomicLoad(const LoadInst &I);
void visitAtomicStore(const StoreInst &I);
define float @test(float %a, float %b) {
entry:
%dum = fadd float %a, %b
define float @test(float %a, float %b) {
entry:
%dum = fadd float %a, %b
- %0 = tail call float @fabsf(float %dum)
+ %0 = tail call float @fabsf(float %dum) readnone
%dum1 = fadd float %0, %b
ret float %dum1
}
%dum1 = fadd float %0, %b
ret float %dum1
}
; HARD: test1:
; HARD: vmov.i32 [[REG1:(d[0-9]+)]], #0x80000000
; HARD: vbsl [[REG1]], d
; HARD: test1:
; HARD: vmov.i32 [[REG1:(d[0-9]+)]], #0x80000000
; HARD: vbsl [[REG1]], d
- %0 = tail call float @copysignf(float %x, float %y) nounwind
+ %0 = tail call float @copysignf(float %x, float %y) nounwind readnone
; HARD: vmov.i32 [[REG2:(d[0-9]+)]], #0x80000000
; HARD: vshl.i64 [[REG2]], [[REG2]], #32
; HARD: vbsl [[REG2]], d1, d0
; HARD: vmov.i32 [[REG2:(d[0-9]+)]], #0x80000000
; HARD: vshl.i64 [[REG2]], [[REG2]], #32
; HARD: vbsl [[REG2]], d1, d0
- %0 = tail call double @copysign(double %x, double %y) nounwind
+ %0 = tail call double @copysign(double %x, double %y) nounwind readnone
; SOFT: vshl.i64 [[REG3]], [[REG3]], #32
; SOFT: vbsl [[REG3]],
%0 = fmul double %x, %y
; SOFT: vshl.i64 [[REG3]], [[REG3]], #32
; SOFT: vbsl [[REG3]],
%0 = fmul double %x, %y
- %1 = tail call double @copysign(double %0, double %z) nounwind
+ %1 = tail call double @copysign(double %0, double %z) nounwind readnone
;CHECK: f11:
;CHECK: bic
entry:
;CHECK: f11:
;CHECK: bic
entry:
- %tmp1 = call float @fabsf( float %a ) ; <float> [#uses=1]
+ %tmp1 = call float @fabsf( float %a ) readnone ; <float> [#uses=1]
;CHECK: f12:
;CHECK: vabs.f64
entry:
;CHECK: f12:
;CHECK: vabs.f64
entry:
- %tmp1 = call double @fabs( double %a ) ; <double> [#uses=1]
+ %tmp1 = call double @fabs( double %a ) readnone ; <double> [#uses=1]
;CHECK: test_abs:
%a = load float* %P ; <float> [#uses=1]
;CHECK: vabs.f32
;CHECK: test_abs:
%a = load float* %P ; <float> [#uses=1]
;CHECK: vabs.f32
- %b = call float @fabsf( float %a ) ; <float> [#uses=1]
+ %b = call float @fabsf( float %a ) readnone ; <float> [#uses=1]
store float %b, float* %P
%A = load double* %D ; <double> [#uses=1]
;CHECK: vabs.f64
store float %b, float* %P
%A = load double* %D ; <double> [#uses=1]
;CHECK: vabs.f64
- %B = call double @fabs( double %A ) ; <double> [#uses=1]
+ %B = call double @fabs( double %A ) readnone ; <double> [#uses=1]
store double %B, double* %D
ret void
}
store double %B, double* %D
ret void
}
define i1 @fcmp_mag_eq(float %arg1, float %arg2) {
; CHECK: fcmeq
; CHECK: bi $lr
define i1 @fcmp_mag_eq(float %arg1, float %arg2) {
; CHECK: fcmeq
; CHECK: bi $lr
- %1 = call float @fabsf(float %arg1)
- %2 = call float @fabsf(float %arg2)
+ %1 = call float @fabsf(float %arg1) readnone
+ %2 = call float @fabsf(float %arg2) readnone
%3 = fcmp oeq float %1, %2
ret i1 %3
}
%3 = fcmp oeq float %1, %2
ret i1 %3
}
declare float @fabsf(float)
define double @fabs_dp(double %X) {
declare float @fabsf(float)
define double @fabs_dp(double %X) {
- %Y = call double @fabs( double %X )
+ %Y = call double @fabs( double %X ) readnone
ret double %Y
}
define float @fabs_sp(float %X) {
ret double %Y
}
define float @fabs_sp(float %X) {
- %Y = call float @fabsf( float %X )
+ %Y = call float @fabsf( float %X ) readnone
%x.addr = alloca float, align 4
store float %x, float* %x.addr, align 4
%0 = load float* %x.addr, align 4
%x.addr = alloca float, align 4
store float %x, float* %x.addr, align 4
%0 = load float* %x.addr, align 4
- %call = call float @fabsf(float %0)
+ %call = call float @fabsf(float %0) readnone
define double @fabs(double %f) {
entry:
define double @fabs(double %f) {
entry:
- %tmp2 = tail call double @fabs( double %f ) ; <double> [#uses=1]
+ %tmp2 = tail call double @fabs( double %f ) readnone ; <double> [#uses=1]
declare double @fabs(double)
define double @test(double %X) {
declare double @fabs(double)
define double @test(double %X) {
- %Y = call double @fabs( double %X ) ; <double> [#uses=1]
+ %Y = call double @fabs( double %X ) readnone ; <double> [#uses=1]
%Z = fsub double -0.000000e+00, %Y ; <double> [#uses=1]
ret double %Z
}
%Z = fsub double -0.000000e+00, %Y ; <double> [#uses=1]
ret double %Z
}
; UNSAFE: test1:
; NOOPT: test1:
define float @test1(float %X) {
; UNSAFE: test1:
; NOOPT: test1:
define float @test1(float %X) {
- %Y = call float @fabsf(float %X)
+ %Y = call float @fabsf(float %X) readnone
ret float %Y
}
; CHECK: {{^[ \t]+fabs$}}
ret float %Y
}
; CHECK: {{^[ \t]+fabs$}}
; UNSAFE: test3:
; NOOPT: test3:
define x86_fp80 @test3(x86_fp80 %X) {
; UNSAFE: test3:
; NOOPT: test3:
define x86_fp80 @test3(x86_fp80 %X) {
- %Y = call x86_fp80 @fabsl(x86_fp80 %X)
+ %Y = call x86_fp80 @fabsl(x86_fp80 %X) readnone
ret x86_fp80 %Y
}
; CHECK: {{^[ \t]+fabs$}}
ret x86_fp80 %Y
}
; CHECK: {{^[ \t]+fabs$}}
define void @test({ double, double }* byval %z, double* %P) nounwind {
entry:
%tmp3 = load double* @G, align 16 ; <double> [#uses=1]
define void @test({ double, double }* byval %z, double* %P) nounwind {
entry:
%tmp3 = load double* @G, align 16 ; <double> [#uses=1]
- %tmp4 = tail call double @fabs( double %tmp3 ) ; <double> [#uses=1]
+ %tmp4 = tail call double @fabs( double %tmp3 ) readnone ; <double> [#uses=1]
store volatile double %tmp4, double* %P
%tmp = getelementptr { double, double }* %z, i32 0, i32 0 ; <double*> [#uses=1]
%tmp1 = load volatile double* %tmp, align 8 ; <double> [#uses=1]
store volatile double %tmp4, double* %P
%tmp = getelementptr { double, double }* %z, i32 0, i32 0 ; <double*> [#uses=1]
%tmp1 = load volatile double* %tmp, align 8 ; <double> [#uses=1]
- %tmp2 = tail call double @fabs( double %tmp1 ) ; <double> [#uses=1]
+ %tmp2 = tail call double @fabs( double %tmp1 ) readnone ; <double> [#uses=1]
; CHECK: andpd{{.*}}4(%esp), %xmm
%tmp6 = fadd double %tmp4, %tmp2 ; <double> [#uses=1]
store volatile double %tmp6, double* %P, align 8
; CHECK: andpd{{.*}}4(%esp), %xmm
%tmp6 = fadd double %tmp4, %tmp2 ; <double> [#uses=1]
store volatile double %tmp6, double* %P, align 8