| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt -S -passes=instcombine < %s | FileCheck %s | |
| declare nofpclass(inf norm sub zero) float @nan_only() | |
| define nofpclass(nan) half @ret_phi_if_ret_0(i1 %cond1, i1 %cond2, half %unknown) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_phi_if_ret_0( | |
| ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], half [[UNKNOWN:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br i1 [[COND1]], label %[[IF:.*]], label %[[RET:.*]] | |
| ; CHECK: [[IF]]: | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[UNKNOWN]], %[[IF]] ], [ 0.000000e+00, %[[ENTRY]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| br i1 %cond1, label %if, label %ret | |
| if: | |
| %select = select i1 %cond2, half 0xH7E00, half %unknown | |
| br label %ret | |
| ret: | |
| %phi = phi half [ %select, %if ], [ 0.0, %entry ] | |
| ret half %phi | |
| } | |
| define nofpclass(nan inf norm sub nzero) half @ret_phi_only_pzero(i1 %cond1, i1 %cond2, half %unknown) { | |
| ; CHECK-LABEL: define nofpclass(nan inf nzero sub norm) half @ret_phi_only_pzero( | |
| ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], half [[UNKNOWN:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br i1 [[COND1]], label %[[IF:.*]], label %[[RET:.*]] | |
| ; CHECK: [[IF]]: | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half 0.000000e+00 | |
| ; | |
| entry: | |
| br i1 %cond1, label %if, label %ret | |
| if: | |
| %select = select i1 %cond2, half 0xH7E00, half %unknown | |
| br label %ret | |
| ret: | |
| %phi = phi half [ %select, %if ], [ 0.0, %entry ] | |
| ret half %phi | |
| } | |
| define nofpclass(inf norm sub zero) half @ret_phi_only_nan(i1 %cond1, i1 %cond2, half %unknown) { | |
| ; CHECK-LABEL: define nofpclass(inf zero sub norm) half @ret_phi_only_nan( | |
| ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], half [[UNKNOWN:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br i1 [[COND1]], label %[[IF:.*]], label %[[RET:.*]] | |
| ; CHECK: [[IF]]: | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND2]], half +qnan, half [[UNKNOWN]] | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[SELECT]], %[[IF]] ], [ poison, %[[ENTRY]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| br i1 %cond1, label %if, label %ret | |
| if: | |
| %select = select i1 %cond2, half 0xH7E00, half %unknown | |
| br label %ret | |
| ret: | |
| %phi = phi half [ %select, %if ], [ 0.0, %entry ] | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @ret_phi_if_ret_1(i1 %cond1, i1 %cond2, half %unknown) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_phi_if_ret_1( | |
| ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], half [[UNKNOWN:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br i1 [[COND1]], label %[[IF:.*]], label %[[RET:.*]] | |
| ; CHECK: [[IF]]: | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ 0.000000e+00, %[[ENTRY]] ], [ [[UNKNOWN]], %[[IF]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| br i1 %cond1, label %if, label %ret | |
| if: | |
| %select = select i1 %cond2, half 0xH7E00, half %unknown | |
| br label %ret | |
| ret: | |
| %phi = phi half [ 0.0, %entry ], [ %select, %if ] | |
| ret half %phi | |
| } | |
| ; Make sure all block references use the same simplified value. | |
| define nofpclass(nan) half @ret_repeated_switch_pred(i8 %switch.cond, i1 %cond2, half %unknown) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_repeated_switch_pred( | |
| ; CHECK-SAME: i8 [[SWITCH_COND:%.*]], i1 [[COND2:%.*]], half [[UNKNOWN:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: switch i8 [[SWITCH_COND]], label %[[DEFAULT:.*]] [ | |
| ; CHECK-NEXT: i8 0, label %[[RET:.*]] | |
| ; CHECK-NEXT: i8 1, label %[[RET]] | |
| ; CHECK-NEXT: i8 2, label %[[IF:.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[IF]]: | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[DEFAULT]]: | |
| ; CHECK-NEXT: unreachable | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ 0.000000e+00, %[[IF]] ], [ [[UNKNOWN]], %[[ENTRY]] ], [ [[UNKNOWN]], %[[ENTRY]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| %select = select i1 %cond2, half 0xH7E00, half %unknown | |
| switch i8 %switch.cond, label %default | |
| [ i8 0, label %ret | |
| i8 1, label %ret | |
| i8 2, label %if | |
| ] | |
| if: | |
| br label %ret | |
| default: | |
| unreachable | |
| ret: | |
| %phi = phi half [ 0.0, %if ], [ %select, %entry ], [ %select, %entry ] | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @ret_phi_chain(i1 %cond1, i1 %cond2, i1 %cond3, half %unknown) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_phi_chain( | |
| ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], i1 [[COND3:%.*]], half [[UNKNOWN:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br i1 [[COND1]], label %[[IF0:.*]], label %[[IF1:.*]] | |
| ; CHECK: [[IF0]]: | |
| ; CHECK-NEXT: br i1 [[COND2]], label %[[IF1]], label %[[RET:.*]] | |
| ; CHECK: [[IF1]]: | |
| ; CHECK-NEXT: [[PHI0:%.*]] = phi half [ [[UNKNOWN]], %[[IF0]] ], [ 0.000000e+00, %[[ENTRY]] ] | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI1:%.*]] = phi half [ [[PHI0]], %[[IF1]] ], [ 0.000000e+00, %[[IF0]] ] | |
| ; CHECK-NEXT: ret half [[PHI1]] | |
| ; | |
| entry: | |
| br i1 %cond1, label %if0, label %if1 | |
| if0: | |
| %select0 = select i1 %cond2, half 0xH7E00, half %unknown | |
| br i1 %cond2, label %if1, label %ret | |
| if1: | |
| %phi0 = phi half [ %select0, %if0 ], [ 0.0, %entry ] | |
| br label %ret | |
| ret: | |
| %phi1 = phi half [ %phi0, %if1 ], [ 0.0, %if0 ] | |
| ret half %phi1 | |
| } | |
| define nofpclass(nan) half @basic_loop_break_entry_block(i1 %cond1, i1 %cond2, half %unknown, ptr %p0, ptr %p1) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @basic_loop_break_entry_block( | |
| ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], half [[UNKNOWN:%.*]], ptr [[P0:%.*]], ptr [[P1:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[LOOP:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[LOAD:%.*]], %[[LOOP]] ], [ [[UNKNOWN]], %[[ENTRY]] ] | |
| ; CHECK-NEXT: [[LOAD]] = load half, ptr [[P1]], align 2 | |
| ; CHECK-NEXT: [[BREAK_COND:%.*]] = load i1, ptr [[P0]], align 1 | |
| ; CHECK-NEXT: br i1 [[BREAK_COND]], label %[[RET:.*]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| %select = select i1 %cond2, half 0xH7E00, half %unknown | |
| br label %loop | |
| loop: | |
| %phi = phi half [ %load, %loop ], [ %select, %entry ] | |
| %load = load half, ptr %p1 | |
| %break.cond = load i1, ptr %p0 | |
| br i1 %break.cond, label %ret, label %loop | |
| ret: | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @basic_loop_break_mid_loop(i1 %cond1, i1 %cond2, half %unknown, ptr %p0, ptr %p1) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @basic_loop_break_mid_loop( | |
| ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], half [[UNKNOWN:%.*]], ptr [[P0:%.*]], ptr [[P1:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[LOOP:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[LOAD:%.*]], %[[LOOP]] ], [ 0.000000e+00, %[[ENTRY]] ] | |
| ; CHECK-NEXT: [[LOAD]] = load half, ptr [[P1]], align 2 | |
| ; CHECK-NEXT: [[BREAK_COND:%.*]] = load i1, ptr [[P0]], align 1 | |
| ; CHECK-NEXT: br i1 [[BREAK_COND]], label %[[RET:.*]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %phi = phi half [ %select, %loop ], [ 0.0, %entry ] | |
| %load = load half, ptr %p1 | |
| %select = select i1 %cond2, half 0xH7E00, half %load | |
| %break.cond = load i1, ptr %p0 | |
| br i1 %break.cond, label %ret, label %loop | |
| ret: | |
| ret half %phi | |
| } | |
| define nofpclass(inf) half @recurrence(i1 %select.cond, half %unknown, ptr %p0, ptr %p1) { | |
| ; CHECK-LABEL: define nofpclass(inf) half @recurrence( | |
| ; CHECK-SAME: i1 [[SELECT_COND:%.*]], half [[UNKNOWN:%.*]], ptr [[P0:%.*]], ptr [[P1:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[LOOP:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[LOAD:%.*]], %[[LOOP]] ], [ 0.000000e+00, %[[ENTRY]] ] | |
| ; CHECK-NEXT: [[LOAD]] = load half, ptr [[P1]], align 2 | |
| ; CHECK-NEXT: [[BREAK_COND:%.*]] = load i1, ptr [[P0]], align 1 | |
| ; CHECK-NEXT: br i1 [[BREAK_COND]], label %[[RET:.*]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %phi = phi half [ %select, %loop ], [ 0.0, %entry ] | |
| %load = load half, ptr %p1 | |
| %select = select i1 %select.cond, half 0xH7C00, half %load | |
| %break.cond = load i1, ptr %p0 | |
| br i1 %break.cond, label %ret, label %loop | |
| ret: | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @path_dependent(i1 %select.cond, half %unknown, half %x) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @path_dependent( | |
| ; CHECK-SAME: i1 [[SELECT_COND:%.*]], half [[UNKNOWN:%.*]], half [[X:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno half [[X]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[IS_NAN]], label %[[IF:.*]], label %[[RET:.*]] | |
| ; CHECK: [[IF]]: | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[UNKNOWN]], %[[IF]] ], [ 0.000000e+00, %[[ENTRY]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| %is.nan = fcmp uno half %x, 0.0 | |
| br i1 %is.nan, label %if, label %ret | |
| if: | |
| %select = select i1 %select.cond, half %x, half %unknown | |
| br label %ret | |
| ret: | |
| %phi = phi half [ %select, %if ], [ 0.0, %entry ] | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @path_dependent_wrong(i1 %select.cond, half %unknown, half %x) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @path_dependent_wrong( | |
| ; CHECK-SAME: i1 [[SELECT_COND:%.*]], half [[UNKNOWN:%.*]], half [[X:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: [[IS_NOT_NAN:%.*]] = fcmp ord half [[X]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[IS_NOT_NAN]], label %[[IF:.*]], label %[[RET:.*]] | |
| ; CHECK: [[IF]]: | |
| ; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[SELECT_COND]], half [[X]], half [[UNKNOWN]] | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[SELECT]], %[[IF]] ], [ 0.000000e+00, %[[ENTRY]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| %is.not.nan = fcmp ord half %x, 0.0 | |
| br i1 %is.not.nan, label %if, label %ret | |
| if: | |
| %select = select i1 %select.cond, half %x, half %unknown | |
| br label %ret | |
| ret: | |
| %phi = phi half [ %select, %if ], [ 0.0, %entry ] | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @diamond_same_select(i1 %select.cond, half %unknown, half %x) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @diamond_same_select( | |
| ; CHECK-SAME: i1 [[SELECT_COND:%.*]], half [[UNKNOWN:%.*]], half [[X:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno half [[X]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[IS_NAN]], label %[[IF:.*]], label %[[ELSE:.*]] | |
| ; CHECK: [[IF]]: | |
| ; CHECK-NEXT: br label %[[ENDIF:.*]] | |
| ; CHECK: [[ELSE]]: | |
| ; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[SELECT_COND]], half [[X]], half [[UNKNOWN]] | |
| ; CHECK-NEXT: br label %[[ENDIF]] | |
| ; CHECK: [[ENDIF]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[UNKNOWN]], %[[IF]] ], [ [[SELECT1]], %[[ELSE]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| %is.nan = fcmp uno half %x, 0.0 | |
| br i1 %is.nan, label %if, label %else | |
| if: | |
| %select0 = select i1 %select.cond, half %x, half %unknown | |
| br label %endif | |
| else: | |
| %select1 = select i1 %select.cond, half %x, half %unknown | |
| br label %endif | |
| endif: | |
| %phi = phi half [ %select0, %if ], [ %select1, %else ] | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @remove_nan_start_value(ptr %p0, ptr %p1) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @remove_nan_start_value( | |
| ; CHECK-SAME: ptr [[P0:%.*]], ptr [[P1:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[LOOP:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[LOAD:%.*]], %[[LOOP]] ], [ poison, %[[ENTRY]] ] | |
| ; CHECK-NEXT: [[LOAD]] = load half, ptr [[P1]], align 2 | |
| ; CHECK-NEXT: [[BREAK_COND:%.*]] = load i1, ptr [[P0]], align 1 | |
| ; CHECK-NEXT: br i1 [[BREAK_COND]], label %[[RET:.*]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %phi = phi half [ %load, %loop ], [ 0xH7E00, %entry ] | |
| %load = load half, ptr %p1 | |
| %break.cond = load i1, ptr %p0 | |
| br i1 %break.cond, label %ret, label %loop | |
| ret: | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @keep_nan_start_value_multi_use(i1 %cond1, i1 %cond2, ptr %p0, ptr %p1) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @keep_nan_start_value_multi_use( | |
| ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], ptr [[P0:%.*]], ptr [[P1:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[LOOP:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[LOAD:%.*]], %[[LOOP]] ], [ +qnan, %[[ENTRY]] ] | |
| ; CHECK-NEXT: [[LOAD]] = load half, ptr [[P1]], align 2 | |
| ; CHECK-NEXT: [[BREAK_COND:%.*]] = load i1, ptr [[P0]], align 1 | |
| ; CHECK-NEXT: br i1 [[BREAK_COND]], label %[[RET:.*]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: store half [[PHI]], ptr [[P0]], align 2 | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %phi = phi half [ %load, %loop ], [ 0xH7E00, %entry ] | |
| %load = load half, ptr %p1 | |
| %break.cond = load i1, ptr %p0 | |
| br i1 %break.cond, label %ret, label %loop | |
| ret: | |
| store half %phi, ptr %p0 | |
| ret half %phi | |
| } | |
| ; TODO: Why doesn't this fold to ret poison? | |
| define nofpclass(nan) half @loop_break_if_nan(ptr %p0) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @loop_break_if_nan( | |
| ; CHECK-SAME: ptr [[P0:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br label %[[LOOP:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[LOAD:%.*]], %[[LOOP]] ], [ poison, %[[ENTRY]] ] | |
| ; CHECK-NEXT: [[LOAD]] = load half, ptr [[P0]], align 2 | |
| ; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno half [[LOAD]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[IS_NAN]], label %[[RET:.*]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %phi = phi half [ %load, %loop ], [ 0xH7E00, %entry ] | |
| %load = load half, ptr %p0 | |
| %is.nan = fcmp uno half %load, 0.0 | |
| br i1 %is.nan, label %ret, label %loop | |
| ret: | |
| ret half %phi | |
| } | |
| define nofpclass(nan) half @loop_break_if_nan_abs(ptr %p0) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @loop_break_if_nan_abs( | |
| ; CHECK-SAME: ptr [[P0:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br label %[[LOOP:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[LOAD:%.*]] = load half, ptr [[P0]], align 2 | |
| ; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno half [[LOAD]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[IS_NAN]], label %[[RET:.*]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half poison | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %phi = phi half [ %load, %loop ], [ 0xH7E00, %entry ] | |
| %load = load half, ptr %p0 | |
| %abs = call half @llvm.fabs.f16(half %load) | |
| %is.nan = fcmp uno half %load, 0.0 | |
| br i1 %is.nan, label %ret, label %loop | |
| ret: | |
| ret half %abs | |
| } | |
| define nofpclass(nan) half @ret_loop_under_if_phi(half %unknown, i1 %cond, i1 %cond2, ptr %p0, ptr %p1) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_loop_under_if_phi( | |
| ; CHECK-SAME: half [[UNKNOWN:%.*]], i1 [[COND:%.*]], i1 [[COND2:%.*]], ptr [[P0:%.*]], ptr [[P1:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br i1 [[COND]], label %[[LOOP:.*]], label %[[RET:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[LOOP_COND:%.*]] = load i1, ptr [[P1]], align 1 | |
| ; CHECK-NEXT: br i1 [[LOOP_COND]], label %[[RET]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half [[UNKNOWN]] | |
| ; | |
| entry: | |
| %entry.select = select i1 %cond2, half 0xH7E00, half %unknown | |
| br i1 %cond, label %loop, label %ret | |
| loop: | |
| %loop.phi = phi half [ %loop.select, %loop ], [ 0xH7E00, %entry ] | |
| %loop.select = select i1 %cond2, half 0xH7E00, half %unknown | |
| %loop.cond = load i1, ptr %p1 | |
| br i1 %loop.cond, label %ret, label %loop | |
| ret: | |
| %outer.phi = phi half [ 0xH7E00, %entry ], [ %loop.phi, %loop ] | |
| ret half %outer.phi | |
| } | |
| define nofpclass(nan) half @assume_in_loop(half %assumed.nan.in.loop, half %unknown, i1 %cond, i1 %cond2, ptr %p0, ptr %p1) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @assume_in_loop( | |
| ; CHECK-SAME: half [[ASSUMED_NAN_IN_LOOP:%.*]], half [[UNKNOWN:%.*]], i1 [[COND:%.*]], i1 [[COND2:%.*]], ptr [[P0:%.*]], ptr [[P1:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: br i1 [[COND]], label %[[LOOP:.*]], label %[[RET:.*]] | |
| ; CHECK: [[LOOP]]: | |
| ; CHECK-NEXT: [[LOOP_PHI:%.*]] = phi half [ [[UNKNOWN]], %[[LOOP]] ], [ [[ASSUMED_NAN_IN_LOOP]], %[[ENTRY]] ] | |
| ; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno half [[ASSUMED_NAN_IN_LOOP]], 0.000000e+00 | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[IS_NAN]]) | |
| ; CHECK-NEXT: [[LOOP_COND:%.*]] = load i1, ptr [[P1]], align 1 | |
| ; CHECK-NEXT: br i1 [[LOOP_COND]], label %[[RET]], label %[[LOOP]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[OUTER_PHI:%.*]] = phi half [ [[ASSUMED_NAN_IN_LOOP]], %[[ENTRY]] ], [ [[LOOP_PHI]], %[[LOOP]] ] | |
| ; CHECK-NEXT: ret half [[OUTER_PHI]] | |
| ; | |
| entry: | |
| br i1 %cond, label %loop, label %ret | |
| loop: | |
| %loop.phi = phi half [ %loop.select, %loop ], [ %assumed.nan.in.loop, %entry ] | |
| %is.nan = fcmp uno half %assumed.nan.in.loop, 0.0 | |
| call void @llvm.assume(i1 %is.nan) | |
| %loop.select = select i1 %cond2, half %assumed.nan.in.loop, half %unknown | |
| %loop.cond = load i1, ptr %p1 | |
| br i1 %loop.cond, label %ret, label %loop | |
| ret: | |
| %outer.phi = phi half [ %assumed.nan.in.loop, %entry ], [ %loop.phi, %loop ] | |
| ret half %outer.phi | |
| } | |
| define nofpclass(nan) half @ret_phi_nan_check(half %checked.if.nan, half %unknown, i1 %cond) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @ret_phi_nan_check( | |
| ; CHECK-SAME: half [[CHECKED_IF_NAN:%.*]], half [[UNKNOWN:%.*]], i1 [[COND:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno half [[CHECKED_IF_NAN]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[IS_NAN]], label %[[IF_NAN:.*]], label %[[RET:.*]] | |
| ; CHECK: [[IF_NAN]]: | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[CHECKED_IF_NAN]], %[[ENTRY]] ], [ [[UNKNOWN]], %[[IF_NAN]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| %is.nan = fcmp uno half %checked.if.nan, 0.0 | |
| br i1 %is.nan, label %if_nan, label %ret | |
| if_nan: | |
| %select = select i1 %cond, half %checked.if.nan, half %unknown | |
| br label %ret | |
| ret: | |
| %phi = phi half [ %checked.if.nan, %entry ], [ %select, %if_nan ] | |
| ret half %phi | |
| } | |
| define nofpclass(nan inf) half @edge_case_if_chain(half %x, i1 %cond, ptr %p0, ptr %p1, ptr %p2) { | |
| ; CHECK-LABEL: define nofpclass(nan inf) half @edge_case_if_chain( | |
| ; CHECK-SAME: half [[X:%.*]], i1 [[COND:%.*]], ptr [[P0:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: [[IS_INF:%.*]] = fcmp oeq half [[X]], +inf | |
| ; CHECK-NEXT: br i1 [[IS_INF]], label %[[IS_INF:.*]], label %[[ELSE:.*]] | |
| ; CHECK: [[IS_INF]]: | |
| ; CHECK-NEXT: [[LOAD0:%.*]] = load half, ptr [[P0]], align 2 | |
| ; CHECK-NEXT: br label %[[RET:.*]] | |
| ; CHECK: [[ELSE]]: | |
| ; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno half [[X]], 0.000000e+00 | |
| ; CHECK-NEXT: [[LOAD1:%.*]] = load half, ptr [[P0]], align 2 | |
| ; CHECK-NEXT: [[VAL1:%.*]] = select i1 [[COND]], half [[LOAD1]], half [[X]] | |
| ; CHECK-NEXT: br i1 [[IS_NAN]], label %[[IS_NAN:.*]], label %[[RET]] | |
| ; CHECK: [[IS_NAN]]: | |
| ; CHECK-NEXT: [[LOAD2:%.*]] = load half, ptr [[P2]], align 2 | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[LOAD0]], %[[IS_INF]] ], [ [[VAL1]], %[[ELSE]] ], [ [[LOAD2]], %[[IS_NAN]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| %is.inf = fcmp oeq half %x, 0xH7C00 | |
| br i1 %is.inf, label %is_inf, label %else | |
| is_inf: | |
| %load0 = load half, ptr %p0 | |
| %val0 = select i1 %cond, half %x, half %load0 | |
| br label %ret | |
| else: | |
| %is.nan = fcmp uno half %x, 0.0 | |
| %load1 = load half, ptr %p0 | |
| %val1 = select i1 %cond, half %load1, half %x | |
| br i1 %is.nan, label %is_nan, label %ret | |
| is_nan: | |
| %load2 = load half, ptr %p2 | |
| %val2 = select i1 %cond, half %x, half %load2 | |
| br label %ret | |
| ret: | |
| %phi = phi half [ %val0, %is_inf ], [ %val1, %else ], [ %val2, %is_nan ] | |
| ret half %phi | |
| } | |
| ; Fold the %is_nan input value to %unknown, though the select is | |
| ; defined in a different block. | |
| define nofpclass(nan) half @evaluate_phi_input_at_incoming_edge(half %known.nan.in.branch, half %unknown, i1 %cond) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @evaluate_phi_input_at_incoming_edge( | |
| ; CHECK-SAME: half [[KNOWN_NAN_IN_BRANCH:%.*]], half [[UNKNOWN:%.*]], i1 [[COND:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: [[IS_NAN:%.*]] = fcmp uno half [[KNOWN_NAN_IN_BRANCH]], 0.000000e+00 | |
| ; CHECK-NEXT: br i1 [[IS_NAN]], label %[[IS_NAN:.*]], label %[[RET:.*]] | |
| ; CHECK: [[IS_NAN]]: | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi half [ [[KNOWN_NAN_IN_BRANCH]], %[[ENTRY]] ], [ [[UNKNOWN]], %[[IS_NAN]] ] | |
| ; CHECK-NEXT: ret half [[PHI]] | |
| ; | |
| entry: | |
| %entry.select = select i1 %cond, half %known.nan.in.branch, half %unknown | |
| %is.nan = fcmp uno half %known.nan.in.branch, 0.0 | |
| br i1 %is.nan, label %is_nan, label %ret | |
| is_nan: | |
| br label %ret | |
| ret: | |
| %phi = phi half [ %known.nan.in.branch, %entry ], [ %entry.select, %is_nan ] | |
| ret half %phi | |
| } | |
| ; This phi should fold out into a ret 0. This depends on trying to | |
| ; simplify both phi inputs at once, with the predecessor terminator as | |
| ; the context. | |
| define nofpclass(nan) half @multi_simplify_lost_phi_context_(half %x, half %y, i1 %cond0, i1 %cond1, i1 %cond2) { | |
| ; CHECK-LABEL: define nofpclass(nan) half @multi_simplify_lost_phi_context_( | |
| ; CHECK-SAME: half [[X:%.*]], half [[Y:%.*]], i1 [[COND0:%.*]], i1 [[COND1:%.*]], i1 [[COND2:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: br i1 [[COND0]], label %[[ASSUME_A:.*]], label %[[ASSUME_B:.*]] | |
| ; CHECK: [[ASSUME_A]]: | |
| ; CHECK-NEXT: [[X_IS_NAN:%.*]] = fcmp uno half [[X]], 0.000000e+00 | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NAN]]) | |
| ; CHECK-NEXT: br label %[[A:.*]] | |
| ; CHECK: [[A]]: | |
| ; CHECK-NEXT: br label %[[RET:.*]] | |
| ; CHECK: [[ASSUME_B]]: | |
| ; CHECK-NEXT: [[Y_IS_NAN:%.*]] = fcmp uno half [[Y]], 0.000000e+00 | |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[Y_IS_NAN]]) | |
| ; CHECK-NEXT: br label %[[B:.*]] | |
| ; CHECK: [[B]]: | |
| ; CHECK-NEXT: br label %[[RET]] | |
| ; CHECK: [[RET]]: | |
| ; CHECK-NEXT: ret half 0.000000e+00 | |
| ; | |
| entry: | |
| br i1 %cond0, label %assume_a, label %assume_b | |
| assume_a: | |
| %x.is.nan = fcmp uno half %x, 0.0 | |
| call void @llvm.assume(i1 %x.is.nan) | |
| br label %a | |
| a: | |
| %select_a = select i1 %cond2, half %x, half 0xH7E00 | |
| br label %ret | |
| assume_b: | |
| %y.is.nan = fcmp uno half %y, 0.0 | |
| call void @llvm.assume(i1 %y.is.nan) | |
| br label %b | |
| b: | |
| %select_b = select i1 %cond2, half %y, half 0xH7E00 | |
| br label %ret | |
| ret: | |
| %phi.must.be.nan = phi half [ %select_a, %a ], [ %select_b, %b ] | |
| %select = select i1 %cond2, half %phi.must.be.nan, half 0.0 | |
| ret half %select | |
| } |