================
@@ -39,13 +39,40 @@ namespace {
 
 /// Lowers operations with the terminator trait that have a single successor.
 void lowerTerminator(mlir::Operation *op, mlir::Block *dest,
-                     mlir::PatternRewriter &rewriter,
-                     cir::LoopHintAttr loopHints = {}) {
+                     mlir::PatternRewriter &rewriter) {
   assert(op->hasTrait<mlir::OpTrait::IsTerminator>() && "not a terminator");
   mlir::OpBuilder::InsertionGuard guard(rewriter);
   rewriter.setInsertionPoint(op);
-  rewriter.replaceOpWithNewOp<cir::BrOp>(op, mlir::ValueRange{}, loopHints,
-                                         dest);
+  rewriter.replaceOpWithNewOp<cir::BrOp>(op, dest);
+}
+
+/// Creates a cir.brcond to `destTrue` if `cond` is true and to `destFalse`
+/// otherwise.  If `cond` is a cir.not, the branch is on its operand with the
+/// destination blocks swapped, repeating for each nested cir.not.  The
+/// cir.not ops are left in place for eraseDeadNots.
+static void createBrCondPeelingNot(mlir::PatternRewriter &rewriter,
+                                   mlir::Location loc, mlir::Value cond,
+                                   mlir::Block *destTrue,
+                                   mlir::Block *destFalse) {
+  while (auto notOp = cond.getDefiningOp<cir::NotOp>()) {
+    cond = notOp.getInput();
+    std::swap(destTrue, destFalse);
+  }
+  cir::BrCondOp::create(rewriter, loc, cond, destTrue, destFalse);
+}
+
+/// Erases `cond` if it is an unused cir.not, then repeats on its operand,
+/// stopping at the first cir.not that still has uses.  Call after the
+/// structured op that used `cond` is replaced, so a cir.not that
+/// createBrCondPeelingNot looked through does not reach LLVM IR as a dead
+/// `xor`.
+static void eraseDeadNots(mlir::PatternRewriter &rewriter, mlir::Value cond) {
----------------
adams381 wrote:

When createBrCondPeelingNot runs, the `cir.if` or `cir.ternary` being flattened 
still uses the `cir.not` as its condition, so the `cir.not` isn't dead yet and 
can't be erased.  It only becomes dead after replaceOp, which is why the erase 
comes afterwards.  If the branch is built after replaceOp instead, both steps 
fit in one helper.  I can make that change if this stays in FlattenCFG.

https://github.com/llvm/llvm-project/pull/233918
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to