Author: adams381 Date: 2026-07-17T09:07:46-05:00 New Revision: 40ae05d4773f5c1b2a84ea7dc908d92671b8daa9
URL: https://github.com/llvm/llvm-project/commit/40ae05d4773f5c1b2a84ea7dc908d92671b8daa9 DIFF: https://github.com/llvm/llvm-project/commit/40ae05d4773f5c1b2a84ea7dc908d92671b8daa9.diff LOG: [CIR] Return power-of-two ABI alignment for non-fundamental int widths (#210187) `cir::IntType::getABIAlignment` returns `width / 8` for non-`_BitInt` integers. For a non-fundamental width such as `i24` it returns 3, which is not a power of two, so a consumer that builds an `llvm::Align` from it would hit the power-of-two assertion unless it rounds the value up itself. This rounds the alignment up to a power of two inside `getABIAlignment`, matching how LLVM's default DataLayout aligns these (an `i24` aligns like `i32`). The fundamental widths are unchanged (`i8` -> 1, `i16` -> 2, `i32` -> 4, `i64` -> 8), `__int128` stays at 16, and a sub-byte width like `i1` now reports 1 instead of 0. A unit test pins these cases. Added: clang/unittests/CIR/IntTypeABIAlignTest.cpp Modified: clang/lib/CIR/Dialect/IR/CIRTypes.cpp clang/unittests/CIR/CMakeLists.txt Removed: ################################################################################ diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 9c2a40e3681aa..afd3364af4ec2 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -809,7 +809,13 @@ uint64_t IntType::getABIAlignment(const mlir::DataLayout &dataLayout, std::min(llvm::PowerOf2Ceil(width), static_cast<uint64_t>(64)); return std::max(alignBits / 8, static_cast<uint64_t>(1)); } - return (uint64_t)(width / 8); + // Round up to a power-of-two byte alignment. DataLayout consumers such as + // llvm::Align require power-of-two alignments, and width / 8 is not a power + // of two for non-fundamental widths (e.g. i24 -> 3). This leaves the + // fundamental widths unchanged (i8 -> 1, i16 -> 2, i32 -> 4, i64 -> 8) and + // keeps __int128 at 16. + uint64_t alignBits = llvm::PowerOf2Ceil(width); + return std::max(alignBits / 8, static_cast<uint64_t>(1)); } mlir::LogicalResult diff --git a/clang/unittests/CIR/CMakeLists.txt b/clang/unittests/CIR/CMakeLists.txt index a431356044cfc..446ca36fc39b0 100644 --- a/clang/unittests/CIR/CMakeLists.txt +++ b/clang/unittests/CIR/CMakeLists.txt @@ -6,6 +6,7 @@ include_directories(${MLIR_TABLEGEN_OUTPUT_DIR}) add_distinct_clang_unittest(CIRUnitTests CallOpTest.cpp ControlFlowTest.cpp + IntTypeABIAlignTest.cpp PointerLikeTest.cpp RecordTypeMetadataTest.cpp UnionTypeSizeTest.cpp diff --git a/clang/unittests/CIR/IntTypeABIAlignTest.cpp b/clang/unittests/CIR/IntTypeABIAlignTest.cpp new file mode 100644 index 0000000000000..5fe0dc5bd2b4b --- /dev/null +++ b/clang/unittests/CIR/IntTypeABIAlignTest.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Unit tests for IntType::getABIAlignment. +// +//===----------------------------------------------------------------------===// + +#include "mlir/IR/BuiltinOps.h" +#include "mlir/IR/MLIRContext.h" +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "llvm/Support/MathExtras.h" +#include "gtest/gtest.h" + +using namespace mlir; +using namespace cir; + +namespace { + +class IntTypeABIAlignTest : public ::testing::Test { +protected: + IntTypeABIAlignTest() { context.loadDialect<cir::CIRDialect>(); } + + MLIRContext context; + + uint64_t abiAlign(unsigned width, bool isSigned) { + IntType ty = IntType::get(&context, width, isSigned); + OpBuilder builder(&context); + auto module = ModuleOp::create(builder.getUnknownLoc()); + mlir::DataLayout dl(module); + uint64_t align = dl.getTypeABIAlignment(ty); + module->erase(); + return align; + } +}; + +// The fundamental integer widths keep their natural alignment. +TEST_F(IntTypeABIAlignTest, FundamentalWidths) { + EXPECT_EQ(abiAlign(8, true), 1u); + EXPECT_EQ(abiAlign(16, true), 2u); + EXPECT_EQ(abiAlign(32, true), 4u); + EXPECT_EQ(abiAlign(64, true), 8u); +} + +// __int128 is 16-byte aligned, so a 128-bit integer must not round down. +TEST_F(IntTypeABIAlignTest, Int128) { EXPECT_EQ(abiAlign(128, true), 16u); } + +// A non-fundamental width must report a power-of-two alignment, not the bare +// width / 8 (which would be 3 for i24 and trip llvm::Align). Rounding is on +// the bit width, so a width that isn't a byte multiple still rounds up like +// LLVM's DataLayout (i17 aligns like i32). +TEST_F(IntTypeABIAlignTest, NonFundamentalWidthIsPowerOfTwo) { + for (unsigned width : {17u, 24u}) { + uint64_t align = abiAlign(width, true); + EXPECT_TRUE(llvm::isPowerOf2_64(align)) + << "i" << width << " alignment " << align << " is not a power of two"; + } + EXPECT_EQ(abiAlign(17, true), 4u); + EXPECT_EQ(abiAlign(24, true), 4u); +} + +// A sub-byte width must still report a valid, non-zero alignment. +TEST_F(IntTypeABIAlignTest, SubByteWidth) { EXPECT_EQ(abiAlign(1, true), 1u); } + +} // namespace _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
