[CIR] Lower constant block addresses for goto#201644
Conversation
GNU computed-goto code that takes a label's address in a constant
context -- the common static dispatch-table idiom
`static const void *tbl[] = {&&L1, &&L2}; goto *tbl[i];` -- hit
`errorNYI` in `ConstantLValueEmitter::VisitAddrLabelExpr`, and the
follow-on `goto *tbl[i]` then tripped the `indirectGotoBlock`
assertion in `emitIndirectGotoStmt` because the label was never
registered as address-taken. The runtime form (`void *p = &&L;
goto *p;`) already worked; only the constant form was missing.
Label addresses had no constant representation: `cir.block_address`
existed only as an operation, which cannot appear inside a
`#cir.const_array` initializer. Add a `#cir.block_address` constant
attribute and lower it to MLIR's `LLVM::BlockAddressAttr`, reusing the
same `BlockTagOp` resolution the operation form already uses
(threading the pass-owned `LLVMBlockAddressInfo` into the constant
value lowering and the Global/Constant lowering patterns).
CIRGen's `ConstantLValueEmitter::VisitAddrLabelExpr` now emits the
attribute and records the label so `finishIndirectBranch` adds it to
the `cir.indirect_br` successors and the indirect-goto block is
instantiated. Because such labels have no function-local
`BlockAddressOp`, `GotoSolver` was deleting them as unused; it now
also keeps labels referenced by a constant `#cir.block_address`
anywhere in the module.
The lowered LLVM matches classic codegen (a `[N x ptr]` of
`blockaddress` constants plus an `indirectbr`). New test
`goto-address-label-table.c` covers CIR, the CIR-lowered LLVM, and
classic OGCG; `label-values.c` (the runtime form) is unchanged.
How to use the Graphite Merge QueueAdd the label FP Bundles to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: adams381 Changes[mlir][spirv][tosa] Add remaining TOSA 1.0 SPIR-V TOSA ops (#200383) Add conversion patterns for additional TOSA 1.0 operations targeting the This covers pooling and convolution ops, FFT/RFFT, matmul, concat, pad, Add a multi-result conversion pattern for FFT/RFFT and share the Also share constant attribute conversion for const and const_shape, Add conversion tests for the newly covered operations. Signed-off-by: Davide Grohmann <davide.grohmann@arm.com> [LV] Fix missing MetaData for histogram instructions (#134241) [libc] Add netinet/udp.h containing struct udphdr (#200839) This patch adds a generated <netinet/udp.h> containing the There are two styles ("linux" and "BSD") of udphdr field names (and both I've added the target to To verify layout and alignment correctness, I've added a layout and Assisted by Gemini. [lldb][Windows] Use captured error in ConnectionGenericFile::Read (#200803) Use the captured value on both branches so the reported error matches [cuda][flang] Diagnose missing CUDA intrinsic modules in Flang semantics (#200509)
[NFC][clang-sycl-linker] Apply LLVM coding standards to ClangSYCLLinker.cpp (#200543) Bring the file in line with llvm/docs/CodingStandards.rst without
Co-Authored-By: Claude [CIR] Implement __builtin_astype for vec4 to vec3 (#199374) Implement __builtin_astype for vec4 to vec3 Issue #192311 [LLDB] Detect cycles during Type resolution (#200304) I got LLDB crash reports from the Swift plugin where (presumably rdar://177856769 Assisted-by: claude [lldb-dap] Cleanup InstructionBreakpoint (#200228) Added mutex like in other breakpoints [libc] Add GPU build-only to fullbuild precommit CIs. (#200593)
[SROA] Canonicalize homogeneous structs to fixed vectors (opt-in, after memcpyopt) (#165159) SROA sometimes keeps temporary allocas around for homogeneous structs Canonicalization is gated behind a new per-pass option Co-authored-by: Yonah Goldberg <ygoldberg@nvidia.com> Co-authored-by: Yonah Goldberg <ygoldberg@nvidia.com> [AMDGPU] Verify data size of load-to-LDS intrinsics (#200587) An out-of-range size immarg (e.g. 0) produced an illegal i0 memory type [DirectX] Implement lowering of llvm.dx.resource.samplebias to the SampleBias DXIL Op (#199745) Fixes #192548 This PR implements the lowering of the Although I reckon that other Assisted-by: Claude Opus 4.6 [lldb-dap] Use SetTarget for launch and attach commands (#200133) Without this patch event listener registration was skipped, as a result [PGO][HIP] Fix profile-only Windows link by gating ROCm interceptor macro (#200859) PR #200111 stops compiling InstrProfilingPlatformROCm.cpp (which defines On ELF the declaration is weak, so the undefined symbol folds to null error LNK2019: unresolved external symbol Add the define only when PROFILE_HAS_HIP_INTERCEPTOR is true, i.e. the Reported by zmodem: [offload][LIT] Disable two tests failing on new Intel GPU driver (#200856) One new consistent failure and one which causes instability. Signed-off-by: Nick Sarnie <nick.sarnie@intel.com> [LV] Add VPlan printing test wih UDiv SCEV expansion. (NFC) (#200845) [X86] Fix X86FixupLEAs displacement check for other types of operands (#200705) This has already bitten us Fixes #200707 [LLVM] Nominate Ehsan as a DA maintainer (#200375) This is related to #200335. I would like to nominate Ehsan as a Co-authored-by: Ehsan Amiri <ehsan.amiri@huawei.com> Reland "[flang][OpenMP] Fix lowering of LINEAR iteration variables (#188851)" (#194623) Linear iteration variables were being treated as private. This fixes The regressions in the OpenMP V&V and Fujitsu testsuites happened [libc++] Applied Towards #172124 [LoopUnroll] Support parallel reductions for minmax (#182473) This patch
Planning to take support for vector types in the next patch. [libc][math] Add missing math.yaml entries for acospif and atan2f16 (#199442) Fixes #199266 This PR adds missing [LifetimeSafety] Store cleanup expressions for temporaries (#200568) Now in This helps user understand lifetime semantics of objects better. Closes #195503 [VPlan] Assert operand correctness at construction. (NFC) (#200686) Update VPWidenPHIRecipe, VPBlendRecipe and VPReductionRecipe to assert PR: #200686 [Support] Remove unused argument of DataExtractor constructor (NFC) (#197121)
[clang] Fix assertion crash in alloc_size structural equivalence check (#199407) (#199980) Fixes #199407 Remove ParamIdx from the [AMDGPU] Use S_MOV_B64_IMM_PSEUDO when moving 64-bit VGPR const to SGPR (#200576) S_MOV_B64 only encodes a 32-bit literal, so rematerializing a non-inline [AMDGPU] Use fpext to widen sub DWORD FP printf args (#200870) Widening half/bfloat printf varargs via bitcast+sext corrupted the FP Extend by value-preserving fpext to float instead Revert "[LoopUnroll] Support parallel reductions for minmax (#182473)" (#200892) This reverts commit 1e79ea1. Make tests added in rd5a24ef work in read-only source filesystems. (#200883) [flang][OpenMP] Simplify checks for type-parameter inquiry (#198217) Remove the no longer needed IsDataRefTypeParamInquiry. [Testing] Allow custom markers in llvm::Annotations (#195570) The current annotation markers can conflict with several language Because the markers are currently hardcoded in Annotations Example(R"cpp(
@<!-- -->name(payload){{[[nodiscard]] int foo(int x);}}~
)cpp", {"~", "@", "{{", "}}"});Alternatively, we can use setters to customize the markers individually: Annotations Example(R"cpp(
@<!-- -->name(payload){{[[nodiscard]] int foo(int x);}}~
)cpp", Annotations::Markers().setPoint("~")
.setName("@@")
.setRangeBegin("{{")
.setRangeEnd("}}"));Using longer markers: Annotations Example(R"cpp(
$$name(payload)[[[[[nodiscard]] int foo(int x);]]]^^
)cpp", {"^^", "$$", "[[[", "]]]"});Using multi-byte characters: Annotations Example(R"cpp(
🏷️name(payload)👉[[nodiscard]] int foo(int x);👈🎯
)cpp", {"🎯", "🏷️", "👉", "👈"});The existing single-argument constructor delegates to the new overload, PS: The original code has a FIXME comment mentioning alternative [NVPTX] Fix fptosi/fptoui to i1. (#200718) The langref says: > The 'fptosi' instruction converts its floating-point operand into the Previously Because the conversion truncates toward zero, the only results that are
So the i1 result is fully determined by a single fp compare:
with any value being acceptable for the poison (out-of-range) inputs. [libc][math] Adding constexpr to tests for Double-type math functions (#200681) Similar to constexpr uint64_t X_COUNT = 123;
constexpr uint64_t X_START = FPBits(0.25).uintval();
constexpr uint64_t X_STOP = FPBits(4.0).uintval();
constexpr uint64_t X_STEP = (X_STOP - X_START) / X_COUNT;
constexpr uint64_t Y_COUNT = 137;
constexpr uint64_t Y_START = FPBits(0.25).uintval();
constexpr uint64_t Y_STOP = FPBits(4.0).uintval();
constexpr uint64_t Y_STEP = (Y_STOP - Y_START) / Y_COUNT;in atan2_test.cpp Additonally, replacing LIBC_NAMESPACE::fputil::FPBits<double>(x).uintval();to FPBits(x).uintval();Assisted using Copilot. [IR] Reorder checks in isInterposable() (NFC) (#200862) The isDSOLocal() check is a lot cheaper than getSemanticInterposition(), [LV] Add users to header phis in tests (NFC). (#200890) Make sure the header phis in various tests are actually used, to make [VectorCombine] Don't fold non-idempotent shuffle reductions when shuffle duplicates element (#200778) This is a small correctness fix for foldShuffleChainsToReduce. For odd / [CIR] Fix ordering of lifetime-extended cleanups (#200874) We had a bug that was causing any lifetime-extended cleanups that This change introduces new functions in RunCleanupsScope to allow The testing for this fix did uncover a significant issue wherein CIR is Assisted-by: Cursor / claude-opus-4.7 [AIX] Set the ifunc constructor's priority to 100, to run before any user code (#200893) Co-authored-by: Wael Yehia <wyehia@ca.ibm.com> [X86] lowerShuffleAsBitBlend - use getConstVector to create selection mask (#200877) Avoids wasteful SDValue creation if the shuffle matching fails, handles Revert "[llvm-objcopy] Strip header from DXContainer's ILDB part during Reverts llvm/llvm-project#198578 [OFFLOAD][L0] Refactor AsyncQueues (#200650) This PR introduces a major refactor on how L0 queues are used in the
As part of this refactor a number of other changes happened:
There are a few more things that still need to be adjusted and cleanup [mlir][Linalg] Enable lowering/decomposing scalable pack ops (#200216) Enables lowering/decomposing Signed-off-by: Ege Beysel <beyselege@gmail.com> [libc][ci] Use lld for linking in precommit CIs. (#200897) [clang-tidy] Fix cert-err33-c inheriting CheckedReturnTypes from bugp… (#200169) …rone-unused-return-value The cert-err33-c alias did not override CheckedReturnTypes, causing it Co-authored-by: EugeneZelenko <eugene.zelenko@gmail.com> [analyzer] Normalize sub-array indices in RegionStore initializer res… (#200044) …olution After #198346, alpha.unix.cstring.UninitializedRead reports a false This patch separates the two concerns. The RegionStore now normalizes Fixes #199271 [gn build] Port commits (#200910) 3d24f9a [MLIR][GPU] Support synchronous gpu.alloc and gpu.dealloc in gpu-to-llvm (#191661) The gpu-to-llvm conversion patterns for gpu.alloc and gpu.dealloc Changes:
Assisted-by: Claude [OFFLOAD][L0] Add support for dynamic l0 fallbacks (#200517) The PR adds support to define fallbacks for DLWRAP routines that are not [openacc] Attach Parallelism Levels to Auto Loops (#200884) Auto loops are analyzed by the compiler in later compilation stages to [X86] lowerShuffleAsBitMask - use getConstVector to create bitmask (#200889) Avoids wasteful SDValue creation if the shuffle matching fails, handles [lldb-dap] Mark source deemphasize if path doesn't exist (#194702) LLDB-DAP has a problem with sanitizers in GCC. When we stop in Fixes #184789 [gn build] Port 7964b66 (#200914) [lldb] Skip minidump case in TestDynamicValue.py for arm64e (#200047) The minidump format does not currently have a way to distinguish arm64e [mlir][ROCDL][AMDGPU] Add result arguments to buffer atomics (#198596) Buffer atomic operations were failing LLVM validation because they [VPlan] Propagate print flags for VPInstructionWithType. (#200838) Update VPInstructionWithType::print to include printing flags. [BOLT] Add perf2bolt pre-aggregated profile output Add a pre-aggregated profile output format ( Supports branch (T traces) and basic samples (S records). Currently only covers main binary, can be extended to cover multi-DSO. Test Plan: Updated perf_test.test, added perf_brstack.test Reviewers: Reviewed By: paschalis-mpeis Pull Request: #199465 [OFFLOAD][L0][NFC] Remove Device TLS table (#200923) After #200650 the Device TLS table is not used anymore so it can be [OFFLOAD][L0][NFC] Rename AsyncQueueTy struct to L0QueueTy (#200921) L0QueueTy is more descriptive after the changes in #200650. Also renamed the header name and one internal field to be more [CIR] Spill and reload values across deferred cleanup scopes (#200904) The This change adds code to spill values ahead of the Assisted-by: Cursor / claude-opus-4.7 [lldb] Fix TestBranchIslands.py for arm64e (#200498) Need to pass CFLAGS to clang when building the asm files, otherwise the [Docs] Update coding standard for TD files (#200848) This PR proposes an update to the coding standards document to make This is in response to this merged PR (#199346), which lead to this RFC Co-authored-by: Vlad Serebrennikov <serebrennikov.vladislav@gmail.com> [lldb] Strip objc superclass pointer in trampoline handler (#200490) The pointer needs to be stripped before being handed off to any objc This fixes TestObjCStepping.py on arm64e. [SelectionDAG] Widen <2 x T> vector types for atomic store (#197618) Vector types of 2 elements must be widened. This change does this Store-side counterpart to #148897. Stacked on top of #197166; and below [LLVM] Fix style issue in Maintainers file (#200917) AMDGPU/GlobalISel: Switch some tests to -new-reg-bank-select (#200853) [SelectOpt] Preserve Profile Information (#200680) If at least one of the SelectLike instructions in the group has profile AMDGPU/GlobalISel: Remove redundant -global-isel from -run-pass MIR tests (NFC) (#200857) [OFFLOAD][L0][NFC] Add struct for deferred memory operations (#200928) Improve readibility a bit by using a well-defined struct instead of [HotColdSplit] Consolidate pass pipeline (#200941) Codegenprepare was added for more of a E2E test in [lld] Remove unused DenseMapInfo::getTombstoneKey (#200636) #200595 changed DenseMap to no longer create tombstone buckets, so [lldb] Remove unused DenseMapInfo::getTombstoneKey (#200635) #200595 changed DenseMap to no longer create tombstone buckets, so [BOLT] Remove unused DenseMapInfo::getTombstoneKey (#200637) #200595 changed DenseMap to no longer create tombstone buckets, so [lld][WebAssembly] Refine type used for internal TLS-related symbols. NFC (#200899) I noticed this while reviewing #200855. [lldb] Add static_assert to catch increases to size of Symbol (#200919) [flang] Remove unused DenseMapInfo::getTombstoneKey (#200632) #200595 changed DenseMap to no longer create tombstone buckets, so [mlir] Remove unused DenseMapInfo::getTombstoneKey (#200633) #200595 changed DenseMap to no longer create tombstone buckets, so [X86] Remove extra MOV after widening atomic store (#197619) This change adds patterns to optimize out an extra MOV present after Store-side counterpart to #148898. Stacked on top of #197618; and below [libc] Add FENV_ACCESS pragma with CMake compiler feature detection (#200268) Related to #199009 Added compiler feature detection for STDC FENV_ACCESS pragma. It is [gn build] Port 7a907089 (#200953) [AMDGPU] Fix disasm of i16 operands fp inline constants (#200944) [libc] Renaming Float128 (DyadicFloat<128>) to DFloat128 (#200907) This is to be able to use the [NVPTX][clang] Remove nvvm scoped atomic intrinsics; use atomicrmw/cmpxchg (#200735) The Moreover, the nvvm atomics are problematic because they don't have Fix by doing the following.
[RISCV] Improve shrinkDemandedConstant. (#196585) Teach shrinkDemandedConstant to restore a constant that can be or: This fixes a regression between clang 18 and 19 on this test case [Polly] Remove unused DenseMapInfo::getTombstoneKey (#200963) #200595 changed DenseMap to no longer create tombstone buckets, so [AMDGPU] Simplicy the logic in checkWMMACoexecutionHazards, NFC (#200717) [lldb/test] Fix variant double-expansion in LLDBTestCaseFactory (#200943) LLDBTestCaseFactory generates the actual test methods that get run: for The variant-expansion helper decides what to copy by name-prefix match: HiddenIvarsTestCase trips this twice in a row (test_expr_stripped before With swift_clang (values clang/noclang) registered, test_expr_stripped + Track each method's expansion in a local dict and merge it back into the [lldb] Skip libc++ category tests on Darwin when no in-tree libc++ is built (#199262)
This fixes On the CMake side, the Signed-off-by: Med Ismail Bennani <ismail@bennani.ma> [Object][DirectX] Fix UB when parsing a DXContainer from a null buffer (#200865) Adds an additional check that [RISCV] Use sspush/sspopchk mnemonics for shadow stack codegen (#200182) After PR #178609, SSPUSH/SSPOPCHK/C_SSPUSH became encodable under the With predicates now aligned, the pseudos are just plain wrappers with [clang] fix transformation of SubstNonTypeTemplateParmExpr nodes from type alias templates and concepts (#200850) This makes sure SubstNonTypeTemplateParmExpr produced from This makes the SubstNonTypeTemplateParmExpr store the parameter type Fixes #191738 [libc] Add a placeholder for swprintf function (#200895) Add a declaration and stub implementation for the We're singling out llvm-project/libcxx/src/string.cpp Line 366 in 2a2e452 and is the last remaining piece of functionality preventing us from turning on wide character support in libc++ built against llvm-libc. Adding the stub function would allow us to test the compilation with _LIBCPP_HAS_WIDE_CHARACTERS enabled, and start keeping track of whattests from libc++ test suite are working / not working yet. [libc++][type_traits] Applied
[NVPTX] Fix sext(shl nsw x, topbit) miscompile. (#200924) Consider the following IR. combineMulWide (renamed in this patch to combineSZExtToMulWide) rewrites The LLVM IR is only meaningful for %x == 0 or -1; all other inputs
Therefore the transformation is not correct. This only happens when we're shifting by N-1 bits (where N is the narrow [CIR] Split RecordType into StructType/UnionType Union tail padding was stored as the last element of the This PR moves union tail padding to a dedicated
The CIR text syntax for padded unions changes from
[Flang] Fix device-side module lookup (#200863) When invoking flang with device-offloading (eg. flang -fc1 host x86_64 --> modfile.mod --> lib/clang/23/finclude/flang/x86_64-linux-gnu/iso_fortran_env.mod We fix this by
[LFI][AArch64] Emit .tlsdesccall with the associated blr (#200903) This PR fixes an issue in the LFI control-flow rewrites if a blr is [LLVM] Add flags to crash the opt/codegen pipeline (#200967) Will be used for testing crash reduction. [DirectX] Disable DCE and DSE for -O0 (#192520) These are optimisation passes which are inappropriate to run when the Co-authored-by: Andrew Savonichev <andrew.savonichev@gmail.com> [Instrumentor] Improve the config wizard script (#199108) This makes the config wizard script more generic as we grow Prepared with Claude (AI) and tested by me afterwards. [NFC][SPIR-V] Fix unused-variable in SPIRVBuiltins (#200842) [clang][HeuristicResolver] Handle non-dependent TemplateSpecializationType gracefully (#200714) Fixes #197716 [clang] fix getTemplateInstantiationArgs (#199528) This implements a new strategy for collecting the template arguments, by This greatly simplifies the signature of that function, by removing a Since this now relies on qualifiers and template parameter lists, this Also makes the explicit specialization AST nodes stop abusing the Fixes #101330 Revert "[LLVM] Add flags to crash the opt/codegen pipeline" (#200977) Reverts llvm/llvm-project#200967 Test failing on some buildbots: [clang][clang-tools-extra] Remove unused DenseMapInfo::getTombstoneKey (#200634) #200595 changed DenseMap to no longer create tombstone buckets, so [VPlan] Move IV predicate handling to VPlan. (#192876) [clang-tidy] Fix false positive in bugprone-use-after-move for std::tie (#192895) std::tie(a, b) = expr reinitializes all variables passed to std::tie std::tie(a, b) = foo(std::move(a), std::move(b)); Add std::tie assignment as a reinitialization case in Fixes #136105. AI Disclosure: Claude (Anthropic) was used to assist in diagnosing Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> [RISCV] Disable Zilsd CSR-pair generation when push/pop or save-restore is enabled (#200623) We were generating duplicate/worse code due to the generation of the [clang-tidy] Add This PR introduces a new check It detects instances where the result of a standard algorithm is used Currently the check can't handle algorithms returning As of AI-Usage: Assisted by Gemini CLI (for pre-commit reviewing, Co-authored-by: EugeneZelenko <eugene.zelenko@gmail.com> [SandboxVec][LoadStoreVec][AMDGPU] Remove early reject of mixed types (#200523) Up until now mixing floats and non-floats was disabled in the legality [ORC] Simplify DylibManager::lookupSymbols, remove LookupRequest. (#195954) DylibManager::lookupSymbols used to take an array of LookupRequests, This commit replaces the array of lookup requests with a single handle In practice all clients were passing a singlton array anyway, and [ORC] Fix header comment. NFC. (#200980) [clang][bytecode] Improve We previously often fell back to the type of the declaration, which is Add a new unit test to vaildate this. [CIR] Fix cir.call_llvm_intrinsic lowering for 0-result ops (#199516)
[CIR][AMDGPU] Implement lowering for __builtin_amdgcn_dispatch_ptr (#199880) Port [llvm-debuginfo-analyzer] Add support for LLVM IR format. (#200603) llvm-debuginfo-analyzer is a command line tool that processes debug Add support for the LLVM IR format and be able to generate logical This relands #135440, which was [SelectionDAG] Don't over-claim alignment on vector splice/compress stack MMOs (#200622) expandVectorSplice and expandVECTOR_COMPRESS allocate their scratch slot [scudo] Return nullptr if a remap fails on linux. (#200537) Add a check if a fixed address mmap doesn't return the expected address. Allow a remap call to fail if the mmap fails and returns a nullptr to Fix a place where if remap fails in the secondary, it didn't do [LLVM][IR] Make sure that DILabel's line is always printed (#200846) This commit ensures that the textual IR of the DILabel always contains [X86] Fold OR of constant splats into GF2P8AFFINEQB (#194330) Fold OR of a constant byte splat into X86ISD::GF2P8AFFINEQB when the For bits forced to 1 by the OR mask, zero the corresponding matrix rows gf2p8affineqb(x, M, imm) | C into: gf2p8affineqb(x, M & KeepMask, imm | C) where KeepMask clears the rows for output bits selected by C. This removes a separate OR after GF2P8AFFINEQB for constant-matrix cases Fixes: #191173 workflows/upload-release-artifact: Fix typo introduced in 01cfbaa (#200730) Revert "[llvm-debuginfo-analyzer] Add support for LLVM IR format. (#200603)" (#201019) This reverts commit 4cef4ef. There are link issues with some buildbots. [RISCV] Ensure LPAD alignment for calls to returns_twice functions (#177515) When Zicfilp is enabled, all LPAD instructions must be 4-byte aligned, This patch handles calls to returns_twice functions (e.g., setjmp) when
Note: Both AsmPrinter and MCCodeEmitter need separate expansion logic
The existing lpad.ll test is updated to add cf-protection-branch module Known issue: When Large Code Model and Zicfilp are both enabled, direct Signed-off-by: Jerry Zhang Jian <jerry.zhangjian@sifive.com> [CMake][Release] Use llvm-bitcode-strip on Darwin for build with -ffat-lto-objects (#200764) Building with --fat-lto-objects was added in #140381 (cff9ae7). On 2026-01-16T12:54:26.0928880Z /Users/runner/work/llvm-project/llvm-project/build/tools/clang/stage2-instrumented-bins/tools/clang/stage2-bins/_CPack_Packages/Darwin/TXZ/LLVM-22.1.0-rc1-macOS-ARM64/bin/llvm-strip: '/Users/runner/work/llvm-project/llvm-project/build/tools/clang/stage2-instrumented-bins/tools/clang/stage2-bins/_CPack_Packages/Darwin/TXZ/LLVM-22.1.0-rc1-macOS-ARM64/lib/libLLVMAArch64AsmParser.a(AArch64AsmParser.cpp.o)': It's assuming bitcode is embedded in section .llvm.lto llvm-bitcode-strip is a driver for the MachO bitcode_strip utility which Fixes #176398. Assisted-by: codex [CodeGen] De-type getMinimalPhysRegClass and related APIs (#197495) Follow-up #193438 to de-type getMinimalPhysRegClass so it can be replaced with There's very few uses of getMinimalPhysRegClass with a non-default type CTMark geomean:
Assisted-by: codex [X86] Move Non-VLX handling for VPMADD52 instructions entirely into tablegen (#200800) Just widen v2i64/v4i64 cases to v8i64 Removes more VLX/NoVLX testing from DAG [CIR] Add cir.lifetime.start and cir.lifetime.end Op (#199599) summaryAdds the [LifetimeSafety] Prevent false-negative lifetimebound verification when origin escapes in an unrelated manner (#200786) This PR removes a false-negative Change summary:
Fixes #200412 Signed-off-by: Abhinav Pradeep <abhinav.pradeep@oracle.com> [clang][CodeGen] Drop TBAA metadata emission on FP libcalls (#200752) TBAA annotation on FP libcalls has been superseded by [lldb][NFCI] Cleanup AppleObjCClassDescriptorV2::ivar_t API (#201042) [LoopInterchange] Prevent interchange when memory-accessing calls exist (#200828) Previously loop-interchange can be applied even though the loop has call // readnone functions do not prevent interchanging.
if (CI->onlyWritesMemory() || isa<PseudoProbeInst>(CI))
continue;However, I think ensuring So, this patch fixes the issue by verifying that all the calls in the Fixes #200796. [SPIR-V] Fix inverted signed/unsigned opcode for int-to-int convert builtins (#200791) [clang][bytecode] Reject invalid UETT_OpenMPRequiredSimdAlign nodes (#200997) [GVN] MemorySSA for GVN: eliminate redundant loads via MemorySSA (#152859) Introduce the main algorithm performing redundant load elimination via Specifically, a reaching value may be of the following descriptor kind
We start off by looking for the users of the defining memory access of Co-authored-by: Momchil Velikov <momchil.velikov@arm.com> [clang][cmake] Move perf-training out of CLANG_INCLUDE_TESTS (#192163) perf-training defines the generate-profdata target used by the PGO But perf-training is a PGO utility, not a test target, and it is Move perf-training out of the CLANG_INCLUDE_TESTS block. This is safe because utils/perf-training/CMakeLists.txt adds targets Also fix the path in lit.site.cfg.in for standalone builds. Assisted-by: claude [LV][RISCV] Add crash test for wide pointer stride in convertToStridedAccesses (#200985) Pre-commit test for #199640. [llubi] Global variables with simple initializers and global-address constants (#200547) This PR implements global variables with simple initializers and [AArch64][GlobalISel] Add handling for scalar sqabs intrinsic (#200222) sqabs is a neon intrinsic, so can only be performed on vector register Remove an invalid FIXME in a MemCpyOpt test (#200809) Call slot optimization explicitly requires So the The test for doing this optimization when the Relevant commits:
The FIXME should probably have been removed with one of these commits. [AMDGPU] Recompute EXEC liveness in SIWholeQuadMode::toExact (#200866) This is required as stale liveness information can lead to an incorrect This is caused by the following code: SlotIndex StartIdx = LIS->getInstructionIndex(SaveExecMI);
SlotIndex EndIdx = LIS->getInstructionIndex(*AndExecMI);
for (MCRegUnit Unit : TRI->regunits(ExecReg)) {
LiveRange &RegUnit = LIS->getRegUnit(Unit);
if (RegUnit.find(StartIdx) != std::prev(RegUnit.find(EndIdx)))
return false;
}When When If only the first range is considered the loop will finish without Patch is 25.13 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/201644.diff 11 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 4032d8219fff3..4cab0e5aab49f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1476,6 +1476,50 @@ def CIR_BlockAddrInfoAttr : CIR_Attr<"BlockAddrInfo", "block_addr_info"> {
let canHaveIllegalCXXABIType = 0;
}
+//===----------------------------------------------------------------------===//
+// CIR_BlockAddressAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_BlockAddressAttr
+ : CIR_ValueLikeAttr<"BlockAddress", "block_address"> {
+ let summary = "Constant address of a label within a function";
+ let description = [{
+ Represents the address of a label inside a function as a constant
+ pointer, mirroring LLVM IR's `blockaddress(@func, %bb)`. Unlike the
+ `cir.block_address` operation, this attribute is a constant, so it can
+ appear in global initializers and `#cir.const_array` elements. This is
+ required for the GNU computed-goto dispatch-table idiom:
+
+ ```c
+ static const void *tbl[] = {&&L1, &&L2};
+ goto *tbl[i];
+ ```
+
+ Example:
+
+ ```mlir
+ #cir.block_address<@func, "label"> : !cir.ptr<!cir.void>
+ ```
+ }];
+
+ let parameters = (ins AttributeSelfTypeParameter<"">:$type,
+ "mlir::FlatSymbolRefAttr":$func,
+ "mlir::StringAttr":$label);
+
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
+ "mlir::FlatSymbolRefAttr":$func,
+ "mlir::StringAttr":$label), [{
+ return $_get(type.getContext(), type, func, label);
+ }]>
+ ];
+
+ let assemblyFormat = "`<` $func `,` $label `>`";
+
+ // A block address is always a plain void pointer, never a C++ ABI type.
+ let canHaveIllegalCXXABIType = 0;
+}
+
//===----------------------------------------------------------------------===//
// Side Effect
//===----------------------------------------------------------------------===//
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index c4d08d5337031..ec06faf468702 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -503,6 +503,11 @@ def CIR_ConstantOp : CIR_Op<"const", [
let hasCXXABILowering = true;
let isLLVMLoweringRecursive = true;
+
+ // The constant initializer may embed a #cir.block_address attribute, whose
+ // lowering shares the pass-owned block-address bookkeeping.
+ let customLLVMLoweringConstructorDecl =
+ LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
}
//===----------------------------------------------------------------------===//
@@ -2984,6 +2989,12 @@ def CIR_GlobalOp : CIR_Op<"global", [
mlir::SymbolRefAttr getComdatAttr(cir::GlobalOp &op,
mlir::OpBuilder &builder) const;
}];
+
+ // A region-initialized global may embed a #cir.block_address attribute
+ // (e.g. a static computed-goto dispatch table), whose lowering shares the
+ // pass-owned block-address bookkeeping.
+ let customLLVMLoweringConstructorDecl =
+ LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 5208af44412a3..04dd80fd7b377 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -1234,6 +1234,10 @@ struct ConstantLValue {
: value(nullptr), hasOffsetApplied(false) {}
/*implicit*/ ConstantLValue(cir::GlobalViewAttr address)
: value(address), hasOffsetApplied(false) {}
+ // A label address has no object offset, so mark the offset as already
+ // applied to skip applyOffset (which only knows how to offset globals).
+ /*implicit*/ ConstantLValue(cir::BlockAddressAttr address)
+ : value(address), hasOffsetApplied(true) {}
ConstantLValue() : value(nullptr), hasOffsetApplied(false) {}
};
@@ -1514,8 +1518,26 @@ ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *e) {
ConstantLValue
ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *e) {
- cgm.errorNYI(e->getSourceRange(), "ConstantLValueEmitter: addr label expr");
- return {};
+ // A label address taken in a constant context, e.g. a static computed-goto
+ // dispatch table `static void *tbl[] = {&&L1, &&L2}`. Emit a constant
+ // #cir.block_address and register the label as address-taken so the
+ // enclosing function gets an indirect-goto block with this label among its
+ // successors. A label is always function-local, so cgf is set here.
+ assert(emitter.cgf &&
+ "label address in a constant requires an enclosing function");
+ assert(value.getLValueOffset().isZero() &&
+ "label address cannot carry an offset");
+ CIRGenFunction &cgf = *const_cast<CIRGenFunction *>(emitter.cgf);
+ mlir::MLIRContext *ctx = cgm.getBuilder().getContext();
+ auto func = cast<cir::FuncOp>(cgf.curFn);
+ mlir::Type ptrTy = cgm.getTypes().convertTypeForMem(destType);
+ assert(mlir::isa<cir::PointerType>(ptrTy) &&
+ "label address in a constant must be a pointer");
+
+ auto info = cir::BlockAddrInfoAttr::get(ctx, func.getSymName(),
+ e->getLabel()->getName());
+ cgf.takeAddressOfConstantLabel(info);
+ return cir::BlockAddressAttr::get(ptrTy, info.getFunc(), info.getLabel());
}
ConstantLValue ConstantLValueEmitter::VisitCallExpr(const CallExpr *e) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 4ecb47a864146..d8e6e3b04f362 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -625,10 +625,20 @@ void CIRGenFunction::finishIndirectBranch() {
succesors.push_back(labelOp->getBlock());
rangeOperands.push_back(labelOp->getBlock()->getArguments());
}
+ // Labels whose address was taken only from a constant initializer have no
+ // function-local BlockAddressOp; add them as successors here. All labels
+ // are emitted by now, so the lookup resolves.
+ for (cir::BlockAddrInfoAttr info : constBlockAddressLabels) {
+ cir::LabelOp labelOp = cgm.lookupBlockAddressInfo(info);
+ assert(labelOp && "expected cir.label to be emitted for const block addr");
+ succesors.push_back(labelOp->getBlock());
+ rangeOperands.push_back(labelOp->getBlock()->getArguments());
+ }
cir::IndirectBrOp::create(builder, builder.getUnknownLoc(),
indirectGotoBlock->getArgument(0), false,
rangeOperands, succesors);
cgm.blockAddressToLabel.clear();
+ constBlockAddressLabels.clear();
}
void CIRGenFunction::finishFunction(SourceLocation endLoc) {
@@ -1476,6 +1486,11 @@ void CIRGenFunction::instantiateIndirectGotoBlock() {
{builder.getUnknownLoc()});
}
+void CIRGenFunction::takeAddressOfConstantLabel(cir::BlockAddrInfoAttr info) {
+ constBlockAddressLabels.push_back(info);
+ instantiateIndirectGotoBlock();
+}
+
mlir::Value CIRGenFunction::emitAlignmentAssumption(
mlir::Value ptrValue, QualType ty, SourceLocation loc,
SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 1e9be3dc2174e..a359b662cd2b0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -730,6 +730,12 @@ class CIRGenFunction : public CIRGenTypeCache {
/// been resolved.
mlir::Block *indirectGotoBlock = nullptr;
+ /// Labels whose address is taken in a constant context (e.g. a static
+ /// computed-goto dispatch table). These have no function-local
+ /// BlockAddressOp, so they are tracked here and added as indirect-goto
+ /// branch successors in finishIndirectBranch.
+ llvm::SmallVector<cir::BlockAddrInfoAttr> constBlockAddressLabels;
+
void resolveBlockAddresses();
void finishIndirectBranch();
@@ -1705,6 +1711,10 @@ class CIRGenFunction : public CIRGenTypeCache {
void instantiateIndirectGotoBlock();
+ /// Record a label whose address is taken from a constant initializer and
+ /// ensure the indirect-goto block exists.
+ void takeAddressOfConstantLabel(cir::BlockAddrInfoAttr info);
+
/// Emit a simple LLVM intrinsic that takes N scalar arguments and whose
/// return type matches the type of the first argument. The intrinsic name is
/// used verbatim; any overload mangling (e.g. `.f32`, `.p1`) must be baked
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index cf07fc4f0833a..3812a8ba45e10 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -588,7 +588,7 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
cir::ConstComplexAttr, cir::ConstRecordAttr,
cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
- cir::VTableAttr>(attrType))
+ cir::VTableAttr, cir::BlockAddressAttr>(attrType))
return success();
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
diff --git a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp
index d590ccce1f540..8b3656c974059 100644
--- a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp
@@ -6,8 +6,10 @@
//
//===----------------------------------------------------------------------===//
#include "PassDetail.h"
+#include "mlir/IR/AttrTypeSubElements.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/Passes.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/Support/TimeProfiler.h"
#include <memory>
@@ -27,7 +29,8 @@ struct GotoSolverPass : public impl::GotoSolverBase<GotoSolverPass> {
void runOnOperation() override;
};
-static void process(cir::FuncOp func) {
+static void process(cir::FuncOp func,
+ const llvm::SmallSet<StringRef, 4> &constBlockAddrLabel) {
mlir::OpBuilder rewriter(func.getContext());
llvm::StringMap<Block *> labels;
llvm::SmallVector<cir::GotoOp, 4> gotos;
@@ -43,6 +46,12 @@ static void process(cir::FuncOp func) {
}
});
+ // Labels whose address is taken only from a constant #cir.block_address
+ // (e.g. a static computed-goto dispatch table) have no function-local
+ // BlockAddressOp. Treat them as address-taken so their LabelOp survives.
+ for (StringRef label : constBlockAddrLabel)
+ blockAddrLabel.insert(label);
+
for (auto &lab : labels) {
StringRef labelName = lab.getKey();
Block *block = lab.getValue();
@@ -65,7 +74,36 @@ static void process(cir::FuncOp func) {
void GotoSolverPass::runOnOperation() {
llvm::TimeTraceScope scope("Goto Solver");
- getOperation()->walk(&process);
+
+ // Collect labels whose address is taken via a constant #cir.block_address
+ // attribute anywhere in the module (e.g. in a static computed-goto dispatch
+ // table's initializer). These references are not function-local
+ // BlockAddressOps, so gather them up front, keyed by function symbol, so the
+ // per-function pass does not erase the still-needed LabelOp.
+ llvm::DenseMap<StringRef, llvm::SmallSet<StringRef, 4>> constBlockAddrLabels;
+ // Only the presence of a label makes the per-function erase logic relevant,
+ // so skip the whole-module attribute walk entirely for the common case of a
+ // translation unit with no labels.
+ bool hasLabel = false;
+ getOperation()->walk([&](cir::LabelOp) {
+ hasLabel = true;
+ return mlir::WalkResult::interrupt();
+ });
+ if (hasLabel) {
+ mlir::AttrTypeWalker walker;
+ walker.addWalk([&](cir::BlockAddressAttr ba) {
+ constBlockAddrLabels[ba.getFunc().getValue()].insert(
+ ba.getLabel().getValue());
+ });
+ getOperation()->walk([&](mlir::Operation *op) {
+ for (const mlir::NamedAttribute &na : op->getAttrs())
+ walker.walk(na.getValue());
+ });
+ }
+
+ getOperation()->walk([&](cir::FuncOp func) {
+ process(func, constBlockAddrLabels.lookup(func.getSymName()));
+ });
}
} // namespace
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index fdd2228edb06c..163ccc0d453c4 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -285,8 +285,10 @@ class CIRAttrToValue {
public:
CIRAttrToValue(mlir::Operation *parentOp,
mlir::ConversionPatternRewriter &rewriter,
- const mlir::TypeConverter *converter)
- : parentOp(parentOp), rewriter(rewriter), converter(converter) {}
+ const mlir::TypeConverter *converter,
+ LLVMBlockAddressInfo &blockInfoAddr)
+ : parentOp(parentOp), rewriter(rewriter), converter(converter),
+ blockInfoAddr(blockInfoAddr) {}
#define GET_CIR_ATTR_TO_VALUE_VISITOR_DECLS
#include "clang/CIR/Dialect/IR/CIRLowering.inc"
@@ -296,14 +298,19 @@ class CIRAttrToValue {
mlir::Operation *parentOp;
mlir::ConversionPatternRewriter &rewriter;
const mlir::TypeConverter *converter;
+ // Pass-owned block-address bookkeeping, shared with the LabelOp and
+ // BlockAddressOp lowerings so a block address embedded in a constant
+ // initializer resolves through the same mechanism as the op form.
+ LLVMBlockAddressInfo &blockInfoAddr;
};
/// Switches on the type of attribute and calls the appropriate conversion.
mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
const mlir::Attribute attr,
mlir::ConversionPatternRewriter &rewriter,
- const mlir::TypeConverter *converter) {
- CIRAttrToValue valueConverter(parentOp, rewriter, converter);
+ const mlir::TypeConverter *converter,
+ LLVMBlockAddressInfo &blockInfoAddr) {
+ CIRAttrToValue valueConverter(parentOp, rewriter, converter, blockInfoAddr);
mlir::Value value = valueConverter.visit(attr);
if (!value)
llvm_unreachable("unhandled attribute type");
@@ -656,6 +663,33 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
llvm_unreachable("Expecting pointer or integer type for GlobalViewAttr");
}
+// BlockAddressAttr visitor. Mirrors CIRToLLVMBlockAddressOpLowering so a
+// block address embedded in a constant initializer (e.g. a static
+// computed-goto dispatch table) resolves through the same mechanism as the
+// cir.block_address op.
+mlir::Value CIRAttrToValue::visitCirAttr(cir::BlockAddressAttr attr) {
+ mlir::MLIRContext *ctx = rewriter.getContext();
+ mlir::Location loc = parentOp->getLoc();
+
+ cir::BlockAddrInfoAttr blockInfo =
+ cir::BlockAddrInfoAttr::get(ctx, attr.getFunc(), attr.getLabel());
+
+ mlir::LLVM::BlockTagOp matchLabel = blockInfoAddr.lookupBlockTag(blockInfo);
+ mlir::LLVM::BlockTagAttr tagAttr;
+ // If the BlockTagOp has not been emitted yet, use a placeholder tag. It is
+ // patched with the correct tag index later in resolveBlockAddressOp.
+ if (matchLabel)
+ tagAttr = matchLabel.getTag();
+
+ auto blkAddr =
+ mlir::LLVM::BlockAddressAttr::get(ctx, attr.getFunc(), tagAttr);
+ auto newOp = mlir::LLVM::BlockAddressOp::create(
+ rewriter, loc, mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
+ if (!matchLabel)
+ blockInfoAddr.addUnresolvedBlockAddress(newOp, blockInfo);
+ return newOp;
+}
+
// TypeInfoAttr visitor.
mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeInfoAttr) {
mlir::Type llvmTy = converter->convertType(typeInfoAttr.getType());
@@ -2006,7 +2040,8 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
}
// Lower GlobalViewAttr to llvm.mlir.addressof
if (auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(op.getValue())) {
- auto newOp = lowerCirAttrAsValue(op, gv, rewriter, getTypeConverter());
+ auto newOp = lowerCirAttrAsValue(op, gv, rewriter, getTypeConverter(),
+ blockInfoAddr);
rewriter.replaceOp(op, newOp);
return mlir::success();
}
@@ -2018,32 +2053,34 @@ mlir::LogicalResult CIRToLLVMConstantOpLowering::matchAndRewrite(
std::optional<mlir::Attribute> denseAttr;
if (constArr && hasTrailingZeros(constArr)) {
- const mlir::Value newOp =
- lowerCirAttrAsValue(op, constArr, rewriter, getTypeConverter());
+ const mlir::Value newOp = lowerCirAttrAsValue(
+ op, constArr, rewriter, getTypeConverter(), blockInfoAddr);
rewriter.replaceOp(op, newOp);
return mlir::success();
} else if (constArr &&
(denseAttr = lowerConstArrayAttr(constArr, typeConverter))) {
attr = denseAttr.value();
} else {
- const mlir::Value initVal =
- lowerCirAttrAsValue(op, op.getValue(), rewriter, typeConverter);
+ const mlir::Value initVal = lowerCirAttrAsValue(
+ op, op.getValue(), rewriter, typeConverter, blockInfoAddr);
rewriter.replaceOp(op, initVal);
return mlir::success();
}
} else if (const auto recordAttr =
mlir::dyn_cast<cir::ConstRecordAttr>(op.getValue())) {
- auto initVal = lowerCirAttrAsValue(op, recordAttr, rewriter, typeConverter);
+ auto initVal = lowerCirAttrAsValue(op, recordAttr, rewriter, typeConverter,
+ blockInfoAddr);
rewriter.replaceOp(op, initVal);
return mlir::success();
} else if (const auto vecTy = mlir::dyn_cast<cir::VectorType>(op.getType())) {
- rewriter.replaceOp(op, lowerCirAttrAsValue(op, op.getValue(), rewriter,
- getTypeConverter()));
+ rewriter.replaceOp(op,
+ lowerCirAttrAsValue(op, op.getValue(), rewriter,
+ getTypeConverter(), blockInfoAddr));
return mlir::success();
} else if (mlir::isa<cir::RecordType>(op.getType())) {
if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(attr)) {
mlir::Value initVal =
- lowerCirAttrAsValue(op, attr, rewriter, typeConverter);
+ lowerCirAttrAsValue(op, attr, rewriter, typeConverter, blockInfoAddr);
rewriter.replaceOp(op, initVal);
return mlir::success();
}
@@ -2430,7 +2467,7 @@ CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
// to the appropriate value.
const mlir::Location loc = op.getLoc();
setupRegionInitializedLLVMGlobalOp(op, rewriter);
- CIRAttrToValue valueConverter(op, rewriter, typeConverter);
+ CIRAttrToValue valueConverter(op, rewriter, typeConverter, blockInfoAddr);
mlir::Value value = valueConverter.visit(init);
mlir::LLVM::ReturnOp::create(rewriter, loc, value);
return mlir::success();
@@ -3715,7 +3752,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
/// repeated O(M) module-wide symbol scans for every call site.
mlir::SymbolTableCollection symbolTables;
mlir::RewritePatternSet patterns(&getContext());
- patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
+ patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering,
+ CIRToLLVMConstantOpLowering, CIRToLLVMGlobalOpLowering>(
converter, patterns.getContext(), dl, blockInfoAddr);
patterns.add<CIRToLLVMCallOpLowering, CIRToLLVMTryCallOpLowering>(
converter, patterns.getContext(), dl, symbolTables);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index c0abb40b7304e..7212a17debfa1 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -22,11 +22,14 @@ namespace cir {
namespace direct {
+struct LLVMBlockAddressInfo;
+
/// Convert a CIR attribu...
[truncated]
|
| // CIR_BlockAddressAttr | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| def CIR_BlockAddressAttr |
There was a problem hiding this comment.
CIR_BlockAddrInfoAttr already does exactly this.
There was a problem hiding this comment.
Switched to embedding BlockAddrInfoAttr as the single parameter, matching how BlockAddressOp already holds it. Custom print/parse keeps the assembly format unchanged.
There was a problem hiding this comment.
The shared part is real -- both carry func+label -- but the two roles can't collapse into one attribute. BlockAddrInfoAttr is the untyped identity: the operand of cir.block_address (the pointer type lives on the op result) and the DenseMap key for label resolution in CIRGen, GotoSolver, and lowering. BlockAddressAttr has to be a ValueLikeAttr carrying a type because the constant form appears in global initializers and #cir.const_array elements, where the initializer whitelist requires a typed value-like attr, and it lowers to an LLVM constant. Making the identity attr value-like instead would force a redundant self-type onto every operand and map-key construction -- the type already lives on the op result and is always !cir.ptr<!cir.void> -- so BlockAddressAttr just wraps the identity attr with that type for the constant positions.
There was a problem hiding this comment.
Reworked CIR_BlockAddressAttr to take a single BlockAddrInfoAttr parameter instead of redeclaring func/label; a custom printer/parser keeps the <@func, "label"> format.
The constant `#cir.block_address` attribute stored its own `func` and `label` parameters, duplicating `BlockAddrInfoAttr`, which already bundles exactly that pair and is what the `cir.block_address` operation takes. Store a `BlockAddrInfoAttr` instead so the constant and operation forms share one representation. The textual format is unchanged (`#cir.block_address<@func, "label">`): a small custom printer/parser flattens the embedded bundle so the two forms keep printing the same way the operation does. Call sites now reach the function and label through `getBlockAddrInfo()`.
There was a problem hiding this comment.
oh just looked at the other Attr which @andykaylor mentioned, do we really need both? Also I would be more for solution with Base class for both attributes, if we really need two of them.
This will allow to reuse assembly format and not to use custom assembly format.
In CIR_BlockAddressAttr one would jst add something like:
let append parameters = (ins AttributeSelfTypeParameter<"">:$type)
let append assemblyFormat = [{ `:` $type }]
to add type.
|
@xlauko on whether both attributes are needed: |
andykaylor
left a comment
There was a problem hiding this comment.
I somehow didn't realize this was handling the same case I was looking at today. See #203644. I think it's a bit cleaner.

GNU computed-goto code that takes a label's address in a constant
context -- the common static dispatch-table idiom
static const void *tbl[] = {&&L1, &&L2}; goto *tbl[i];-- hiterrorNYIinConstantLValueEmitter::VisitAddrLabelExpr, and thefollow-on
goto *tbl[i]then tripped theindirectGotoBlockassertion in
emitIndirectGotoStmtbecause the label was neverregistered as address-taken. The runtime form (
void *p = &&L; goto *p;) already worked; only the constant form was missing.Label addresses had no constant representation:
cir.block_addressexisted only as an operation, which cannot appear inside a
#cir.const_arrayinitializer. Add a#cir.block_addressconstantattribute and lower it to MLIR's
LLVM::BlockAddressAttr, reusing thesame
BlockTagOpresolution the operation form already uses(threading the pass-owned
LLVMBlockAddressInfointo the constantvalue lowering and the Global/Constant lowering patterns).
CIRGen's
ConstantLValueEmitter::VisitAddrLabelExprnow emits theattribute and records the label so
finishIndirectBranchadds it tothe
cir.indirect_brsuccessors and the indirect-goto block isinstantiated. Because such labels have no function-local
BlockAddressOp,GotoSolverwas deleting them as unused; it nowalso keeps labels referenced by a constant
#cir.block_addressanywhere in the module.
The lowered LLVM matches classic codegen (a
[N x ptr]ofblockaddressconstants plus anindirectbr). New testgoto-address-label-table.ccovers CIR, the CIR-lowered LLVM, andclassic OGCG;
label-values.c(the runtime form) is unchanged.