aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/ConstantFold.cpp
AgeCommit message (Collapse)AuthorFilesLines
7 days[IR] Require DataLayout for pointer cast elimination (#162279)Nikita Popov1-8/+1
isEliminableCastPair() currently tries to support elimination of ptrtoint/inttoptr cast pairs by assuming that the maximum possible pointer size is 64 bits. Of course, this is no longer the case nowadays. This PR changes isEliminableCastPair() to accept an optional DataLayout argument, which is required to eliminate pointer casts. This means that we no longer eliminate these cast pairs during ConstExpr construction, and instead only do it during DL-aware constant folding. This had a lot of annoying fallout on tests, most of which I've addressed in advance of this change.
2025-08-08[IR] Introduce the `ptrtoaddr` instructionAlexander Richardson1-0/+1
This introduces a new `ptrtoaddr` instruction which is similar to `ptrtoint` but has two differences: 1) Unlike `ptrtoint`, `ptrtoaddr` does not capture provenance 2) `ptrtoaddr` only extracts (and then extends/truncates) the low index-width bits of the pointer For most architectures, difference 2) does not matter since index (address) width and pointer representation width are the same, but this does make a difference for architectures that have pointers that aren't just plain integer addresses such as AMDGPU fat pointers or CHERI capabilities. This commit introduces textual and bitcode IR support as well as basic code generation, but optimization passes do not handle the new instruction yet so it may result in worse code than using ptrtoint. Follow-up changes will update capture tracking, etc. for the new instruction. RFC: https://discourse.llvm.org/t/clarifiying-the-semantics-of-ptrtoint/83987/54 Reviewed By: nikic Pull Request: https://github.com/llvm/llvm-project/pull/139357
2025-06-10[ConstantFolding] Fold scalable shufflevector of poison/undef. (#143475)Craig Topper1-4/+3
2025-06-03[ConstantFold] Constant fold icmp of boolean scalable vectors (#142528)Yingwei Zheng1-2/+2
Closes https://github.com/llvm/llvm-project/issues/142447.
2025-04-03[ConstantFold] Support scalable constant splats in ↵Luke Lau1-4/+5
ConstantFoldCastInstruction (#133207) Previously only fixed vector splats were handled. This adds supports for scalable vectors too by allowing ConstantExpr splats. We need to add the extra V->getType()->isVectorTy() check because a ConstantExpr might be a scalar to vector bitcast. By allowing ConstantExprs this also allow fixed vector ConstantExprs to be folded, which causes the diffs in llvm/test/Analysis/ValueTracking/known-bits-from-operator-constexpr.ll and llvm/test/Transforms/InstSimplify/ConstProp/cast-vector.ll. I can remove them from this PR if reviewers would prefer. Fixes #132922
2024-12-16[LLVM][ConstantFold] Remove remaining uses of ↵Paul Walker1-15/+14
ConstantInt/FP::get(LLVMContext... (#119912) This extends the constant folds to support vector ConstantInt/FP.
2024-11-21[LLVM][IR] Refactor ConstantFold:FoldBitCast to fully support vector ↵Paul Walker1-23/+24
ConstantInt/FP. (#116787) This fixes the code quality issue reported in https://github.com/llvm/llvm-project/pull/111149.
2024-11-13[LLVM][IR] Teach constant integer binop folds about vector ConstantInts. ↵Paul Walker1-27/+23
(#115739) The existing logic mostly works with the main changes being: * Use getScalarSizeInBits instead of IntegerType::getBitWidth * Use ConstantInt::get(Type* instead of ConstantInt::get(LLVMContext
2024-11-02[IR] Remove unused includes (NFC) (#114679)Kazu Hirata1-1/+0
Identified with misc-include-cleaner.
2024-11-01[InstSimplify][InstCombine][ConstantFold] Move vector div/rem by zero fold ↵Yingwei Zheng1-5/+0
to InstCombine (#114280) Previously we fold `div/rem X, C` into `poison` if any element of the constant divisor `C` is zero or undef. However, it is incorrect when threading udiv over an vector select: https://alive2.llvm.org/ce/z/3Ninx5 ``` define <2 x i32> @vec_select_udiv_poison(<2 x i1> %x) { %sel = select <2 x i1> %x, <2 x i32> <i32 -1, i32 -1>, <2 x i32> <i32 0, i32 1> %div = udiv <2 x i32> <i32 42, i32 -7>, %sel ret <2 x i32> %div } ``` In this case, `threadBinOpOverSelect` folds `udiv <i32 42, i32 -7>, <i32 -1, i32 -1>` and `udiv <i32 42, i32 -7>, <i32 0, i32 1>` into `zeroinitializer` and `poison`, respectively. One solution is to introduce a new flag indicating that we are threading over a vector select. But it requires to modify both `InstSimplify` and `ConstantFold`. However, this optimization doesn't provide benefits to real-world programs: https://dtcxzyw.github.io/llvm-opt-benchmark/coverage/data/zyw/opt-ci/actions-runner/_work/llvm-opt-benchmark/llvm-opt-benchmark/llvm/llvm-project/llvm/lib/IR/ConstantFold.cpp.html#L908 https://dtcxzyw.github.io/llvm-opt-benchmark/coverage/data/zyw/opt-ci/actions-runner/_work/llvm-opt-benchmark/llvm-opt-benchmark/llvm/llvm-project/llvm/lib/Analysis/InstructionSimplify.cpp.html#L1107 This patch moves the fold into InstCombine to avoid breaking numerous existing tests. Fixes #114191 and #113866 (only poison-safety issue).
2024-10-25[InstCombine] Fix a cycle when folding fneg(select) with scalable vector ↵ssijaric-nv1-14/+15
types (#112465) The two folding operations are causing a cycle for the following case with scalable vector types: define <vscale x 2 x double> @test_fneg_select_abs(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) { %1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> %b %2 = fneg fast <vscale x 2 x double> %1 ret <vscale x 2 x double> %2 } 1) fold fneg: -(Cond ? C : Y) -> Cond ? -C : -Y 2) fold select: (Cond ? -X : -Y) -> -(Cond ? X : Y) 1) results in the following since '<vscale x 2 x double> zeroinitializer' passes the check for the immediate constant: %.neg = fneg fast <vscale x 2 x double> zeroinitializer %b.neg = fneg fast <vscale x 2 x double> %b %1 = select fast <vscale x 2 x i1> %cond, <vscale x 2 x double> %.neg, <vscale x 2 x double> %b.neg and so we end up going back and forth between 1) and 2). Attempt to fold scalable vector constants, so that we end up with a splat instead: define <vscale x 2 x double> @test_fneg_select_abs(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) { %b.neg = fneg fast <vscale x 2 x double> %b %1 = select fast <vscale x 2 x i1> %cond, <vscale x 2 x double> shufflevector (<vscale x 2 x double> insertelement (<vscale x 2 x double> poison, double -0.000000e+00, i64 0), <vscale x 2 x double> poison, <vscale x 2 x i32> zeroinitializer), <vscale x 2 x double> %b.neg ret <vscale x 2 x double> %1 }
2024-10-08[LLVM][ConstFolds] Verify a scalar src before attempting scalar->vector ↵Paul Walker1-2/+3
bitcast transformation. (#111149) It was previously safe to assume isa<Constant{Int,FP}> meant a scalar value. This is not true when use-constant-##-for-###-splat are enabled.
2024-10-01[ConstantFold][RFC] Add AllowLHSConstant parameter in getBinOpAbsorber (#109736)eric-xtang10081-24/+8
Add a AllowLHSConstant parameter in getBinOpAbsorber function for supporting more binary operators.
2024-07-25Remove the `x86_mmx` IR type. (#98505)James Y Knight1-1/+1
It is now translated to `<1 x i64>`, which allows the removal of a bunch of special casing. This _incompatibly_ changes the ABI of any LLVM IR function with `x86_mmx` arguments or returns: instead of passing in mmx registers, they will now be passed via integer registers. However, the real-world incompatibility caused by this is expected to be minimal, because Clang never uses the x86_mmx type -- it lowers `__m64` to either `<1 x i64>` or `double`, depending on ABI. This change does _not_ eliminate the SelectionDAG `MVT::x86mmx` type. That type simply no longer corresponds to an IR type, and is used only by MMX intrinsics and inline-asm operands. Because SelectionDAGBuilder only knows how to generate the operands/results of intrinsics based on the IR type, it thus now generates the intrinsics with the type MVT::v1i64, instead of MVT::x86mmx. We need to fix this before the DAG LegalizeTypes, and thus have the X86 backend fix them up in DAGCombine. (This may be a short-lived hack, if all the MMX intrinsics can be removed in upcoming changes.) Works towards issue #98272.
2024-06-20[IR] Remove support for shl constant expressions (#96037)Nikita Popov1-68/+0
Remove support for shl constant expressions, as part of: https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179
2024-06-13Reapply [ConstantFold] Drop gep of gep fold entirely (#95126)Nikita Popov1-33/+0
Reapplying without changes. The flang+openmp buildbot failure should be addressed by https://github.com/llvm/llvm-project/pull/94541. ----- This is a followup to https://github.com/llvm/llvm-project/pull/93823 and drops the DataLayout-unaware GEP of GEP fold entirely. All cases are now left to the DataLayout-aware constant folder, which will fold everything to a single i8 GEP. We didn't have any test coverage for this fold in LLVM, but some Clang tests change.
2024-06-12Revert "[ConstantFold] Drop gep of gep fold entirely (#95126)"Nikita Popov1-0/+33
This reverts commit 3b3b839c66dc49674fd6646650525a2173030690. This broke the flang+openmp+offload buildbot, as reported in https://github.com/llvm/llvm-project/pull/95126#issuecomment-2162424019.
2024-06-12[ConstantFold] Drop gep of gep fold entirely (#95126)Nikita Popov1-33/+0
This is a followup to https://github.com/llvm/llvm-project/pull/93823 and drops the DataLayout-unaware GEP of GEP fold entirely. All cases are now left to the DataLayout-aware constant folder, which will fold everything to a single i8 GEP. We didn't have any test coverage for this fold in LLVM, but some Clang tests change.
2024-06-10Reapply [ConstantFold] Remove non-trivial gep-of-gep fold (#93823)Nikita Popov1-52/+4
Reapply after https://github.com/llvm/llvm-project/pull/93956, which changed clang array initialization codegen to avoid size regressions for unoptimized builds. ----- This fold is subtly incorrect, because DL-unaware constant folding does not know the correct index type to use, and just performs the addition in the type that happens to already be there. This is incorrect, since sext(X)+sext(Y) is generally not the same as sext(X+Y). See the `@constexpr_gep_of_gep_with_narrow_type()` for a miscompile with the current implementation. One could try to restrict the fold to cases where no overflow occurs, but I'm not bothering with that here, because the DL-aware constant folding will take care of this anyway. I've only kept the straightforward zero-index case, where we just concatenate two GEPs.
2024-06-04[IR] Remove support for icmp and fcmp constant expressions (#93038)Nikita Popov1-16/+0
Remove support for the icmp and fcmp constant expressions. This is part of: https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179 As usual, many of the updated tests will no longer test what they were originally intended to -- this is hard to preserve when constant expressions get removed, and in many cases just impossible as the existence of a specific kind of constant expression was the cause of the issue in the first place.
2024-05-31Revert "[ConstantFold] Remove non-trivial gep-of-gep fold (#93823)"Nikita Popov1-4/+52
This reverts commit e1cc9e4eaddcc295b4e775512e33b947b1514c17. This causes some non-trivial text size increases in unoptimized builds for Bullet. Revert while I investigate.
2024-05-31[ConstantFold] Remove non-trivial gep-of-gep fold (#93823)Nikita Popov1-52/+4
This fold is subtly incorrect, because DL-unaware constant folding does not know the correct index type to use, and just performs the addition in the type that happens to already be there. This is incorrect, since sext(X)+sext(Y) is generally not the same as sext(X+Y). See the `@constexpr_gep_of_gep_with_narrow_type()` for a miscompile with the current implementation. One could try to restrict the fold to cases where no overflow occurs, but I'm not bothering with that here, because the DL-aware constant folding will take care of this anyway. I've only kept the straightforward zero-index case, where we just concatenate two GEPs.
2024-05-31Reapply [IR] Avoid creating icmp/fcmp constant expressions (#92885)Nikita Popov1-5/+8
Reapply after https://github.com/llvm/llvm-project/pull/93548, which should address the lldb failure on macos. ----- Do not create icmp/fcmp constant expressions in IRBuilder etc anymore, i.e. treat them as "undesirable". This is in preparation for removing them entirely. Part of: https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179
2024-05-30[ConstantFold] Remove notional over-indexing fold (#93697)Nikita Popov1-196/+0
The data-layout independent constant folding currently has some rather gnarly code for canonicalizing GEP indices to reduce "notional overindexing", and then infers inbounds based on that canonicalization. Now that we canonicalize to i8 GEPs, this canonicalization is essentially useless, as we'll discard it as soon as the GEP hits the data-layout aware constant folder anyway. As such, I'd like to remove this code entirely. This shouldn't have any impact on optimization capabilities.
2024-05-28[ConstFold] Fix incorrect gep inbounds of undef foldNikita Popov1-2/+1
gep inbounds of undef can only be folded to poison if we know that the offset is non-zero. I don't think precise handling here is important, so just drop the inbounds special case. This matches what InstSimplify does.
2024-05-27[IR] Add getelementptr nusw and nuw flags (#90824)Nikita Popov1-2/+3
This implements the `nusw` and `nuw` flags for `getelementptr` as proposed at https://discourse.llvm.org/t/rfc-add-nusw-and-nuw-flags-for-getelementptr/78672. The three possible flags are encapsulated in the new `GEPNoWrapFlags` class. Currently this class has a ctor from bool, interpreted as the InBounds flag. This ctor should be removed in the future, as code gets migrated to handle all flags. There are a few places annotated with `TODO(gep_nowrap)`, where I've had to touch code but opted to not infer or precisely preserve the new flags, so as to keep this as NFC as possible and make sure any changes of that kind get test coverage when they are made.
2024-05-22Revert "[IR] Avoid creating icmp/fcmp constant expressions" (#93087)Daniel Thornburgh1-8/+5
Reverts llvm/llvm-project#92885 due to LLDB CI breakages.
2024-05-22[IR] Avoid creating icmp/fcmp constant expressions (#92885)Nikita Popov1-5/+8
Do not create icmp/fcmp constant expressions in IRBuilder etc anymore, i.e. treat them as "undesirable". This is in preparation for removing them entirely. Part of: https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179
2024-05-17[NFC][LLVM] Mainly whitespace changes.Paul Walker1-0/+1
Also marks AliasSetTracker::size() as const.
2024-03-20[IR] Change representation of getelementptr inrange (#84341)Nikita Popov1-22/+13
As part of the migration to ptradd (https://discourse.llvm.org/t/rfc-replacing-getelementptr-with-ptradd/68699), we need to change the representation of the `inrange` attribute, which is used for vtable splitting. Currently, inrange is specified as follows: ``` getelementptr inbounds ({ [4 x ptr], [4 x ptr] }, ptr @vt, i64 0, inrange i32 1, i64 2) ``` The `inrange` is placed on a GEP index, and all accesses must be "in range" of that index. The new representation is as follows: ``` getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr @vt, i64 0, i32 1, i64 2) ``` This specifies which offsets are "in range" of the GEP result. The new representation will continue working when canonicalizing to ptradd representation: ``` getelementptr inbounds inrange(-16, 16) (i8, ptr @vt, i64 48) ``` The inrange offsets are relative to the return value of the GEP. An alternative design could make them relative to the source pointer instead. The result-relative format was chosen on the off-chance that we want to extend support to non-constant GEPs in the future, in which case this variant is more expressive. This implementation "upgrades" the old inrange representation in bitcode by simply dropping it. This is a very niche feature, and I don't think trying to upgrade it is worthwhile. Let me know if you disagree.
2024-03-19[ConstantFold] Fix comparison between special pointer constantsNikita Popov1-2/+1
This code was assuming that the LHS would always be one of GlobalVariable, BlockAddress or ConstantExpr. However, it can also be a special constant like dso_local_equivalent or no_cfi. Make sure this is handled gracefully.
2024-01-18[ConstantFold] Clean up binop identity foldingNikita Popov1-36/+13
Resolve the two FIXMEs: Perform the binop identitiy fold with AllowRHSConstant, and remove redundant folds later in the code.
2023-12-18[LLVM][IR] Replace ConstantInt's specialisation of getType() with ↵Paul Walker1-1/+1
getIntegerType(). (#75217) The specialisation will not be valid when ConstantInt gains native support for vector types. This is largely a mechanical change but with extra attention paid to constant folding, InstCombineVectorOps.cpp, LoopFlatten.cpp and Verifier.cpp to remove the need to call `getIntegerType()`. Co-authored-by: Nikita Popov <github@npopov.com>
2023-11-14[llvm] Fix -Wunused-variable in ConstantFold.cpp (NFC)Jie Fu1-1/+1
/llvm-project/llvm/lib/IR/ConstantFold.cpp:137:12: error: unused variable 'CSize' [-Werror,-Wunused-variable] unsigned CSize = cast<IntegerType>(C->getType())->getBitWidth()/8; ^ 1 error generated.
2023-11-14[IR] Remove support for lshr/ashr constant expressions (#71955)Nikita Popov1-23/+0
Remove support for the lshr and ashr constant expressions. All places creating them have been removed beforehand, so this just removes the APIs and uses of these constant expressions in tests. This is part of https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179.
2023-11-03[ConstantFold] Remove redundant zero index gep fold (NFCI)Nikita Popov1-33/+0
We already handle the more general case of zero index GEPs above, so we don't need to also handle GEPs with null based and zero indices. (Strictly speaking, this code could handle the special case of an inrange gep with null base and zero indices, but that has no practical relevance.)
2023-11-03[ConstantFold] Remove redundant bitcast icmp handling (NFCI)Nikita Popov1-14/+0
This code excludes vector/scalar and FP bitcasts. All other integer/pointer bitcasts are no-op bitcasts and will be removed entirely.
2023-11-03[ConstantFold] Remove redundant constantFoldCompareGlobalToNull() fold (NFCI)Nikita Popov1-27/+0
This is already handled in evaluateICmpRelation().
2023-11-03[ConstantFold] Fix incorrect type assumptionsNikita Popov1-10/+4
If a pointer isn't a constant expression, global or block address, it's not guaranteed to be a null pointer. It can also be a no_cfi or dso_local_equivalent constant.
2023-11-03[ConstantFold] Simplify evaluateICmpRelation() implementation (NFCI)Nikita Popov1-68/+38
Clarify that most of this only works on pointer icmps, and remove the unnecessary isSigned parameter, as well as the ConstantInt fallback. Also perform complexity sorting upfront, so we don't need to deal with swapped cases in the individual branches.
2023-11-03[ConstantFold] Remove handling for icmp of bitcastNikita Popov1-14/+0
This only handles the case where the bitcast result is an integer or pointer, and the input is not FP. This means that the input can only be a vector. However, converting a comparison of the whole vector into an element-wise comparison is generally not correct. I assume that this code was originally intended to handle the case where a pointer bitcast is compared to a null pointer, which is no longer relevant with opaque pointers. Given the complete lack of test coverage, and the risk of miscompiles if this code actually did something, I'm opting to remove it entirely.
2023-11-03[ConstantFold] Remove handling for comparison of bitcasted global (NFCI)Nikita Popov1-6/+0
The bitcast will be folded away in this case, no need to handle it explicitly.
2023-11-03[ConstantFold] Don't mention irrelevant opcodes (NFCI)Nikita Popov1-10/+1
This is folding an icmp, so fptrunc, fpext, uitofp, sitofp cannot appear here at all. Also drop the explicit checks for trunc, fptoui, fptosi, which can appear, but are just some random subset of opcodes that are not handled by this code.
2023-11-03[ConstantFold] Remove unnecessarily complicated evaluateFCmpRelation() (NFCI)Nikita Popov1-134/+5
The only thing this actually handles is if the operands are the same, in which case ueq is returned. Given that nearly all FP constant expressions have already been removed, I think it's safe to say that we aren't going to extend this code in a way that makes use of the more general structure.
2023-11-03[ConstantFold] Remove redundant handling for casts of null (NFCI)Nikita Popov1-10/+2
ConstantFoldCastInstruction() has generic handling for null values at the top. No need to repeat it for inttoptr and ptrtoint.
2023-11-03Reapply [ConstantFold] Remove unnecessary BitCastConstantVector() (NFCI)Nikita Popov1-51/+3
ConstantFoldCastInstruction() already has generic code to perform lane-wise casts for vectors. There is no need to repeate it specifically for bitcasts. However, we do need to keep the special case for vectors of -1, which is not handled elsewhere.
2023-11-03Revert "[ConstantFold] Remove unnecessary BitCastConstantVector() (NFCI)"Nikita Popov1-1/+52
This reverts commit 2182561b7ba675ca87356c02474eecb6ecfaa23f. The all-ones special case in this case isn't redundant. Will redo the change while preserving it.
2023-11-03[ConstantFold] Remove unnecessary cast of zero gep fold (NFCI)Nikita Popov1-22/+0
Zero GEPs will be optimized away entirely, except in the cases which this transform also excludes (splat, inrange).
2023-11-03[ConstantFold] Remove unnecessary checks in FoldBitCast() (NFCI)Nikita Popov1-10/+0
These are no-op casts, which are already handled earlier.
2023-11-03[ConstantFold] Remove unnecessary BitCastConstantVector() (NFCI)Nikita Popov1-52/+1
ConstantFoldCastInstruction() already has generic code to perform lane-wise casts for vectors. There is no need to repeate it specifically for bitcasts.