Skip to content

Commit 0666422

Browse files
bruteforceboylanza
authored andcommitted
[CIR][Lowering] Fix BrCond Lowering (#819)
This PR fixes the lowering for BrCond. Consider the following code snippet: ``` #include <stdbool.h> bool test() { bool x = false; if (x) return x; return x; } ``` Emitting the CIR to `tmp.cir` using `-fclangir-mem2reg` produces the following CIR (truncated): ``` !s32i = !cir.int<s, 32> #fn_attr = #cir<extra({inline = #cir.inline<no>, nothrow = #cir.nothrow, optnone = #cir.optnone})> module { cir.func no_proto @test() -> !cir.bool extra(#fn_attr) { %0 = cir.const #cir.int<0> : !s32i %1 = cir.cast(int_to_bool, %0 : !s32i), !cir.bool cir.br ^bb1 ^bb1: // pred: ^bb0 cir.brcond %1 ^bb2, ^bb3 ^bb2: // pred: ^bb1 cir.return %1 : !cir.bool ^bb3: // pred: ^bb1 cir.br ^bb4 ^bb4: // pred: ^bb3 cir.return %1 : !cir.bool } } ``` Lowering the CIR to LLVM using `cir-opt tmp.cir -cir-to-llvm` fails with: ``` tmp.cir:5:10: error: failed to legalize operation 'llvm.zext' marked as erased ``` The CIR cast `%1 = cir.cast(int_to_bool, %0 : !s32i)` is lowered to a CIR comparison with zero, which is then lowered to an `LLVM::ICmpOp` and `LLVM::ZExtOp`. In the BrCond lowering, the zext is deleted when `zext->use_empty()`, but during this phase the lowering for the CIR above is not complete yet, because the zext will still have usage(s) later. The current check for when the zext is deleted is error-prone and can be improved. To fix this, in addition to checking that the use of the zext is empty, an additional check that the defining operation for the BrCond in the CIR (the cast operation in this case) is used exactly once is added.
1 parent 5301f74 commit 0666422

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,12 +612,18 @@ class CIRBrCondOpLowering
612612
mlir::ConversionPatternRewriter &rewriter) const override {
613613
mlir::Value i1Condition;
614614

615+
auto hasOneUse = false;
616+
617+
if (auto defOp = brOp.getCond().getDefiningOp())
618+
hasOneUse = defOp->getResult(0).hasOneUse();
619+
615620
if (auto defOp = adaptor.getCond().getDefiningOp()) {
616621
if (auto zext = dyn_cast<mlir::LLVM::ZExtOp>(defOp)) {
617622
if (zext->use_empty() &&
618623
zext->getOperand(0).getType() == rewriter.getI1Type()) {
619624
i1Condition = zext->getOperand(0);
620-
rewriter.eraseOp(zext);
625+
if (hasOneUse)
626+
rewriter.eraseOp(zext);
621627
}
622628
}
623629
}

clang/test/CIR/Lowering/brcond.cir

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: cir-opt %s -cir-to-llvm | FileCheck %s -check-prefix=MLIR
2+
// RUN: cir-translate %s -cir-to-llvmir | FileCheck %s -check-prefix=LLVM
3+
4+
!s32i = !cir.int<s, 32>
5+
#fn_attr = #cir<extra({inline = #cir.inline<no>, nothrow = #cir.nothrow, optnone = #cir.optnone})>
6+
module { cir.func no_proto @test() -> !cir.bool extra(#fn_attr) {
7+
%0 = cir.const #cir.int<0> : !s32i
8+
%1 = cir.cast(int_to_bool, %0 : !s32i), !cir.bool
9+
cir.br ^bb1
10+
^bb1:
11+
cir.brcond %1 ^bb2, ^bb3
12+
^bb2:
13+
cir.return %1 : !cir.bool
14+
^bb3:
15+
cir.br ^bb4
16+
^bb4:
17+
cir.return %1 : !cir.bool
18+
}
19+
}
20+
21+
// MLIR: {{.*}} = llvm.mlir.constant(0 : i32) : i32
22+
// MLIR-NEXT: {{.*}} = llvm.mlir.constant(0 : i32) : i32
23+
// MLIR-NEXT: {{.*}} = llvm.icmp "ne" {{.*}}, {{.*}} : i32
24+
// MLIR-NEXT: {{.*}} = llvm.zext {{.*}} : i1 to i8
25+
// MLIR-NEXT: llvm.br ^bb1
26+
// MLIR-NEXT: ^bb1:
27+
// MLIR-NEXT: llvm.cond_br {{.*}}, ^bb2, ^bb3
28+
// MLIR-NEXT: ^bb2:
29+
// MLIR-NEXT: llvm.return {{.*}} : i8
30+
// MLIR-NEXT: ^bb3:
31+
// MLIR-NEXT: llvm.br ^bb4
32+
// MLIR-NEXT: ^bb4:
33+
// MLIR-NEXT: llvm.return {{.*}} : i8
34+
35+
// LLVM: br label {{.*}}
36+
// LLVM: 1:
37+
// LLVM: br i1 false, label {{.*}}, label {{.*}}
38+
// LLVM: 2:
39+
// LLVM: ret i8 0
40+
// LLVM: 3:
41+
// LLVM: br label {{.*}}
42+
// LLVM: 4:
43+
// LLVM: ret i8 0

0 commit comments

Comments
 (0)