| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 | |
| ; RUN: opt -S -passes='inline,instcombine' < %s | FileCheck %s | |
| define float @inline_rec_true_successor(float %x, float %scale) { | |
| ; CHECK-LABEL: define float @inline_rec_true_successor( | |
| ; CHECK-SAME: float [[X:%.*]], float [[SCALE:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] | |
| ; CHECK: [[COMMON_RET18:.*]]: | |
| ; CHECK-NEXT: [[COMMON_RET18_OP:%.*]] = phi float [ [[COMMON_RET18_OP_I:%.*]], %[[INLINE_REC_TRUE_SUCCESSOR_EXIT:.*]] ], [ [[MUL:%.*]], %[[IF_END]] ] | |
| ; CHECK-NEXT: ret float [[COMMON_RET18_OP]] | |
| ; CHECK: [[IF_THEN]]: | |
| ; CHECK-NEXT: br i1 false, label %[[IF_THEN_I:.*]], label %[[IF_END_I:.*]] | |
| ; CHECK: [[IF_THEN_I]]: | |
| ; CHECK-NEXT: br label %[[INLINE_REC_TRUE_SUCCESSOR_EXIT]] | |
| ; CHECK: [[IF_END_I]]: | |
| ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[X]] | |
| ; CHECK-NEXT: [[MUL_I:%.*]] = fmul float [[SCALE]], [[FNEG]] | |
| ; CHECK-NEXT: br label %[[INLINE_REC_TRUE_SUCCESSOR_EXIT]] | |
| ; CHECK: [[INLINE_REC_TRUE_SUCCESSOR_EXIT]]: | |
| ; CHECK-NEXT: [[COMMON_RET18_OP_I]] = phi float [ poison, %[[IF_THEN_I]] ], [ [[MUL_I]], %[[IF_END_I]] ] | |
| ; CHECK-NEXT: br label %[[COMMON_RET18]] | |
| ; CHECK: [[IF_END]]: | |
| ; CHECK-NEXT: [[MUL]] = fmul float [[X]], [[SCALE]] | |
| ; CHECK-NEXT: br label %[[COMMON_RET18]] | |
| ; | |
| entry: | |
| %cmp = fcmp olt float %x, 0.000000e+00 | |
| br i1 %cmp, label %if.then, label %if.end | |
| common.ret18: ; preds = %if.then, %if.end | |
| %common.ret18.op = phi float [ %call, %if.then ], [ %mul, %if.end ] | |
| ret float %common.ret18.op | |
| if.then: ; preds = %entry | |
| %fneg = fneg float %x | |
| %call = tail call float @inline_rec_true_successor(float %fneg, float %scale) | |
| br label %common.ret18 | |
| if.end: ; preds = %entry | |
| %mul = fmul float %x, %scale | |
| br label %common.ret18 | |
| } | |
| ; Same as previous test except that the recursive callsite is in the false successor | |
| define float @inline_rec_false_successor(float %x, float %scale) { | |
| ; CHECK-LABEL: define float @inline_rec_false_successor( | |
| ; CHECK-SAME: float [[Y:%.*]], float [[SCALE:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[Y]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] | |
| ; CHECK: [[COMMON_RET18:.*]]: | |
| ; CHECK-NEXT: [[COMMON_RET18_OP:%.*]] = phi float [ [[MUL:%.*]], %[[IF_THEN]] ], [ [[COMMON_RET18_OP_I:%.*]], %[[INLINE_REC_FALSE_SUCCESSOR_EXIT:.*]] ] | |
| ; CHECK-NEXT: ret float [[COMMON_RET18_OP]] | |
| ; CHECK: [[IF_THEN]]: | |
| ; CHECK-NEXT: [[MUL]] = fmul float [[Y]], [[SCALE]] | |
| ; CHECK-NEXT: br label %[[COMMON_RET18]] | |
| ; CHECK: [[IF_END]]: | |
| ; CHECK-NEXT: br i1 true, label %[[IF_THEN_I:.*]], label %[[IF_END_I:.*]] | |
| ; CHECK: [[IF_THEN_I]]: | |
| ; CHECK-NEXT: [[FNEG:%.*]] = fneg float [[Y]] | |
| ; CHECK-NEXT: [[MUL_I:%.*]] = fmul float [[SCALE]], [[FNEG]] | |
| ; CHECK-NEXT: br label %[[INLINE_REC_FALSE_SUCCESSOR_EXIT]] | |
| ; CHECK: [[IF_END_I]]: | |
| ; CHECK-NEXT: br label %[[INLINE_REC_FALSE_SUCCESSOR_EXIT]] | |
| ; CHECK: [[INLINE_REC_FALSE_SUCCESSOR_EXIT]]: | |
| ; CHECK-NEXT: [[COMMON_RET18_OP_I]] = phi float [ [[MUL_I]], %[[IF_THEN_I]] ], [ poison, %[[IF_END_I]] ] | |
| ; CHECK-NEXT: br label %[[COMMON_RET18]] | |
| ; | |
| entry: | |
| %cmp = fcmp uge float %x, 0.000000e+00 | |
| br i1 %cmp, label %if.then, label %if.end | |
| common.ret18: ; preds = %if.then, %if.end | |
| %common.ret18.op = phi float [ %mul, %if.then ], [ %call, %if.end ] | |
| ret float %common.ret18.op | |
| if.then: ; preds = %entry | |
| %mul = fmul float %x, %scale | |
| br label %common.ret18 | |
| if.end: ; preds = %entry | |
| %fneg = fneg float %x | |
| %call = tail call float @inline_rec_false_successor(float %fneg, float %scale) | |
| br label %common.ret18 | |
| } | |
| ; Test when the BR has Value not cmp instruction | |
| define float @inline_rec_no_cmp(i1 %flag, float %scale) { | |
| ; CHECK-LABEL: define float @inline_rec_no_cmp( | |
| ; CHECK-SAME: i1 [[FLAG:%.*]], float [[SCALE:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br i1 [[FLAG]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] | |
| ; CHECK: [[IF_THEN]]: | |
| ; CHECK-NEXT: [[SUM:%.*]] = fadd float [[SCALE]], 5.000000e+00 | |
| ; CHECK-NEXT: [[SUM1:%.*]] = fadd float [[SUM]], [[SCALE]] | |
| ; CHECK-NEXT: br label %[[COMMON_RET:.*]] | |
| ; CHECK: [[IF_END]]: | |
| ; CHECK-NEXT: [[SUM2:%.*]] = fadd float [[SCALE]], 5.000000e+00 | |
| ; CHECK-NEXT: br label %[[COMMON_RET]] | |
| ; CHECK: [[COMMON_RET]]: | |
| ; CHECK-NEXT: [[COMMON_RET_RES:%.*]] = phi float [ [[SUM1]], %[[IF_THEN]] ], [ [[SUM2]], %[[IF_END]] ] | |
| ; CHECK-NEXT: ret float [[COMMON_RET_RES]] | |
| ; | |
| entry: | |
| br i1 %flag, label %if.then, label %if.end | |
| if.then: | |
| %res = tail call float @inline_rec_no_cmp(i1 false, float %scale) | |
| %sum1 = fadd float %res, %scale | |
| br label %common.ret | |
| if.end: | |
| %sum2 = fadd float %scale, 5.000000e+00 | |
| br label %common.ret | |
| common.ret: | |
| %common.ret.res = phi float [ %sum1, %if.then ], [ %sum2, %if.end ] | |
| ret float %common.ret.res | |
| } | |
| define float @no_inline_rec(float %x, float %scale) { | |
| ; CHECK-LABEL: define float @no_inline_rec( | |
| ; CHECK-SAME: float [[Z:%.*]], float [[SCALE:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[Z]], 5.000000e+00 | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] | |
| ; CHECK: [[COMMON_RET18:.*]]: | |
| ; CHECK-NEXT: [[COMMON_RET18_OP:%.*]] = phi float [ [[FNEG1:%.*]], %[[IF_THEN]] ], [ [[MUL:%.*]], %[[IF_END]] ] | |
| ; CHECK-NEXT: ret float [[COMMON_RET18_OP]] | |
| ; CHECK: [[IF_THEN]]: | |
| ; CHECK-NEXT: [[FADD:%.*]] = fadd float [[Z]], 5.000000e+00 | |
| ; CHECK-NEXT: [[CALL:%.*]] = tail call float @no_inline_rec(float [[FADD]], float [[SCALE]]) | |
| ; CHECK-NEXT: [[FNEG1]] = fneg float [[CALL]] | |
| ; CHECK-NEXT: br label %[[COMMON_RET18]] | |
| ; CHECK: [[IF_END]]: | |
| ; CHECK-NEXT: [[MUL]] = fmul float [[Z]], [[SCALE]] | |
| ; CHECK-NEXT: br label %[[COMMON_RET18]] | |
| ; | |
| entry: | |
| %cmp = fcmp olt float %x, 5.000000e+00 | |
| br i1 %cmp, label %if.then, label %if.end | |
| common.ret18: ; preds = %if.then, %if.end | |
| %common.ret18.op = phi float [ %fneg1, %if.then ], [ %mul, %if.end ] | |
| ret float %common.ret18.op | |
| if.then: ; preds = %entry | |
| %fadd = fadd float %x, 5.000000e+00 | |
| %call = tail call float @no_inline_rec(float %fadd, float %scale) | |
| %fneg1 = fneg float %call | |
| br label %common.ret18 | |
| if.end: ; preds = %entry | |
| %mul = fmul float %x, %scale | |
| br label %common.ret18 | |
| } | |
| ; Test when the icmp can be simplified but the recurison depth is NOT 1, | |
| ; so the recursive call will not be inlined. | |
| define float @no_inline_rec_depth_not_1(float %x, float %scale) { | |
| ; CHECK-LABEL: define float @no_inline_rec_depth_not_1( | |
| ; CHECK-SAME: float [[X:%.*]], float [[SCALE:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[CMP]], label %[[IF_THEN:.*]], label %[[IF_END:.*]] | |
| ; CHECK: [[COMMON_RET18:.*]]: | |
| ; CHECK-NEXT: [[COMMON_RET18_OP:%.*]] = phi float [ [[CALL:%.*]], %[[IF_THEN]] ], [ [[MUL:%.*]], %[[IF_END]] ] | |
| ; CHECK-NEXT: ret float [[COMMON_RET18_OP]] | |
| ; CHECK: [[IF_THEN]]: | |
| ; CHECK-NEXT: [[CALL]] = tail call float @no_inline_rec_depth_not_1(float [[X]], float [[SCALE]]) | |
| ; CHECK-NEXT: br label %[[COMMON_RET18]] | |
| ; CHECK: [[IF_END]]: | |
| ; CHECK-NEXT: [[MUL]] = fmul float [[X]], [[SCALE]] | |
| ; CHECK-NEXT: br label %[[COMMON_RET18]] | |
| ; | |
| entry: | |
| %cmp = fcmp olt float %x, 0.000000e+00 | |
| br i1 %cmp, label %if.then, label %if.end | |
| common.ret18: ; preds = %if.then, %if.end | |
| %common.ret18.op = phi float [ %call, %if.then ], [ %mul, %if.end ] | |
| ret float %common.ret18.op | |
| if.then: ; preds = %entry | |
| %fneg1 = fneg float %x | |
| %fneg = fneg float %fneg1 | |
| %call = tail call float @no_inline_rec_depth_not_1(float %fneg, float %scale) | |
| br label %common.ret18 | |
| if.end: ; preds = %entry | |
| %mul = fmul float %x, %scale | |
| br label %common.ret18 | |
| } | |