mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[WebAssembly] Remove saturating fp-to-int target intrinsics
Use the target-independent @llvm.fptosi and @llvm.fptoui intrinsics instead. This includes removing the instrinsics for i32x4.trunc_sat_zero_f64x2_{s,u}, which are now represented in IR as a saturating truncation to a v2i32 followed by a concatenation with a zero vector. Differential Revision: https://reviews.llvm.org/D100596
This commit is contained in:
parent
773674bb59
commit
135ccc6ee6
@ -264,12 +264,6 @@ def int_wasm_extadd_pairwise_unsigned :
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
|
||||
// TODO: Remove these if possible if they are merged to the spec.
|
||||
def int_wasm_trunc_sat_zero_signed :
|
||||
Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
def int_wasm_trunc_sat_zero_unsigned :
|
||||
Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
def int_wasm_demote_zero :
|
||||
Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty],
|
||||
[IntrNoMem, IntrSpeculatable]>;
|
||||
|
@ -1493,8 +1493,6 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
|
||||
// WebAssembly float semantics are always known
|
||||
case Intrinsic::wasm_trunc_signed:
|
||||
case Intrinsic::wasm_trunc_unsigned:
|
||||
case Intrinsic::wasm_trunc_saturate_signed:
|
||||
case Intrinsic::wasm_trunc_saturate_unsigned:
|
||||
return true;
|
||||
|
||||
// Floating point operations cannot be folded in strictfp functions in
|
||||
@ -1896,17 +1894,11 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
|
||||
APFloat U = Op->getValueAPF();
|
||||
|
||||
if (IntrinsicID == Intrinsic::wasm_trunc_signed ||
|
||||
IntrinsicID == Intrinsic::wasm_trunc_unsigned ||
|
||||
IntrinsicID == Intrinsic::wasm_trunc_saturate_signed ||
|
||||
IntrinsicID == Intrinsic::wasm_trunc_saturate_unsigned) {
|
||||
|
||||
bool Saturating = IntrinsicID == Intrinsic::wasm_trunc_saturate_signed ||
|
||||
IntrinsicID == Intrinsic::wasm_trunc_saturate_unsigned;
|
||||
bool Signed = IntrinsicID == Intrinsic::wasm_trunc_signed ||
|
||||
IntrinsicID == Intrinsic::wasm_trunc_saturate_signed;
|
||||
IntrinsicID == Intrinsic::wasm_trunc_unsigned) {
|
||||
bool Signed = IntrinsicID == Intrinsic::wasm_trunc_signed;
|
||||
|
||||
if (U.isNaN())
|
||||
return Saturating ? ConstantInt::get(Ty, 0) : nullptr;
|
||||
return nullptr;
|
||||
|
||||
unsigned Width = Ty->getIntegerBitWidth();
|
||||
APSInt Int(Width, !Signed);
|
||||
@ -1917,15 +1909,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
|
||||
if (Status == APFloat::opOK || Status == APFloat::opInexact)
|
||||
return ConstantInt::get(Ty, Int);
|
||||
|
||||
if (!Saturating)
|
||||
return nullptr;
|
||||
|
||||
if (U.isNegative())
|
||||
return Signed ? ConstantInt::get(Ty, APInt::getSignedMinValue(Width))
|
||||
: ConstantInt::get(Ty, APInt::getMinValue(Width));
|
||||
else
|
||||
return Signed ? ConstantInt::get(Ty, APInt::getSignedMaxValue(Width))
|
||||
: ConstantInt::get(Ty, APInt::getMaxValue(Width));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (IntrinsicID == Intrinsic::fptoui_sat ||
|
||||
|
@ -35,6 +35,8 @@ HANDLE_NODETYPE(EXTEND_HIGH_S)
|
||||
HANDLE_NODETYPE(EXTEND_HIGH_U)
|
||||
HANDLE_NODETYPE(CONVERT_LOW_S)
|
||||
HANDLE_NODETYPE(CONVERT_LOW_U)
|
||||
HANDLE_NODETYPE(TRUNC_SAT_ZERO_S)
|
||||
HANDLE_NODETYPE(TRUNC_SAT_ZERO_U)
|
||||
HANDLE_NODETYPE(THROW)
|
||||
HANDLE_NODETYPE(CATCH)
|
||||
HANDLE_NODETYPE(MEMORY_COPY)
|
||||
|
@ -121,6 +121,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
||||
setOperationAction(Op, T, Expand);
|
||||
}
|
||||
|
||||
if (Subtarget->hasNontrappingFPToInt())
|
||||
for (auto Op : {ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT})
|
||||
for (auto T : {MVT::i32, MVT::i64})
|
||||
setOperationAction(Op, T, Custom);
|
||||
|
||||
// SIMD-specific configuration
|
||||
if (Subtarget->hasSIMD128()) {
|
||||
// Hoist bitcasts out of shuffles
|
||||
@ -134,6 +139,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
||||
setTargetDAGCombine(ISD::SINT_TO_FP);
|
||||
setTargetDAGCombine(ISD::UINT_TO_FP);
|
||||
|
||||
// Combine concat of {s,u}int_to_fp_sat to i32x4.trunc_sat_f64x2_zero_{s,u}
|
||||
setTargetDAGCombine(ISD::CONCAT_VECTORS);
|
||||
|
||||
// Support saturating add for i8x16 and i16x8
|
||||
for (auto Op : {ISD::SADDSAT, ISD::UADDSAT})
|
||||
for (auto T : {MVT::v16i8, MVT::v8i16})
|
||||
@ -198,6 +206,10 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
|
||||
{ISD::SINT_TO_FP, ISD::UINT_TO_FP, ISD::FP_TO_SINT, ISD::FP_TO_UINT})
|
||||
for (auto T : {MVT::v2i64, MVT::v2f64})
|
||||
setOperationAction(Op, T, Expand);
|
||||
|
||||
// But saturating fp_to_int converstions are
|
||||
for (auto Op : {ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT})
|
||||
setOperationAction(Op, MVT::v4i32, Custom);
|
||||
}
|
||||
|
||||
// As a special case, these operators use the type to mean the type to
|
||||
@ -1237,6 +1249,9 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
|
||||
case ISD::SRA:
|
||||
case ISD::SRL:
|
||||
return LowerShift(Op, DAG);
|
||||
case ISD::FP_TO_SINT_SAT:
|
||||
case ISD::FP_TO_UINT_SAT:
|
||||
return LowerFP_TO_INT_SAT(Op, DAG);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1953,6 +1968,21 @@ SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
|
||||
return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0), ShiftVal);
|
||||
}
|
||||
|
||||
SDValue WebAssemblyTargetLowering::LowerFP_TO_INT_SAT(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDLoc DL(Op);
|
||||
EVT ResT = Op.getValueType();
|
||||
uint64_t Width = Op.getConstantOperandVal(1);
|
||||
|
||||
if ((ResT == MVT::i32 || ResT == MVT::i64) && (Width == 32 || Width == 64))
|
||||
return Op;
|
||||
|
||||
if (ResT == MVT::v4i32 && Width == 32)
|
||||
return Op;
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Custom DAG combine hooks
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -2041,6 +2071,8 @@ performVectorConvertLowCombine(SDNode *N,
|
||||
if (Extract.getOpcode() != ISD::EXTRACT_SUBVECTOR)
|
||||
return SDValue();
|
||||
auto Source = Extract.getOperand(0);
|
||||
if (Source.getValueType() != MVT::v4i32)
|
||||
return SDValue();
|
||||
auto *IndexNode = dyn_cast<ConstantSDNode>(Extract.getOperand(1));
|
||||
if (IndexNode == nullptr)
|
||||
return SDValue();
|
||||
@ -2062,6 +2094,49 @@ performVectorConvertLowCombine(SDNode *N,
|
||||
return DAG.getNode(Op, SDLoc(N), ResVT, Source);
|
||||
}
|
||||
|
||||
static SDValue
|
||||
performVectorTruncSatLowCombine(SDNode *N,
|
||||
TargetLowering::DAGCombinerInfo &DCI) {
|
||||
auto &DAG = DCI.DAG;
|
||||
assert(N->getOpcode() == ISD::CONCAT_VECTORS);
|
||||
|
||||
// Combine this:
|
||||
//
|
||||
// (concat_vectors (v2i32 (fp_to_{s,u}int_sat $x, 32)), (v2i32 (splat 0)))
|
||||
//
|
||||
// into (i32x4.trunc_sat_f64x2_zero_{s,u} $x).
|
||||
EVT ResVT = N->getValueType(0);
|
||||
if (ResVT != MVT::v4i32)
|
||||
return SDValue();
|
||||
|
||||
auto FPToInt = N->getOperand(0);
|
||||
auto FPToIntOp = FPToInt.getOpcode();
|
||||
if (FPToIntOp != ISD::FP_TO_SINT_SAT && FPToIntOp != ISD::FP_TO_UINT_SAT)
|
||||
return SDValue();
|
||||
if (FPToInt.getConstantOperandVal(1) != 32)
|
||||
return SDValue();
|
||||
|
||||
auto Source = FPToInt.getOperand(0);
|
||||
if (Source.getValueType() != MVT::v2f64)
|
||||
return SDValue();
|
||||
|
||||
auto *Splat = dyn_cast<BuildVectorSDNode>(N->getOperand(1));
|
||||
APInt SplatValue, SplatUndef;
|
||||
unsigned SplatBitSize;
|
||||
bool HasAnyUndefs;
|
||||
if (!Splat || !Splat->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
|
||||
HasAnyUndefs))
|
||||
return SDValue();
|
||||
if (SplatValue != 0)
|
||||
return SDValue();
|
||||
|
||||
unsigned Op = FPToIntOp == ISD::FP_TO_SINT_SAT
|
||||
? WebAssemblyISD::TRUNC_SAT_ZERO_S
|
||||
: WebAssemblyISD::TRUNC_SAT_ZERO_U;
|
||||
|
||||
return DAG.getNode(Op, SDLoc(N), ResVT, Source);
|
||||
}
|
||||
|
||||
SDValue
|
||||
WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
|
||||
DAGCombinerInfo &DCI) const {
|
||||
@ -2076,5 +2151,7 @@ WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
|
||||
case ISD::SINT_TO_FP:
|
||||
case ISD::UINT_TO_FP:
|
||||
return performVectorConvertLowCombine(N, DCI);
|
||||
case ISD::CONCAT_VECTORS:
|
||||
return performVectorTruncSatLowCombine(N, DCI);
|
||||
}
|
||||
}
|
||||
|
@ -119,6 +119,7 @@ private:
|
||||
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerAccessVectorElement(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
// Custom DAG combine hooks
|
||||
SDValue
|
||||
|
@ -96,23 +96,15 @@ defm I64_TRUNC_U_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins),
|
||||
"i64.trunc_sat_f64_u", 0xfc07>,
|
||||
Requires<[HasNontrappingFPToInt]>;
|
||||
|
||||
// Lower llvm.wasm.trunc.saturate.* to saturating instructions
|
||||
def : Pat<(int_wasm_trunc_saturate_signed F32:$src),
|
||||
(I32_TRUNC_S_SAT_F32 F32:$src)>;
|
||||
def : Pat<(int_wasm_trunc_saturate_unsigned F32:$src),
|
||||
(I32_TRUNC_U_SAT_F32 F32:$src)>;
|
||||
def : Pat<(int_wasm_trunc_saturate_signed F64:$src),
|
||||
(I32_TRUNC_S_SAT_F64 F64:$src)>;
|
||||
def : Pat<(int_wasm_trunc_saturate_unsigned F64:$src),
|
||||
(I32_TRUNC_U_SAT_F64 F64:$src)>;
|
||||
def : Pat<(int_wasm_trunc_saturate_signed F32:$src),
|
||||
(I64_TRUNC_S_SAT_F32 F32:$src)>;
|
||||
def : Pat<(int_wasm_trunc_saturate_unsigned F32:$src),
|
||||
(I64_TRUNC_U_SAT_F32 F32:$src)>;
|
||||
def : Pat<(int_wasm_trunc_saturate_signed F64:$src),
|
||||
(I64_TRUNC_S_SAT_F64 F64:$src)>;
|
||||
def : Pat<(int_wasm_trunc_saturate_unsigned F64:$src),
|
||||
(I64_TRUNC_U_SAT_F64 F64:$src)>;
|
||||
// Support the explicitly saturating operations as well.
|
||||
def : Pat<(fp_to_sint_sat F32:$src, (i32 32)), (I32_TRUNC_S_SAT_F32 F32:$src)>;
|
||||
def : Pat<(fp_to_uint_sat F32:$src, (i32 32)), (I32_TRUNC_U_SAT_F32 F32:$src)>;
|
||||
def : Pat<(fp_to_sint_sat F64:$src, (i32 32)), (I32_TRUNC_S_SAT_F64 F64:$src)>;
|
||||
def : Pat<(fp_to_uint_sat F64:$src, (i32 32)), (I32_TRUNC_U_SAT_F64 F64:$src)>;
|
||||
def : Pat<(fp_to_sint_sat F32:$src, (i32 64)), (I64_TRUNC_S_SAT_F32 F32:$src)>;
|
||||
def : Pat<(fp_to_uint_sat F32:$src, (i32 64)), (I64_TRUNC_U_SAT_F32 F32:$src)>;
|
||||
def : Pat<(fp_to_sint_sat F64:$src, (i32 64)), (I64_TRUNC_S_SAT_F64 F64:$src)>;
|
||||
def : Pat<(fp_to_uint_sat F64:$src, (i32 64)), (I64_TRUNC_U_SAT_F64 F64:$src)>;
|
||||
|
||||
// Conversion from floating point to integer pseudo-instructions which don't
|
||||
// trap on overflow or invalid.
|
||||
|
@ -1091,11 +1091,21 @@ multiclass SIMDConvert<Vec vec, Vec arg, SDPatternOperator op, string name,
|
||||
defm "" : SIMDConvert<I32x4, F32x4, fp_to_sint, "trunc_sat_f32x4_s", 248>;
|
||||
defm "" : SIMDConvert<I32x4, F32x4, fp_to_uint, "trunc_sat_f32x4_u", 249>;
|
||||
|
||||
// Lower llvm.wasm.trunc.sat.* to saturating instructions
|
||||
def : Pat<(v4i32 (int_wasm_trunc_saturate_signed (v4f32 V128:$src))),
|
||||
(fp_to_sint_I32x4 $src)>;
|
||||
def : Pat<(v4i32 (int_wasm_trunc_saturate_unsigned (v4f32 V128:$src))),
|
||||
(fp_to_uint_I32x4 $src)>;
|
||||
// Support the saturating variety as well.
|
||||
def trunc_s_sat32 : PatFrag<(ops node:$x), (fp_to_sint_sat $x, (i32 32))>;
|
||||
def trunc_u_sat32 : PatFrag<(ops node:$x), (fp_to_uint_sat $x, (i32 32))>;
|
||||
def : Pat<(v4i32 (trunc_s_sat32 (v4f32 V128:$src))), (fp_to_sint_I32x4 $src)>;
|
||||
def : Pat<(v4i32 (trunc_u_sat32 (v4f32 V128:$src))), (fp_to_uint_I32x4 $src)>;
|
||||
|
||||
def trunc_sat_zero_t : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>]>;
|
||||
def trunc_sat_zero_s :
|
||||
SDNode<"WebAssemblyISD::TRUNC_SAT_ZERO_S", trunc_sat_zero_t>;
|
||||
def trunc_sat_zero_u :
|
||||
SDNode<"WebAssemblyISD::TRUNC_SAT_ZERO_U", trunc_sat_zero_t>;
|
||||
defm "" : SIMDConvert<I32x4, F64x2, trunc_sat_zero_s, "trunc_sat_zero_f64x2_s",
|
||||
0xfc>;
|
||||
defm "" : SIMDConvert<I32x4, F64x2, trunc_sat_zero_u, "trunc_sat_zero_f64x2_u",
|
||||
0xfd>;
|
||||
|
||||
// Integer to floating point: convert
|
||||
def convert_low_t : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>]>;
|
||||
@ -1248,10 +1258,6 @@ defm "" : SIMDConvert<F32x4, F64x2, int_wasm_demote_zero,
|
||||
"demote_zero_f64x2", 0x5e>;
|
||||
defm "" : SIMDConvert<F64x2, F32x4, int_wasm_promote_low,
|
||||
"promote_low_f32x4", 0x5f>;
|
||||
defm "" : SIMDConvert<I32x4, F64x2, int_wasm_trunc_sat_zero_signed,
|
||||
"trunc_sat_zero_f64x2_s", 0xfc>;
|
||||
defm "" : SIMDConvert<I32x4, F64x2, int_wasm_trunc_sat_zero_unsigned,
|
||||
"trunc_sat_zero_f64x2_u", 0xfd>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Saturating Rounding Q-Format Multiplication
|
||||
|
@ -45,9 +45,9 @@ define i32 @i32_trunc_s_f32(float %x) {
|
||||
; CHECK-NEXT: .functype i32_trunc_sat_s_f32 (f32) -> (i32){{$}}
|
||||
; CHECK-NEXT: i32.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[NUM]]{{$}}
|
||||
declare i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float)
|
||||
declare i32 @llvm.fptosi.sat.i32.f32(float)
|
||||
define i32 @i32_trunc_sat_s_f32(float %x) {
|
||||
%a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %x)
|
||||
%a = call i32 @llvm.fptosi.sat.i32.f32(float %x)
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
@ -64,9 +64,9 @@ define i32 @i32_trunc_u_f32(float %x) {
|
||||
; CHECK-NEXT: .functype i32_trunc_sat_u_f32 (f32) -> (i32){{$}}
|
||||
; CHECK-NEXT: i32.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[NUM]]{{$}}
|
||||
declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float)
|
||||
declare i32 @llvm.fptoui.sat.i32.f32(float)
|
||||
define i32 @i32_trunc_sat_u_f32(float %x) {
|
||||
%a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %x)
|
||||
%a = call i32 @llvm.fptoui.sat.i32.f32(float %x)
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
@ -83,9 +83,9 @@ define i32 @i32_trunc_s_f64(double %x) {
|
||||
; CHECK-NEXT: .functype i32_trunc_sat_s_f64 (f64) -> (i32){{$}}
|
||||
; CHECK-NEXT: i32.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[NUM]]{{$}}
|
||||
declare i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double)
|
||||
declare i32 @llvm.fptosi.sat.i32.f64(double)
|
||||
define i32 @i32_trunc_sat_s_f64(double %x) {
|
||||
%a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %x)
|
||||
%a = call i32 @llvm.fptosi.sat.i32.f64(double %x)
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
@ -102,9 +102,9 @@ define i32 @i32_trunc_u_f64(double %x) {
|
||||
; CHECK-NEXT: .functype i32_trunc_sat_u_f64 (f64) -> (i32){{$}}
|
||||
; CHECK-NEXT: i32.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[NUM]]{{$}}
|
||||
declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double)
|
||||
declare i32 @llvm.fptoui.sat.i32.f64(double)
|
||||
define i32 @i32_trunc_sat_u_f64(double %x) {
|
||||
%a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %x)
|
||||
%a = call i32 @llvm.fptoui.sat.i32.f64(double %x)
|
||||
ret i32 %a
|
||||
}
|
||||
|
||||
@ -121,9 +121,9 @@ define i64 @i64_trunc_s_f32(float %x) {
|
||||
; CHECK-NEXT: .functype i64_trunc_sat_s_f32 (f32) -> (i64){{$}}
|
||||
; CHECK-NEXT: i64.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[NUM]]{{$}}
|
||||
declare i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float)
|
||||
declare i64 @llvm.fptosi.sat.i64.f32(float)
|
||||
define i64 @i64_trunc_sat_s_f32(float %x) {
|
||||
%a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %x)
|
||||
%a = call i64 @llvm.fptosi.sat.i64.f32(float %x)
|
||||
ret i64 %a
|
||||
}
|
||||
|
||||
@ -140,9 +140,9 @@ define i64 @i64_trunc_u_f32(float %x) {
|
||||
; CHECK-NEXT: .functype i64_trunc_sat_u_f32 (f32) -> (i64){{$}}
|
||||
; CHECK-NEXT: i64.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[NUM]]{{$}}
|
||||
declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float)
|
||||
declare i64 @llvm.fptoui.sat.i64.f32(float)
|
||||
define i64 @i64_trunc_sat_u_f32(float %x) {
|
||||
%a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %x)
|
||||
%a = call i64 @llvm.fptoui.sat.i64.f32(float %x)
|
||||
ret i64 %a
|
||||
}
|
||||
|
||||
@ -159,9 +159,9 @@ define i64 @i64_trunc_s_f64(double %x) {
|
||||
; CHECK-NEXT: .functype i64_trunc_sat_s_f64 (f64) -> (i64){{$}}
|
||||
; CHECK-NEXT: i64.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[NUM]]{{$}}
|
||||
declare i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double)
|
||||
declare i64 @llvm.fptosi.sat.i64.f64(double)
|
||||
define i64 @i64_trunc_sat_s_f64(double %x) {
|
||||
%a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %x)
|
||||
%a = call i64 @llvm.fptosi.sat.i64.f64(double %x)
|
||||
ret i64 %a
|
||||
}
|
||||
|
||||
@ -178,9 +178,9 @@ define i64 @i64_trunc_u_f64(double %x) {
|
||||
; CHECK-NEXT: .functype i64_trunc_sat_u_f64 (f64) -> (i64){{$}}
|
||||
; CHECK-NEXT: i64.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[NUM]]{{$}}
|
||||
declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double)
|
||||
declare i64 @llvm.fptoui.sat.i64.f64(double)
|
||||
define i64 @i64_trunc_sat_u_f64(double %x) {
|
||||
%a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %x)
|
||||
%a = call i64 @llvm.fptoui.sat.i64.f64(double %x)
|
||||
ret i64 %a
|
||||
}
|
||||
|
||||
@ -274,7 +274,7 @@ define float @f32_demote_f64(double %x) {
|
||||
ret float %a
|
||||
}
|
||||
|
||||
; If the high its are unused, LLVM will optimize sext/zext into anyext, which
|
||||
; If the high bits are unused, LLVM will optimize sext/zext into anyext, which
|
||||
; we need to patterm-match back to a specific instruction.
|
||||
|
||||
; CHECK-LABEL: anyext:
|
||||
@ -312,3 +312,46 @@ define i64 @bitcast_double_to_i64(double %a) {
|
||||
%t = bitcast double %a to i64
|
||||
ret i64 %t
|
||||
}
|
||||
|
||||
; Check that saturating fptoint with unsupported target bit widths is lowered
|
||||
; correctly.
|
||||
|
||||
; CHECK-LABEL: i16_trunc_sat_s_f32:
|
||||
; CHECK-NEXT: .functype i16_trunc_sat_s_f32 (f32) -> (i32){{$}}
|
||||
; CHECK: i32.select
|
||||
; CHECK: return
|
||||
declare i16 @llvm.fptosi.sat.i16.f32(float)
|
||||
define i16 @i16_trunc_sat_s_f32(float %x) {
|
||||
%a = call i16 @llvm.fptosi.sat.i16.f32(float %x)
|
||||
ret i16 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: i16_trunc_sat_u_f32:
|
||||
; CHECK-NEXT: .functype i16_trunc_sat_u_f32 (f32) -> (i32){{$}}
|
||||
; CHECK: i32.select
|
||||
; CHECK: return
|
||||
declare i16 @llvm.fptoui.sat.i16.f32(float)
|
||||
define i16 @i16_trunc_sat_u_f32(float %x) {
|
||||
%a = call i16 @llvm.fptoui.sat.i16.f32(float %x)
|
||||
ret i16 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: i16_trunc_sat_s_f64:
|
||||
; CHECK-NEXT: .functype i16_trunc_sat_s_f64 (f64) -> (i32){{$}}
|
||||
; CHECK: i32.select
|
||||
; CHECK: return
|
||||
declare i16 @llvm.fptosi.sat.i16.f64(double)
|
||||
define i16 @i16_trunc_sat_s_f64(double %x) {
|
||||
%a = call i16 @llvm.fptosi.sat.i16.f64(double %x)
|
||||
ret i16 %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: i16_trunc_sat_u_f64:
|
||||
; CHECK-NEXT: .functype i16_trunc_sat_u_f64 (f64) -> (i32){{$}}
|
||||
; CHECK: i32.select
|
||||
; CHECK: return
|
||||
declare i16 @llvm.fptoui.sat.i16.f64(double)
|
||||
define i16 @i16_trunc_sat_u_f64(double %x) {
|
||||
%a = call i16 @llvm.fptoui.sat.i16.f64(double %x)
|
||||
ret i16 %a
|
||||
}
|
||||
|
@ -513,9 +513,9 @@ define <4 x i32> @bitselect_v4i32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %c) {
|
||||
; CHECK-NEXT: .functype trunc_sat_s_v4i32 (v128) -> (v128){{$}}
|
||||
; CHECK-NEXT: i32x4.trunc_sat_f32x4_s $push[[R:[0-9]+]]=, $0
|
||||
; CHECK-NEXT: return $pop[[R]]
|
||||
declare <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float>)
|
||||
declare <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float>)
|
||||
define <4 x i32> @trunc_sat_s_v4i32(<4 x float> %x) {
|
||||
%a = call <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float> %x)
|
||||
%a = call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> %x)
|
||||
ret <4 x i32> %a
|
||||
}
|
||||
|
||||
@ -524,30 +524,34 @@ define <4 x i32> @trunc_sat_s_v4i32(<4 x float> %x) {
|
||||
; CHECK-NEXT: .functype trunc_sat_u_v4i32 (v128) -> (v128){{$}}
|
||||
; CHECK-NEXT: i32x4.trunc_sat_f32x4_u $push[[R:[0-9]+]]=, $0
|
||||
; CHECK-NEXT: return $pop[[R]]
|
||||
declare <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float>)
|
||||
declare <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float>)
|
||||
define <4 x i32> @trunc_sat_u_v4i32(<4 x float> %x) {
|
||||
%a = call <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float> %x)
|
||||
%a = call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> %x)
|
||||
ret <4 x i32> %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: trunc_sat_zero_signed_v4i32:
|
||||
; CHECK-NEXT: .functype trunc_sat_zero_signed_v4i32 (v128) -> (v128){{$}}
|
||||
; CHECK-LABEL: trunc_sat_zero_s_v4i32:
|
||||
; CHECK-NEXT: .functype trunc_sat_zero_s_v4i32 (v128) -> (v128){{$}}
|
||||
; CHECK-NEXT: i32x4.trunc_sat_zero_f64x2_s $push[[R:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[R]]{{$}}
|
||||
declare <4 x i32> @llvm.wasm.trunc.sat.zero.signed(<2 x double>)
|
||||
define <4 x i32> @trunc_sat_zero_signed_v4i32(<2 x double> %a) {
|
||||
%v = call <4 x i32> @llvm.wasm.trunc.sat.zero.signed(<2 x double> %a)
|
||||
ret <4 x i32> %v
|
||||
declare <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double>)
|
||||
define <4 x i32> @trunc_sat_zero_s_v4i32(<2 x double> %x) {
|
||||
%v = call <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double> %x)
|
||||
%a = shufflevector <2 x i32> %v, <2 x i32> <i32 0, i32 0>,
|
||||
<4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
||||
ret <4 x i32> %a
|
||||
}
|
||||
|
||||
; CHECK-LABEL: trunc_sat_zero_unsigned_v4i32:
|
||||
; CHECK-NEXT: .functype trunc_sat_zero_unsigned_v4i32 (v128) -> (v128){{$}}
|
||||
; CHECK-LABEL: trunc_sat_zero_u_v4i32:
|
||||
; CHECK-NEXT: .functype trunc_sat_zero_u_v4i32 (v128) -> (v128){{$}}
|
||||
; CHECK-NEXT: i32x4.trunc_sat_zero_f64x2_u $push[[R:[0-9]+]]=, $0{{$}}
|
||||
; CHECK-NEXT: return $pop[[R]]{{$}}
|
||||
declare <4 x i32> @llvm.wasm.trunc.sat.zero.unsigned(<2 x double>)
|
||||
define <4 x i32> @trunc_sat_zero_unsigned_v4i32(<2 x double> %a) {
|
||||
%v = call <4 x i32> @llvm.wasm.trunc.sat.zero.unsigned(<2 x double> %a)
|
||||
ret <4 x i32> %v
|
||||
declare <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double>)
|
||||
define <4 x i32> @trunc_sat_zero_u_v4i32(<2 x double> %x) {
|
||||
%v = call <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double> %x)
|
||||
%a = shufflevector <2 x i32> %v, <2 x i32> <i32 0, i32 0>,
|
||||
<4 x i32> <i32 0, i32 1, i32 2, i32 3>
|
||||
ret <4 x i32> %a
|
||||
}
|
||||
|
||||
; ==============================================================================
|
||||
|
@ -1,610 +0,0 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -instsimplify -S | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
|
||||
declare i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float)
|
||||
declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float)
|
||||
declare i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double)
|
||||
declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double)
|
||||
declare i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float)
|
||||
declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float)
|
||||
declare i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double)
|
||||
declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double)
|
||||
|
||||
define void @test_i32_trunc_sat_f32_s(i32* %p) {
|
||||
; CHECK-LABEL: @test_i32_trunc_sat_f32_s(
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 2147483520, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%t0 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float +0.0)
|
||||
store volatile i32 %t0, i32* %p
|
||||
%t1 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -0.0)
|
||||
store volatile i32 %t1, i32* %p
|
||||
%t2 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x36a0000000000000); 0x1p-149
|
||||
store volatile i32 %t2, i32* %p
|
||||
%t3 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xb6a0000000000000); -0x1p-149
|
||||
store volatile i32 %t3, i32* %p
|
||||
%t4 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 1.0)
|
||||
store volatile i32 %t4, i32* %p
|
||||
%t5 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
|
||||
store volatile i32 %t5, i32* %p
|
||||
%t6 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 1.5)
|
||||
store volatile i32 %t6, i32* %p
|
||||
%t7 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -1.0)
|
||||
store volatile i32 %t7, i32* %p
|
||||
%t8 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xbff19999a0000000); -0x1.19999ap+0
|
||||
store volatile i32 %t8, i32* %p
|
||||
%t9 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -1.5)
|
||||
store volatile i32 %t9, i32* %p
|
||||
%t10 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xbffe666660000000); -1.9
|
||||
store volatile i32 %t10, i32* %p
|
||||
%t11 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -2.0)
|
||||
store volatile i32 %t11, i32* %p
|
||||
%t12 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 2147483520.0)
|
||||
store volatile i32 %t12, i32* %p
|
||||
%t13 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -2147483648.0)
|
||||
store volatile i32 %t13, i32* %p
|
||||
%t14 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 2147483648.0)
|
||||
store volatile i32 %t14, i32* %p
|
||||
%t15 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -2147483904.0)
|
||||
store volatile i32 %t15, i32* %p
|
||||
%t16 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x7ff0000000000000); inf
|
||||
store volatile i32 %t16, i32* %p
|
||||
%t17 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xfff0000000000000); -inf
|
||||
store volatile i32 %t17, i32* %p
|
||||
%t18 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x7ff8000000000000); nan
|
||||
store volatile i32 %t18, i32* %p
|
||||
%t19 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x7ffa000000000000); nan:0x200000
|
||||
store volatile i32 %t19, i32* %p
|
||||
%t20 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xfff8000000000000); -nan
|
||||
store volatile i32 %t20, i32* %p
|
||||
%t21 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xfffa000000000000); -nan:0x200000
|
||||
store volatile i32 %t21, i32* %p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_i32_trunc_sat_f32_u(i32* %p) {
|
||||
; CHECK-LABEL: @test_i32_trunc_sat_f32_u(
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 2, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -256, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%t0 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float +0.0)
|
||||
store volatile i32 %t0, i32* %p
|
||||
%t1 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float -0.0)
|
||||
store volatile i32 %t1, i32* %p
|
||||
%t2 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x36a0000000000000); 0x1p-149
|
||||
store volatile i32 %t2, i32* %p
|
||||
%t3 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xb6a0000000000000); -0x1p-149
|
||||
store volatile i32 %t3, i32* %p
|
||||
%t4 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 1.0)
|
||||
store volatile i32 %t4, i32* %p
|
||||
%t5 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
|
||||
store volatile i32 %t5, i32* %p
|
||||
%t6 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 1.5)
|
||||
store volatile i32 %t6, i32* %p
|
||||
%t7 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x3ffe666660000000); 1.9
|
||||
store volatile i32 %t7, i32* %p
|
||||
%t8 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 2.0)
|
||||
store volatile i32 %t8, i32* %p
|
||||
%t9 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 2147483648.0)
|
||||
store volatile i32 %t9, i32* %p
|
||||
%t10 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 4294967040.0)
|
||||
store volatile i32 %t10, i32* %p
|
||||
%t11 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xbfecccccc0000000); -0x1.ccccccp-1
|
||||
store volatile i32 %t11, i32* %p
|
||||
%t12 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xbfefffffe0000000); -0x1.fffffep-1
|
||||
store volatile i32 %t12, i32* %p
|
||||
%t13 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 4294967296.0)
|
||||
store volatile i32 %t13, i32* %p
|
||||
%t14 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float -1.0)
|
||||
store volatile i32 %t14, i32* %p
|
||||
%t15 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x7ff0000000000000); inf
|
||||
store volatile i32 %t15, i32* %p
|
||||
%t16 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xfff0000000000000); -inf
|
||||
store volatile i32 %t16, i32* %p
|
||||
%t17 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x7ff8000000000000); nan
|
||||
store volatile i32 %t17, i32* %p
|
||||
%t18 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x7ffa000000000000); nan:0x200000
|
||||
store volatile i32 %t18, i32* %p
|
||||
%t19 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xfff8000000000000); -nan
|
||||
store volatile i32 %t19, i32* %p
|
||||
%t20 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xfffa000000000000); -nan:0x200000
|
||||
store volatile i32 %t20, i32* %p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_i32_trunc_sat_f64_s(i32* %p) {
|
||||
; CHECK-LABEL: @test_i32_trunc_sat_f64_s(
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%t0 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double +0.0)
|
||||
store volatile i32 %t0, i32* %p
|
||||
%t1 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -0.0)
|
||||
store volatile i32 %t1, i32* %p
|
||||
%t2 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
|
||||
store volatile i32 %t2, i32* %p
|
||||
%t3 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x8010000000000001); -0x1.0000000000001p-1022
|
||||
store volatile i32 %t3, i32* %p
|
||||
%t4 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 1.0)
|
||||
store volatile i32 %t4, i32* %p
|
||||
%t5 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
|
||||
store volatile i32 %t5, i32* %p
|
||||
%t6 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 1.5)
|
||||
store volatile i32 %t6, i32* %p
|
||||
%t7 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -1.0)
|
||||
store volatile i32 %t7, i32* %p
|
||||
%t8 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0xbff199999999999a); -0x1.199999999999ap+0
|
||||
store volatile i32 %t8, i32* %p
|
||||
%t9 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -1.5)
|
||||
store volatile i32 %t9, i32* %p
|
||||
%t10 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0xbffe666666666666); -1.9
|
||||
store volatile i32 %t10, i32* %p
|
||||
%t11 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -2.0)
|
||||
store volatile i32 %t11, i32* %p
|
||||
%t12 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 2147483647.0)
|
||||
store volatile i32 %t12, i32* %p
|
||||
%t13 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -2147483648.0)
|
||||
store volatile i32 %t13, i32* %p
|
||||
%t14 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 2147483648.0)
|
||||
store volatile i32 %t14, i32* %p
|
||||
%t15 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -2147483649.0)
|
||||
store volatile i32 %t15, i32* %p
|
||||
%t16 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x7ff0000000000000); inf
|
||||
store volatile i32 %t16, i32* %p
|
||||
%t17 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0xfff0000000000000); -inf
|
||||
store volatile i32 %t17, i32* %p
|
||||
%t18 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x7ff8000000000000); nan
|
||||
store volatile i32 %t18, i32* %p
|
||||
%t19 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x7ff4000000000000); nan:0x4000000000000
|
||||
store volatile i32 %t19, i32* %p
|
||||
%t20 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0xfff8000000000000); -nan
|
||||
store volatile i32 %t20, i32* %p
|
||||
%t21 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x7ff4000000000000); -nan:0x4000000000000
|
||||
store volatile i32 %t21, i32* %p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_i32_trunc_sat_f64_u(i32* %p) {
|
||||
; CHECK-LABEL: @test_i32_trunc_sat_f64_u(
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 2, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 100000000, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%t0 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double +0.0)
|
||||
store volatile i32 %t0, i32* %p
|
||||
%t1 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double -0.0)
|
||||
store volatile i32 %t1, i32* %p
|
||||
%t2 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
|
||||
store volatile i32 %t2, i32* %p
|
||||
%t3 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x8010000000000001); -0x0.0000000000001p-1022
|
||||
store volatile i32 %t3, i32* %p
|
||||
%t4 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 1.0)
|
||||
store volatile i32 %t4, i32* %p
|
||||
%t5 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
|
||||
store volatile i32 %t5, i32* %p
|
||||
%t6 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 1.5)
|
||||
store volatile i32 %t6, i32* %p
|
||||
%t7 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x3ffe666666666666); 1.9
|
||||
store volatile i32 %t7, i32* %p
|
||||
%t8 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 2.0)
|
||||
store volatile i32 %t8, i32* %p
|
||||
%t9 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 2147483648.0)
|
||||
store volatile i32 %t9, i32* %p
|
||||
%t10 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 4294967295.0)
|
||||
store volatile i32 %t10, i32* %p
|
||||
%t11 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xbfeccccccccccccd); -0x1.ccccccccccccdp-1
|
||||
store volatile i32 %t11, i32* %p
|
||||
%t12 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xbfefffffffffffff); -0x1.fffffffffffffp-1
|
||||
store volatile i32 %t12, i32* %p
|
||||
%t13 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 100000000.0); 1e8
|
||||
store volatile i32 %t13, i32* %p
|
||||
%t14 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 4294967296.0)
|
||||
store volatile i32 %t14, i32* %p
|
||||
%t15 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double -1.0)
|
||||
store volatile i32 %t15, i32* %p
|
||||
%t16 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 10000000000000000.0); 1e16
|
||||
store volatile i32 %t16, i32* %p
|
||||
%t17 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 1000000000000000000000000000000.0); 1e30
|
||||
store volatile i32 %t17, i32* %p
|
||||
%t18 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 9223372036854775808.0)
|
||||
store volatile i32 %t18, i32* %p
|
||||
%t19 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x7ff0000000000000); inf
|
||||
store volatile i32 %t19, i32* %p
|
||||
%t20 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xfff0000000000000); -inf
|
||||
store volatile i32 %t20, i32* %p
|
||||
%t21 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x7ff8000000000000); nan
|
||||
store volatile i32 %t21, i32* %p
|
||||
%t22 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x7ff4000000000000); nan:0x4000000000000
|
||||
store volatile i32 %t22, i32* %p
|
||||
%t23 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xfff8000000000000); -nan
|
||||
store volatile i32 %t23, i32* %p
|
||||
%t24 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xfff4000000000000); -nan:0x4000000000000
|
||||
store volatile i32 %t24, i32* %p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_i64_trunc_sat_f32_s(i64* %p) {
|
||||
; CHECK-LABEL: @test_i64_trunc_sat_f32_s(
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P:%.*]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -2, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 4294967296, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -4294967296, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 9223371487098961920, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 9223372036854775807, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 9223372036854775807, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%t0 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float +0.0)
|
||||
store volatile i64 %t0, i64* %p
|
||||
%t1 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -0.0)
|
||||
store volatile i64 %t1, i64* %p
|
||||
%t2 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x36a0000000000000); 0x1p-149
|
||||
store volatile i64 %t2, i64* %p
|
||||
%t3 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xb6a0000000000000); -0x1p-149
|
||||
store volatile i64 %t3, i64* %p
|
||||
%t4 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 1.0)
|
||||
store volatile i64 %t4, i64* %p
|
||||
%t5 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
|
||||
store volatile i64 %t5, i64* %p
|
||||
%t6 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 1.5)
|
||||
store volatile i64 %t6, i64* %p
|
||||
%t7 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -1.0)
|
||||
store volatile i64 %t7, i64* %p
|
||||
%t8 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xbff19999a0000000); -0x1.19999ap+0
|
||||
store volatile i64 %t8, i64* %p
|
||||
%t9 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -1.5)
|
||||
store volatile i64 %t9, i64* %p
|
||||
%t10 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xbffe666660000000); -1.9
|
||||
store volatile i64 %t10, i64* %p
|
||||
%t11 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -2.0)
|
||||
store volatile i64 %t11, i64* %p
|
||||
%t12 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 4294967296.0)
|
||||
store volatile i64 %t12, i64* %p
|
||||
%t13 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -4294967296.0)
|
||||
store volatile i64 %t13, i64* %p
|
||||
%t14 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 9223371487098961920.0)
|
||||
store volatile i64 %t14, i64* %p
|
||||
%t15 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -9223372036854775808.0)
|
||||
store volatile i64 %t15, i64* %p
|
||||
%t16 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 9223372036854775808.0)
|
||||
store volatile i64 %t16, i64* %p
|
||||
%t17 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -9223373136366403584.0)
|
||||
store volatile i64 %t17, i64* %p
|
||||
%t18 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x7ff0000000000000); inf
|
||||
store volatile i64 %t18, i64* %p
|
||||
%t19 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xfff0000000000000); -inf
|
||||
store volatile i64 %t19, i64* %p
|
||||
%t20 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x7ff8000000000000); nan
|
||||
store volatile i64 %t20, i64* %p
|
||||
%t21 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x7ffa000000000000); nan:0x200000
|
||||
store volatile i64 %t21, i64* %p
|
||||
%t22 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xfff8000000000000); -nan
|
||||
store volatile i64 %t22, i64* %p
|
||||
%t23 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xfffa000000000000); -nan:0x200000
|
||||
store volatile i64 %t23, i64* %p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_i64_trunc_sat_f32_u(i64* %p) {
|
||||
; CHECK-LABEL: @test_i64_trunc_sat_f32_u(
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P:%.*]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 4294967296, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1099511627776, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%t0 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float +0.0)
|
||||
store volatile i64 %t0, i64* %p
|
||||
%t1 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float -0.0)
|
||||
store volatile i64 %t1, i64* %p
|
||||
%t2 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x36a0000000000000); 0x1p-149
|
||||
store volatile i64 %t2, i64* %p
|
||||
%t3 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xb6a0000000000000); -0x1p-149
|
||||
store volatile i64 %t3, i64* %p
|
||||
%t4 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 1.0)
|
||||
store volatile i64 %t4, i64* %p
|
||||
%t5 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
|
||||
store volatile i64 %t5, i64* %p
|
||||
%t6 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 1.5)
|
||||
store volatile i64 %t6, i64* %p
|
||||
%t7 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 4294967296.0)
|
||||
store volatile i64 %t7, i64* %p
|
||||
%t8 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 18446742974197923840.0)
|
||||
store volatile i64 %t8, i64* %p
|
||||
%t9 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xbfecccccc0000000); -0x1.ccccccp-1
|
||||
store volatile i64 %t9, i64* %p
|
||||
%t10 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xbfefffffe0000000); -0x1.fffffep-1
|
||||
store volatile i64 %t10, i64* %p
|
||||
%t11 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 18446744073709551616.0)
|
||||
store volatile i64 %t11, i64* %p
|
||||
%t12 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float -1.0)
|
||||
store volatile i64 %t12, i64* %p
|
||||
%t13 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x7ff0000000000000); inf
|
||||
store volatile i64 %t13, i64* %p
|
||||
%t14 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xfff0000000000000); -inf
|
||||
store volatile i64 %t14, i64* %p
|
||||
%t15 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x7ff8000000000000); nan
|
||||
store volatile i64 %t15, i64* %p
|
||||
%t16 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x7ffa000000000000); nan:0x200000
|
||||
store volatile i64 %t16, i64* %p
|
||||
%t17 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xfff8000000000000); -nan
|
||||
store volatile i64 %t17, i64* %p
|
||||
%t18 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xfffa000000000000); -nan:0x200000
|
||||
store volatile i64 %t18, i64* %p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_i64_trunc_sat_f64_s(i64* %p) {
|
||||
; CHECK-LABEL: @test_i64_trunc_sat_f64_s(
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P:%.*]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -2, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 4294967296, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -4294967296, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 9223372036854774784, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 9223372036854775807, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 9223372036854775807, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%t0 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double +0.0)
|
||||
store volatile i64 %t0, i64* %p
|
||||
%t1 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -0.0)
|
||||
store volatile i64 %t1, i64* %p
|
||||
%t2 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
|
||||
store volatile i64 %t2, i64* %p
|
||||
%t3 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x8010000000000001); -0x1.0000000000001p-1022
|
||||
store volatile i64 %t3, i64* %p
|
||||
%t4 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 1.0)
|
||||
store volatile i64 %t4, i64* %p
|
||||
%t5 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
|
||||
store volatile i64 %t5, i64* %p
|
||||
%t6 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 1.5)
|
||||
store volatile i64 %t6, i64* %p
|
||||
%t7 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -1.0)
|
||||
store volatile i64 %t7, i64* %p
|
||||
%t8 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0xbff199999999999a); -0x1.199999999999ap+0
|
||||
store volatile i64 %t8, i64* %p
|
||||
%t9 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -1.5)
|
||||
store volatile i64 %t9, i64* %p
|
||||
%t10 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0xbffe666666666666); -1.9
|
||||
store volatile i64 %t10, i64* %p
|
||||
%t11 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -2.0)
|
||||
store volatile i64 %t11, i64* %p
|
||||
%t12 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 4294967296.0)
|
||||
store volatile i64 %t12, i64* %p
|
||||
%t13 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -4294967296.0)
|
||||
store volatile i64 %t13, i64* %p
|
||||
%t14 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 9223372036854774784.0)
|
||||
store volatile i64 %t14, i64* %p
|
||||
%t15 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -9223372036854775808.0)
|
||||
store volatile i64 %t15, i64* %p
|
||||
%t16 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 9223372036854775808.0)
|
||||
store volatile i64 %t16, i64* %p
|
||||
%t17 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -9223372036854777856.0)
|
||||
store volatile i64 %t17, i64* %p
|
||||
%t18 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x7ff0000000000000); inf
|
||||
store volatile i64 %t18, i64* %p
|
||||
%t19 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0xfff0000000000000); -inf
|
||||
store volatile i64 %t19, i64* %p
|
||||
%t20 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x7ff8000000000000); nan
|
||||
store volatile i64 %t20, i64* %p
|
||||
%t21 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x7ff4000000000000); nan:0x4000000000000
|
||||
store volatile i64 %t21, i64* %p
|
||||
%t22 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0xfff8000000000000); -nan
|
||||
store volatile i64 %t22, i64* %p
|
||||
%t23 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x7ff4000000000000); -nan:0x4000000000000
|
||||
store volatile i64 %t23, i64* %p
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_i64_trunc_sat_f64_u(i64* %p) {
|
||||
; CHECK-LABEL: @test_i64_trunc_sat_f64_u(
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P:%.*]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 4294967295, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 4294967296, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -2048, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 100000000, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 10000000000000000, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%t0 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double +0.0)
|
||||
store volatile i64 %t0, i64* %p
|
||||
%t1 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double -0.0)
|
||||
store volatile i64 %t1, i64* %p
|
||||
%t2 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
|
||||
store volatile i64 %t2, i64* %p
|
||||
%t3 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x8010000000000001); -0x0.0000000000001p-1022
|
||||
store volatile i64 %t3, i64* %p
|
||||
%t4 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 1.0)
|
||||
store volatile i64 %t4, i64* %p
|
||||
%t5 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
|
||||
store volatile i64 %t5, i64* %p
|
||||
%t6 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 1.5)
|
||||
store volatile i64 %t6, i64* %p
|
||||
%t7 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 4294967295.0)
|
||||
store volatile i64 %t7, i64* %p
|
||||
%t8 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 4294967296.0)
|
||||
store volatile i64 %t8, i64* %p
|
||||
%t9 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 18446744073709549568.0)
|
||||
store volatile i64 %t9, i64* %p
|
||||
%t10 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xbfeccccccccccccd); -0x1.ccccccccccccdp-1
|
||||
store volatile i64 %t10, i64* %p
|
||||
%t11 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xbfefffffffffffff); -0x1.fffffffffffffp-1
|
||||
store volatile i64 %t11, i64* %p
|
||||
%t12 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 100000000.0); 1e8
|
||||
store volatile i64 %t12, i64* %p
|
||||
%t13 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 10000000000000000.0); 1e16
|
||||
store volatile i64 %t13, i64* %p
|
||||
%t14 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 9223372036854775808.0);
|
||||
store volatile i64 %t14, i64* %p
|
||||
%t15 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 18446744073709551616.0)
|
||||
store volatile i64 %t15, i64* %p
|
||||
%t16 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double -1.0)
|
||||
store volatile i64 %t16, i64* %p
|
||||
%t17 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x7ff0000000000000); inf
|
||||
store volatile i64 %t17, i64* %p
|
||||
%t18 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xfff0000000000000); -inf
|
||||
store volatile i64 %t18, i64* %p
|
||||
%t19 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x7ff8000000000000); nan
|
||||
store volatile i64 %t19, i64* %p
|
||||
%t20 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x7ff4000000000000); nan:0x4000000000000
|
||||
store volatile i64 %t20, i64* %p
|
||||
%t21 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xfff8000000000000); -nan
|
||||
store volatile i64 %t21, i64* %p
|
||||
%t22 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xfff4000000000000); -nan:0x4000000000000
|
||||
store volatile i64 %t22, i64* %p
|
||||
ret void
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user