Skip to content

Commit 404479b

Browse files
committed
[InstCombine] Use known bits to determine exact int->fp cast
Reviewed By: spatel, nikic Differential Revision: https://reviews.llvm.org/D127854
1 parent 70557eb commit 404479b

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,7 +1720,7 @@ static Type *getMinimumFPType(Value *V) {
17201720

17211721
/// Return true if the cast from integer to FP can be proven to be exact for all
17221722
/// possible inputs (the conversion does not lose any precision).
1723-
static bool isKnownExactCastIntToFP(CastInst &I) {
1723+
static bool isKnownExactCastIntToFP(CastInst &I, InstCombinerImpl &IC) {
17241724
CastInst::CastOps Opcode = I.getOpcode();
17251725
assert((Opcode == CastInst::SIToFP || Opcode == CastInst::UIToFP) &&
17261726
"Unexpected cast");
@@ -1757,6 +1757,12 @@ static bool isKnownExactCastIntToFP(CastInst &I) {
17571757
// TODO:
17581758
// Try harder to find if the source integer type has less significant bits.
17591759
// For example, compute number of sign bits or compute low bit mask.
1760+
KnownBits SrcKnown = IC.computeKnownBits(Src, 0, &I);
1761+
int LowBits =
1762+
(int)SrcTy->getScalarSizeInBits() - SrcKnown.countMinLeadingZeros();
1763+
if (LowBits <= DestNumSigBits)
1764+
return true;
1765+
17601766
return false;
17611767
}
17621768

@@ -1937,7 +1943,7 @@ Instruction *InstCombinerImpl::visitFPTrunc(FPTruncInst &FPT) {
19371943
Value *Src = FPT.getOperand(0);
19381944
if (isa<SIToFPInst>(Src) || isa<UIToFPInst>(Src)) {
19391945
auto *FPCast = cast<CastInst>(Src);
1940-
if (isKnownExactCastIntToFP(*FPCast))
1946+
if (isKnownExactCastIntToFP(*FPCast, *this))
19411947
return CastInst::Create(FPCast->getOpcode(), FPCast->getOperand(0), Ty);
19421948
}
19431949

@@ -1951,7 +1957,7 @@ Instruction *InstCombinerImpl::visitFPExt(CastInst &FPExt) {
19511957
Value *Src = FPExt.getOperand(0);
19521958
if (isa<SIToFPInst>(Src) || isa<UIToFPInst>(Src)) {
19531959
auto *FPCast = cast<CastInst>(Src);
1954-
if (isKnownExactCastIntToFP(*FPCast))
1960+
if (isKnownExactCastIntToFP(*FPCast, *this))
19551961
return CastInst::Create(FPCast->getOpcode(), FPCast->getOperand(0), Ty);
19561962
}
19571963

@@ -1978,7 +1984,7 @@ Instruction *InstCombinerImpl::foldItoFPtoI(CastInst &FI) {
19781984

19791985
// This means this is also safe for a signed input and unsigned output, since
19801986
// a negative input would lead to undefined behavior.
1981-
if (!isKnownExactCastIntToFP(*OpI)) {
1987+
if (!isKnownExactCastIntToFP(*OpI, *this)) {
19821988
// The first cast may not round exactly based on the source integer width
19831989
// and FP width, but the overflow UB rules can still allow this to fold.
19841990
// If the destination type is narrow, that means the intermediate FP value

llvm/test/Transforms/InstCombine/fpcast.ll

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,7 @@ define half @sint_to_fptrunc(i32 %x) {
170170
define half @masked_sint_to_fptrunc1(i32 %x) {
171171
; CHECK-LABEL: @masked_sint_to_fptrunc1(
172172
; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215
173-
; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[M]] to float
174-
; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half
173+
; CHECK-NEXT: [[R:%.*]] = sitofp i32 [[M]] to half
175174
; CHECK-NEXT: ret half [[R]]
176175
;
177176
%m = and i32 %x, 16777215
@@ -183,8 +182,7 @@ define half @masked_sint_to_fptrunc1(i32 %x) {
183182
define half @masked_sint_to_fptrunc2(i32 %x) {
184183
; CHECK-LABEL: @masked_sint_to_fptrunc2(
185184
; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8
186-
; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[M]] to float
187-
; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half
185+
; CHECK-NEXT: [[R:%.*]] = sitofp i32 [[M]] to half
188186
; CHECK-NEXT: ret half [[R]]
189187
;
190188
%m = lshr i32 %x, 8
@@ -220,8 +218,7 @@ define double @sint_to_fpext(i32 %x) {
220218
define double @masked_sint_to_fpext1(i32 %x) {
221219
; CHECK-LABEL: @masked_sint_to_fpext1(
222220
; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215
223-
; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[M]] to float
224-
; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double
221+
; CHECK-NEXT: [[R:%.*]] = sitofp i32 [[M]] to double
225222
; CHECK-NEXT: ret double [[R]]
226223
;
227224
%m = and i32 %x, 16777215
@@ -233,8 +230,7 @@ define double @masked_sint_to_fpext1(i32 %x) {
233230
define double @masked_sint_to_fpext2(i32 %x) {
234231
; CHECK-LABEL: @masked_sint_to_fpext2(
235232
; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8
236-
; CHECK-NEXT: [[F:%.*]] = sitofp i32 [[M]] to float
237-
; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double
233+
; CHECK-NEXT: [[R:%.*]] = sitofp i32 [[M]] to double
238234
; CHECK-NEXT: ret double [[R]]
239235
;
240236
%m = lshr i32 %x, 8
@@ -270,8 +266,7 @@ define half @uint_to_fptrunc(i32 %x) {
270266
define half @masked_uint_to_fptrunc1(i32 %x) {
271267
; CHECK-LABEL: @masked_uint_to_fptrunc1(
272268
; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215
273-
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[M]] to float
274-
; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half
269+
; CHECK-NEXT: [[R:%.*]] = uitofp i32 [[M]] to half
275270
; CHECK-NEXT: ret half [[R]]
276271
;
277272
%m = and i32 %x, 16777215
@@ -283,8 +278,7 @@ define half @masked_uint_to_fptrunc1(i32 %x) {
283278
define half @masked_uint_to_fptrunc2(i32 %x) {
284279
; CHECK-LABEL: @masked_uint_to_fptrunc2(
285280
; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8
286-
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[M]] to float
287-
; CHECK-NEXT: [[R:%.*]] = fptrunc float [[F]] to half
281+
; CHECK-NEXT: [[R:%.*]] = uitofp i32 [[M]] to half
288282
; CHECK-NEXT: ret half [[R]]
289283
;
290284
%m = lshr i32 %x, 8
@@ -320,8 +314,7 @@ define double @uint_to_fpext(i32 %x) {
320314
define double @masked_uint_to_fpext1(i32 %x) {
321315
; CHECK-LABEL: @masked_uint_to_fpext1(
322316
; CHECK-NEXT: [[M:%.*]] = and i32 [[X:%.*]], 16777215
323-
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[M]] to float
324-
; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double
317+
; CHECK-NEXT: [[R:%.*]] = uitofp i32 [[M]] to double
325318
; CHECK-NEXT: ret double [[R]]
326319
;
327320
%m = and i32 %x, 16777215
@@ -333,8 +326,7 @@ define double @masked_uint_to_fpext1(i32 %x) {
333326
define double @masked_uint_to_fpext2(i32 %x) {
334327
; CHECK-LABEL: @masked_uint_to_fpext2(
335328
; CHECK-NEXT: [[M:%.*]] = lshr i32 [[X:%.*]], 8
336-
; CHECK-NEXT: [[F:%.*]] = uitofp i32 [[M]] to float
337-
; CHECK-NEXT: [[R:%.*]] = fpext float [[F]] to double
329+
; CHECK-NEXT: [[R:%.*]] = uitofp i32 [[M]] to double
338330
; CHECK-NEXT: ret double [[R]]
339331
;
340332
%m = lshr i32 %x, 8

llvm/test/Transforms/InstCombine/sitofp.ll

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,16 +218,38 @@ define i55 @test19(i64 %A) {
218218
ret i55 %C
219219
}
220220

221-
; TODO: The mask guarantees that the input is small enough to eliminate the FP casts.
221+
; The mask guarantees that the input is small enough to eliminate the FP casts.
222222

223223
define i25 @masked_input(i25 %A) {
224224
; CHECK-LABEL: @masked_input(
225225
; CHECK-NEXT: [[M:%.*]] = and i25 [[A:%.*]], 65535
226+
; CHECK-NEXT: ret i25 [[M]]
227+
;
228+
%m = and i25 %A, 65535
229+
%B = uitofp i25 %m to float
230+
%C = fptoui float %B to i25
231+
ret i25 %C
232+
}
233+
234+
define i25 @max_masked_input(i25 %A) {
235+
; CHECK-LABEL: @max_masked_input(
236+
; CHECK-NEXT: [[M:%.*]] = and i25 [[A:%.*]], 16777215
237+
; CHECK-NEXT: ret i25 [[M]]
238+
;
239+
%m = and i25 %A, 16777215 ; max intermediate 16777215 (= 1 << 24)-1
240+
%B = uitofp i25 %m to float
241+
%C = fptoui float %B to i25
242+
ret i25 %C
243+
}
244+
245+
define i25 @overflow_masked_input(i25 %A) {
246+
; CHECK-LABEL: @overflow_masked_input(
247+
; CHECK-NEXT: [[M:%.*]] = and i25 [[A:%.*]], -16777216
226248
; CHECK-NEXT: [[B:%.*]] = uitofp i25 [[M]] to float
227249
; CHECK-NEXT: [[C:%.*]] = fptoui float [[B]] to i25
228250
; CHECK-NEXT: ret i25 [[C]]
229251
;
230-
%m = and i25 %A, 65535
252+
%m = and i25 %A, 16777216 ; Negative test - intermediate 16777216 (= 1 << 24)
231253
%B = uitofp i25 %m to float
232254
%C = fptoui float %B to i25
233255
ret i25 %C

0 commit comments

Comments
 (0)