[llvm-branch-commits] [clang] [CIR] Emit inbounds nuw flags on GetMemberOp GEP lowering (PR #186738)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Mar 15 22:50:03 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Henrich Lauko (xlauko)
<details>
<summary>Changes</summary>
Struct member accesses via GetMemberOp are always inbounds and cannot
unsigned-wrap, matching LLVM's IRBuilder::CreateStructGEP behavior.
---
Patch is 53.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/186738.diff
25 Files Affected:
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+8-2)
- (modified) clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c (+7-7)
- (modified) clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/atomic-thread-fence.c (+4-4)
- (modified) clang/test/CIR/CodeGen/bitfields.c (+9-9)
- (modified) clang/test/CIR/CodeGen/bitfields.cpp (+4-4)
- (modified) clang/test/CIR/CodeGen/bitfields_be.c (+4-4)
- (modified) clang/test/CIR/CodeGen/call-via-class-member-funcptr.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/class.cpp (+3-3)
- (modified) clang/test/CIR/CodeGen/complex.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/copy-constructor.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/cxx-default-init.cpp (+14-14)
- (modified) clang/test/CIR/CodeGen/delete.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/dtors.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/inline-asm.c (+2-2)
- (modified) clang/test/CIR/CodeGen/inline-cxx-func.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/instantiate-init.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/lambda.cpp (+13-13)
- (modified) clang/test/CIR/CodeGen/no-unique-address.cpp (+1-1)
- (modified) clang/test/CIR/CodeGen/statement-exprs.c (+1-1)
- (modified) clang/test/CIR/CodeGen/struct-init.cpp (+6-6)
- (modified) clang/test/CIR/CodeGen/struct.c (+6-6)
- (modified) clang/test/CIR/CodeGen/struct.cpp (+11-11)
- (modified) clang/test/CIR/CodeGen/variable-decomposition.cpp (+2-2)
- (modified) clang/test/CIR/CodeGen/volatile.cpp (+8-8)
``````````diff
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4a1b4292b23dd..062739d85991f 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3713,8 +3713,14 @@ mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
// is always zero. The second offset tell us which member it will access.
llvm::SmallVector<mlir::LLVM::GEPArg, 2> offset{0, op.getIndex()};
const mlir::Type elementTy = getTypeConverter()->convertType(recordTy);
- rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResTy, elementTy,
- adaptor.getAddr(), offset);
+ // Struct member accesses are always inbounds and nuw: the base pointer
+ // is valid and the member offset is a positive, constant offset within
+ // the struct layout, so it cannot wrap. This matches LLVM's
+ // IRBuilder::CreateStructGEP.
+ mlir::LLVM::GEPNoWrapFlags flags =
+ mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
+ rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
+ op, llResTy, elementTy, adaptor.getAddr(), offset, flags);
return mlir::success();
}
case cir::RecordType::Union:
diff --git a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
index 5218a29848fb0..ecde8f24b2334 100644
--- a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
+++ b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
@@ -93,7 +93,7 @@ int check_load(st1 *s1) {
// LLVM:define dso_local i32 @check_load
// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8
-// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st1, ptr [[LOAD]], i32 0, i32 0
+// LLVM: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.st1, ptr [[LOAD]], i32 0, i32 0
// LLVM: [[LOADVOL:%.*]] = load volatile i32, ptr [[MEMBER]], align 4
// LLVM: [[LSHR:%.*]] = lshr i32 [[LOADVOL]], 9
// LLVM: [[CLEAR:%.*]] = and i32 [[LSHR]], 1
@@ -125,7 +125,7 @@ int check_load_exception(st3 *s3) {
// LLVM:define dso_local i32 @check_load_exception
// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8
-// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st3, ptr [[LOAD]], i32 0, i32 2
+// LLVM: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.st3, ptr [[LOAD]], i32 0, i32 2
// LLVM: [[LOADVOL:%.*]] = load volatile i8, ptr [[MEMBER]], align 4
// LLVM: [[CLEAR:%.*]] = and i8 [[LOADVOL]], 31
// LLVM: [[CAST:%.*]] = zext i8 [[CLEAR]] to i32
@@ -161,7 +161,7 @@ int clip_load_exception2(clip *c) {
// LLVM:define dso_local i32 @clip_load_exception2
// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8
-// LLVM: [[MEMBER:%.*]] = getelementptr %struct.clip, ptr [[LOAD]], i32 0, i32 0
+// LLVM: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.clip, ptr [[LOAD]], i32 0, i32 0
// LLVM: [[LOADVOL:%.*]] = load volatile i24, ptr [[MEMBER]], align 4
// LLVM: [[CAST:%.*]] = sext i24 [[LOADVOL]] to i32
// LLVM: store i32 [[CAST]], ptr [[RETVAL:%.*]], align 4
@@ -187,7 +187,7 @@ void check_store(st2 *s2) {
// LLVM:define dso_local void @check_store
// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8
-// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st2, ptr [[LOAD]], i32 0, i32 0
+// LLVM: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.st2, ptr [[LOAD]], i32 0, i32 0
// LLVM: [[LOADVOL:%.*]] = load volatile i16, ptr [[MEMBER]], align 8
// LLVM: [[CLEAR:%.*]] = and i16 [[LOADVOL]], -8
// LLVM: [[SET:%.*]] = or i16 [[CLEAR]], 1
@@ -217,7 +217,7 @@ void check_store_exception(st3 *s3) {
// LLVM:define dso_local void @check_store_exception
// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8
-// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st3, ptr [[LOAD]], i32 0, i32 2
+// LLVM: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.st3, ptr [[LOAD]], i32 0, i32 2
// LLVM: [[LOADVOL:%.*]] = load volatile i8, ptr [[MEMBER]], align 4
// LLVM: [[CLEAR:%.*]] = and i8 [[LOADVOL]], -32
// LLVM: [[SET:%.*]] = or i8 [[CLEAR]], 2
@@ -246,7 +246,7 @@ void clip_store_exception2(clip *c) {
// LLVM:define dso_local void @clip_store_exception2
// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8
-// LLVM: [[MEMBER:%.*]] = getelementptr %struct.clip, ptr [[LOAD]], i32 0, i32 0
+// LLVM: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.clip, ptr [[LOAD]], i32 0, i32 0
// LLVM: store volatile i24 3, ptr [[MEMBER]], align 4
// LLVM: ret void
@@ -267,7 +267,7 @@ void check_store_second_member (st4 *s4) {
// LLVM: define dso_local void @check_store_second_member
// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8
-// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st4, ptr [[LOAD]], i32 0, i32 2
+// LLVM: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.st4, ptr [[LOAD]], i32 0, i32 2
// LLVM: [[VAL:%.*]] = load volatile i64, ptr [[MEMBER]], align 8
// LLVM: [[CLEAR:%.*]] = and i64 [[VAL]], -65536
// LLVM: [[SET:%.*]] = or i64 [[CLEAR]], 1
diff --git a/clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp b/clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp
index bcad743a2c9db..507bdad91b4cd 100644
--- a/clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp
+++ b/clang/test/CIR/CodeGen/aggregate-copy-overlap.cpp
@@ -41,7 +41,7 @@ struct Outer : virtual VBase {
// CIR-NEXT: cir.libc.memcpy %[[SIZE]] bytes from %[[SRC]] to %[[DST]]
// LLVM-LABEL: define {{.*}} void @_ZN5OuterC1ERK10HasPaddingc(
-// LLVM: %[[GEP:.*]] = getelementptr %struct.Outer, ptr %{{.+}}, i32 0, i32 1
+// LLVM: %[[GEP:.*]] = getelementptr inbounds nuw %struct.Outer, ptr %{{.+}}, i32 0, i32 1
// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[GEP]], ptr %{{.+}}, i64 5, i1 false)
// OGCG-LABEL: define {{.*}} void @_ZN5OuterC1ERK10HasPaddingc(
@@ -64,7 +64,7 @@ struct NonOverlapping {
// CIR: cir.copy %{{.+}} to %{{.+}} : !cir.ptr<!rec_HasPadding>
// LLVM-LABEL: define {{.*}} void @_ZN14NonOverlappingC2ERK10HasPaddingc(
-// LLVM: %[[GEP:.*]] = getelementptr %struct.NonOverlapping, ptr %{{.+}}, i32 0, i32 0
+// LLVM: %[[GEP:.*]] = getelementptr inbounds nuw %struct.NonOverlapping, ptr %{{.+}}, i32 0, i32 0
// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[GEP]], ptr %{{.+}}, i64 8, i1 false)
// OGCG-LABEL: define {{.*}} void @_ZN14NonOverlappingC2ERK10HasPaddingc(
diff --git a/clang/test/CIR/CodeGen/atomic-thread-fence.c b/clang/test/CIR/CodeGen/atomic-thread-fence.c
index eced95b1e6e59..bca91a61d8d24 100644
--- a/clang/test/CIR/CodeGen/atomic-thread-fence.c
+++ b/clang/test/CIR/CodeGen/atomic-thread-fence.c
@@ -58,7 +58,7 @@ void modifyWithThreadFence(DataPtr d) {
// LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
// LLVM: fence seq_cst
// LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
- // LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
+ // LLVM: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
// LLVM: store i32 42, ptr %[[DATA_VALUE]], align 8
// LLVM: ret void
@@ -87,7 +87,7 @@ void modifyWithSignalFence(DataPtr d) {
// LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
// LLVM: fence syncscope("singlethread") seq_cst
// LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
- // LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
+ // LLVM: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
// LLVM: store i32 24, ptr %[[DATA_VALUE]], align 8
// LLVM: ret void
@@ -119,7 +119,7 @@ void loadWithThreadFence(DataPtr d) {
// LLVM: %[[DATA_TEMP:.*]] = alloca ptr, i64 1, align 8
// LLVM: fence seq_cst
// LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
- // LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
+ // LLVM: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
// LLVM: %[[ATOMIC_LOAD:.*]] = load atomic ptr, ptr %[[DATA_VALUE]] seq_cst, align 8
// LLVM: store ptr %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8
// LLVM: %[[DATA_TEMP_LOAD:.*]] = load ptr, ptr %[[DATA_TEMP]], align 8
@@ -156,7 +156,7 @@ void loadWithSignalFence(DataPtr d) {
// LLVM: %[[DATA_TEMP:.*]] = alloca ptr, i64 1, align 8
// LLVM: fence syncscope("singlethread") seq_cst
// LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
- // LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
+ // LLVM: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
// LLVM: %[[ATOMIC_LOAD:.*]] = load atomic ptr, ptr %[[DATA_VALUE]] seq_cst, align 8
// LLVM: store ptr %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8
// LLVM: %[[DATA_TEMP_LOAD]] = load ptr, ptr %[[DATA_TEMP]], align 8
diff --git a/clang/test/CIR/CodeGen/bitfields.c b/clang/test/CIR/CodeGen/bitfields.c
index 7d86bc36a31e6..be76fb4da2644 100644
--- a/clang/test/CIR/CodeGen/bitfields.c
+++ b/clang/test/CIR/CodeGen/bitfields.c
@@ -104,7 +104,7 @@ int load_field(S* s) {
// LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8
// LLVM: [[TMP1:%.*]] = alloca i32, i64 1, align 4
// LLVM: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8
-// LLVM: [[TMP3:%.*]] = getelementptr %struct.S, ptr [[TMP2]], i32 0, i32 0
+// LLVM: [[TMP3:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP2]], i32 0, i32 0
// LLVM: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4
// LLVM: [[TMP5:%.*]] = shl i64 [[TMP4]], 15
// LLVM: [[TMP6:%.*]] = ashr i64 [[TMP5]], 47
@@ -131,7 +131,7 @@ unsigned int load_field_unsigned(A* s) {
//LLVM: define dso_local i32 @load_field_unsigned
//LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8
//LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
-//LLVM: [[TMP2:%.*]] = getelementptr %struct.A, ptr [[TMP1]], i32 0, i32 3
+//LLVM: [[TMP2:%.*]] = getelementptr inbounds nuw %struct.A, ptr [[TMP1]], i32 0, i32 3
//LLVM: [[TMP3:%.*]] = load i16, ptr [[TMP2]], align 1
//LLVM: [[TMP4:%.*]] = lshr i16 [[TMP3]], 3
//LLVM: [[TMP5:%.*]] = and i16 [[TMP4]], 15
@@ -158,7 +158,7 @@ void store_field() {
// LLVM: define dso_local void @store_field()
// LLVM: [[TMP0:%.*]] = alloca %struct.S, i64 1, align 4
-// LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 1
+// LLVM: [[TMP1:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP0]], i32 0, i32 1
// LLVM: [[TMP2:%.*]] = load i16, ptr [[TMP1]], align 4
// LLVM: [[TMP3:%.*]] = and i16 [[TMP2]], -32768
// LLVM: [[TMP4:%.*]] = or i16 [[TMP3]], 3
@@ -186,12 +186,12 @@ void store_bitfield_to_bitfield() {
// LLVM: define dso_local void @store_bitfield_to_bitfield()
// LLVM: [[TMP0:%.*]] = alloca %struct.S, i64 1, align 4
-// LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0
+// LLVM: [[TMP1:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP0]], i32 0, i32 0
// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// LLVM: [[TMP3:%.*]] = shl i64 [[TMP2]], 15
// LLVM: [[TMP4:%.*]] = ashr i64 [[TMP3]], 47
// LLVM: [[TMP5:%.*]] = trunc i64 [[TMP4]] to i32
-// LLVM: [[TMP6:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0
+// LLVM: [[TMP6:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP0]], i32 0, i32 0
// LLVM: [[TMP7:%.*]] = zext i32 [[TMP5]] to i64
// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP6]], align 4
// LLVM: [[TMP9:%.*]] = and i64 [[TMP7]], 15
@@ -238,7 +238,7 @@ void get_volatile(V* v) {
// LLVM: define dso_local void @get_volatile
// LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8
// LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
-// LLVM: [[TMP2:%.*]] = getelementptr %struct.V, ptr [[TMP1]], i32 0, i32 0
+// LLVM: [[TMP2:%.*]] = getelementptr inbounds nuw %struct.V, ptr [[TMP1]], i32 0, i32 0
// LLVM: [[TMP3:%.*]] = load volatile i64, ptr [[TMP2]], align 4
// LLVM: [[TMP4:%.*]] = and i64 [[TMP3]], -1095216660481
// LLVM: [[TMP5:%.*]] = or i64 [[TMP4]], 12884901888
@@ -265,7 +265,7 @@ void set_volatile(V* v) {
// LLVM: define dso_local void @set_volatile
// LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8
// LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
-// LLVM: [[TMP2:%.*]] = getelementptr %struct.V, ptr [[TMP1]], i32 0, i32 0
+// LLVM: [[TMP2:%.*]] = getelementptr inbounds nuw %struct.V, ptr [[TMP1]], i32 0, i32 0
// LLVM: [[TMP3:%.*]] = load volatile i64, ptr [[TMP2]], align 4
// LLVM: [[TMP4:%.*]] = and i64 [[TMP3]], -1095216660481
// LLVM: [[TMP5:%.*]] = or i64 [[TMP4]], 12884901888
@@ -292,7 +292,7 @@ void unOp(S* s) {
// CIR: cir.set_bitfield align(4) (#bfi_d, [[TMP2]] : !cir.ptr<!u64i>, [[TMP4]] : !s32i)
// LLVM: define {{.*@unOp}}
-// LLVM: [[TMP0:%.*]] = getelementptr %struct.S, ptr [[LOAD0:%.*]], i32 0, i32 0
+// LLVM: [[TMP0:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[LOAD0:%.*]], i32 0, i32 0
// LLVM: [[TMP1:%.*]] = load i64, ptr [[TMP0]], align 4
// LLVM: [[TMP2:%.*]] = shl i64 [[TMP1]], 13
// LLVM: [[TMP3:%.*]] = ashr i64 [[TMP2]], 62
@@ -340,7 +340,7 @@ void binOp(S* s) {
// LLVM: define {{.*@binOp}}
// LLVM: [[TMP0:%.*]] = load ptr, ptr {{.*}}, align 8
-// LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0
+// LLVM: [[TMP1:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP0]], i32 0, i32 0
// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// LLVM: [[TMP3:%.*]] = shl i64 [[TMP2]], 13
// LLVM: [[TMP4:%.*]] = ashr i64 [[TMP3]], 62
diff --git a/clang/test/CIR/CodeGen/bitfields.cpp b/clang/test/CIR/CodeGen/bitfields.cpp
index 04e06b37d6e00..d91c5af275400 100644
--- a/clang/test/CIR/CodeGen/bitfields.cpp
+++ b/clang/test/CIR/CodeGen/bitfields.cpp
@@ -45,7 +45,7 @@ int load_field(S* s) {
// LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8
// LLVM: [[TMP1:%.*]] = alloca i32, i64 1, align 4
// LLVM: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8
-// LLVM: [[TMP3:%.*]] = getelementptr %struct.S, ptr [[TMP2]], i32 0, i32 0
+// LLVM: [[TMP3:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP2]], i32 0, i32 0
// LLVM: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 4
// LLVM: [[TMP5:%.*]] = shl i64 [[TMP4]], 15
// LLVM: [[TMP6:%.*]] = ashr i64 [[TMP5]], 47
@@ -71,7 +71,7 @@ void store_field() {
// LLVM: define dso_local void @_Z11store_fieldv
// LLVM: [[TMP0:%.*]] = alloca %struct.S, i64 1, align 4
-// LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 0
+// LLVM: [[TMP1:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP0]], i32 0, i32 0
// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4
// LLVM: [[TMP3:%.*]] = and i64 [[TMP2]], -16
// LLVM: [[TMP4:%.*]] = or i64 [[TMP3]], 3
@@ -101,13 +101,13 @@ void store_bitfield_to_bitfield(S* s) {
// LLVM: define dso_local void @_Z26store_bitfield_to_bitfieldP1S
// LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8
// LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
-// LLVM: [[TMP2:%.*]] = getelementptr %struct.S, ptr [[TMP1]], i32 0, i32 0
+// LLVM: [[TMP2:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP1]], i32 0, i32 0
// LLVM: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 4
// LLVM: [[TMP4:%.*]] = and i64 [[TMP3]], -2147483633
// LLVM: [[TMP5:%.*]] = or i64 [[TMP4]], 48
// LLVM: store i64 [[TMP5]], ptr [[TMP2]], align 4
// LLVM: [[TMP6:%.*]] = load ptr, ptr [[TMP0]], align 8
-// LLVM: [[TMP7:%.*]] = getelementptr %struct.S, ptr [[TMP6]], i32 0, i32 0
+// LLVM: [[TMP7:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP6]], i32 0, i32 0
// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP7]], align 4
// LLVM: [[TMP9:%.*]] = and i64 [[TMP8]], -16
// LLVM: [[TMP10:%.*]] = or i64 [[TMP9]], 3
diff --git a/clang/test/CIR/CodeGen/bitfields_be.c b/clang/test/CIR/CodeGen/bitfields_be.c
index 79801a38df3db..3c8366a8d39c0 100644
--- a/clang/test/CIR/CodeGen/bitfields_be.c
+++ b/clang/test/CIR/CodeGen/bitfields_be.c
@@ -31,7 +31,7 @@ int init(S* s) {
//LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8
//LLVM: [[TMP1:%.*]] = alloca i32, i64 1, align 4
//LLVM: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8
-//LLVM: [[TMP3:%.*]] = getelementptr %struct.S, ptr [[TMP2]], i32 0, i32 0
+//LLVM: [[TMP3:%.*]] = getelementptr inbounds nuw %struct.S, ptr [[TMP2]], i32 0, i32 0
//LLVM: [[TMP4:%.*]] = load i32, ptr [[TMP3]], align 4
//LLVM: [[TMP5:%.*]] = shl i32 [[TMP4]], 15
//LLVM: [[TMP6:%.*]] = ashr i32 [[TMP5]], 15
@@ -60,7 +60,7 @@ void load(S* s) {
// LLVM: define dso_local void @load{{.*}}{{.*}}
// LLVM: %[[PTR0:.*]] = load ptr
-// LLVM: %[[GET0:.*]] = getelementptr %struct.S, ptr %[[PTR0]], i32 0, i32 0
+// LLVM: %[[GET0:.*]] = getelementptr inbounds nuw %struct.S, ptr %[[PTR0]], i32 0, i32 0
// LLVM: %[[VAL0:.*]] = load i32, ptr %[[GET0]], align 4
// LLVM: %[[AND0:.*]] = and i32 %[[VAL0]], 268435455
// LLVM: %[[OR0:.*]] = or i32 %[[AND0]], -1073741824
@@ -80,7 +80,7 @@ void load(S* s) {
// CIR: %[[SET1:.*]] = cir.set_bitfield align(4) (#bfi_b, %[[GET1]] : !cir.ptr<!u32i>, %[[CONST2]] : !s32i) -> !s32i
// LLVM: %[[PTR1:.*]] = load ptr
-// LLVM: %[[GET1:.*]] = getelementptr %struct.S, ptr %[[PTR1]], i32 0, i32 0
+// LLVM: %[[GET1:.*]] = getelementptr inbounds nuw %struct.S, ptr %[[PTR1]], i32 0, i32 0
// LLVM: %[[VAL1:.*]] = load i32, ptr %[[GET1]], align 4
// LLVM: %[[AND1:.*]] = and i32 %[[VAL1]], -268304385
// LLVM: %[[OR1:.*]] = or i32 %[[AND1]], 5505024
@@ -99,7 +99,7 @@ void load(S* s) {
// CIR: %[[SET2:.*]] = cir.set_bitfield align(4) (#bfi_c, %[[GET2]] : !cir.ptr<!u32i>, %[[CONST3]] : !s32i) -> !s32i
// LLVM: %[[PTR2:.*]] = load ptr
-// LLVM: %[[GET2:.*]] = getelementptr %struct.S, ptr %[[PTR2]], i32 0, i32 0
+// LLVM: %[[GET2:.*]] = getelementptr inbounds nuw %struct.S, ptr %[[PTR2]], i32 0, i32 0
// LLVM: %[[VAL2:.*]] = load i32, ptr %[[GET2]], align 4
// LLVM: %[[AND2:.*]] = and i32 %[[VAL2]], -131072
// LLVM: %[[OR2:.*]] = or i32 %[[AND2]], 118727
diff --git a/clang/test/CIR/CodeGen/call-via-class-member-funcptr.cpp b/clang/test/CIR/CodeGen/call-via-class-member-funcptr.cpp
index 0e41324f3bfd8..de3369e169bb2 100644
--- a/clang/test/CIR/CodeGen/call-via-class-member-funcptr.cpp
+++ b/clang/test/CIR/CodeGen/call-via-class-member-funcptr.cpp
@@ -67,8 +67,8 @@ void fn2() { C c1; c1.call_indirect(2); }
// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
// LLVM: store i32 %[[V_ARG]], ptr %[[V_ADDR]]
// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
-// LLVM: %[[INNER:.*]] = getelementptr %class.C, ptr %[[THIS]], i32 0, i32 0
-// LLVM: %[[INDIRECT_CALLEE_PTR:.*]] = getelementptr %class.B, ptr %[[INNER]], i32 0, i32 0
+// LLVM: %[[INNER:.*]] = getelementptr inbounds nuw %class.C, ptr %[[THIS]], i32 0, i32 0
+// LLVM: %[[INDIRECT_CALLEE_PTR:.*]] = getelementptr inbounds nuw %class.B, ptr %[[INNER]], i32 0, i32 0
// LLVM: %[[INDIRECT_CALLEE:.*]] = load ptr, ptr %[[INDIRECT_CALLEE_PTR]]
// LLVM: %[[V:.*]] = load i32, ptr %[[V_ADDR]]
// LLVM: %[[RET:.*]] = call noundef i32 %[[INDIRECT_CALLEE]](i32 noundef %[[V]])
diff --git a/clang/test/CIR/CodeGen/class.cpp b/clang/test/CIR/CodeGen/class.cpp
index eb9d5d73c3616..243eb746ade52 100644
--- a/clang/test/CIR/CodeGen/class.cpp
+++ b/clang/test/CIR/CodeGen/class.cpp
@@ -59,7 +59,7 @@ int use(Derived *d) { return d->b; }
// CIR: %[[D_B:.*]] = cir.load align(4) %[[D_B_ADDR]]
// LLVM: define{{.*}} i32 @_Z3useP7Derived
-// LLVM: getelementptr %class.Derived, ptr %{{.*}}, i32 0, i32 1
+// LLVM: getelementptr inbounds nuw %class.Derived, ptr %{{.*}}, i32 0, i32 1
// OGCG: define{{.*}} i32 @_Z3useP7Derived
// OGCG: getelementptr inbounds nuw %class.Derived, ptr %{{.*}}, i32 0, i32 1
@@ -77,7 +77,7 @@ int use_base() {
// LLVM: define{{.*}} i32 @_Z8use_basev
// LLVM: %[[D:.*]] = alloca %class.Derived
-// LLVM: %[[D_A_ADDR:.*]] = getelementptr %class.Base, ptr %[[D]], i32 0, i32 0
+// LLVM: %[[D_A_ADDR:.*]] = getelementptr inbounds nuw %class.Base, ptr %[[D]], i32 0, i32 0
// OGCG: define{{.*}} i32 @_Z8use_basev
// OGCG: %[[D:.*]] = alloca %class.Derived
@@ -96,7 +96,7 @@ int use_base_vi...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/186738
More information about the llvm-branch-commits
mailing list