Skip to content

Commit fd1749b

Browse files
[CIR] Backport bitfield changes from upstream (#1840)
This PR backports the changes from LLVM upstream, including: - Adding a new attribute to `cir.set_bitfield` and `cir.get_bitfield`. - Replacing the bitcast used to access the first member with a `getMemberOp`. - Adding support for `FineGrainedBitfieldAccesses`. - Updating the related tests.
1 parent 20a8624 commit fd1749b

File tree

14 files changed

+471
-121
lines changed

14 files changed

+471
-121
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2820,20 +2820,23 @@ def CIR_SetBitfieldOp : CIR_Op<"set_bitfield"> {
28202820
%1 = cir.const #cir.int<3> : !s32i
28212821
%2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>
28222822
%3 = cir.get_member %2[1] {name = "d"} : !cir.ptr<!record_type> -> !cir.ptr<!u32i>
2823-
%4 = cir.set_bitfield(#bfi_d, %3 : !cir.ptr<!u32i>, %1 : !s32i) -> !s32i
2823+
%4 = cir.set_bitfield align(4) (#bfi_d, %3 : !cir.ptr<!u32i>, %1 : !s32i) -> !s32i
28242824
```
28252825
}];
28262826

28272827
let arguments = (ins
28282828
Arg<CIR_PointerType, "the address to store the value", [MemWrite]>:$addr,
28292829
CIR_AnyType:$src,
28302830
CIR_BitfieldInfoAttr:$bitfield_info,
2831+
DefaultValuedOptionalAttr<I64Attr, "0">:$alignment,
28312832
UnitAttr:$is_volatile
28322833
);
28332834

28342835
let results = (outs CIR_IntType:$result);
28352836

2836-
let assemblyFormat = [{ `(`$bitfield_info`,` $addr`:`qualified(type($addr))`,`
2837+
let assemblyFormat = [{
2838+
(`align` `(` $alignment^ `)`)?
2839+
`(`$bitfield_info`,` $addr`:`qualified(type($addr))`,`
28372840
$src`:`type($src) `)` attr-dict `->` type($result) }];
28382841

28392842
let builders = [
@@ -2845,14 +2848,15 @@ def CIR_SetBitfieldOp : CIR_Op<"set_bitfield"> {
28452848
"unsigned":$size,
28462849
"unsigned":$offset,
28472850
"bool":$is_signed,
2848-
"bool":$is_volatile
2851+
"bool":$is_volatile,
2852+
CArg<"unsigned", "0">:$alignment
28492853
),
28502854
[{
28512855
BitfieldInfoAttr info =
28522856
BitfieldInfoAttr::get($_builder.getContext(),
28532857
name, storage_type,
28542858
size, offset, is_signed);
2855-
build($_builder, $_state, type, addr, src, info, is_volatile);
2859+
build($_builder, $_state, type, addr, src, info, alignment, is_volatile);
28562860
}]>
28572861
];
28582862
}
@@ -2899,20 +2903,23 @@ def CIR_GetBitfieldOp : CIR_Op<"get_bitfield"> {
28992903

29002904
%2 = cir.load %0 : !cir.ptr<!cir.ptr<!record_type>>, !cir.ptr<!record_type>
29012905
%3 = cir.get_member %2[1] {name = "d"} : !cir.ptr<!record_type> -> !cir.ptr<!u32i>
2902-
%4 = cir.get_bitfield(#bfi_d, %3 : !cir.ptr<!u32i>) -> !s32i
2906+
%4 = cir.get_bitfield align(4) (#bfi_d, %3 : !cir.ptr<!u32i>) -> !s32i
29032907
```
29042908
}];
29052909

29062910
let arguments = (ins
29072911
Arg<CIR_PointerType, "the address to load from", [MemRead]>:$addr,
29082912
CIR_BitfieldInfoAttr:$bitfield_info,
2913+
DefaultValuedOptionalAttr<I64Attr, "0">:$alignment,
29092914
UnitAttr:$is_volatile
29102915
);
29112916

29122917
let results = (outs CIR_IntType:$result);
29132918

2914-
let assemblyFormat = [{ `(`$bitfield_info `,` $addr attr-dict `:`
2915-
qualified(type($addr)) `)` `->` type($result) }];
2919+
let assemblyFormat = [{
2920+
(`align` `(` $alignment^ `)`)?
2921+
`(`$bitfield_info `,` $addr attr-dict `:`
2922+
qualified(type($addr)) `)` `->` type($result) }];
29162923

29172924
let builders = [
29182925
OpBuilder<(ins "mlir::Type":$type,
@@ -2922,14 +2929,15 @@ def CIR_GetBitfieldOp : CIR_Op<"get_bitfield"> {
29222929
"unsigned":$size,
29232930
"unsigned":$offset,
29242931
"bool":$is_signed,
2925-
"bool":$is_volatile
2932+
"bool":$is_volatile,
2933+
CArg<"unsigned", "0">:$alignment
29262934
),
29272935
[{
29282936
BitfieldInfoAttr info =
29292937
BitfieldInfoAttr::get($_builder.getContext(),
29302938
name, storage_type,
29312939
size, offset, is_signed);
2932-
build($_builder, $_state, type, addr, info, is_volatile);
2940+
build($_builder, $_state, type, addr, info, alignment, is_volatile);
29332941
}]>
29342942
];
29352943
}

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -767,23 +767,25 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
767767
}
768768

769769
mlir::Value createGetBitfield(mlir::Location loc, mlir::Type resultType,
770-
mlir::Value addr, mlir::Type storageType,
770+
Address addr, mlir::Type storageType,
771771
const CIRGenBitFieldInfo &info,
772772
bool isLvalueVolatile, bool useVolatile) {
773773
auto offset = useVolatile ? info.VolatileOffset : info.Offset;
774-
return create<cir::GetBitfieldOp>(loc, resultType, addr, storageType,
775-
info.Name, info.Size, offset,
776-
info.IsSigned, isLvalueVolatile);
774+
return create<cir::GetBitfieldOp>(loc, resultType, addr.getPointer(),
775+
storageType, info.Name, info.Size, offset,
776+
info.IsSigned, isLvalueVolatile,
777+
addr.getAlignment().getAsAlign().value());
777778
}
778779

779780
mlir::Value createSetBitfield(mlir::Location loc, mlir::Type resultType,
780-
mlir::Value dstAddr, mlir::Type storageType,
781+
Address dstAddr, mlir::Type storageType,
781782
mlir::Value src, const CIRGenBitFieldInfo &info,
782783
bool isLvalueVolatile, bool useVolatile) {
783784
auto offset = useVolatile ? info.VolatileOffset : info.Offset;
784-
return create<cir::SetBitfieldOp>(loc, resultType, dstAddr, storageType,
785-
src, info.Name, info.Size, offset,
786-
info.IsSigned, isLvalueVolatile);
785+
return create<cir::SetBitfieldOp>(
786+
loc, resultType, dstAddr.getPointer(), storageType, src, info.Name,
787+
info.Size, offset, info.IsSigned, isLvalueVolatile,
788+
dstAddr.getAlignment().getAsAlign().value());
787789
}
788790

789791
/// Create a pointer to a record member.

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,15 @@ Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base,
259259
const FieldDecl *field,
260260
mlir::Type fieldType,
261261
unsigned index) {
262-
if (index == 0)
263-
return base.getAddress();
264262
auto loc = getLoc(field->getLocation());
265263
auto fieldPtr = cir::PointerType::get(fieldType);
266-
auto sea = getBuilder().createGetMember(loc, fieldPtr, base.getPointer(),
267-
field->getName(), index);
268-
return Address(sea, CharUnits::One());
264+
auto rec = cast<cir::RecordType>(base.getAddress().getElementType());
265+
auto sea = getBuilder().createGetMember(
266+
loc, fieldPtr, base.getPointer(), field->getName(),
267+
rec.isUnion() ? field->getFieldIndex() : index);
268+
CharUnits offset = CharUnits::fromQuantity(
269+
rec.getElementOffset(CGM.getDataLayout().layout, index));
270+
return Address(sea, base.getAlignment().alignmentAtOffset(offset));
269271
}
270272

271273
static bool useVolatileForBitField(const CIRGenModule &cgm, LValue base,
@@ -753,9 +755,9 @@ RValue CIRGenFunction::emitLoadOfBitfieldLValue(LValue LV, SourceLocation Loc) {
753755
bool useVolatile = LV.isVolatileQualified() &&
754756
info.VolatileStorageSize != 0 && isAAPCS(CGM.getTarget());
755757

756-
auto field = builder.createGetBitfield(getLoc(Loc), resLTy, ptr.getPointer(),
757-
ptr.getElementType(), info,
758-
LV.isVolatile(), useVolatile);
758+
auto field =
759+
builder.createGetBitfield(getLoc(Loc), resLTy, ptr, ptr.getElementType(),
760+
info, LV.isVolatile(), useVolatile);
759761
assert(!cir::MissingFeatures::emitScalarRangeCheck() && "NYI");
760762
return RValue::get(field);
761763
}
@@ -896,8 +898,8 @@ void CIRGenFunction::emitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
896898
mlir::Value dstAddr = Dst.getAddress().getPointer();
897899

898900
Result = builder.createSetBitfield(
899-
dstAddr.getLoc(), resLTy, dstAddr, ptr.getElementType(),
900-
Src.getScalarVal(), info, Dst.isVolatileQualified(), useVolatile);
901+
dstAddr.getLoc(), resLTy, ptr, ptr.getElementType(), Src.getScalarVal(),
902+
info, Dst.isVolatileQualified(), useVolatile);
901903
}
902904

903905
static LValue emitGlobalVarDeclLValue(CIRGenFunction &CGF, const Expr *E,

clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ CIRRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
649649
} else if (cirGenTypes.getModule()
650650
.getCodeGenOpts()
651651
.FineGrainedBitfieldAccesses) {
652-
llvm_unreachable("NYI");
652+
InstallBest = true;
653653
} else {
654654
// Otherwise, we're not installing. Update the bit size
655655
// of the current span to go all the way to LimitOffset, which is

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4076,7 +4076,7 @@ mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
40764076
assert(storageSize > size && "Invalid bitfield size.");
40774077

40784078
mlir::Value val = rewriter.create<mlir::LLVM::LoadOp>(
4079-
op.getLoc(), intType, adaptor.getAddr(), /* alignment */ 0,
4079+
op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
40804080
op.getIsVolatile());
40814081

40824082
srcVal =
@@ -4093,7 +4093,7 @@ mlir::LogicalResult CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
40934093
}
40944094

40954095
rewriter.create<mlir::LLVM::StoreOp>(op.getLoc(), srcVal, adaptor.getAddr(),
4096-
/* alignment */ 0, op.getIsVolatile());
4096+
op.getAlignment(), op.getIsVolatile());
40974097

40984098
auto resultTy = getTypeConverter()->convertType(op.getType());
40994099

@@ -4140,7 +4140,8 @@ mlir::LogicalResult CIRToLLVMGetBitfieldOpLowering::matchAndRewrite(
41404140
auto intType = mlir::IntegerType::get(context, storageSize);
41414141

41424142
mlir::Value val = rewriter.create<mlir::LLVM::LoadOp>(
4143-
op.getLoc(), intType, adaptor.getAddr(), 0, op.getIsVolatile());
4143+
op.getLoc(), intType, adaptor.getAddr(), op.getAlignment(),
4144+
op.getIsVolatile());
41444145
val = rewriter.create<mlir::LLVM::BitcastOp>(op.getLoc(), intType, val);
41454146

41464147
if (info.getIsSigned()) {
Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,71 @@
11
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2-
// RUN: FileCheck --input-file=%t.cir %s
3-
4-
void main() {
5-
union demo {
6-
int x;
7-
int y : 4;
8-
int z : 8;
9-
};
10-
union demo d;
2+
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
4+
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
6+
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
7+
8+
typedef union {
9+
int x;
10+
int y : 4;
11+
int z : 8;
12+
} demo;
13+
14+
// CIR: !rec_demo = !cir.record<union "demo" {!s32i, !u8i, !u8i}>
15+
// LLVM: %union.demo = type { i32 }
16+
// OGCG: %union.demo = type { i32 }
17+
18+
typedef union {
19+
int x;
20+
int y : 3;
21+
int : 0;
22+
int z : 2;
23+
} zero_bit;
24+
25+
// CIR: !rec_zero_bit = !cir.record<union "zero_bit" {!s32i, !u8i, !u8i} #cir.record.decl.ast>
26+
// LLVM: %union.zero_bit = type { i32 }
27+
// OGCG: %union.zero_bit = type { i32 }
28+
29+
demo d;
30+
zero_bit z;
31+
32+
void f() {
33+
demo d;
1134
d.x = 1;
1235
d.y = 2;
1336
d.z = 0;
1437
}
1538

16-
// CHECK: !rec_demo = !cir.record<union "demo" {!s32i, !u8i, !u8i}>
17-
// CHECK: #bfi_y = #cir.bitfield_info<name = "y", storage_type = !u8i, size = 4, offset = 0, is_signed = true>
18-
// CHECK: #bfi_z = #cir.bitfield_info<name = "z", storage_type = !u8i, size = 8, offset = 0, is_signed = true>
19-
20-
// cir.func no_proto dso_local @main() extra(#fn_attr) {
21-
// %0 = cir.alloca !rec_demo, !cir.ptr<!rec_demo>, ["d"] {alignment = 4 : i64}
22-
// %1 = cir.const #cir.int<1> : !s32i
23-
// %2 = cir.get_member %0[0] {name = "x"} : !cir.ptr<!rec_demo> -> !cir.ptr<!s32i>
24-
// cir.store %1, %2 : !s32i, !cir.ptr<!s32i>
25-
// %3 = cir.const #cir.int<2> : !s32i
26-
// %4 = cir.cast(bitcast, %0 : !cir.ptr<!rec_demo>), !cir.ptr<!u8i>
27-
// %5 = cir.set_bitfield(#bfi_y, %4 : !cir.ptr<!u8i>, %3 : !s32i) -> !s32i
28-
// %6 = cir.const #cir.int<0> : !s32i loc(#loc10)
29-
// %7 = cir.cast(bitcast, %0 : !cir.ptr<!rec_demo>), !cir.ptr<!u8i>
30-
// %8 = cir.set_bitfield(#bfi_z, %7 : !cir.ptr<!u8i>, %6 : !s32i) -> !s32i
31-
// cir.return
32-
// }
39+
// CIR: #bfi_y = #cir.bitfield_info<name = "y", storage_type = !u8i, size = 4, offset = 0, is_signed = true>
40+
// CIR: #bfi_z = #cir.bitfield_info<name = "z", storage_type = !u8i, size = 8, offset = 0, is_signed = true>
41+
42+
// CIR: cir.func no_proto dso_local @f
43+
// CIR: [[ALLOC:%.*]] = cir.alloca !rec_demo, !cir.ptr<!rec_demo>, ["d"] {alignment = 4 : i64}
44+
// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i
45+
// CIR: [[X:%.*]] = cir.get_member [[ALLOC]][0] {name = "x"} : !cir.ptr<!rec_demo> -> !cir.ptr<!s32i>
46+
// CIR: cir.store align(4) [[ONE]], [[X]] : !s32i, !cir.ptr<!s32i>
47+
// CIR: [[TWO:%.*]] = cir.const #cir.int<2> : !s32i
48+
// CIR: [[Y:%.*]] = cir.get_member [[ALLOC]][1] {name = "y"} : !cir.ptr<!rec_demo> -> !cir.ptr<!u8i>
49+
// CIR: [[SET:%.*]] = cir.set_bitfield align(4) (#bfi_y, [[Y]] : !cir.ptr<!u8i>, [[TWO]] : !s32i) -> !s32i
50+
// CIR: [[ZERO:%.*]] = cir.const #cir.int<0> : !s32i
51+
// CIR: [[Z:%.*]] = cir.get_member [[ALLOC]][2] {name = "z"} : !cir.ptr<!rec_demo> -> !cir.ptr<!u8i>
52+
// CIR: [[SET2:%.*]] = cir.set_bitfield align(4) (#bfi_z, [[Z]] : !cir.ptr<!u8i>, [[ZERO]] : !s32i) -> !s32i
53+
// CIR: cir.return
54+
55+
// LLVM: define dso_local void @f
56+
// LLVM: [[ALLOC:%.*]] = alloca %union.demo, i64 1, align 4
57+
// LLVM: store i32 1, ptr [[ALLOC]], align 4
58+
// LLVM: [[BFLOAD:%.*]] = load i8, ptr [[ALLOC]], align 4
59+
// LLVM: [[CLEAR:%.*]] = and i8 [[BFLOAD]], -16
60+
// LLVM: [[SET:%.*]] = or i8 [[CLEAR]], 2
61+
// LLVM: store i8 [[SET]], ptr [[ALLOC]], align 4
62+
// LLVM: store i8 0, ptr [[ALLOC]], align 4
63+
64+
// OGCG: define dso_local void @f
65+
// OGCG: [[ALLOC:%.*]] = alloca %union.demo, align 4
66+
// OGCG: store i32 1, ptr [[ALLOC]], align 4
67+
// OGCG: [[BFLOAD:%.*]] = load i8, ptr [[ALLOC]], align 4
68+
// OGCG: [[CLEAR:%.*]] = and i8 [[BFLOAD]], -16
69+
// OGCG: [[SET:%.*]] = or i8 [[CLEAR]], 2
70+
// OGCG: store i8 [[SET]], ptr [[ALLOC]], align 4
71+
// OGCG: store i8 0, ptr [[ALLOC]], align 4

clang/test/CIR/CodeGen/bitfields.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ typedef struct {
6868
// CHECK: [[TMP0:%.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>
6969
// CHECK: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i
7070
// CHECK: [[TMP2:%.*]] = cir.get_member [[TMP0]][1] {name = "e"} : !cir.ptr<!rec_S> -> !cir.ptr<!u16i>
71-
// CHECK: cir.set_bitfield(#bfi_e, [[TMP2]] : !cir.ptr<!u16i>, [[TMP1]] : !s32i)
71+
// CHECK: cir.set_bitfield align(4) (#bfi_e, [[TMP2]] : !cir.ptr<!u16i>, [[TMP1]] : !s32i)
7272
void store_field() {
7373
S s;
7474
s.e = 3;
@@ -77,27 +77,27 @@ void store_field() {
7777
// CHECK: cir.func {{.*@load_field}}
7878
// CHECK: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init]
7979
// CHECK: [[TMP1:%.*]] = cir.load{{.*}} [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
80-
// CHECK: [[TMP2:%.*]] = cir.cast(bitcast, [[TMP1]] : !cir.ptr<!rec_S>), !cir.ptr<!u64i>
81-
// CHECK: [[TMP3:%.*]] = cir.get_bitfield(#bfi_d, [[TMP2]] : !cir.ptr<!u64i>) -> !s32i
80+
// CHECK: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "d"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
81+
// CHECK: [[TMP3:%.*]] = cir.get_bitfield align(4) (#bfi_d, [[TMP2]] : !cir.ptr<!u64i>) -> !s32i
8282
int load_field(S* s) {
8383
return s->d;
8484
}
8585

8686
// CHECK: cir.func {{.*@unOp}}
87-
// CHECK: [[TMP0:%.*]] = cir.cast(bitcast, {{.*}} : !cir.ptr<!rec_S>), !cir.ptr<!u64i>
88-
// CHECK: [[TMP1:%.*]] = cir.get_bitfield(#bfi_d, [[TMP0]] : !cir.ptr<!u64i>) -> !s32i
87+
// CHECK: [[TMP0:%.*]] = cir.get_member {{.*}}[0] {name = "d"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
88+
// CHECK: [[TMP1:%.*]] = cir.get_bitfield align(4) (#bfi_d, [[TMP0]] : !cir.ptr<!u64i>) -> !s32i
8989
// CHECK: [[TMP2:%.*]] = cir.unary(inc, [[TMP1]]) nsw : !s32i, !s32i
90-
// CHECK: cir.set_bitfield(#bfi_d, [[TMP0]] : !cir.ptr<!u64i>, [[TMP2]] : !s32i)
90+
// CHECK: cir.set_bitfield align(4) (#bfi_d, [[TMP0]] : !cir.ptr<!u64i>, [[TMP2]] : !s32i)
9191
void unOp(S* s) {
9292
s->d++;
9393
}
9494

9595
// CHECK: cir.func {{.*@binOp}}
9696
// CHECK: [[TMP0:%.*]] = cir.const #cir.int<42> : !s32i
97-
// CHECK: [[TMP1:%.*]] = cir.cast(bitcast, {{.*}} : !cir.ptr<!rec_S>), !cir.ptr<!u64i>
98-
// CHECK: [[TMP2:%.*]] = cir.get_bitfield(#bfi_d, [[TMP1]] : !cir.ptr<!u64i>) -> !s32i
97+
// CHECK: [[TMP1:%.*]] = cir.get_member {{.*}}[0] {name = "d"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
98+
// CHECK: [[TMP2:%.*]] = cir.get_bitfield align(4) (#bfi_d, [[TMP1]] : !cir.ptr<!u64i>) -> !s32i
9999
// CHECK: [[TMP3:%.*]] = cir.binop(or, [[TMP2]], [[TMP0]]) : !s32i
100-
// CHECK: cir.set_bitfield(#bfi_d, [[TMP1]] : !cir.ptr<!u64i>, [[TMP3]] : !s32i)
100+
// CHECK: cir.set_bitfield align(4) (#bfi_d, [[TMP1]] : !cir.ptr<!u64i>, [[TMP3]] : !s32i)
101101
void binOp(S* s) {
102102
s->d |= 42;
103103
}

clang/test/CIR/CodeGen/bitfields.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ typedef struct {
3636
// CHECK: cir.func dso_local @_Z11store_field
3737
// CHECK: [[TMP0:%.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>
3838
// CHECK: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i
39-
// CHECK: [[TMP2:%.*]] = cir.cast(bitcast, [[TMP0]] : !cir.ptr<!rec_S>), !cir.ptr<!u64i>
40-
// CHECK: cir.set_bitfield(#bfi_a, [[TMP2]] : !cir.ptr<!u64i>, [[TMP1]] : !s32i)
39+
// CHECK: [[TMP2:%.*]] = cir.get_member [[TMP0]][0] {name = "a"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
40+
// CHECK: cir.set_bitfield align(4) (#bfi_a, [[TMP2]] : !cir.ptr<!u64i>, [[TMP1]] : !s32i)
4141
void store_field() {
4242
S s;
4343
s.a = 3;
@@ -46,8 +46,8 @@ void store_field() {
4646
// CHECK: cir.func dso_local @_Z10load_field
4747
// CHECK: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init, const]
4848
// CHECK: [[TMP1:%.*]] = cir.load [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
49-
// CHECK: [[TMP2:%.*]] = cir.cast(bitcast, [[TMP1]] : !cir.ptr<!rec_S>), !cir.ptr<!u64i>
50-
// CHECK: [[TMP3:%.*]] = cir.get_bitfield(#bfi_d, [[TMP2]] : !cir.ptr<!u64i>) -> !s32i
49+
// CHECK: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "d"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
50+
// CHECK: [[TMP3:%.*]] = cir.get_bitfield align(4) (#bfi_d, [[TMP2]] : !cir.ptr<!u64i>) -> !s32i
5151
int load_field(S& s) {
5252
return s.d;
5353
}

0 commit comments

Comments
 (0)