| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -S -passes=instsimplify < %s | FileCheck %s |
| |
| declare <4 x i16> @llvm.abs.v4i16(<4 x i16>, i1 immarg) |
| declare i32 @llvm.abs.i32(i32, i1 immarg) |
| declare i64 @llvm.abs.i64(i64, i1 immarg) |
| |
| ; check (a == 0) ? 0 : abs(a) |
| |
| define i32 @select_i32_eq0_abs_f(i32 %a) { |
| ; CHECK-LABEL: @select_i32_eq0_abs_f( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, 0 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 0, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @select_i32_eq0_abs_t(i32 %a) { |
| ; CHECK-LABEL: @select_i32_eq0_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, 0 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 true) |
| %res = select i1 %cond, i32 0, i32 %abs |
| ret i32 %res |
| } |
| |
| ; check (a == int_min) ? int_min : abs(a) |
| |
| define i32 @select_i32_eqINTMIN_abs_f(i32 %a) { |
| ; CHECK-LABEL: @select_i32_eqINTMIN_abs_f( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, -2147483648 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 -2147483648, i32 %abs |
| ret i32 %res |
| } |
| |
| ; should not transform |
| define i32 @select_i32_eqINTMIN_abs_t(i32 %a) { |
| ; CHECK-LABEL: @select_i32_eqINTMIN_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], -2147483648 |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A]], i1 true) |
| ; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND]], i32 -2147483648, i32 [[ABS]] |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, -2147483648 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 true) |
| %res = select i1 %cond, i32 -2147483648, i32 %abs |
| ret i32 %res |
| } |
| |
| ; check random values, like (a == -255) ? 255 : abs(a) |
| define i32 @select_i32_eqneg255_abs_f(i32 %a) { |
| ; CHECK-LABEL: @select_i32_eqneg255_abs_f( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, -255 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 255, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @select_i32_eqneg255_abs_t(i32 %a) { |
| ; CHECK-LABEL: @select_i32_eqneg255_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, -255 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 true) |
| %res = select i1 %cond, i32 255, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @select_i32_eq65555_abs_f(i32 %a) { |
| ; CHECK-LABEL: @select_i32_eq65555_abs_f( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, 65555 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 65555, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @select_i32_eq65555_abs_t(i32 %a) { |
| ; CHECK-LABEL: @select_i32_eq65555_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, 65555 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 true) |
| %res = select i1 %cond, i32 65555, i32 %abs |
| ret i32 %res |
| } |
| |
| |
| ; check random values, but the transform doesn't make sense, e.g. |
| ; (a == 255) ? -255 : abs(a) |
| define i32 @bad_select_i32_eq255_abs_f(i32 %a) { |
| ; CHECK-LABEL: @bad_select_i32_eq255_abs_f( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], 255 |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A]], i1 false) |
| ; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND]], i32 -255, i32 [[ABS]] |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, 255 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 -255, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @bad_select_i32_eq255_abs_t(i32 %a) { |
| ; CHECK-LABEL: @bad_select_i32_eq255_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], 255 |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A]], i1 true) |
| ; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND]], i32 -255, i32 [[ABS]] |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, 255 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 true) |
| %res = select i1 %cond, i32 -255, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @bad_select_i32_eq65555_abs_f(i32 %a) { |
| ; CHECK-LABEL: @bad_select_i32_eq65555_abs_f( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], -65555 |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A]], i1 false) |
| ; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND]], i32 65554, i32 [[ABS]] |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, -65555 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 65554, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @bad_select_i32_eq65555_abs_t(i32 %a) { |
| ; CHECK-LABEL: @bad_select_i32_eq65555_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], -65555 |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A]], i1 true) |
| ; CHECK-NEXT: [[RES:%.*]] = select i1 [[COND]], i32 65554, i32 [[ABS]] |
| ; CHECK-NEXT: ret i32 [[RES]] |
| ; |
| entry: |
| %cond = icmp eq i32 %a, -65555 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 true) |
| %res = select i1 %cond, i32 65554, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @select_i32_ne0_abs_f(i32 %a) { |
| ; CHECK-LABEL: @select_i32_ne0_abs_f( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp ne i32 %a, 0 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 %abs, i32 0 |
| ret i32 %res |
| } |
| |
| define i32 @select_i32_ne0_abs_t(i32 %a) { |
| ; CHECK-LABEL: @select_i32_ne0_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret i32 [[ABS]] |
| ; |
| entry: |
| %cond = icmp ne i32 %a, 0 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 true) |
| %res = select i1 %cond, i32 %abs, i32 0 |
| ret i32 %res |
| } |
| |
| define i64 @select_i64_eq0_abs_t(i64 %a) { |
| ; CHECK-LABEL: @select_i64_eq0_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i64 @llvm.abs.i64(i64 [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret i64 [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq i64 %a, 0 |
| %abs = tail call i64 @llvm.abs.i64(i64 %a, i1 true) |
| %res = select i1 %cond, i64 0, i64 %abs |
| ret i64 %res |
| } |
| |
| define i64 @select_i64_ne0_abs_t(i64 %a) { |
| ; CHECK-LABEL: @select_i64_ne0_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call i64 @llvm.abs.i64(i64 [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret i64 [[ABS]] |
| ; |
| entry: |
| %cond = icmp ne i64 %a, 0 |
| %abs = tail call i64 @llvm.abs.i64(i64 %a, i1 true) |
| %res = select i1 %cond, i64 %abs, i64 0 |
| ret i64 %res |
| } |
| |
| define <4 x i16> @select_v4i16_eq0_abs_t(<4 x i16> %a) { |
| ; CHECK-LABEL: @select_v4i16_eq0_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret <4 x i16> [[ABS]] |
| ; |
| entry: |
| %cond = icmp eq <4 x i16> %a, <i16 0, i16 0, i16 0, i16 0> |
| %abs = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> %a, i1 true) |
| %res = select <4 x i1> %cond, <4 x i16> <i16 0, i16 0, i16 0, i16 0>, <4 x i16> %abs |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @select_v4i16_ne0_abs_t(<4 x i16> %a) { |
| ; CHECK-LABEL: @select_v4i16_ne0_abs_t( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret <4 x i16> [[ABS]] |
| ; |
| entry: |
| %cond = icmp ne <4 x i16> %a, <i16 0, i16 0, i16 0, i16 0> |
| %abs = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> %a, i1 true) |
| %res = select <4 x i1> %cond, <4 x i16> %abs, <4 x i16> <i16 0, i16 0, i16 0, i16 0> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @select_v4i16_ne0_abs_t_with_undef(<4 x i16> %a) { |
| ; CHECK-LABEL: @select_v4i16_ne0_abs_t_with_undef( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne <4 x i16> [[A:%.*]], zeroinitializer |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> [[A]], i1 true) |
| ; CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[COND]], <4 x i16> [[ABS]], <4 x i16> <i16 undef, i16 0, i16 0, i16 0> |
| ; CHECK-NEXT: ret <4 x i16> [[RES]] |
| ; |
| entry: |
| %cond = icmp ne <4 x i16> %a, <i16 0, i16 0, i16 0, i16 0> |
| %abs = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> %a, i1 true) |
| %res = select <4 x i1> %cond, <4 x i16> %abs, <4 x i16> <i16 undef, i16 0, i16 0, i16 0> |
| ret <4 x i16> %res |
| } |
| |
| define i32 @bad_select_i32_ne0_abs(i32 %a) { |
| ; CHECK-LABEL: @bad_select_i32_ne0_abs( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| entry: |
| %cond = icmp ne i32 %a, 0 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 0, i32 %abs |
| ret i32 %res |
| } |
| |
| define i32 @bad_select_i32_eq0_abs(i32 %a) { |
| ; CHECK-LABEL: @bad_select_i32_eq0_abs( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: ret i32 0 |
| ; |
| entry: |
| %cond = icmp eq i32 %a, 0 |
| %abs = tail call i32 @llvm.abs.i32(i32 %a, i1 false) |
| %res = select i1 %cond, i32 %abs, i32 0 |
| ret i32 %res |
| } |
| |
| define <4 x i16> @badsplat1_select_v4i16_ne0_abs(<4 x i16> %a) { |
| ; CHECK-LABEL: @badsplat1_select_v4i16_ne0_abs( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> [[A:%.*]], i1 true) |
| ; CHECK-NEXT: ret <4 x i16> [[ABS]] |
| ; |
| entry: |
| %cond = icmp ne <4 x i16> %a, <i16 0, i16 1, i16 0, i16 0> |
| %abs = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> %a, i1 true) |
| %res = select <4 x i1> %cond, <4 x i16> %abs, <4 x i16> <i16 0, i16 1, i16 0, i16 0> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @badsplat2_select_v4i16_ne0_abs(<4 x i16> %a) { |
| ; CHECK-LABEL: @badsplat2_select_v4i16_ne0_abs( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne <4 x i16> [[A:%.*]], <i16 0, i16 undef, i16 0, i16 0> |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> [[A]], i1 true) |
| ; CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[COND]], <4 x i16> [[ABS]], <4 x i16> <i16 0, i16 1, i16 0, i16 0> |
| ; CHECK-NEXT: ret <4 x i16> [[RES]] |
| ; |
| entry: |
| %cond = icmp ne <4 x i16> %a, <i16 0, i16 undef, i16 0, i16 0> |
| %abs = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> %a, i1 true) |
| %res = select <4 x i1> %cond, <4 x i16> %abs, <4 x i16> <i16 0, i16 1, i16 0, i16 0> |
| ret <4 x i16> %res |
| } |
| |
| define <4 x i16> @badsplat3_select_v4i16_ne0_abs(<4 x i16> %a) { |
| ; CHECK-LABEL: @badsplat3_select_v4i16_ne0_abs( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[COND:%.*]] = icmp ne <4 x i16> [[A:%.*]], zeroinitializer |
| ; CHECK-NEXT: [[ABS:%.*]] = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> [[A]], i1 true) |
| ; CHECK-NEXT: [[RES:%.*]] = select <4 x i1> [[COND]], <4 x i16> [[ABS]], <4 x i16> <i16 0, i16 1, i16 0, i16 0> |
| ; CHECK-NEXT: ret <4 x i16> [[RES]] |
| ; |
| entry: |
| %cond = icmp ne <4 x i16> %a, <i16 0, i16 0, i16 0, i16 0> |
| %abs = tail call <4 x i16> @llvm.abs.v4i16(<4 x i16> %a, i1 true) |
| %res = select <4 x i1> %cond, <4 x i16> %abs, <4 x i16> <i16 0, i16 1, i16 0, i16 0> |
| ret <4 x i16> %res |
| } |