Skip to content

Enh : use llvm.powi to handle ** with integer type exponent for accurate precision#6191

Merged
certik merged 17 commits into
lfortran:mainfrom
assem2002:precision-with-pow
Feb 3, 2025
Merged

Enh : use llvm.powi to handle ** with integer type exponent for accurate precision#6191
certik merged 17 commits into
lfortran:mainfrom
assem2002:precision-with-pow

Conversation

@assem2002

Copy link
Copy Markdown
Contributor

Fix #6150

Comment thread tests/errors/pow_02.f90 Outdated
Comment thread tests/reference/asr-derived_types_15-7fde02a.stdout Outdated
Comment thread src/libasr/codegen/asr_to_llvm.cpp Outdated
exponent_type = base_type;
} else {
throw CodeGenError("Only [Integer , Real] exponent operator are supported.",
x.m_right->base.loc);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this convert v^2 to mul(v, v)?

@assem2002 assem2002 Feb 3, 2025

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the main motive behind hard coding **2 into mul operation was that we want to preserve the the precision because we thought llvm only had llvm.pow(float,float) intrinsic function, I looked for llvm intrinsic that accepts an i32 exponent and I found llvm.powi function. so now we don't need to hard code ** into mul (for **2 and **3 only), unless we do it for sake for efficiency(though I think it won't matter).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be strict about the operands to be of matching types (by using cast if needed)?

Comment thread src/libasr/codegen/asr_to_wasm.cpp Outdated
@certik certik marked this pull request as draft February 3, 2025 04:26
@assem2002 assem2002 marked this pull request as ready for review February 3, 2025 13:15
@assem2002

assem2002 commented Feb 3, 2025

Copy link
Copy Markdown
Contributor Author

I made some critical changes. It might need a review from the top again :).
The commits may need to be squashed.

@assem2002 assem2002 added the PRIMA Related to compiling the PRIMA code label Feb 3, 2025
@assem2002 assem2002 marked this pull request as draft February 3, 2025 13:48
@certik

certik commented Feb 3, 2025

Copy link
Copy Markdown
Contributor

Let me know when the tests pass, then I'll review carefully again.

@assem2002 assem2002 marked this pull request as ready for review February 3, 2025 18:40
@assem2002

Copy link
Copy Markdown
Contributor Author

It's ready for review.

Level::Error, Stage::Semantic, {Label("", {loc})}));
throw SemanticAbort();
}
return nullptr;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this mean that unimplemented combinations are silently ignored?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked for the places using this function and returning nullptr fits nice.
The reciever of the function should be expr_t* value (the compile time value of the whole expression), If we can't create one, we return nullptr indicating that the whole expression doesn't have compile time value.

@certik certik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this is good. So it turned out that llvm already had a good support for integer powers, we just didn't use it before?

@certik certik merged commit 644d3f5 into lfortran:main Feb 3, 2025
@assem2002

Copy link
Copy Markdown
Contributor Author

I think that this is good. So it turned out that llvm already had a good support for integer powers, we just didn't use it before?

Yeah, that's right.

galactus3050 pushed a commit to galactus3050/lfortran that referenced this pull request Feb 18, 2025
…ccurate precision (lfortran#6191)

* Chore : Fix `convert_kind` utility function to appropriately truncate or extend floating point values

* Enh : Enhance `BinOpHelper` to be a function that attempts to craete a compile-time binary operation of some Binop expression, if it's possible to be done.
If it can't it will return a nullptr and the caller would know that the requested compile-time calculation isn't possible and the BinOp expression can't have a compile-time value

* Fix : Don't attempt to do a cast if :
- `BinOp` is `**`
- Base expression is `REAL`
- Exponent expression in `INTEGER`

* Enh : Use `llvm.powi` intrinsic function with `IntegerBinOp`

* Fix : Use `llvm.powi` intrinsic function if exponent is `Integer` type within `RealBinOp` expression to preserve precision.

* Minor : Handle exponent of type integer in WASM backend

* Add and register integration test

* Test : Enhance test by using precision tolerance instead of direct comparison

* Add NOFAST label, as we're testing precision so we shouldn't optimize

* LLVM_VERSION : Use `powi.f**` and `powi.f**.i32` based on llvm version

* Warning : Remove real(8) exponent warning as it isn't that helpful

* Minor : initialize pointer, to silent warnings

* minor fix : use f64_mul with real of kind 8

* minor : Use `llvm.powi.f**` name with llvm_version 12"

* tests: Update reference tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PRIMA Related to compiling the PRIMA code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug : precision loss with using power ** operator

2 participants