forked from OSchip/llvm-project
parent
cde5e5b600
commit
2511c031de
|
@ -494,6 +494,8 @@ static bool fnegFoldsIntoOp(unsigned Opc) {
|
|||
case ISD::FMUL:
|
||||
case ISD::FMA:
|
||||
case ISD::FMAD:
|
||||
case ISD::FMINNUM:
|
||||
case ISD::FMAXNUM:
|
||||
case ISD::FSIN:
|
||||
case ISD::FTRUNC:
|
||||
case ISD::FRINT:
|
||||
|
@ -2896,6 +2898,12 @@ SDValue AMDGPUTargetLowering::performSelectCombine(SDNode *N,
|
|||
return performCtlzCombine(SDLoc(N), Cond, True, False, DCI);
|
||||
}
|
||||
|
||||
static bool isConstantFPZero(SDValue N) {
|
||||
if (const ConstantFPSDNode *C = isConstOrConstSplatFP(N))
|
||||
return C->isZero() && !C->isNegative();
|
||||
return false;
|
||||
}
|
||||
|
||||
SDValue AMDGPUTargetLowering::performFNegCombine(SDNode *N,
|
||||
DAGCombinerInfo &DCI) const {
|
||||
SelectionDAG &DAG = DCI.DAG;
|
||||
|
@ -2990,6 +2998,28 @@ SDValue AMDGPUTargetLowering::performFNegCombine(SDNode *N,
|
|||
DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
|
||||
return Res;
|
||||
}
|
||||
case ISD::FMAXNUM:
|
||||
case ISD::FMINNUM: {
|
||||
// fneg (fmaxnum x, y) -> fminnum (fneg x), (fneg y)
|
||||
// fneg (fminnum x, y) -> fmaxnum (fneg x), (fneg y)
|
||||
SDValue LHS = N0.getOperand(0);
|
||||
SDValue RHS = N0.getOperand(1);
|
||||
|
||||
// 0 doesn't have a negated inline immediate.
|
||||
// TODO: Shouldn't fold 1/2pi either, and should be generalized to other
|
||||
// operations.
|
||||
if (isConstantFPZero(RHS))
|
||||
return SDValue();
|
||||
|
||||
SDValue NegLHS = DAG.getNode(ISD::FNEG, SL, VT, LHS);
|
||||
SDValue NegRHS = DAG.getNode(ISD::FNEG, SL, VT, RHS);
|
||||
unsigned Opposite = (Opc == ISD::FMAXNUM) ? ISD::FMINNUM : ISD::FMAXNUM;
|
||||
|
||||
SDValue Res = DAG.getNode(Opposite, SL, VT, NegLHS, NegRHS, N0->getFlags());
|
||||
if (!N0.hasOneUse())
|
||||
DAG.ReplaceAllUsesWith(N0, DAG.getNode(ISD::FNEG, SL, VT, Res));
|
||||
return Res;
|
||||
}
|
||||
case ISD::FP_EXTEND:
|
||||
case ISD::FTRUNC:
|
||||
case ISD::FRINT:
|
||||
|
|
|
@ -385,6 +385,268 @@ define void @v_fneg_mul_multi_use_fneg_x_f32(float addrspace(1)* %out, float add
|
|||
ret void
|
||||
}
|
||||
|
||||
; --------------------------------------------------------------------------------
|
||||
; fminnum tests
|
||||
; --------------------------------------------------------------------------------
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_minnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]]
|
||||
; GCN: v_max_f32_e64 [[RESULT:v[0-9]+]], -[[A]], -[[B]]
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_minnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr, float addrspace(1)* %b.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%b.gep = getelementptr inbounds float, float addrspace(1)* %b.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%b = load volatile float, float addrspace(1)* %b.gep
|
||||
%min = call float @llvm.minnum.f32(float %a, float %b)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
store float %fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_self_minnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: v_max_f32_e64 [[RESULT:v[0-9]+]], -[[A]], -[[A]]
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_self_minnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%min = call float @llvm.minnum.f32(float %a, float %a)
|
||||
%min.fneg = fsub float -0.0, %min
|
||||
store float %min.fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_posk_minnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: v_max_f32_e64 [[RESULT:v[0-9]+]], -[[A]], -4.0
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_posk_minnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%min = call float @llvm.minnum.f32(float 4.0, float %a)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
store float %fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_negk_minnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: v_max_f32_e64 [[RESULT:v[0-9]+]], -[[A]], 4.0
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_negk_minnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%min = call float @llvm.minnum.f32(float -4.0, float %a)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
store float %fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_0_minnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[A]]
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_0_minnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%min = call float @llvm.minnum.f32(float 0.0, float %a)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
store float %fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_0_minnum_foldable_use_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]]
|
||||
; GCN: v_min_f32_e32 [[MIN:v[0-9]+]], 0, [[A]]
|
||||
; GCN: v_mul_f32_e64 [[RESULT:v[0-9]+]], -[[MIN]], [[B]]
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_0_minnum_foldable_use_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr, float addrspace(1)* %b.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%b.gep = getelementptr inbounds float, float addrspace(1)* %b.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%b = load volatile float, float addrspace(1)* %b.gep
|
||||
%min = call float @llvm.minnum.f32(float 0.0, float %a)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
%mul = fmul float %fneg, %b
|
||||
store float %mul, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_minnum_multi_use_minnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]]
|
||||
; GCN: v_max_f32_e64 [[MAX0:v[0-9]+]], -[[A]], -[[B]]
|
||||
; GCN-NEXT: v_mul_f32_e32 [[MUL1:v[0-9]+]], -4.0, [[MUL0]]
|
||||
; GCN-NEXT: buffer_store_dword [[MAX0]]
|
||||
; GCN-NEXT: buffer_store_dword [[MUL1]]
|
||||
define void @v_fneg_minnum_multi_use_minnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr, float addrspace(1)* %b.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%b.gep = getelementptr inbounds float, float addrspace(1)* %b.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%b = load volatile float, float addrspace(1)* %b.gep
|
||||
%min = call float @llvm.minnum.f32(float %a, float %b)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
%use1 = fmul float %min, 4.0
|
||||
store volatile float %fneg, float addrspace(1)* %out
|
||||
store volatile float %use1, float addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
||||
; --------------------------------------------------------------------------------
|
||||
; fmaxnum tests
|
||||
; --------------------------------------------------------------------------------
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_maxnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]]
|
||||
; GCN: v_min_f32_e64 [[RESULT:v[0-9]+]], -[[A]], -[[B]]
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_maxnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr, float addrspace(1)* %b.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%b.gep = getelementptr inbounds float, float addrspace(1)* %b.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%b = load volatile float, float addrspace(1)* %b.gep
|
||||
%min = call float @llvm.maxnum.f32(float %a, float %b)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
store float %fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_self_maxnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: v_min_f32_e64 [[RESULT:v[0-9]+]], -[[A]], -[[A]]
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_self_maxnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%min = call float @llvm.maxnum.f32(float %a, float %a)
|
||||
%min.fneg = fsub float -0.0, %min
|
||||
store float %min.fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_posk_maxnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: v_min_f32_e64 [[RESULT:v[0-9]+]], -[[A]], -4.0
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_posk_maxnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%min = call float @llvm.maxnum.f32(float 4.0, float %a)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
store float %fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_negk_maxnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: v_min_f32_e64 [[RESULT:v[0-9]+]], -[[A]], 4.0
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_negk_maxnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%min = call float @llvm.maxnum.f32(float -4.0, float %a)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
store float %fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_0_maxnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[A]]
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_0_maxnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%max = call float @llvm.maxnum.f32(float 0.0, float %a)
|
||||
%fneg = fsub float -0.000000e+00, %max
|
||||
store float %fneg, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_0_maxnum_foldable_use_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]]
|
||||
; GCN: v_max_f32_e32 [[MAX:v[0-9]+]], 0, [[A]]
|
||||
; GCN: v_mul_f32_e64 [[RESULT:v[0-9]+]], -[[MAX]], [[B]]
|
||||
; GCN: buffer_store_dword [[RESULT]]
|
||||
define void @v_fneg_0_maxnum_foldable_use_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr, float addrspace(1)* %b.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%b.gep = getelementptr inbounds float, float addrspace(1)* %b.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%b = load volatile float, float addrspace(1)* %b.gep
|
||||
%max = call float @llvm.maxnum.f32(float 0.0, float %a)
|
||||
%fneg = fsub float -0.000000e+00, %max
|
||||
%mul = fmul float %fneg, %b
|
||||
store float %mul, float addrspace(1)* %out.gep
|
||||
ret void
|
||||
}
|
||||
|
||||
; GCN-LABEL: {{^}}v_fneg_maxnum_multi_use_maxnum_f32:
|
||||
; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]]
|
||||
; GCN: {{buffer|flat}}_load_dword [[B:v[0-9]+]]
|
||||
; GCN: v_min_f32_e64 [[MAX0:v[0-9]+]], -[[A]], -[[B]]
|
||||
; GCN-NEXT: v_mul_f32_e32 [[MUL1:v[0-9]+]], -4.0, [[MUL0]]
|
||||
; GCN-NEXT: buffer_store_dword [[MAX0]]
|
||||
; GCN-NEXT: buffer_store_dword [[MUL1]]
|
||||
define void @v_fneg_maxnum_multi_use_maxnum_f32(float addrspace(1)* %out, float addrspace(1)* %a.ptr, float addrspace(1)* %b.ptr) #0 {
|
||||
%tid = call i32 @llvm.amdgcn.workitem.id.x()
|
||||
%tid.ext = sext i32 %tid to i64
|
||||
%a.gep = getelementptr inbounds float, float addrspace(1)* %a.ptr, i64 %tid.ext
|
||||
%b.gep = getelementptr inbounds float, float addrspace(1)* %b.ptr, i64 %tid.ext
|
||||
%out.gep = getelementptr inbounds float, float addrspace(1)* %out, i64 %tid.ext
|
||||
%a = load volatile float, float addrspace(1)* %a.gep
|
||||
%b = load volatile float, float addrspace(1)* %b.gep
|
||||
%min = call float @llvm.maxnum.f32(float %a, float %b)
|
||||
%fneg = fsub float -0.000000e+00, %min
|
||||
%use1 = fmul float %min, 4.0
|
||||
store volatile float %fneg, float addrspace(1)* %out
|
||||
store volatile float %use1, float addrspace(1)* %out
|
||||
ret void
|
||||
}
|
||||
|
||||
; --------------------------------------------------------------------------------
|
||||
; fma tests
|
||||
; --------------------------------------------------------------------------------
|
||||
|
@ -1825,6 +2087,8 @@ declare float @llvm.trunc.f32(float) #1
|
|||
declare float @llvm.round.f32(float) #1
|
||||
declare float @llvm.rint.f32(float) #1
|
||||
declare float @llvm.nearbyint.f32(float) #1
|
||||
declare float @llvm.minnum.f32(float, float) #1
|
||||
declare float @llvm.maxnum.f32(float, float) #1
|
||||
|
||||
declare double @llvm.fma.f64(double, double, double) #1
|
||||
|
||||
|
|
Loading…
Reference in New Issue