Skip to content

Commit 42a1c5c

Browse files
committed
add cir ABIlowering code for lowerVAArgOp
1 parent 9c4fb4b commit 42a1c5c

File tree

5 files changed

+264
-3
lines changed

5 files changed

+264
-3
lines changed

clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp

+16-2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> {
7070

7171
void runOnOp(Operation *op);
7272
void lowerThreeWayCmpOp(CmpThreeWayOp op);
73+
void lowerVAArgOp(VAArgOp op);
7374
void lowerGlobalOp(GlobalOp op);
7475
void lowerDynamicCastOp(DynamicCastOp op);
7576
void lowerStdFindOp(StdFindOp op);
@@ -320,6 +321,16 @@ static void canonicalizeIntrinsicThreeWayCmp(CIRBaseBuilderTy &builder,
320321
op.erase();
321322
}
322323

324+
void LoweringPreparePass::lowerVAArgOp(VAArgOp op) {
325+
CIRBaseBuilderTy builder(getContext());
326+
builder.setInsertionPoint(op);
327+
328+
auto res = cxxABI->lowerVAArg(builder, op);
329+
op.replaceAllUsesWith(res);
330+
op.erase();
331+
return;
332+
}
333+
323334
void LoweringPreparePass::lowerThreeWayCmpOp(CmpThreeWayOp op) {
324335
CIRBaseBuilderTy builder(getContext());
325336
builder.setInsertionPointAfter(op);
@@ -601,6 +612,8 @@ void LoweringPreparePass::lowerIterEndOp(IterEndOp op) {
601612
void LoweringPreparePass::runOnOp(Operation *op) {
602613
if (auto threeWayCmp = dyn_cast<CmpThreeWayOp>(op)) {
603614
lowerThreeWayCmpOp(threeWayCmp);
615+
} else if (auto vaArgOp = dyn_cast<VAArgOp>(op)) {
616+
lowerVAArgOp(vaArgOp);
604617
} else if (auto getGlobal = dyn_cast<GlobalOp>(op)) {
605618
lowerGlobalOp(getGlobal);
606619
} else if (auto dynamicCast = dyn_cast<DynamicCastOp>(op)) {
@@ -633,8 +646,9 @@ void LoweringPreparePass::runOnOperation() {
633646

634647
SmallVector<Operation *> opsToTransform;
635648
op->walk([&](Operation *op) {
636-
if (isa<CmpThreeWayOp, GlobalOp, DynamicCastOp, StdFindOp, IterEndOp,
637-
IterBeginOp, ArrayCtor, ArrayDtor, mlir::cir::FuncOp>(op))
649+
if (isa<CmpThreeWayOp, VAArgOp, GlobalOp, DynamicCastOp, StdFindOp,
650+
IterEndOp, IterBeginOp, ArrayCtor, ArrayDtor, mlir::cir::FuncOp>(
651+
op))
638652
opsToTransform.push_back(op);
639653
});
640654

clang/lib/CIR/Dialect/Transforms/LoweringPrepareCXXABI.h

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class LoweringPrepareCXXABI {
2828
virtual mlir::Value lowerDynamicCast(CIRBaseBuilderTy &builder,
2929
mlir::cir::DynamicCastOp op) = 0;
3030

31+
virtual mlir::Value lowerVAArg(CIRBaseBuilderTy &builder,
32+
mlir::cir::VAArgOp op) = 0;
3133
virtual ~LoweringPrepareCXXABI() {}
3234
};
3335

clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.cpp

+104-1
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,20 @@
2020
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
2121
#include "clang/CIR/Dialect/IR/CIRDialect.h"
2222

23-
using namespace cir;
23+
using cir::CIRBaseBuilderTy;
24+
using cir::LoweringPrepareCXXABI;
25+
using cir::MissingFeatures;
26+
using namespace mlir;
27+
using namespace mlir::cir;
2428

2529
namespace {
2630

2731
class LoweringPrepareItaniumCXXABI : public LoweringPrepareCXXABI {
2832
public:
2933
mlir::Value lowerDynamicCast(CIRBaseBuilderTy &builder,
3034
mlir::cir::DynamicCastOp op) override;
35+
mlir::Value lowerVAArg(CIRBaseBuilderTy &builder,
36+
mlir::cir::VAArgOp op) override;
3137
};
3238

3339
} // namespace
@@ -115,3 +121,100 @@ LoweringPrepareItaniumCXXABI::lowerDynamicCast(CIRBaseBuilderTy &builder,
115121
})
116122
.getResult();
117123
}
124+
125+
static mlir::Value createGetMemberOp(CIRBaseBuilderTy &builder,
126+
mlir::Location &loc, mlir::Value structPtr,
127+
const char *fldName, unsigned idx) {
128+
129+
assert(structPtr.getType().isa<mlir::cir::PointerType>());
130+
auto structBaseTy =
131+
structPtr.getType().cast<mlir::cir::PointerType>().getPointee();
132+
assert(structBaseTy.isa<mlir::cir::StructType>());
133+
auto fldTy = structBaseTy.cast<mlir::cir::StructType>().getMembers()[idx];
134+
auto fldPtrTy = ::mlir::cir::PointerType::get(builder.getContext(), fldTy);
135+
return builder.create<mlir::cir::GetMemberOp>(loc, fldPtrTy, structPtr,
136+
fldName, idx);
137+
}
138+
139+
mlir::Value LoweringPrepareItaniumCXXABI::lowerVAArg(CIRBaseBuilderTy &builder,
140+
mlir::cir::VAArgOp op) {
141+
auto loc = op->getLoc();
142+
auto valist = op->getOperand(0);
143+
auto opResTy = op.getType();
144+
bool isFloatingType =
145+
opResTy.isa<mlir::cir::SingleType, mlir::cir::DoubleType>();
146+
auto offsP = createGetMemberOp(builder, loc, valist,
147+
isFloatingType ? "vr_offs" : "gr_offs",
148+
isFloatingType ? 4 : 3);
149+
auto offs = builder.create<mlir::cir::LoadOp>(loc, offsP);
150+
auto boolTy = builder.getBoolTy();
151+
auto zeroValue = builder.create<mlir::cir::ConstantOp>(
152+
loc, offs.getType(), mlir::cir::IntAttr::get(offs.getType(), 0));
153+
auto cmpRes = builder.create<mlir::cir::CmpOp>(loc, boolTy, CmpOpKind::ge,
154+
offs, zeroValue);
155+
auto curInsertionP = builder.saveInsertionPoint();
156+
auto currentBlock = builder.getInsertionBlock();
157+
158+
auto maybeRegBlock = builder.createBlock(builder.getBlock()->getParent());
159+
auto inRegBlock = builder.createBlock(builder.getBlock()->getParent());
160+
auto onStackBlock = builder.createBlock(builder.getBlock()->getParent());
161+
162+
builder.restoreInsertionPoint(curInsertionP);
163+
builder.create<mlir::cir::BrCondOp>(loc, cmpRes, onStackBlock, maybeRegBlock);
164+
auto newEndBlock = currentBlock->splitBlock(op);
165+
166+
builder.setInsertionPointToEnd(onStackBlock);
167+
auto stackP = createGetMemberOp(builder, loc, valist, "stack", 0);
168+
auto stack = builder.create<mlir::cir::LoadOp>(loc, stackP);
169+
auto ptrDiffTy =
170+
mlir::cir::IntType::get(builder.getContext(), 64, /*signed=*/false);
171+
auto eight = builder.create<mlir::cir::ConstantOp>(
172+
loc, ptrDiffTy, mlir::cir::IntAttr::get(ptrDiffTy, 8));
173+
auto i8Ty = IntegerType::get(builder.getContext(), 8);
174+
auto i8PtrTy = PointerType::get(builder.getContext(), i8Ty);
175+
auto castStack =
176+
builder.createCast(mlir::cir::CastKind::bitcast, stack, i8PtrTy);
177+
auto newStackAsi8Ptr = builder.create<mlir::cir::PtrStrideOp>(
178+
loc, castStack.getType(), castStack, eight);
179+
auto newStack = builder.createCast(mlir::cir::CastKind::bitcast,
180+
newStackAsi8Ptr, stack.getType());
181+
builder.createStore(loc, newStack, stackP);
182+
builder.create<mlir::cir::BrOp>(loc, mlir::ValueRange{stack}, newEndBlock);
183+
184+
builder.setInsertionPointToEnd(maybeRegBlock);
185+
auto boundaryValue = builder.create<mlir::cir::ConstantOp>(
186+
loc, offs.getType(),
187+
mlir::cir::IntAttr::get(offs.getType(), isFloatingType ? 16 : 8));
188+
auto newRegsOffs = builder.create<mlir::cir::BinOp>(
189+
loc, offs.getType(), mlir::cir::BinOpKind::Add, offs, boundaryValue);
190+
builder.createStore(loc, newRegsOffs, offsP);
191+
auto maybeRegCmpRes = builder.create<mlir::cir::CmpOp>(
192+
loc, boolTy, CmpOpKind::le, newRegsOffs, zeroValue);
193+
builder.create<mlir::cir::BrCondOp>(loc, maybeRegCmpRes, inRegBlock,
194+
onStackBlock);
195+
196+
builder.setInsertionPointToEnd(inRegBlock);
197+
auto regTopP = createGetMemberOp(builder, loc, valist,
198+
isFloatingType ? "vr_top" : "gr_top",
199+
isFloatingType ? 2 : 1);
200+
auto regTop = builder.create<mlir::cir::LoadOp>(loc, regTopP);
201+
auto castRegTop =
202+
builder.createCast(mlir::cir::CastKind::bitcast, regTop, i8PtrTy);
203+
auto resAsInt8P = builder.create<mlir::cir::PtrStrideOp>(
204+
loc, castRegTop.getType(), castRegTop, offs);
205+
auto resAsVoidP = builder.createCast(mlir::cir::CastKind::bitcast, resAsInt8P,
206+
regTop.getType());
207+
builder.create<mlir::cir::BrOp>(loc, mlir::ValueRange{resAsVoidP},
208+
newEndBlock);
209+
210+
// generate additional instructions for end block
211+
builder.setInsertionPoint(op);
212+
newEndBlock->addArgument(stack.getType(), loc);
213+
auto resP = newEndBlock->getArgument(0);
214+
assert(resP.getType().isa<mlir::cir::PointerType>());
215+
auto opResPTy = PointerType::get(builder.getContext(), opResTy);
216+
auto castResP =
217+
builder.createCast(mlir::cir::CastKind::bitcast, resP, opResPTy);
218+
auto res = builder.create<mlir::cir::LoadOp>(loc, castResP);
219+
return res.getResult();
220+
}
+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir-enable -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2>&1 | FileCheck %s -check-prefix=BEFORE
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir-enable -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare %s -o %t.cir 2>&1 | FileCheck %s -check-prefix=AFTER
3+
4+
#include <stdarg.h>
5+
6+
double f1(int n, ...) {
7+
va_list valist;
8+
va_start(valist, n);
9+
double res = va_arg(valist, double);
10+
va_end(valist);
11+
return res;
12+
}
13+
14+
// BEFORE: !ty_22__va_list22 = !cir.struct<struct "__va_list" {!cir.ptr<!cir.void>, !cir.ptr<!cir.void>, !cir.ptr<!cir.void>, !cir.int<s, 32>, !cir.int<s, 32>}
15+
// BEFORE: cir.func @f1(%arg0: !s32i, ...) -> !cir.double
16+
// BEFORE: [[RETP:%.*]] = cir.alloca !cir.double, cir.ptr <!cir.double>, ["__retval"]
17+
// BEFORE: [[RESP:%.*]] = cir.alloca !cir.double, cir.ptr <!cir.double>, ["res", init]
18+
// BEFORE: cir.va.start [[VARLIST:%.*]] : !cir.ptr<!ty_22__va_list22>
19+
// BEFORE: [[TMP0:%.*]] = cir.va.arg [[VARLIST]] : (!cir.ptr<!ty_22__va_list22>) -> !cir.double
20+
// BEFORE: cir.store [[TMP0]], [[RESP]] : !cir.double, cir.ptr <!cir.double>
21+
// BEFORE: cir.va.end [[VARLIST]] : !cir.ptr<!ty_22__va_list22>
22+
// BEFORE: [[RES:%.*]] = cir.load [[RESP]] : cir.ptr <!cir.double>, !cir.double
23+
// BEFORE: cir.store [[RES]], [[RETP]] : !cir.double, cir.ptr <!cir.double>
24+
// BEFORE: [[RETV:%.*]] = cir.load [[RETP]] : cir.ptr <!cir.double>, !cir.double
25+
// BEFORE: cir.return [[RETV]] : !cir.double
26+
27+
// AFTER: !ty_22__va_list22 = !cir.struct<struct "__va_list" {!cir.ptr<!cir.void>, !cir.ptr<!cir.void>, !cir.ptr<!cir.void>, !cir.int<s, 32>, !cir.int<s, 32>}
28+
// AFTER: cir.func @f1(%arg0: !s32i, ...) -> !cir.double
29+
// AFTER: [[RETP:%.*]] = cir.alloca !cir.double, cir.ptr <!cir.double>, ["__retval"]
30+
// AFTER: [[RESP:%.*]] = cir.alloca !cir.double, cir.ptr <!cir.double>, ["res", init]
31+
// AFTER: cir.va.start [[VARLIST:%.*]] : !cir.ptr<!ty_22__va_list22>
32+
// AFTER: [[VR_OFFS_P:%.*]] = cir.get_member [[VARLIST]][4] {name = "vr_offs"} : !cir.ptr<!ty_22__va_list22> -> !cir.ptr<!s32i>
33+
// AFTER: [[VR_OFFS:%.*]] = cir.load [[VR_OFFS_P]] : cir.ptr <!s32i>, !s32i
34+
// AFTER: [[ZERO:%.*]] = cir.const(#cir.int<0> : !s32i) : !s32i
35+
// AFTER: [[CMP0:%.*]] = cir.cmp(ge, [[VR_OFFS]], [[ZERO]]) : !s32i, !cir.bool
36+
// AFTER-NEXT: cir.brcond [[CMP0]] [[BB_ON_STACK:\^bb.*]], [[BB_MAY_REG:\^bb.*]]
37+
38+
// AFTER-NEXT: [[BB_END:\^bb.*]]([[BLK_ARG:%.*]]: !cir.ptr<!void>): // 2 preds: [[BB_IN_REG:\^bb.*]], [[BB_ON_STACK]]
39+
// AFTER-NEXT: [[TMP0:%.*]] = cir.cast(bitcast, [[BLK_ARG]] : !cir.ptr<!void>), !cir.ptr<!cir.double>
40+
// AFTER-NEXT: [[TMP1:%.*]] = cir.load [[TMP0]] : cir.ptr <!cir.double>, !cir.double
41+
// AFTER: cir.store [[TMP1]], [[RESP]] : !cir.double, cir.ptr <!cir.double>
42+
// AFTER: cir.va.end [[VARLIST]] : !cir.ptr<!ty_22__va_list22>
43+
// AFTER: [[RES:%.*]] = cir.load [[RESP]] : cir.ptr <!cir.double>, !cir.double
44+
// AFTER: cir.store [[RES]], [[RETP]] : !cir.double, cir.ptr <!cir.double>
45+
// AFTER: [[RETV:%.*]] = cir.load [[RETP]] : cir.ptr <!cir.double>, !cir.double
46+
// AFTER: cir.return [[RETV]] : !cir.double
47+
48+
// AFTER: [[BB_MAY_REG]]: // pred: [[BB_BEGIN:\^bb.*]]
49+
// AFTER-NEXT: [[SIXTEEN:%.*]] = cir.const(#cir.int<16> : !s32i) : !s32i
50+
// AFTER-NEXT: [[NEW_REG_OFFS:%.*]] = cir.binop(add, [[VR_OFFS]], [[SIXTEEN]]) : !s32i
51+
// AFTER-NEXT: cir.store [[NEW_REG_OFFS]], [[VR_OFFS_P]] : !s32i, cir.ptr <!s32i>
52+
// AFTER-NEXT: [[CMP1:%.*]] = cir.cmp(le, [[NEW_REG_OFFS]], [[ZERO]]) : !s32i, !cir.bool
53+
// AFTER-NEXT: cir.brcond [[CMP1]] [[BB_IN_REG]], [[BB_ON_STACK]]
54+
55+
// AFTER: [[BB_IN_REG]]: // pred: [[BB_MAY_REG]]
56+
// AFTER-NEXT: [[VR_TOP_P:%.*]] = cir.get_member [[VARLIST]][2] {name = "vr_top"} : !cir.ptr<!ty_22__va_list22> -> !cir.ptr<!cir.ptr<!void>>
57+
// AFTER-NEXT: [[VR_TOP:%.*]] = cir.load [[VR_TOP_P]] : cir.ptr <!cir.ptr<!void>>, !cir.ptr<!void>
58+
// AFTER-NEXT: [[TMP2:%.*]] = cir.cast(bitcast, [[VR_TOP]] : !cir.ptr<!void>), !cir.ptr<i8>
59+
// AFTER-NEXT: [[TMP3:%.*]] = cir.ptr_stride([[TMP2]] : !cir.ptr<i8>, [[VR_OFFS]] : !s32i), !cir.ptr<i8>
60+
// AFTER-NEXT: [[IN_REG_OUTPUT:%.*]] = cir.cast(bitcast, [[TMP3]] : !cir.ptr<i8>), !cir.ptr<!void>
61+
// AFTER-NEXT: cir.br [[BB_END]]([[IN_REG_OUTPUT]] : !cir.ptr<!void>)
62+
63+
// AFTER: [[BB_ON_STACK]]: // 2 preds: [[BB_BEGIN]], [[BB_MAY_REG]]
64+
// AFTER-NEXT: [[STACK_P:%.*]] = cir.get_member [[VARLIST]][0] {name = "stack"} : !cir.ptr<!ty_22__va_list22> -> !cir.ptr<!cir.ptr<!void>>
65+
// AFTER-NEXT: [[STACK_V:%.*]] = cir.load [[STACK_P]] : cir.ptr <!cir.ptr<!void>>, !cir.ptr<!void>
66+
// AFTER-NEXT: [[EIGHT_IN_PTR_ARITH:%.*]] = cir.const(#cir.int<8> : !u64i) : !u64i
67+
// AFTER-NEXT: [[TMP4:%.*]] = cir.cast(bitcast, [[STACK_V]] : !cir.ptr<!void>), !cir.ptr<i8>
68+
// AFTER-NEXT: [[TMP5:%.*]] = cir.ptr_stride([[TMP4]] : !cir.ptr<i8>, [[EIGHT_IN_PTR_ARITH]] : !u64i), !cir.ptr<i8>
69+
// AFTER-NEXT: [[NEW_STACK_V:%.*]] = cir.cast(bitcast, [[TMP5]] : !cir.ptr<i8>), !cir.ptr<!void>
70+
// AFTER-NEXT: cir.store [[NEW_STACK_V]], [[STACK_P]] : !cir.ptr<!void>, cir.ptr <!cir.ptr<!void>>
71+
// AFTER-NEXT: cir.br [[BB_END]]([[STACK_V]] : !cir.ptr<!void>)

clang/test/CIR/CodeGen/var-arg.c

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir-enable -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2>&1 | FileCheck %s -check-prefix=BEFORE
2+
// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir-enable -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare %s -o %t.cir 2>&1 | FileCheck %s -check-prefix=AFTER
3+
4+
#include <stdarg.h>
5+
6+
int f1(int n, ...) {
7+
va_list valist;
8+
va_start(valist, n);
9+
int res = va_arg(valist, int);
10+
va_end(valist);
11+
return res;
12+
}
13+
14+
// BEFORE: !ty_22__va_list22 = !cir.struct<struct "__va_list" {!cir.ptr<!cir.void>, !cir.ptr<!cir.void>, !cir.ptr<!cir.void>, !cir.int<s, 32>, !cir.int<s, 32>}
15+
// BEFORE: cir.func @f1(%arg0: !s32i, ...) -> !s32i
16+
// BEFORE: [[RETP:%.*]] = cir.alloca !s32i, cir.ptr <!s32i>, ["__retval"]
17+
// BEFORE: [[RESP:%.*]] = cir.alloca !s32i, cir.ptr <!s32i>, ["res", init]
18+
// BEFORE: cir.va.start [[VARLIST:%.*]] : !cir.ptr<!ty_22__va_list22>
19+
// BEFORE: [[TMP0:%.*]] = cir.va.arg [[VARLIST]] : (!cir.ptr<!ty_22__va_list22>) -> !s32i
20+
// BEFORE: cir.store [[TMP0]], [[RESP]] : !s32i, cir.ptr <!s32i>
21+
// BEFORE: cir.va.end [[VARLIST]] : !cir.ptr<!ty_22__va_list22>
22+
// BEFORE: [[RES:%.*]] = cir.load [[RESP]] : cir.ptr <!s32i>, !s32i
23+
// BEFORE: cir.store [[RES]], [[RETP]] : !s32i, cir.ptr <!s32i>
24+
// BEFORE: [[RETV:%.*]] = cir.load [[RETP]] : cir.ptr <!s32i>, !s32i
25+
// BEFORE: cir.return [[RETV]] : !s32i
26+
27+
// AFTER: !ty_22__va_list22 = !cir.struct<struct "__va_list" {!cir.ptr<!cir.void>, !cir.ptr<!cir.void>, !cir.ptr<!cir.void>, !cir.int<s, 32>, !cir.int<s, 32>}
28+
// AFTER: cir.func @f1(%arg0: !s32i, ...) -> !s32i
29+
// AFTER: [[RETP:%.*]] = cir.alloca !s32i, cir.ptr <!s32i>, ["__retval"]
30+
// AFTER: [[RESP:%.*]] = cir.alloca !s32i, cir.ptr <!s32i>, ["res", init]
31+
// AFTER: cir.va.start [[VARLIST:%.*]] : !cir.ptr<!ty_22__va_list22>
32+
// AFTER: [[GR_OFFS_P:%.*]] = cir.get_member [[VARLIST]][3] {name = "gr_offs"} : !cir.ptr<!ty_22__va_list22> -> !cir.ptr<!s32i>
33+
// AFTER: [[GR_OFFS:%.*]] = cir.load [[GR_OFFS_P]] : cir.ptr <!s32i>, !s32i
34+
// AFTER: [[ZERO:%.*]] = cir.const(#cir.int<0> : !s32i) : !s32i
35+
// AFTER: [[CMP0:%.*]] = cir.cmp(ge, [[GR_OFFS]], [[ZERO]]) : !s32i, !cir.bool
36+
// AFTER-NEXT: cir.brcond [[CMP0]] [[BB_ON_STACK:\^bb.*]], [[BB_MAY_REG:\^bb.*]]
37+
38+
// AFTER-NEXT: [[BB_END:\^bb.*]]([[BLK_ARG:%.*]]: !cir.ptr<!void>): // 2 preds: [[BB_IN_REG:\^bb.*]], [[BB_ON_STACK]]
39+
// AFTER-NEXT: [[TMP0:%.*]] = cir.cast(bitcast, [[BLK_ARG]] : !cir.ptr<!void>), !cir.ptr<!s32i>
40+
// AFTER-NEXT: [[TMP1:%.*]] = cir.load [[TMP0]] : cir.ptr <!s32i>, !s32i
41+
// AFTER: cir.store [[TMP1]], [[RESP]] : !s32i, cir.ptr <!s32i>
42+
// AFTER: cir.va.end [[VARLIST]] : !cir.ptr<!ty_22__va_list22>
43+
// AFTER: [[RES:%.*]] = cir.load [[RESP]] : cir.ptr <!s32i>, !s32i
44+
// AFTER: cir.store [[RES]], [[RETP]] : !s32i, cir.ptr <!s32i>
45+
// AFTER: [[RETV:%.*]] = cir.load [[RETP]] : cir.ptr <!s32i>, !s32i
46+
// AFTER: cir.return [[RETV]] : !s32i
47+
48+
// AFTER: [[BB_MAY_REG]]: // pred: [[BB_BEGIN:\^bb.*]]
49+
// AFTER-NEXT: [[EIGHT:%.*]] = cir.const(#cir.int<8> : !s32i) : !s32i
50+
// AFTER-NEXT: [[NEW_REG_OFFS:%.*]] = cir.binop(add, [[GR_OFFS]], [[EIGHT]]) : !s32i
51+
// AFTER-NEXT: cir.store [[NEW_REG_OFFS]], [[GR_OFFS_P]] : !s32i, cir.ptr <!s32i>
52+
// AFTER-NEXT: [[CMP1:%.*]] = cir.cmp(le, [[NEW_REG_OFFS]], [[ZERO]]) : !s32i, !cir.bool
53+
// AFTER-NEXT: cir.brcond [[CMP1]] [[BB_IN_REG]], [[BB_ON_STACK]]
54+
55+
// AFTER: [[BB_IN_REG]]: // pred: [[BB_MAY_REG]]
56+
// AFTER-NEXT: [[GR_TOP_P:%.*]] = cir.get_member [[VARLIST]][1] {name = "gr_top"} : !cir.ptr<!ty_22__va_list22> -> !cir.ptr<!cir.ptr<!void>>
57+
// AFTER-NEXT: [[GR_TOP:%.*]] = cir.load [[GR_TOP_P]] : cir.ptr <!cir.ptr<!void>>, !cir.ptr<!void>
58+
// AFTER-NEXT: [[TMP2:%.*]] = cir.cast(bitcast, [[GR_TOP]] : !cir.ptr<!void>), !cir.ptr<i8>
59+
// AFTER-NEXT: [[TMP3:%.*]] = cir.ptr_stride([[TMP2]] : !cir.ptr<i8>, [[GR_OFFS]] : !s32i), !cir.ptr<i8>
60+
// AFTER-NEXT: [[IN_REG_OUTPUT:%.*]] = cir.cast(bitcast, [[TMP3]] : !cir.ptr<i8>), !cir.ptr<!void>
61+
// AFTER-NEXT: cir.br [[BB_END]]([[IN_REG_OUTPUT]] : !cir.ptr<!void>)
62+
63+
// AFTER: [[BB_ON_STACK]]: // 2 preds: [[BB_BEGIN]], [[BB_MAY_REG]]
64+
// AFTER-NEXT: [[STACK_P:%.*]] = cir.get_member [[VARLIST]][0] {name = "stack"} : !cir.ptr<!ty_22__va_list22> -> !cir.ptr<!cir.ptr<!void>>
65+
// AFTER-NEXT: [[STACK_V:%.*]] = cir.load [[STACK_P]] : cir.ptr <!cir.ptr<!void>>, !cir.ptr<!void>
66+
// AFTER-NEXT: [[EIGHT_IN_PTR_ARITH:%.*]] = cir.const(#cir.int<8> : !u64i) : !u64i
67+
// AFTER-NEXT: [[TMP4:%.*]] = cir.cast(bitcast, [[STACK_V]] : !cir.ptr<!void>), !cir.ptr<i8>
68+
// AFTER-NEXT: [[TMP5:%.*]] = cir.ptr_stride([[TMP4]] : !cir.ptr<i8>, [[EIGHT_IN_PTR_ARITH]] : !u64i), !cir.ptr<i8>
69+
// AFTER-NEXT: [[NEW_STACK_V:%.*]] = cir.cast(bitcast, [[TMP5]] : !cir.ptr<i8>), !cir.ptr<!void>
70+
// AFTER-NEXT: cir.store [[NEW_STACK_V]], [[STACK_P]] : !cir.ptr<!void>, cir.ptr <!cir.ptr<!void>>
71+
// AFTER-NEXT: cir.br [[BB_END]]([[STACK_V]] : !cir.ptr<!void>)

0 commit comments

Comments
 (0)