[llvm] [InstCombine] Add folds for `(fp_binop ({s|u}itofp x), ({s|u}itofp y))` (PR #82555)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 29 10:11:23 PST 2024
================
@@ -1401,6 +1401,176 @@ Value *InstCombinerImpl::dyn_castNegVal(Value *V) const {
return nullptr;
}
+// Try to fold:
+// 1) (fp_binop ({s|u}itofp x), ({s|u}itofp y))
+// -> ({s|u}itofp (int_binop x, y))
+// 2) (fp_binop ({s|u}itofp x), FpC)
+// -> ({s|u}itofp (int_binop x, (fpto{s|u}i FpC)))
+Instruction *InstCombinerImpl::foldFBinOpOfIntCasts(BinaryOperator &BO) {
+ Value *IntOps[2] = {nullptr, nullptr};
+ Constant *Op1FpC = nullptr;
+
+ // Check for:
+ // 1) (binop ({s|u}itofp x), ({s|u}itofp y))
+ // 2) (binop ({s|u}itofp x), FpC)
+ if (!match(BO.getOperand(0), m_SIToFP(m_Value(IntOps[0]))) &&
+ !match(BO.getOperand(0), m_UIToFP(m_Value(IntOps[0]))))
+ return nullptr;
+
+ if (!match(BO.getOperand(1), m_Constant(Op1FpC)) &&
+ !match(BO.getOperand(1), m_SIToFP(m_Value(IntOps[1]))) &&
+ !match(BO.getOperand(1), m_UIToFP(m_Value(IntOps[1]))))
+ return nullptr;
+
+ Type *FPTy = BO.getType();
+ Type *IntTy = IntOps[0]->getType();
+
+ // Do we have signed casts?
+ bool OpsFromSigned = isa<SIToFPInst>(BO.getOperand(0));
+
+ unsigned IntSz = IntTy->getScalarSizeInBits();
+ // This is the maximum number of inuse bits by the integer where the int -> fp
+ // casts are exact.
+ unsigned MaxRepresentableBits =
+ APFloat::semanticsPrecision(FPTy->getScalarType()->getFltSemantics());
----------------
goldsteinn wrote:
Yes, we are overly conservative if `IntSz == MaxRepresentableBits + 1` and its signed (not we can't expand the bound for say `sitofp i16 to half` b.c it won't sign extend). So for things like `i12`, `i24`, ...
I'll add comment to the affect, although don't think its really worth increase code complexity to handle a special case that will almost never actually apply (weird integer widths are rare).
Proofs:
```
; $> /home/noah/programs/opensource/llvm-dev/src/alive2/build/alive-tv (-smt-to=200000000)
----------------------------------------
define half @src_sisi_add_i12(i12 noundef %x, i12 noundef %y) {
#0:
%overflow_info = sadd_overflow i12 noundef %x, noundef %y
%does_overflow = extractvalue {i12, i1, i8} %overflow_info, 1
%doesnot_overflow = xor i1 %does_overflow, 1
assume i1 %doesnot_overflow
%xf = sitofp i12 noundef %x to half
%yf = sitofp i12 noundef %y to half
%r = fadd half %xf, %yf
ret half %r
}
=>
define half @tgt_sisi_add_i12(i12 noundef %x, i12 noundef %y) {
#0:
%overflow_info = sadd_overflow i12 noundef %x, noundef %y
%does_overflow = extractvalue {i12, i1, i8} %overflow_info, 1
%doesnot_overflow = xor i1 %does_overflow, 1
assume i1 %doesnot_overflow
%xy = add i12 noundef %x, noundef %y
%r = sitofp i12 %xy to half
ret half %r
}
Transformation seems to be correct!
----------------------------------------
define half @src_uiui_add_i12(i12 noundef %x, i12 noundef %y) {
#0:
%overflow_info = uadd_overflow i12 noundef %x, noundef %y
%does_overflow = extractvalue {i12, i1, i8} %overflow_info, 1
%doesnot_overflow = xor i1 %does_overflow, 1
assume i1 %doesnot_overflow
%xf = uitofp i12 noundef %x to half
%yf = uitofp i12 noundef %y to half
%r = fadd half %xf, %yf
ret half %r
}
=>
define half @tgt_uiui_add_i12(i12 noundef %x, i12 noundef %y) {
#0:
%overflow_info = uadd_overflow i12 noundef %x, noundef %y
%does_overflow = extractvalue {i12, i1, i8} %overflow_info, 1
%doesnot_overflow = xor i1 %does_overflow, 1
assume i1 %doesnot_overflow
%xy = add i12 noundef %x, noundef %y
%r = uitofp i12 %xy to half
ret half %r
}
Transformation doesn't verify!
ERROR: Value mismatch
Example:
i12 noundef %x = #x80d (2061, -2035)
i12 noundef %y = #x002 (2)
Source:
{i12, i1, i8} %overflow_info = { #x80f (2063, -2033), #x0 (0), poison }
i1 %does_overflow = #x0 (0)
i1 %doesnot_overflow = #x1 (1)
half %xf = #x6806 (2060)
half %yf = #x4000 (2)
half %r = #x6807 (2062)
Target:
{i12, i1, i8} %overflow_info = { #x80f (2063, -2033), #x0 (0), poison }
i1 %does_overflow = #x0 (0)
i1 %doesnot_overflow = #x1 (1)
i12 %xy = #x80f (2063, -2033)
half %r = #x6808 (2064)
Source value: #x6807 (2062)
Target value: #x6808 (2064)
Summary:
1 correct transformations
1 incorrect transformations
0 failed-to-prove transformations
0 Alive2 errors
```
https://github.com/llvm/llvm-project/pull/82555
More information about the llvm-commits
mailing list