================
@@ -33,6 +33,141 @@ struct HoistAllocasPass : public
impl::HoistAllocasBase<HoistAllocasPass> {
void runOnOperation() override;
};
+static bool isOpInLoop(mlir::Operation *op) {
+ return op->getParentOfType<cir::LoopOpInterface>();
+}
+
+static bool hasStoreToAllocaInWhileCond(cir::AllocaOp alloca) {
+ // This function determines whether the given alloca operation represents
+ // a variable defined as a while loop's condition.
+ //
+ // Specifically, C/C++ allows the condition of a while loop be a variable
+ // declaration:
+ //
+ // while (const int x = foo()) { /* body... */ }
+ //
+ // CIRGen would emit the following CIR for the above code:
+ //
+ // cir.scope {
+ // %x.slot = cir.alloca !s32i [init, const]
+ // cir.while {
+ // %0 = cir.call @foo()
+ // cir.store %0, %x
+ // %1 = cir.load %x
+ // %2 = cir.cast int_to_bool %1
+ // cir.condition(%2)
+ // } do {
+ // // loop body goes here.
+ // }
+ // }
+ //
+ // Note that %x.slot is emitted outside the cir.while operation. Ideally, the
+ // cir.while operation should cover this cir.alloca operation, but currently
+ // CIR does not work this way. When hoisting such an alloca operation, one
+ // must remove the "const" flag from it, otherwise LLVM lowering code will
+ // mistakenly attach invariant group metadata to the load and store
operations
+ // in the while body, indicating that all loads and stores across all
+ // iterations of the loop are constant.
+
+ for (mlir::Operation *user : alloca->getUsers()) {
+ if (!mlir::isa<cir::StoreOp>(user))
+ continue;
+
+ auto store = mlir::cast<cir::StoreOp>(user);
+ mlir::Operation *storeParentOp = store->getParentOp();
+ if (!mlir::isa<cir::WhileOp>(storeParentOp))
+ continue;
+
+ auto whileOp = mlir::cast<cir::WhileOp>(storeParentOp);
+ return &whileOp.getCond() == store->getParentRegion();
+ }
+
+ return false;
+}
+
+static void processConstAlloca(cir::AllocaOp alloca) {
+ // When optimization is enabled, LLVM lowering would start emitting invariant
+ // group metadata for loads and stores to alloca-ed objects with "const"
+ // attribute. For example, the following CIR:
+ //
+ // %slot = cir.alloca !s32i [init, const]
+ // cir.store %0, %slot
+ // %1 = cir.load %slot
+ //
+ // would be lowered to the following LLVM IR:
+ //
+ // %slot = alloca i32, i64 1
+ // store i32 %0, ptr %slot, !invariant.group !0
+ // %1 = load i32, ptr %slot, !invariant.group !0
+ //
+ // The invariant group metadata would tell LLVM optimizer that the store and
+ // load instruction would store and load the same value from %slot.
+ //
+ // However, things started to get tricky when such an alloca operation
+ // appears in the body of a loop construct:
+ //
+ // cir.some_loop_construct {
+ // %slot = cir.alloca !s32i [init, const]
+ // cir.store %0, %slot
+ // %1 = cir.load %slot
+ // }
+ //
+ // After alloca hoisting, the CIR code above would be transformed into:
+ //
+ // %slot = cir.alloca !s32i [init, const]
+ // cir.some_loop_construct {
+ // cir.store %0, %slot
+ // %1 = cir.load %slot
+ // }
+ //
+ // Notice how alloca hoisting change the semantics of the program in such a
+ // case. The transformed code now indicates the optimizer that the load and
+ // store operations load and store the same value **across all iterations of
+ // the loop**!
+ //
+ // To overcome this problem, we instead transform the program into this:
+ //
+ // %slot = cir.alloca !s32i [init, const]
+ // cir.some_loop_construct {
+ // %slot.inv = cir.invariant_group %slot
+ // cir.store %0, %slot.inv
+ // %1 = cir.load %slot.inv
+ // }
+ //
+ // The cir.invariant_group operation attaches fresh invariant information to
+ // the operand pointer and yields a pointer with the fresh invariant
+ // information. Upon each loop iteration, the old invariant information is
+ // disgarded, and a new invariant information is attached, thus the correct
+ // program semantic retains. During LLVM lowering, the cir.invariant_group
+ // operation would eventually become an intrinsic call to
----------------
andykaylor wrote:
```suggestion
// operation will eventually become an intrinsic call to
```
https://github.com/llvm/llvm-project/pull/175037
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits