
For some reason, isOperationLegalOrCustom is not the same as isOperationLegal || isOperationCustom. Unfortunately, it checks if the type is legal which makes it uesless for custom lowering on non-legal types (which is always ppcf128). Really the DAG builder shouldn't be going to expand this in the builder, it makes it difficult to work with. It's only here to work around the DAG requiring legal integer types the same size as the FP type after type legalization.
448 lines
12 KiB
LLVM
448 lines
12 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs -o - %s | FileCheck %s
|
|
|
|
|
|
define i1 @isnan_float(float %x) nounwind {
|
|
; CHECK-LABEL: isnan_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcsp 0, 1, 64
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 3) ; nan
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnan_double(double %x) nounwind {
|
|
; CHECK-LABEL: isnan_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 64
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 3) ; nan
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnan_ppc_fp128(ppc_fp128 %x) nounwind {
|
|
; CHECK-LABEL: isnan_ppc_fp128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 64
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.ppcf128(ppc_fp128 %x, i32 3) ; nan
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnan_f128(fp128 %x) nounwind {
|
|
; CHECK-LABEL: isnan_f128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcqp 0, 2, 64
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 3) ; nan
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnan_float_strictfp(float %x) strictfp nounwind {
|
|
; CHECK-LABEL: isnan_float_strictfp:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcsp 0, 1, 64
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 3) strictfp ; nan
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnan_double_strictfp(double %x) strictfp nounwind {
|
|
; CHECK-LABEL: isnan_double_strictfp:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 64
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 3) strictfp ; nan
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnan_ppc_fp128_strictfp(ppc_fp128 %x) strictfp nounwind {
|
|
; CHECK-LABEL: isnan_ppc_fp128_strictfp:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 64
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.ppcf128(ppc_fp128 %x, i32 3) strictfp ; nan
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnan_f128_strictfp(fp128 %x) strictfp nounwind {
|
|
; CHECK-LABEL: isnan_f128_strictfp:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcqp 0, 2, 64
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 3) strictfp ; nan
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isinf_float(float %x) nounwind {
|
|
; CHECK-LABEL: isinf_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcsp 0, 1, 48
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 516) ; 0x204 = "inf"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isinf_ppc_fp128(ppc_fp128 %x) nounwind {
|
|
; CHECK-LABEL: isinf_ppc_fp128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 48
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.ppcf128(ppc_fp128 %x, i32 516) ; 0x204 = "inf"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isinf_f128(fp128 %x) nounwind {
|
|
; CHECK-LABEL: isinf_f128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcqp 0, 2, 48
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 516) ; 0x204 = "inf"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isfinite_float(float %x) nounwind {
|
|
; CHECK-LABEL: isfinite_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcsp 0, 1, 112
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: iseleq 3, 0, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 504) ; 0x1f8 = "finite"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isfinite_f128(fp128 %x) nounwind {
|
|
; CHECK-LABEL: isfinite_f128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcqp 0, 2, 112
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: iseleq 3, 0, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 504) ; 0x1f8 = "finite"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnormal_float(float %x) nounwind {
|
|
; CHECK-LABEL: isnormal_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcsp 0, 1, 127
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: iseleq 3, 0, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 264) ; 0x108 = "normal"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnormal_f128(fp128 %x) nounwind {
|
|
; CHECK-LABEL: isnormal_f128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcqp 0, 2, 127
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: iseleq 3, 0, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 264) ; 0x108 = "normal"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @issubnormal_float(float %x) nounwind {
|
|
; CHECK-LABEL: issubnormal_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcsp 0, 1, 3
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 144) ; 0x90 = "subnormal"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @issubnormal_f128(fp128 %x) nounwind {
|
|
; CHECK-LABEL: issubnormal_f128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcqp 0, 2, 3
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 144) ; 0x90 = "subnormal"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @iszero_float(float %x) nounwind {
|
|
; CHECK-LABEL: iszero_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcsp 0, 1, 12
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 96) ; 0x60 = "zero"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @iszero_f128(fp128 %x) nounwind {
|
|
; CHECK-LABEL: iszero_f128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcqp 0, 2, 12
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 96) ; 0x60 = "zero"
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @issnan_float(float %x) nounwind {
|
|
; CHECK-LABEL: issnan_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xscvdpspn 0, 1
|
|
; CHECK-NEXT: xststdcsp 1, 1, 64
|
|
; CHECK-NEXT: mffprwz 3, 0
|
|
; CHECK-NEXT: andis. 3, 3, 64
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnand 20, 6, 2
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 1)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @issnan_double(double %x) nounwind {
|
|
; CHECK-LABEL: issnan_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: mffprd 3, 1
|
|
; CHECK-NEXT: xststdcdp 1, 1, 64
|
|
; CHECK-NEXT: rldicl 3, 3, 32, 32
|
|
; CHECK-NEXT: andis. 3, 3, 8
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnand 20, 6, 2
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 1)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @issnan_fp128(fp128 %x) nounwind {
|
|
; CHECK-LABEL: issnan_fp128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: li 3, 12
|
|
; CHECK-NEXT: xststdcqp 1, 2, 64
|
|
; CHECK-NEXT: vextuwrx 3, 3, 2
|
|
; CHECK-NEXT: andi. 3, 3, 32768
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnand 20, 6, 2
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 1)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @issnan_ppc_fp128(ppc_fp128 %x) nounwind {
|
|
; CHECK-LABEL: issnan_ppc_fp128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: mffprd 3, 1
|
|
; CHECK-NEXT: xststdcdp 1, 1, 64
|
|
; CHECK-NEXT: rldicl 3, 3, 32, 32
|
|
; CHECK-NEXT: andis. 3, 3, 8
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnand 20, 6, 2
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.ppcf128(ppc_fp128 %x, i32 1)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isqnan_float(float %x) nounwind {
|
|
; CHECK-LABEL: isqnan_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xscvdpspn 0, 1
|
|
; CHECK-NEXT: xststdcsp 1, 1, 64
|
|
; CHECK-NEXT: mffprwz 3, 0
|
|
; CHECK-NEXT: srwi 3, 3, 22
|
|
; CHECK-NEXT: andi. 3, 3, 1
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnand 20, 6, 1
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 2)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isqnan_double(double %x) nounwind {
|
|
; CHECK-LABEL: isqnan_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: mffprd 3, 1
|
|
; CHECK-NEXT: xststdcdp 1, 1, 64
|
|
; CHECK-NEXT: rldicl 3, 3, 13, 51
|
|
; CHECK-NEXT: andi. 3, 3, 1
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnand 20, 6, 1
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 2)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isqnan_fp128(fp128 %x) nounwind {
|
|
; CHECK-LABEL: isqnan_fp128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: li 3, 12
|
|
; CHECK-NEXT: xststdcqp 1, 2, 64
|
|
; CHECK-NEXT: vextuwrx 3, 3, 2
|
|
; CHECK-NEXT: srwi 3, 3, 15
|
|
; CHECK-NEXT: andi. 3, 3, 1
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnand 20, 6, 1
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f128(fp128 %x, i32 2)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isqnan_ppc_fp128(ppc_fp128 %x) nounwind {
|
|
; CHECK-LABEL: isqnan_ppc_fp128:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: mffprd 3, 1
|
|
; CHECK-NEXT: xststdcdp 1, 1, 64
|
|
; CHECK-NEXT: rldicl 3, 3, 13, 51
|
|
; CHECK-NEXT: andi. 3, 3, 1
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnand 20, 6, 1
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.ppcf128(ppc_fp128 %x, i32 2)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isposzero_double(double %x) nounwind {
|
|
; CHECK-LABEL: isposzero_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 8
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 64)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnegzero_double(double %x) nounwind {
|
|
; CHECK-LABEL: isnegzero_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 4
|
|
; CHECK-NEXT: li 3, 0
|
|
; CHECK-NEXT: li 4, 1
|
|
; CHECK-NEXT: iseleq 3, 4, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 32)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isposnormal_double(double %x) nounwind {
|
|
; CHECK-LABEL: isposnormal_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 127
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: cror 20, 0, 2
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 256)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnegnormal_double(double %x) nounwind {
|
|
; CHECK-LABEL: isnegnormal_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 127
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crorc 20, 2, 0
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 8)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isnormal_double(double %x) nounwind {
|
|
; CHECK-LABEL: isnormal_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcdp 0, 1, 127
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: iseleq 3, 0, 3
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 264)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isclass_00d_double(double %x) nounwind {
|
|
; CHECK-LABEL: isclass_00d_double:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: mffprd 3, 1
|
|
; CHECK-NEXT: xststdcdp 0, 1, 127
|
|
; CHECK-NEXT: xststdcdp 1, 1, 64
|
|
; CHECK-NEXT: rldicl 3, 3, 32, 32
|
|
; CHECK-NEXT: crandc 20, 0, 2
|
|
; CHECK-NEXT: andis. 3, 3, 8
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crand 21, 6, 2
|
|
; CHECK-NEXT: xststdcdp 0, 1, 16
|
|
; CHECK-NEXT: cror 21, 2, 21
|
|
; CHECK-NEXT: crnor 20, 21, 20
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 13)
|
|
ret i1 %1
|
|
}
|
|
|
|
define i1 @isclass_1c0_float(float %x) nounwind {
|
|
; CHECK-LABEL: isclass_1c0_float:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: xststdcsp 0, 1, 127
|
|
; CHECK-NEXT: li 3, 1
|
|
; CHECK-NEXT: crnor 20, 0, 2
|
|
; CHECK-NEXT: xststdcsp 0, 1, 10
|
|
; CHECK-NEXT: crnor 20, 2, 20
|
|
; CHECK-NEXT: isel 3, 0, 3, 20
|
|
; CHECK-NEXT: blr
|
|
%1 = call i1 @llvm.is.fpclass.f32(float %x, i32 448)
|
|
ret i1 %1
|
|
}
|
|
|
|
declare i1 @llvm.is.fpclass.f32(float, i32)
|
|
declare i1 @llvm.is.fpclass.f64(double, i32)
|
|
declare i1 @llvm.is.fpclass.ppcf128(ppc_fp128, i32)
|
|
declare i1 @llvm.is.fpclass.f128(fp128, i32)
|