From 295ba49330e6ae1d029a0430769c80c0606b0402 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sun, 4 Dec 2022 18:51:57 +0300 Subject: [PATCH] [NFC][SimplifyCFG] Add some tests with PHI's for fold-branch-to-common-dest xform --- .../SimplifyCFG/fold-branch-to-common-dest-phis.ll | 194 +++++++++++++++++++++ .../SimplifyCFG/fold-branch-to-common-dest.ll | 45 +++++ 2 files changed, 239 insertions(+) create mode 100644 llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll diff --git a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll new file mode 100644 index 0000000..b3af7f7 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest-phis.ll @@ -0,0 +1,194 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -bonus-inst-threshold=1 | FileCheck %s --check-prefixes=ALL + +declare void @sideeffect0(i8) +declare void @sideeffect1(i8) +declare void @sideeffect2(i8) +declare i8 @gen8() speculatable + +define void @incompatible_ivs_of_single_phi(i8 %v0, i8 %v1, i8 %iv.of.final_left.from.dispatch, i8 %iv.of.final_right.from.pred, i8 %iv.of.final_right.from.dispatch) { +; ALL-LABEL: @incompatible_ivs_of_single_phi( +; ALL-NEXT: pred: +; ALL-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0 +; ALL-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]] +; ALL: dispatch: +; ALL-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0 +; ALL-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]] +; ALL: common.ret: +; ALL-NEXT: ret void +; ALL: final_left: +; ALL-NEXT: [[FINAL_LEFT_PHI:%.*]] = phi i8 [ [[IV_OF_FINAL_LEFT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect0(i8 [[FINAL_LEFT_PHI]]) +; ALL-NEXT: br label [[COMMON_RET:%.*]] +; ALL: final_right: +; ALL-NEXT: [[FINAL_RIGHT_PHI:%.*]] = phi i8 [ [[IV_OF_FINAL_RIGHT_FROM_PRED:%.*]], [[PRED:%.*]] ], [ [[IV_OF_FINAL_RIGHT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect1(i8 [[FINAL_RIGHT_PHI]]) +; ALL-NEXT: br label [[COMMON_RET]] +; +pred: + %c0 = icmp eq i8 %v0, 0 + br i1 %c0, label %dispatch, label %final_right +dispatch: + %c1 = icmp eq i8 %v1, 0 + br i1 %c1, label %final_left, label %final_right +final_left: + %final_left.phi = phi i8 [ %iv.of.final_left.from.dispatch, %dispatch ] + call void @sideeffect0(i8 %final_left.phi) + ret void +final_right: + %final_right.phi = phi i8 [ %iv.of.final_right.from.pred, %pred ], [ %iv.of.final_right.from.dispatch, %dispatch ] + call void @sideeffect1(i8 %final_right.phi) + ret void +} + +define void @incompatible_ivs_of_single_phi.invert_pred_cond(i8 %v0, i8 %v1, i8 %iv.of.final_left.from.dispatch, i8 %iv.of.final_right.from.pred, i8 %iv.of.final_right.from.dispatch) { +; ALL-LABEL: @incompatible_ivs_of_single_phi.invert_pred_cond( +; ALL-NEXT: pred: +; ALL-NEXT: [[C0:%.*]] = icmp ne i8 [[V0:%.*]], 0 +; ALL-NEXT: br i1 [[C0]], label [[FINAL_RIGHT:%.*]], label [[DISPATCH:%.*]] +; ALL: dispatch: +; ALL-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0 +; ALL-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]] +; ALL: common.ret: +; ALL-NEXT: ret void +; ALL: final_left: +; ALL-NEXT: [[FINAL_LEFT_PHI:%.*]] = phi i8 [ [[IV_OF_FINAL_LEFT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect0(i8 [[FINAL_LEFT_PHI]]) +; ALL-NEXT: br label [[COMMON_RET:%.*]] +; ALL: final_right: +; ALL-NEXT: [[FINAL_RIGHT_PHI:%.*]] = phi i8 [ [[IV_OF_FINAL_RIGHT_FROM_PRED:%.*]], [[PRED:%.*]] ], [ [[IV_OF_FINAL_RIGHT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect1(i8 [[FINAL_RIGHT_PHI]]) +; ALL-NEXT: br label [[COMMON_RET]] +; +pred: + %c0 = icmp ne i8 %v0, 0 + br i1 %c0, label %final_right, label %dispatch +dispatch: + %c1 = icmp eq i8 %v1, 0 + br i1 %c1, label %final_left, label %final_right +final_left: + %final_left.phi = phi i8 [ %iv.of.final_left.from.dispatch, %dispatch ] + call void @sideeffect0(i8 %final_left.phi) + ret void +final_right: + %final_right.phi = phi i8 [ %iv.of.final_right.from.pred, %pred ], [ %iv.of.final_right.from.dispatch, %dispatch ] + call void @sideeffect1(i8 %final_right.phi) + ret void +} + +define void @incompatible_ivs_of_single_phi.insertpos(i8 %v0, i8 %v1, i8 %iv.of.final_left.from.dispatch) { +; ALL-LABEL: @incompatible_ivs_of_single_phi.insertpos( +; ALL-NEXT: pred: +; ALL-NEXT: [[IV_OF_FINAL_RIGHT_FROM_PRED:%.*]] = call i8 @gen8() +; ALL-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0 +; ALL-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]] +; ALL: dispatch: +; ALL-NEXT: [[IV_OF_FINAL_RIGHT_FROM_DISPATCH:%.*]] = call i8 @gen8() +; ALL-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0 +; ALL-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]] +; ALL: common.ret: +; ALL-NEXT: ret void +; ALL: final_left: +; ALL-NEXT: [[FINAL_LEFT_PHI:%.*]] = phi i8 [ [[IV_OF_FINAL_LEFT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect0(i8 [[FINAL_LEFT_PHI]]) +; ALL-NEXT: br label [[COMMON_RET:%.*]] +; ALL: final_right: +; ALL-NEXT: [[FINAL_RIGHT_PHI:%.*]] = phi i8 [ [[IV_OF_FINAL_RIGHT_FROM_PRED]], [[PRED:%.*]] ], [ [[IV_OF_FINAL_RIGHT_FROM_DISPATCH]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect1(i8 [[FINAL_RIGHT_PHI]]) +; ALL-NEXT: br label [[COMMON_RET]] +; +pred: + %iv.of.final_right.from.pred = call i8 @gen8() + %c0 = icmp eq i8 %v0, 0 + br i1 %c0, label %dispatch, label %final_right +dispatch: + %iv.of.final_right.from.dispatch = call i8 @gen8() + %c1 = icmp eq i8 %v1, 0 + br i1 %c1, label %final_left, label %final_right +final_left: + %final_left.phi = phi i8 [ %iv.of.final_left.from.dispatch, %dispatch ] + call void @sideeffect0(i8 %final_left.phi) + ret void +final_right: + %final_right.phi = phi i8 [ %iv.of.final_right.from.pred, %pred ], [ %iv.of.final_right.from.dispatch, %dispatch ] + call void @sideeffect1(i8 %final_right.phi) + ret void +} + +define void @incompatible_ivs_of_one_of_two_phis(i8 %v0, i8 %v1, i8 %iv.of.final_left.from.dispatch, i8 %iv.of.final_right.from.pred, i8 %iv.of.final_right.from.dispatch) { +; ALL-LABEL: @incompatible_ivs_of_one_of_two_phis( +; ALL-NEXT: pred: +; ALL-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0 +; ALL-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]] +; ALL: dispatch: +; ALL-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0 +; ALL-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]] +; ALL: common.ret: +; ALL-NEXT: ret void +; ALL: final_left: +; ALL-NEXT: [[FINAL_LEFT_PHI:%.*]] = phi i8 [ [[IV_OF_FINAL_LEFT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect0(i8 [[FINAL_LEFT_PHI]]) +; ALL-NEXT: br label [[COMMON_RET:%.*]] +; ALL: final_right: +; ALL-NEXT: [[FINAL_RIGHT_PHI_0:%.*]] = phi i8 [ [[IV_OF_FINAL_RIGHT_FROM_PRED:%.*]], [[PRED:%.*]] ], [ [[IV_OF_FINAL_RIGHT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: [[FINAL_RIGHT_PHI_1:%.*]] = phi i8 [ 42, [[PRED]] ], [ 42, [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect1(i8 [[FINAL_RIGHT_PHI_0]]) +; ALL-NEXT: call void @sideeffect1(i8 [[FINAL_RIGHT_PHI_1]]) +; ALL-NEXT: br label [[COMMON_RET]] +; +pred: + %c0 = icmp eq i8 %v0, 0 + br i1 %c0, label %dispatch, label %final_right +dispatch: + %c1 = icmp eq i8 %v1, 0 + br i1 %c1, label %final_left, label %final_right +final_left: + %final_left.phi = phi i8 [ %iv.of.final_left.from.dispatch, %dispatch ] + call void @sideeffect0(i8 %final_left.phi) + ret void +final_right: + %final_right.phi.0 = phi i8 [ %iv.of.final_right.from.pred, %pred ], [ %iv.of.final_right.from.dispatch, %dispatch ] + %final_right.phi.1 = phi i8 [ 42, %pred ], [ 42, %dispatch ] + call void @sideeffect1(i8 %final_right.phi.0) + call void @sideeffect1(i8 %final_right.phi.1) + ret void +} + +define void @incompatible_ivs_of_two_phis(i8 %v0, i8 %v1, i8 %iv.of.final_left.from.dispatch, i8 %iv0.of.final_right.from.pred, i8 %iv0.of.final_right.from.dispatch, i8 %iv1.of.final_right.from.pred, i8 %iv1.of.final_right.from.dispatch) { +; ALL-LABEL: @incompatible_ivs_of_two_phis( +; ALL-NEXT: pred: +; ALL-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0 +; ALL-NEXT: br i1 [[C0]], label [[DISPATCH:%.*]], label [[FINAL_RIGHT:%.*]] +; ALL: dispatch: +; ALL-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0 +; ALL-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT]] +; ALL: common.ret: +; ALL-NEXT: ret void +; ALL: final_left: +; ALL-NEXT: [[FINAL_LEFT_PHI:%.*]] = phi i8 [ [[IV_OF_FINAL_LEFT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect0(i8 [[FINAL_LEFT_PHI]]) +; ALL-NEXT: br label [[COMMON_RET:%.*]] +; ALL: final_right: +; ALL-NEXT: [[FINAL_RIGHT_PHI_0:%.*]] = phi i8 [ [[IV0_OF_FINAL_RIGHT_FROM_PRED:%.*]], [[PRED:%.*]] ], [ [[IV0_OF_FINAL_RIGHT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: [[FINAL_RIGHT_PHI_1:%.*]] = phi i8 [ [[IV1_OF_FINAL_RIGHT_FROM_PRED:%.*]], [[PRED]] ], [ [[IV1_OF_FINAL_RIGHT_FROM_DISPATCH:%.*]], [[DISPATCH]] ] +; ALL-NEXT: call void @sideeffect1(i8 [[FINAL_RIGHT_PHI_0]]) +; ALL-NEXT: call void @sideeffect1(i8 [[FINAL_RIGHT_PHI_1]]) +; ALL-NEXT: br label [[COMMON_RET]] +; +pred: + %c0 = icmp eq i8 %v0, 0 + br i1 %c0, label %dispatch, label %final_right +dispatch: + %c1 = icmp eq i8 %v1, 0 + br i1 %c1, label %final_left, label %final_right +final_left: + %final_left.phi = phi i8 [ %iv.of.final_left.from.dispatch, %dispatch ] + call void @sideeffect0(i8 %final_left.phi) + ret void +final_right: + %final_right.phi.0 = phi i8 [ %iv0.of.final_right.from.pred, %pred ], [ %iv0.of.final_right.from.dispatch, %dispatch ] + %final_right.phi.1 = phi i8 [ %iv1.of.final_right.from.pred, %pred ], [ %iv1.of.final_right.from.dispatch, %dispatch ] + call void @sideeffect1(i8 %final_right.phi.0) + call void @sideeffect1(i8 %final_right.phi.1) + ret void +} diff --git a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll index d594596..0c3914c 100644 --- a/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll +++ b/llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll @@ -1117,4 +1117,49 @@ cleanup: ret i32 %retval.0 } +define i32 @test_builtin_fpclassify(float %x) { +; CHECK-LABEL: @test_builtin_fpclassify( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[ISZERO:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00 +; CHECK-NEXT: br i1 [[ISZERO]], label [[FPCLASSIFY_END:%.*]], label [[FPCLASSIFY_NOT_ZERO:%.*]] +; CHECK: fpclassify_end: +; CHECK-NEXT: [[FPCLASSIFY_RESULT:%.*]] = phi i32 [ 2, [[ENTRY:%.*]] ], [ 0, [[FPCLASSIFY_NOT_ZERO]] ], [ 1, [[FPCLASSIFY_NOT_NAN:%.*]] ], [ [[NORMAL_OR_SUBNORMAL:%.*]], [[FPCLASSIFY_NOT_INF:%.*]] ] +; CHECK-NEXT: ret i32 [[FPCLASSIFY_RESULT]] +; CHECK: fpclassify_not_zero: +; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X]], 0.000000e+00 +; CHECK-NEXT: br i1 [[CMP]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_NAN]] +; CHECK: fpclassify_not_nan: +; CHECK-NEXT: [[X_ABS:%.*]] = tail call float @llvm.fabs.f32(float [[X]]) +; CHECK-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X_ABS]], 0x7FF0000000000000 +; CHECK-NEXT: br i1 [[ISINF]], label [[FPCLASSIFY_END]], label [[FPCLASSIFY_NOT_INF]] +; CHECK: fpclassify_not_inf: +; CHECK-NEXT: [[ISNORMAL:%.*]] = fcmp uge float [[X_ABS]], 0x3810000000000000 +; CHECK-NEXT: [[NORMAL_OR_SUBNORMAL]] = select i1 [[ISNORMAL]], i32 4, i32 3 +; CHECK-NEXT: br label [[FPCLASSIFY_END]] +; +entry: + %iszero = fcmp oeq float %x, 0.000000e+00 + br i1 %iszero, label %fpclassify_end, label %fpclassify_not_zero + +fpclassify_end: + %fpclassify_result = phi i32 [ 2, %entry ], [ 0, %fpclassify_not_zero ], [ 1, %fpclassify_not_nan ], [ %normal_or_subnormal, %fpclassify_not_inf ] + ret i32 %fpclassify_result + +fpclassify_not_zero: + %cmp = fcmp uno float %x, 0.000000e+00 + br i1 %cmp, label %fpclassify_end, label %fpclassify_not_nan + +fpclassify_not_nan: + %x.abs = tail call float @llvm.fabs.f32(float %x) + %isinf = fcmp oeq float %x.abs, 0x7FF0000000000000 + br i1 %isinf, label %fpclassify_end, label %fpclassify_not_inf + +fpclassify_not_inf: + %isnormal = fcmp uge float %x.abs, 0x3810000000000000 + %normal_or_subnormal = select i1 %isnormal, i32 4, i32 3 + br label %fpclassify_end +} + +declare float @llvm.fabs.f32(float) + attributes #0 = { nounwind argmemonly speculatable } -- 2.7.4