From 682ac8cb267035a4ba638a7de6805c1a266dd3e8 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Thu, 11 Apr 2024 19:56:13 +0800 Subject: [PATCH 1/7] [ValueTracking] Add pre-commit tests. NFC. --- .../test/Transforms/InstCombine/known-bits.ll | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 8b4249b2c25a9..8fa42b6075bec 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1374,5 +1374,185 @@ define i8 @nonzero_reduce_xor_vscale_odd( %xx) { ret i8 %r } +define i1 @test_sign_pos(float %x) { +; CHECK-LABEL: @test_sign_pos( +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[FABS]] to i32 +; CHECK-NEXT: [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1 +; CHECK-NEXT: ret i1 [[SIGN]] +; + %fabs = call float @llvm.fabs.f32(float %x) + %y = bitcast float %fabs to i32 + %sign = icmp sgt i32 %y, -1 + ret i1 %sign +} + +define i1 @test_sign_neg(float %x) { +; CHECK-LABEL: @test_sign_neg( +; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) +; CHECK-NEXT: [[FNABS:%.*]] = fneg float [[FABS]] +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[FNABS]] to i32 +; CHECK-NEXT: [[SIGN:%.*]] = icmp slt i32 [[Y]], 0 +; CHECK-NEXT: ret i1 [[SIGN]] +; + %fabs = call float @llvm.fabs.f32(float %x) + %fnabs = fneg float %fabs + %y = bitcast float %fnabs to i32 + %sign = icmp slt i32 %y, 0 + ret i1 %sign +} + +define <2 x i1> @test_sign_pos_vec(<2 x float> %x) { +; CHECK-LABEL: @test_sign_pos_vec( +; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) +; CHECK-NEXT: [[Y:%.*]] = bitcast <2 x float> [[FABS]] to <2 x i32> +; CHECK-NEXT: [[SIGN:%.*]] = icmp slt <2 x i32> [[Y]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[SIGN]] +; + %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x) + %y = bitcast <2 x float> %fabs to <2 x i32> + %sign = icmp slt <2 x i32> %y, zeroinitializer + ret <2 x i1> %sign +} + +define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) +; CHECK-NEXT: [[AND:%.*]] = bitcast float [[TMP1]] to i32 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2147483647 + ret i32 %and +} + +define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) { +; CHECK-LABEL: @test_zero_only( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) +; CHECK-NEXT: [[AND:%.*]] = bitcast float [[TMP1]] to i32 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2147483647 + ret i32 %and +} + +define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) { +; CHECK-LABEL: @test_zero_only_non_ieee( +; CHECK-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[X:%.*]]) +; CHECK-NEXT: [[AND:%.*]] = bitcast x86_fp80 [[TMP1]] to i80 +; CHECK-NEXT: ret i80 [[AND]] +; + %y = bitcast x86_fp80 %x to i80 + %and = and i80 %y, 604462909807314587353087 + ret i80 %and +} + +define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) { +; CHECK-LABEL: @test_inf_nan_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2130706432 + ret i32 %and +} + +define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) { +; CHECK-LABEL: @test_sub_zero_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 2130706432 + ret i32 %and +} + +define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) { +; CHECK-LABEL: @test_inf_zero_only( +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 16777215 +; CHECK-NEXT: ret i32 [[AND]] +; + %y = bitcast float %x to i32 + %and = and i32 %y, 16777215 + ret i32 %and +} + +define i1 @test_simplify_icmp(i32 %x) { +; CHECK-LABEL: @test_simplify_icmp( +; CHECK-NEXT: [[CAST1:%.*]] = uitofp i32 [[X:%.*]] to double +; CHECK-NEXT: [[CAST2:%.*]] = bitcast double [[CAST1]] to i64 +; CHECK-NEXT: [[MASK:%.*]] = and i64 [[CAST2]], -140737488355328 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[MASK]], -1970324836974592 +; CHECK-NEXT: ret i1 [[CMP]] +; + %cast1 = uitofp i32 %x to double + %cast2 = bitcast double %cast1 to i64 + %mask = and i64 %cast2, -140737488355328 + %cmp = icmp eq i64 %mask, -1970324836974592 + ret i1 %cmp +} + +define i16 @test_simplify_mask(i32 %ui, float %x) { +; CHECK-LABEL: @test_simplify_mask( +; CHECK-NEXT: [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[CONV]], [[X:%.*]] +; CHECK-NEXT: br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]] +; CHECK: if.end: +; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[CONV]] to i32 +; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[CAST]], 16 +; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[SHR]] to i16 +; CHECK-NEXT: [[AND:%.*]] = and i16 [[TRUNC]], -32768 +; CHECK-NEXT: [[OR:%.*]] = or disjoint i16 [[AND]], 31744 +; CHECK-NEXT: ret i16 [[OR]] +; CHECK: if.else: +; CHECK-NEXT: ret i16 0 +; + %conv = uitofp i32 %ui to float + %cmp = fcmp olt float %x, %conv + br i1 %cmp, label %if.else, label %if.end + +if.end: + %cast = bitcast float %conv to i32 + %shr = lshr i32 %cast, 16 + %trunc = trunc i32 %shr to i16 + %and = and i16 %trunc, -32768 + %or = or disjoint i16 %and, 31744 + ret i16 %or + +if.else: + ret i16 0 +} + +; TODO: %cmp always evaluates to false + +define i1 @test_simplify_icmp2(double %x) { +; CHECK-LABEL: @test_simplify_icmp2( +; CHECK-NEXT: [[ABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]]) +; CHECK-NEXT: [[COND:%.*]] = fcmp oeq double [[ABS]], 0x7FF0000000000000 +; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[CAST:%.*]] = bitcast double [[X]] to i64 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[CAST]], 3458764513820540928 +; CHECK-NEXT: ret i1 [[CMP]] +; CHECK: if.else: +; CHECK-NEXT: ret i1 false +; + %abs = tail call double @llvm.fabs.f64(double %x) + %cond = fcmp oeq double %abs, 0x7FF0000000000000 + br i1 %cond, label %if.then, label %if.else + +if.then: + %cast = bitcast double %x to i64 + %cmp = icmp eq i64 %cast, 3458764513820540928 + ret i1 %cmp + +if.else: + ret i1 false +} + declare void @use(i1) declare void @sink(i8) From 6f5ac7466d4cd33436d19d768cc0c770366144c7 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Thu, 11 Apr 2024 20:05:09 +0800 Subject: [PATCH 2/7] [ValueTracking] Infer knownbits from fp classes --- llvm/include/llvm/Analysis/ValueTracking.h | 5 ++ llvm/lib/Analysis/ValueTracking.cpp | 34 +++++++++++++ .../AMDGPU/amdgpu-simplify-libcall-pow.ll | 14 +++--- .../AMDGPU/amdgpu-simplify-libcall-pown.ll | 12 ++--- llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll | 10 ++-- .../test/Transforms/InstCombine/known-bits.ll | 49 ++++--------------- 6 files changed, 67 insertions(+), 57 deletions(-) diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index bab7c8868532d..4181adbda5a65 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -259,6 +259,11 @@ struct KnownFPClass { return (KnownFPClasses & Mask) == fcNone; } + /// Return true if it's known this can only be one of the mask entries. + bool isKnownOnly(FPClassTest Mask) const { + return (KnownFPClasses & ~Mask) == fcNone; + } + bool isUnknown() const { return KnownFPClasses == fcAllFlags && !SignBit; } diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index c038f7eaabbb6..30adb9c32e3bf 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1111,6 +1111,40 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } + Value *V; + // Handle bitcast from floating point to integer. + if (match(const_cast(I), m_ElementWiseBitCast(m_Value(V))) && + V->getType()->isFPOrFPVectorTy()) { + KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q); + if (Result.SignBit) { + if (*Result.SignBit) + Known.makeNegative(); + else + Known.makeNonNegative(); + } + + Type *FPType = V->getType()->getScalarType(); + if (FPType->isIEEELikeFPTy()) { + int MantissaWidth = FPType->getFPMantissaWidth(); + if (MantissaWidth != -1) { + if (Result.isKnownOnly(fcInf)) { + Known.Zero.setLowBits(MantissaWidth); + Known.One.setBits(MantissaWidth, BitWidth - 1); + } else if (Result.isKnownOnly(fcZero)) { + Known.Zero.setLowBits(BitWidth - 1); + } else if (Result.isKnownOnly(fcInf | fcNan)) { + Known.One.setBits(MantissaWidth, BitWidth - 1); + } else if (Result.isKnownOnly(fcSubnormal | fcZero)) { + Known.Zero.setBits(MantissaWidth, BitWidth - 1); + } else if (Result.isKnownOnly(fcInf | fcZero)) { + Known.Zero.setLowBits(MantissaWidth); + } + } + } + + break; + } + // Handle cast from vector integer type to scalar or vector integer. auto *SrcVecTy = dyn_cast(SrcTy); if (!SrcVecTy || !SrcVecTy->getElementType()->isIntegerTy() || diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll index c4bd4bc126f73..5db25a59d33fc 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pow.ll @@ -2216,7 +2216,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp(float %x, i32 %y) ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2304,7 +2304,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp(float %x, i32 %y) ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2353,7 +2353,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_uitofp_i256(float %x, i2 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2376,7 +2376,7 @@ define float @test_pow_afn_nnan_ninf_f32_known_integral_sitofp_i256(float %x, i2 ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; @@ -2399,7 +2399,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_sitofp(<2 x floa ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP5]] ; @@ -2448,7 +2448,7 @@ define <2 x float> @test_pow_afn_nnan_ninf_v2f32_known_integral_uitofp(<2 x floa ; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP4:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast <2 x i32> [[TMP4]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP5]] ; @@ -2560,7 +2560,7 @@ define float @test_pow_afn_f32_nnan_ninf__y_known_integral_trunc(float %x, float ; CHECK-NEXT: [[TMP2:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP2]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP4:%.*]] = or i32 [[__POW_SIGN]], [[TMP3]] +; CHECK-NEXT: [[TMP4:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP3]] ; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32 [[TMP4]] to float ; CHECK-NEXT: ret float [[TMP5]] ; diff --git a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll index 8ddaf243db92c..e298226ee7ccd 100644 --- a/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll +++ b/llvm/test/CodeGen/AMDGPU/amdgpu-simplify-libcall-pown.ll @@ -680,7 +680,7 @@ define float @test_pown_afn_nnan_ninf_f32(float %x, i32 %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; @@ -703,7 +703,7 @@ define <2 x float> @test_pown_afn_nnan_ninf_v2f32(<2 x float> %x, <2 x i32> %y) ; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x float> [[X]] to <2 x i32> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i32> [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x float> [[__EXP2]] to <2 x i32> -; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i32> [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint <2 x i32> [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i32> [[TMP2]] to <2 x float> ; CHECK-NEXT: ret <2 x float> [[TMP3]] ; @@ -772,7 +772,7 @@ define half @test_pown_afn_nnan_ninf_f16(half %x, i32 %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast half [[X]] to i16 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i16 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast half [[__EXP2]] to i16 -; CHECK-NEXT: [[TMP2:%.*]] = or i16 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i16 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16 [[TMP2]] to half ; CHECK-NEXT: ret half [[TMP3]] ; @@ -795,7 +795,7 @@ define <2 x half> @test_pown_afn_nnan_ninf_v2f16(<2 x half> %x, <2 x i32> %y) { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast <2 x half> [[X]] to <2 x i16> ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and <2 x i16> [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x half> [[__EXP2]] to <2 x i16> -; CHECK-NEXT: [[TMP2:%.*]] = or <2 x i16> [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint <2 x i16> [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast <2 x i16> [[TMP2]] to <2 x half> ; CHECK-NEXT: ret <2 x half> [[TMP3]] ; @@ -829,7 +829,7 @@ define float @test_pown_fast_f32_strictfp(float %x, i32 %y) #1 { ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; @@ -1075,7 +1075,7 @@ define float @test_pown_afn_ninf_nnan_f32__x_known_positive(float nofpclass(ninf ; CHECK-NEXT: [[TMP0:%.*]] = bitcast float [[X]] to i32 ; CHECK-NEXT: [[__POW_SIGN:%.*]] = and i32 [[__YEVEN]], [[TMP0]] ; CHECK-NEXT: [[TMP1:%.*]] = bitcast float [[__EXP2]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[__POW_SIGN]], [[TMP1]] +; CHECK-NEXT: [[TMP2:%.*]] = or disjoint i32 [[__POW_SIGN]], [[TMP1]] ; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32 [[TMP2]] to float ; CHECK-NEXT: ret float [[TMP3]] ; diff --git a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll index 204c8140d3f17..54ca33401ccf4 100644 --- a/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll +++ b/llvm/test/CodeGen/AMDGPU/simplify-libcalls.ll @@ -360,7 +360,7 @@ declare half @_Z4pownDhi(half, i32) ; GCN-NATIVE: %0 = bitcast half %x to i16 ; GCN-NATIVE: %__pow_sign = and i16 %__yeven, %0 ; GCN-NATIVE: %1 = bitcast half %__exp2 to i16 -; GCN-NATIVE: %2 = or i16 %__pow_sign, %1 +; GCN-NATIVE: %2 = or disjoint i16 %__pow_sign, %1 ; GCN-NATIVE: %3 = bitcast i16 %2 to half define half @test_pown_f16(half %x, i32 %y) { entry: @@ -378,7 +378,7 @@ declare float @_Z4pownfi(float, i32) ; GCN: %[[r0:.*]] = bitcast float %tmp to i32 ; GCN: %__pow_sign = and i32 %[[r0]], -2147483648 ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32 -; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]] +; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]] ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4 define amdgpu_kernel void @test_pow(ptr addrspace(1) nocapture %a) { entry: @@ -414,7 +414,7 @@ entry: ; GCN: %[[r0:.*]] = bitcast float %tmp to i32 ; GCN: %__pow_sign = and i32 %__yeven, %[[r0]] ; GCN: %[[r1:.*]] = bitcast float %__exp2 to i32 -; GCN: %[[r2:.*]] = or i32 %__pow_sign, %[[r1]] +; GCN: %[[r2:.*]] = or disjoint i32 %__pow_sign, %[[r1]] ; GCN: store i32 %[[r2]], ptr addrspace(1) %a, align 4 define amdgpu_kernel void @test_pown(ptr addrspace(1) nocapture %a) { entry: @@ -438,7 +438,7 @@ declare <2 x half> @_Z3powDv2_DhS_(<2 x half>, <2 x half>) ; GCN: %1 = bitcast half %x to i16 ; GCN: %__pow_sign = and i16 %1, -32768 ; GCN: %2 = bitcast half %__exp2 to i16 -; GCN: %3 = or i16 %__pow_sign, %2 +; GCN: %3 = or disjoint i16 %__pow_sign, %2 ; GCN: %4 = bitcast i16 %3 to half define half @test_pow_fast_f16__y_13(half %x) { %powr = tail call fast half @_Z3powDhDh(half %x, half 13.0) @@ -453,7 +453,7 @@ define half @test_pow_fast_f16__y_13(half %x) { ; GCN: %1 = bitcast <2 x half> %x to <2 x i16> ; GCN: %__pow_sign = and <2 x i16> %1, ; GCN: %2 = bitcast <2 x half> %__exp2 to <2 x i16> -; GCN: %3 = or <2 x i16> %__pow_sign, %2 +; GCN: %3 = or disjoint <2 x i16> %__pow_sign, %2 ; GCN: %4 = bitcast <2 x i16> %3 to <2 x half> define <2 x half> @test_pow_fast_v2f16__y_13(<2 x half> %x) { %powr = tail call fast <2 x half> @_Z3powDv2_DhS_(<2 x half> %x, <2 x half> ) diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 8fa42b6075bec..e624d9c253ea4 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1376,10 +1376,7 @@ define i8 @nonzero_reduce_xor_vscale_odd( %xx) { define i1 @test_sign_pos(float %x) { ; CHECK-LABEL: @test_sign_pos( -; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[FABS]] to i32 -; CHECK-NEXT: [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1 -; CHECK-NEXT: ret i1 [[SIGN]] +; CHECK-NEXT: ret i1 true ; %fabs = call float @llvm.fabs.f32(float %x) %y = bitcast float %fabs to i32 @@ -1389,11 +1386,7 @@ define i1 @test_sign_pos(float %x) { define i1 @test_sign_neg(float %x) { ; CHECK-LABEL: @test_sign_neg( -; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) -; CHECK-NEXT: [[FNABS:%.*]] = fneg float [[FABS]] -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[FNABS]] to i32 -; CHECK-NEXT: [[SIGN:%.*]] = icmp slt i32 [[Y]], 0 -; CHECK-NEXT: ret i1 [[SIGN]] +; CHECK-NEXT: ret i1 true ; %fabs = call float @llvm.fabs.f32(float %x) %fnabs = fneg float %fabs @@ -1404,10 +1397,7 @@ define i1 @test_sign_neg(float %x) { define <2 x i1> @test_sign_pos_vec(<2 x float> %x) { ; CHECK-LABEL: @test_sign_pos_vec( -; CHECK-NEXT: [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X:%.*]]) -; CHECK-NEXT: [[Y:%.*]] = bitcast <2 x float> [[FABS]] to <2 x i32> -; CHECK-NEXT: [[SIGN:%.*]] = icmp slt <2 x i32> [[Y]], zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[SIGN]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %x) %y = bitcast <2 x float> %fabs to <2 x i32> @@ -1417,9 +1407,7 @@ define <2 x i1> @test_sign_pos_vec(<2 x float> %x) { define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { ; CHECK-LABEL: @test_inf_only( -; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = bitcast float [[TMP1]] to i32 -; CHECK-NEXT: ret i32 [[AND]] +; CHECK-NEXT: ret i32 2130706432 ; %y = bitcast float %x to i32 %and = and i32 %y, 2147483647 @@ -1428,9 +1416,7 @@ define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) { ; CHECK-LABEL: @test_zero_only( -; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = bitcast float [[TMP1]] to i32 -; CHECK-NEXT: ret i32 [[AND]] +; CHECK-NEXT: ret i32 0 ; %y = bitcast float %x to i32 %and = and i32 %y, 2147483647 @@ -1450,9 +1436,7 @@ define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) { define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) { ; CHECK-LABEL: @test_inf_nan_only( -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 -; CHECK-NEXT: ret i32 [[AND]] +; CHECK-NEXT: ret i32 2130706432 ; %y = bitcast float %x to i32 %and = and i32 %y, 2130706432 @@ -1461,9 +1445,7 @@ define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) { define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) { ; CHECK-LABEL: @test_sub_zero_only( -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 -; CHECK-NEXT: ret i32 [[AND]] +; CHECK-NEXT: ret i32 0 ; %y = bitcast float %x to i32 %and = and i32 %y, 2130706432 @@ -1472,9 +1454,7 @@ define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) { define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) { ; CHECK-LABEL: @test_inf_zero_only( -; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 16777215 -; CHECK-NEXT: ret i32 [[AND]] +; CHECK-NEXT: ret i32 0 ; %y = bitcast float %x to i32 %and = and i32 %y, 16777215 @@ -1483,11 +1463,7 @@ define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) { define i1 @test_simplify_icmp(i32 %x) { ; CHECK-LABEL: @test_simplify_icmp( -; CHECK-NEXT: [[CAST1:%.*]] = uitofp i32 [[X:%.*]] to double -; CHECK-NEXT: [[CAST2:%.*]] = bitcast double [[CAST1]] to i64 -; CHECK-NEXT: [[MASK:%.*]] = and i64 [[CAST2]], -140737488355328 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[MASK]], -1970324836974592 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %cast1 = uitofp i32 %x to double %cast2 = bitcast double %cast1 to i64 @@ -1502,12 +1478,7 @@ define i16 @test_simplify_mask(i32 %ui, float %x) { ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[CONV]], [[X:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]] ; CHECK: if.end: -; CHECK-NEXT: [[CAST:%.*]] = bitcast float [[CONV]] to i32 -; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[CAST]], 16 -; CHECK-NEXT: [[TRUNC:%.*]] = trunc i32 [[SHR]] to i16 -; CHECK-NEXT: [[AND:%.*]] = and i16 [[TRUNC]], -32768 -; CHECK-NEXT: [[OR:%.*]] = or disjoint i16 [[AND]], 31744 -; CHECK-NEXT: ret i16 [[OR]] +; CHECK-NEXT: ret i16 31744 ; CHECK: if.else: ; CHECK-NEXT: ret i16 0 ; From a7a923343a9b2d9d2cd610d99fe3771271ebfa53 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Fri, 12 Apr 2024 16:19:13 +0800 Subject: [PATCH 3/7] [ValueTracking] Add additional tests. NFC. --- .../test/Transforms/InstCombine/known-bits.ll | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index e624d9c253ea4..c4bf7bf5a1b71 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1384,6 +1384,29 @@ define i1 @test_sign_pos(float %x) { ret i1 %sign } +define i1 @test_sign_pos_half(half %x) { +; CHECK-LABEL: @test_sign_pos_half( +; CHECK-NEXT: ret i1 true +; + %fabs = call half @llvm.fabs.f16(half %x) + %y = bitcast half %fabs to i16 + %sign = icmp sgt i16 %y, -1 + ret i1 %sign +} + +define i1 @test_sign_pos_half_non_elementwise(<2 x half> %x) { +; CHECK-LABEL: @test_sign_pos_half_non_elementwise( +; CHECK-NEXT: [[FABS:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]]) +; CHECK-NEXT: [[Y:%.*]] = bitcast <2 x half> [[FABS]] to i32 +; CHECK-NEXT: [[SIGN:%.*]] = icmp sgt i32 [[Y]], -1 +; CHECK-NEXT: ret i1 [[SIGN]] +; + %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x) + %y = bitcast <2 x half> %fabs to i32 + %sign = icmp sgt i32 %y, -1 + ret i1 %sign +} + define i1 @test_sign_neg(float %x) { ; CHECK-LABEL: @test_sign_neg( ; CHECK-NEXT: ret i1 true @@ -1414,6 +1437,26 @@ define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { ret i32 %and } +define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only_bfloat( +; CHECK-NEXT: ret i16 32512 +; + %y = bitcast bfloat %x to i16 + %and = and i16 %y, 32767 + ret i16 %and +} + +define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) { +; CHECK-LABEL: @test_inf_only_ppc_fp128( +; CHECK-NEXT: [[Y:%.*]] = bitcast ppc_fp128 [[X:%.*]] to i128 +; CHECK-NEXT: [[AND:%.*]] = and i128 [[Y]], 170141183460469231731687303715884105727 +; CHECK-NEXT: ret i128 [[AND]] +; + %y = bitcast ppc_fp128 %x to i128 + %and = and i128 %y, 170141183460469231731687303715884105727 + ret i128 %and +} + define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) { ; CHECK-LABEL: @test_zero_only( ; CHECK-NEXT: ret i32 0 From c089c591e9e8306ac30b9c14c5e3003d8cc0ea1c Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Sun, 14 Apr 2024 01:44:45 +0800 Subject: [PATCH 4/7] [ValueTracking] Address review comments. --- llvm/include/llvm/IR/PatternMatch.h | 2 +- llvm/lib/Analysis/ValueTracking.cpp | 29 ++++++++++++++--------------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 1b418a9854541..ab24e41e58a3a 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1838,7 +1838,7 @@ template struct ElementWiseBitCast_match { ElementWiseBitCast_match(const Op_t &OpMatch) : Op(OpMatch) {} template bool match(OpTy *V) { - BitCastInst *I = dyn_cast(V); + auto *I = dyn_cast(V); if (!I) return false; Type *SrcType = I->getSrcTy(); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 30adb9c32e3bf..ecbba433f4145 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1111,9 +1111,9 @@ static void computeKnownBitsFromOperator(const Operator *I, break; } - Value *V; + const Value *V; // Handle bitcast from floating point to integer. - if (match(const_cast(I), m_ElementWiseBitCast(m_Value(V))) && + if (match(I, m_ElementWiseBitCast(m_Value(V))) && V->getType()->isFPOrFPVectorTy()) { KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q); if (Result.SignBit) { @@ -1126,19 +1126,18 @@ static void computeKnownBitsFromOperator(const Operator *I, Type *FPType = V->getType()->getScalarType(); if (FPType->isIEEELikeFPTy()) { int MantissaWidth = FPType->getFPMantissaWidth(); - if (MantissaWidth != -1) { - if (Result.isKnownOnly(fcInf)) { - Known.Zero.setLowBits(MantissaWidth); - Known.One.setBits(MantissaWidth, BitWidth - 1); - } else if (Result.isKnownOnly(fcZero)) { - Known.Zero.setLowBits(BitWidth - 1); - } else if (Result.isKnownOnly(fcInf | fcNan)) { - Known.One.setBits(MantissaWidth, BitWidth - 1); - } else if (Result.isKnownOnly(fcSubnormal | fcZero)) { - Known.Zero.setBits(MantissaWidth, BitWidth - 1); - } else if (Result.isKnownOnly(fcInf | fcZero)) { - Known.Zero.setLowBits(MantissaWidth); - } + assert(MantissaWidth != -1 && "Invalid mantissa width"); + if (Result.isKnownOnly(fcInf)) { + Known.Zero.setLowBits(MantissaWidth); + Known.One.setBits(MantissaWidth, BitWidth - 1); + } else if (Result.isKnownOnly(fcZero)) { + Known.Zero.setLowBits(BitWidth - 1); + } else if (Result.isKnownOnly(fcInf | fcNan)) { + Known.One.setBits(MantissaWidth, BitWidth - 1); + } else if (Result.isKnownOnly(fcSubnormal | fcZero)) { + Known.Zero.setBits(MantissaWidth, BitWidth - 1); + } else if (Result.isKnownOnly(fcInf | fcZero)) { + Known.Zero.setLowBits(MantissaWidth); } } From 937a405347b1c3afc0229a0ef5a6f9749689a26e Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 22 Apr 2024 15:19:10 +0800 Subject: [PATCH 5/7] [InstCombine] Address review comments. --- llvm/include/llvm/Analysis/ValueTracking.h | 5 -- llvm/lib/Analysis/ValueTracking.cpp | 55 +++++++++++++------ .../test/Transforms/InstCombine/known-bits.ll | 38 +++++++++---- 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index 4181adbda5a65..bab7c8868532d 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -259,11 +259,6 @@ struct KnownFPClass { return (KnownFPClasses & Mask) == fcNone; } - /// Return true if it's known this can only be one of the mask entries. - bool isKnownOnly(FPClassTest Mask) const { - return (KnownFPClasses & ~Mask) == fcNone; - } - bool isUnknown() const { return KnownFPClasses == fcAllFlags && !SignBit; } diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index ecbba433f4145..3963b44533b86 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1115,31 +1115,52 @@ static void computeKnownBitsFromOperator(const Operator *I, // Handle bitcast from floating point to integer. if (match(I, m_ElementWiseBitCast(m_Value(V))) && V->getType()->isFPOrFPVectorTy()) { + Type *FPType = V->getType()->getScalarType(); KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q); + FPClassTest FPClasses = Result.KnownFPClasses; + + if (Result.isKnownNever(fcNormal | fcSubnormal)) { + Known.Zero.setAllBits(); + Known.One.setAllBits(); + + if (FPClasses & fcSNan) { + APInt Payload = APInt::getAllOnes(FPType->getScalarSizeInBits()); + Known = Known.intersectWith(KnownBits::makeConstant( + APFloat::getSNaN(FPType->getFltSemantics()).bitcastToAPInt())); + Known = Known.intersectWith(KnownBits::makeConstant( + APFloat::getSNaN(FPType->getFltSemantics(), &Payload) + .bitcastToAPInt())); + } + + if (FPClasses & fcQNan) { + APInt Payload = APInt::getAllOnes(FPType->getScalarSizeInBits()); + Known = Known.intersectWith(KnownBits::makeConstant( + APFloat::getQNaN(FPType->getFltSemantics()).bitcastToAPInt())); + Known = Known.intersectWith(KnownBits::makeConstant( + APFloat::getQNaN(FPType->getFltSemantics(), &Payload) + .bitcastToAPInt())); + } + + if (FPClasses & fcInf) + Known = Known.intersectWith(KnownBits::makeConstant( + APFloat::getInf(FPType->getFltSemantics()).bitcastToAPInt())); + + if (FPClasses & fcZero) + Known = Known.intersectWith(KnownBits::makeConstant( + APInt::getZero(FPType->getScalarSizeInBits()))); + } + if (Result.SignBit) { if (*Result.SignBit) Known.makeNegative(); else Known.makeNonNegative(); + } else { + Known.Zero.clearSignBit(); + Known.One.clearSignBit(); } - Type *FPType = V->getType()->getScalarType(); - if (FPType->isIEEELikeFPTy()) { - int MantissaWidth = FPType->getFPMantissaWidth(); - assert(MantissaWidth != -1 && "Invalid mantissa width"); - if (Result.isKnownOnly(fcInf)) { - Known.Zero.setLowBits(MantissaWidth); - Known.One.setBits(MantissaWidth, BitWidth - 1); - } else if (Result.isKnownOnly(fcZero)) { - Known.Zero.setLowBits(BitWidth - 1); - } else if (Result.isKnownOnly(fcInf | fcNan)) { - Known.One.setBits(MantissaWidth, BitWidth - 1); - } else if (Result.isKnownOnly(fcSubnormal | fcZero)) { - Known.Zero.setBits(MantissaWidth, BitWidth - 1); - } else if (Result.isKnownOnly(fcInf | fcZero)) { - Known.Zero.setLowBits(MantissaWidth); - } - } + assert(!Known.hasConflict() && "Bits known to be one AND zero?"); break; } diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index c4bf7bf5a1b71..dd6b6a9ef25fa 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1430,7 +1430,7 @@ define <2 x i1> @test_sign_pos_vec(<2 x float> %x) { define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { ; CHECK-LABEL: @test_inf_only( -; CHECK-NEXT: ret i32 2130706432 +; CHECK-NEXT: ret i32 2139095040 ; %y = bitcast float %x to i32 %and = and i32 %y, 2147483647 @@ -1439,7 +1439,7 @@ define i32 @test_inf_only(float nofpclass(nan sub norm zero) %x) { define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) { ; CHECK-LABEL: @test_inf_only_bfloat( -; CHECK-NEXT: ret i16 32512 +; CHECK-NEXT: ret i16 32640 ; %y = bitcast bfloat %x to i16 %and = and i16 %y, 32767 @@ -1448,9 +1448,7 @@ define i16 @test_inf_only_bfloat(bfloat nofpclass(nan sub norm zero) %x) { define i128 @test_inf_only_ppc_fp128(ppc_fp128 nofpclass(nan sub norm zero) %x) { ; CHECK-LABEL: @test_inf_only_ppc_fp128( -; CHECK-NEXT: [[Y:%.*]] = bitcast ppc_fp128 [[X:%.*]] to i128 -; CHECK-NEXT: [[AND:%.*]] = and i128 [[Y]], 170141183460469231731687303715884105727 -; CHECK-NEXT: ret i128 [[AND]] +; CHECK-NEXT: ret i128 9218868437227405312 ; %y = bitcast ppc_fp128 %x to i128 %and = and i128 %y, 170141183460469231731687303715884105727 @@ -1468,9 +1466,7 @@ define i32 @test_zero_only(float nofpclass(nan sub norm inf) %x) { define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) { ; CHECK-LABEL: @test_zero_only_non_ieee( -; CHECK-NEXT: [[TMP1:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 [[X:%.*]]) -; CHECK-NEXT: [[AND:%.*]] = bitcast x86_fp80 [[TMP1]] to i80 -; CHECK-NEXT: ret i80 [[AND]] +; CHECK-NEXT: ret i80 0 ; %y = bitcast x86_fp80 %x to i80 %and = and i80 %y, 604462909807314587353087 @@ -1488,7 +1484,9 @@ define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) { define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) { ; CHECK-LABEL: @test_sub_zero_only( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 +; CHECK-NEXT: ret i32 [[AND]] ; %y = bitcast float %x to i32 %and = and i32 %y, 2130706432 @@ -1497,7 +1495,9 @@ define i32 @test_sub_zero_only(float nofpclass(nan norm inf) %x) { define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) { ; CHECK-LABEL: @test_inf_zero_only( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 8388608 +; CHECK-NEXT: ret i32 [[AND]] ; %y = bitcast float %x to i32 %and = and i32 %y, 16777215 @@ -1568,5 +1568,23 @@ if.else: ret i1 false } +define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) { +; CHECK-LABEL: @test_snan_only( +; CHECK-NEXT: ret i32 0 +; + %y = bitcast float %x to i32 + %and = and i32 %y, 4194304 + ret i32 %and +} + +define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) { +; CHECK-LABEL: @test_qnan_only( +; CHECK-NEXT: ret i32 4194304 +; + %y = bitcast float %x to i32 + %and = and i32 %y, 4194304 + ret i32 %and +} + declare void @use(i1) declare void @sink(i8) From 57b3d5ed9fea40f8baa23af6ab457e8f5d7f537d Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 13 May 2024 16:28:06 +0800 Subject: [PATCH 6/7] [ValueTracking] Add additional snan/qnan tests. NFC. --- .../test/Transforms/InstCombine/known-bits.ll | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index dd6b6a9ef25fa..9b29ebe13e346 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1504,6 +1504,8 @@ define i32 @test_inf_zero_only(float nofpclass(nan norm sub) %x) { ret i32 %and } + + define i1 @test_simplify_icmp(i32 %x) { ; CHECK-LABEL: @test_simplify_icmp( ; CHECK-NEXT: ret i1 false @@ -1515,6 +1517,46 @@ define i1 @test_simplify_icmp(i32 %x) { ret i1 %cmp } +define i32 @test_snan_quiet_bit1(float nofpclass(sub norm inf qnan) %x) { +; CHECK-LABEL: @test_snan_quiet_bit1( +; CHECK-NEXT: ret i32 0 +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 4194304 + ret i32 %masked +} + +define i32 @test_snan_quiet_bit2(float nofpclass(sub norm inf qnan) %x) { +; CHECK-LABEL: @test_snan_quiet_bit2( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 2097152 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 2097152 + ret i32 %masked +} + +define i32 @test_qnan_quiet_bit1(float nofpclass(sub norm inf snan) %x) { +; CHECK-LABEL: @test_qnan_quiet_bit1( +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 4194304 +; CHECK-NEXT: ret i32 [[MASKED]] +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 4194304 + ret i32 %masked +} + +define i32 @test_qnan_quiet_bit2(float nofpclass(sub norm inf snan) %x) { +; CHECK-LABEL: @test_qnan_quiet_bit2( +; CHECK-NEXT: ret i32 0 +; + %bits = bitcast float %x to i32 + %masked = and i32 %bits, 2097152 + ret i32 %masked +} + define i16 @test_simplify_mask(i32 %ui, float %x) { ; CHECK-LABEL: @test_simplify_mask( ; CHECK-NEXT: [[CONV:%.*]] = uitofp i32 [[UI:%.*]] to float From 1d364885e5752155eeb0f13b8ab3da68bd5125c0 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Mon, 13 May 2024 16:28:46 +0800 Subject: [PATCH 7/7] [ValueTracking] Remove snan/qnan support --- llvm/lib/Analysis/ValueTracking.cpp | 20 +------------------ .../test/Transforms/InstCombine/known-bits.ll | 20 ++++++++++++++----- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 3963b44533b86..b8bb8286aec95 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1119,28 +1119,10 @@ static void computeKnownBitsFromOperator(const Operator *I, KnownFPClass Result = computeKnownFPClass(V, fcAllFlags, Depth + 1, Q); FPClassTest FPClasses = Result.KnownFPClasses; - if (Result.isKnownNever(fcNormal | fcSubnormal)) { + if (Result.isKnownNever(fcNormal | fcSubnormal | fcNan)) { Known.Zero.setAllBits(); Known.One.setAllBits(); - if (FPClasses & fcSNan) { - APInt Payload = APInt::getAllOnes(FPType->getScalarSizeInBits()); - Known = Known.intersectWith(KnownBits::makeConstant( - APFloat::getSNaN(FPType->getFltSemantics()).bitcastToAPInt())); - Known = Known.intersectWith(KnownBits::makeConstant( - APFloat::getSNaN(FPType->getFltSemantics(), &Payload) - .bitcastToAPInt())); - } - - if (FPClasses & fcQNan) { - APInt Payload = APInt::getAllOnes(FPType->getScalarSizeInBits()); - Known = Known.intersectWith(KnownBits::makeConstant( - APFloat::getQNaN(FPType->getFltSemantics()).bitcastToAPInt())); - Known = Known.intersectWith(KnownBits::makeConstant( - APFloat::getQNaN(FPType->getFltSemantics(), &Payload) - .bitcastToAPInt())); - } - if (FPClasses & fcInf) Known = Known.intersectWith(KnownBits::makeConstant( APFloat::getInf(FPType->getFltSemantics()).bitcastToAPInt())); diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index 9b29ebe13e346..816bd6f352df1 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -1475,7 +1475,9 @@ define i80 @test_zero_only_non_ieee(x86_fp80 nofpclass(nan sub norm inf) %x) { define i32 @test_inf_nan_only(float nofpclass(sub norm zero) %x) { ; CHECK-LABEL: @test_inf_nan_only( -; CHECK-NEXT: ret i32 2130706432 +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 2130706432 +; CHECK-NEXT: ret i32 [[AND]] ; %y = bitcast float %x to i32 %and = and i32 %y, 2130706432 @@ -1519,7 +1521,9 @@ define i1 @test_simplify_icmp(i32 %x) { define i32 @test_snan_quiet_bit1(float nofpclass(sub norm inf qnan) %x) { ; CHECK-LABEL: @test_snan_quiet_bit1( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 4194304 +; CHECK-NEXT: ret i32 [[MASKED]] ; %bits = bitcast float %x to i32 %masked = and i32 %bits, 4194304 @@ -1550,7 +1554,9 @@ define i32 @test_qnan_quiet_bit1(float nofpclass(sub norm inf snan) %x) { define i32 @test_qnan_quiet_bit2(float nofpclass(sub norm inf snan) %x) { ; CHECK-LABEL: @test_qnan_quiet_bit2( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[BITS:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[MASKED:%.*]] = and i32 [[BITS]], 2097152 +; CHECK-NEXT: ret i32 [[MASKED]] ; %bits = bitcast float %x to i32 %masked = and i32 %bits, 2097152 @@ -1612,7 +1618,9 @@ if.else: define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) { ; CHECK-LABEL: @test_snan_only( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 +; CHECK-NEXT: ret i32 [[AND]] ; %y = bitcast float %x to i32 %and = and i32 %y, 4194304 @@ -1621,7 +1629,9 @@ define i32 @test_snan_only(float nofpclass(qnan sub norm zero inf) %x) { define i32 @test_qnan_only(float nofpclass(snan sub norm zero inf) %x) { ; CHECK-LABEL: @test_qnan_only( -; CHECK-NEXT: ret i32 4194304 +; CHECK-NEXT: [[Y:%.*]] = bitcast float [[X:%.*]] to i32 +; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y]], 4194304 +; CHECK-NEXT: ret i32 [[AND]] ; %y = bitcast float %x to i32 %and = and i32 %y, 4194304