Skip to content

Commit 83eaf76

Browse files
seven-milelanza
authored andcommitted
[CIR][Transforms] Simplify redundant bitcasts (llvm#591)
Fix llvm#479 . There are three available stages to place the simplification in. * A straightforward method is to extend `fold` method for CastOp. But CIR does not use CanonicalizerPass, so it does not work. * As for somehow equivalent to it, append a pattern to `MergeCleanupsPass`. But now it is mainly for CFG-related simplifications like block merging. I don't know if this is the proper way. Shall we rename it to a broader definition? * Add a new pass for this issue. This is definitely not very reasonable XD. We won't consider it unless we're really out of options. This PR includes the second option. What do you think @bcardosolopes ?
1 parent 8dcb386 commit 83eaf76

File tree

6 files changed

+55
-23
lines changed

6 files changed

+55
-23
lines changed

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

+16-9
Original file line numberDiff line numberDiff line change
@@ -502,17 +502,24 @@ LogicalResult CastOp::verify() {
502502
}
503503

504504
OpFoldResult CastOp::fold(FoldAdaptor adaptor) {
505-
if (getKind() != mlir::cir::CastKind::integral)
506-
return {};
507505
if (getSrc().getType() != getResult().getType())
508506
return {};
509-
// TODO: for sign differences, it's possible in certain conditions to
510-
// create a new attributes that's capable or representing the source.
511-
SmallVector<mlir::OpFoldResult, 1> foldResults;
512-
auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
513-
if (foldOrder.succeeded() && foldResults[0].is<mlir::Attribute>())
514-
return foldResults[0].get<mlir::Attribute>();
515-
return {};
507+
switch (getKind()) {
508+
case mlir::cir::CastKind::integral: {
509+
// TODO: for sign differences, it's possible in certain conditions to
510+
// create a new attribute that's capable of representing the source.
511+
SmallVector<mlir::OpFoldResult, 1> foldResults;
512+
auto foldOrder = getSrc().getDefiningOp()->fold(foldResults);
513+
if (foldOrder.succeeded() && foldResults[0].is<mlir::Attribute>())
514+
return foldResults[0].get<mlir::Attribute>();
515+
return {};
516+
}
517+
case mlir::cir::CastKind::bitcast: {
518+
return getSrc();
519+
}
520+
default:
521+
return {};
522+
}
516523
}
517524

518525
//===----------------------------------------------------------------------===//

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace {
3434
/// To:
3535
/// ^bb0:
3636
/// cir.return
37-
struct RemoveRedudantBranches : public OpRewritePattern<BrOp> {
37+
struct RemoveRedundantBranches : public OpRewritePattern<BrOp> {
3838
using OpRewritePattern<BrOp>::OpRewritePattern;
3939

4040
LogicalResult matchAndRewrite(BrOp op,
@@ -104,7 +104,7 @@ struct MergeCleanupsPass : public MergeCleanupsBase<MergeCleanupsPass> {
104104
void populateMergeCleanupPatterns(RewritePatternSet &patterns) {
105105
// clang-format off
106106
patterns.add<
107-
RemoveRedudantBranches,
107+
RemoveRedundantBranches,
108108
RemoveEmptyScope,
109109
RemoveEmptySwitch
110110
>(patterns.getContext());
@@ -119,7 +119,9 @@ void MergeCleanupsPass::runOnOperation() {
119119
// Collect operations to apply patterns.
120120
SmallVector<Operation *, 16> ops;
121121
getOperation()->walk([&](Operation *op) {
122-
if (isa<BrOp, BrCondOp, ScopeOp, SwitchOp>(op))
122+
// CastOp here is to perform a manual `fold` in
123+
// applyOpPatternsAndFold
124+
if (isa<BrOp, BrCondOp, ScopeOp, SwitchOp, CastOp>(op))
123125
ops.push_back(op);
124126
});
125127

clang/test/CIR/CodeGen/no-proto-fun-ptr.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ void check_noproto_ptr() {
99
// CHECK: cir.func no_proto @check_noproto_ptr()
1010
// CHECK: [[ALLOC:%.*]] = cir.alloca !cir.ptr<!cir.func<!void ()>>, !cir.ptr<!cir.ptr<!cir.func<!void ()>>>, ["fun", init] {alignment = 8 : i64}
1111
// CHECK: [[GGO:%.*]] = cir.get_global @empty : !cir.ptr<!cir.func<!void ()>>
12-
// CHECK: [[CAST:%.*]] = cir.cast(bitcast, [[GGO]] : !cir.ptr<!cir.func<!void ()>>), !cir.ptr<!cir.func<!void ()>>
13-
// CHECK: cir.store [[CAST]], [[ALLOC]] : !cir.ptr<!cir.func<!void ()>>, !cir.ptr<!cir.ptr<!cir.func<!void ()>>>
12+
// CHECK: cir.store [[GGO]], [[ALLOC]] : !cir.ptr<!cir.func<!void ()>>, !cir.ptr<!cir.ptr<!cir.func<!void ()>>>
1413
// CHECK: cir.return
1514

1615
void empty(void) {}

clang/test/CIR/CodeGen/no-prototype.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ int noProto2();
3636
int test2(int x) {
3737
return noProto2(x);
3838
// CHECK: [[GGO:%.*]] = cir.get_global @noProto2 : !cir.ptr<!cir.func<!s32i (!s32i)>>
39-
// CHECK: [[CAST:%.*]] = cir.cast(bitcast, %3 : !cir.ptr<!cir.func<!s32i (!s32i)>>), !cir.ptr<!cir.func<!s32i (!s32i)>>
40-
// CHECK: {{.*}} = cir.call [[CAST]](%{{[0-9]+}}) : (!cir.ptr<!cir.func<!s32i (!s32i)>>, !s32i) -> !s32i
39+
// CHECK: {{.*}} = cir.call [[GGO]](%{{[0-9]+}}) : (!cir.ptr<!cir.func<!s32i (!s32i)>>, !s32i) -> !s32i
4140
}
4241
int noProto2(int x) { return x; }
4342
// CHECK: cir.func no_proto @noProto2(%arg0: !s32i {{.+}}) -> !s32i

clang/test/CIR/CodeGen/unary.c

+23-7
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,42 @@
11
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -Wno-unused-value -emit-cir %s -o %t.cir
22
// RUN: FileCheck --input-file=%t.cir %s
33

4-
void valueNegation(int i, short s, long l, float f, double d) {
5-
// CHECK: cir.func @valueNegation(
6-
!i;
4+
int valueNegationInt(int i) {
5+
// CHECK: cir.func @valueNegationInt(
6+
return !i;
77
// CHECK: %[[#INT:]] = cir.load %{{[0-9]+}} : !cir.ptr<!s32i>, !s32i
88
// CHECK: %[[#INT_TO_BOOL:]] = cir.cast(int_to_bool, %[[#INT]] : !s32i), !cir.bool
99
// CHECK: = cir.unary(not, %[[#INT_TO_BOOL]]) : !cir.bool, !cir.bool
10-
!s;
10+
}
11+
12+
short valueNegationShort(short s) {
13+
// CHECK: cir.func @valueNegationShort(
14+
return !s;
1115
// CHECK: %[[#SHORT:]] = cir.load %{{[0-9]+}} : !cir.ptr<!s16i>, !s16i
1216
// CHECK: %[[#SHORT_TO_BOOL:]] = cir.cast(int_to_bool, %[[#SHORT]] : !s16i), !cir.bool
1317
// CHECK: = cir.unary(not, %[[#SHORT_TO_BOOL]]) : !cir.bool, !cir.bool
14-
!l;
18+
}
19+
20+
long valueNegationLong(long l) {
21+
// CHECK: cir.func @valueNegationLong(
22+
return !l;
1523
// CHECK: %[[#LONG:]] = cir.load %{{[0-9]+}} : !cir.ptr<!s64i>, !s64i
1624
// CHECK: %[[#LONG_TO_BOOL:]] = cir.cast(int_to_bool, %[[#LONG]] : !s64i), !cir.bool
1725
// CHECK: = cir.unary(not, %[[#LONG_TO_BOOL]]) : !cir.bool, !cir.bool
18-
!f;
26+
}
27+
28+
float valueNegationFloat(float f) {
29+
// CHECK: cir.func @valueNegationFloat(
30+
return !f;
1931
// CHECK: %[[#FLOAT:]] = cir.load %{{[0-9]+}} : !cir.ptr<!cir.float>, !cir.float
2032
// CHECK: %[[#FLOAT_TO_BOOL:]] = cir.cast(float_to_bool, %[[#FLOAT]] : !cir.float), !cir.bool
2133
// CHECK: %[[#FLOAT_NOT:]] = cir.unary(not, %[[#FLOAT_TO_BOOL]]) : !cir.bool, !cir.bool
2234
// CHECK: = cir.cast(bool_to_int, %[[#FLOAT_NOT]] : !cir.bool), !s32i
23-
!d;
35+
}
36+
37+
double valueNegationDouble(double d) {
38+
// CHECK: cir.func @valueNegationDouble(
39+
return !d;
2440
// CHECK: %[[#DOUBLE:]] = cir.load %{{[0-9]+}} : !cir.ptr<!cir.double>, !cir.double
2541
// CHECK: %[[#DOUBLE_TO_BOOL:]] = cir.cast(float_to_bool, %[[#DOUBLE]] : !cir.double), !cir.bool
2642
// CHECK: %[[#DOUBLE_NOT:]] = cir.unary(not, %[[#DOUBLE_TO_BOOL]]) : !cir.bool, !cir.bool

clang/test/CIR/Transforms/merge-cleanups.cir

+9
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,13 @@ module {
117117
// CHECK: cir.return
118118
}
119119

120+
// Should remove redundant bitcasts.
121+
// CHECK-LABEL: @ptrbitcastfold
122+
// CHECK: %[[ARG0:.+]]: !cir.ptr<!s32i>
123+
// CHECK: cir.return %[[ARG0]] : !cir.ptr<!s32i>
124+
cir.func @ptrbitcastfold(%arg0: !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {
125+
%0 = cir.cast(bitcast, %arg0: !cir.ptr<!s32i>), !cir.ptr<!s32i>
126+
cir.return %0 : !cir.ptr<!s32i>
127+
}
128+
120129
}

0 commit comments

Comments
 (0)