[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