; 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 }