; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt -passes=instcombine %s -S | FileCheck %s define i8 @abs_sub_two_sexts(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @abs_sub_two_sexts( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[SX:%.*]] = sext i8 [[X]] to i16 ; CHECK-NEXT: [[SY:%.*]] = sext i8 [[Y]] to i16 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i16 [[SX]], [[SY]] ; CHECK-NEXT: [[A:%.*]] = call i16 @llvm.abs.i16(i16 [[SUB]], i1 false) ; CHECK-NEXT: [[T:%.*]] = trunc i16 [[A]] to i8 ; CHECK-NEXT: ret i8 [[T]] ; %sx = sext i8 %x to i32 %sy = sext i8 %y to i32 %sub = sub nsw i32 %sx, %sy %a = call i32 @llvm.abs.i32(i32 %sub, i1 false) %t = trunc i32 %a to i8 ret i8 %t } define i8 @smin_of_abs_chain(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @smin_of_abs_chain( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[SX:%.*]] = sext i8 [[X]] to i16 ; CHECK-NEXT: [[SY:%.*]] = sext i8 [[Y]] to i16 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i16 [[SX]], [[SY]] ; CHECK-NEXT: [[A:%.*]] = call i16 @llvm.abs.i16(i16 [[SUB]], i1 false) ; CHECK-NEXT: [[U:%.*]] = call i16 @llvm.smin.i16(i16 [[A]], i16 100) ; CHECK-NEXT: [[T:%.*]] = trunc i16 [[U]] to i8 ; CHECK-NEXT: ret i8 [[T]] ; %sx = sext i8 %x to i32 %sy = sext i8 %y to i32 %sub = sub nsw i32 %sx, %sy %a = call i32 @llvm.abs.i32(i32 %sub, i1 false) %u = call i32 @llvm.smin.i32(i32 %a, i32 100) %t = trunc i32 %u to i8 ret i8 %t } define i8 @abs_sub_intmin_poison_dropped(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @abs_sub_intmin_poison_dropped( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[SX:%.*]] = sext i8 [[X]] to i16 ; CHECK-NEXT: [[SY:%.*]] = sext i8 [[Y]] to i16 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i16 [[SX]], [[SY]] ; CHECK-NEXT: [[A:%.*]] = call i16 @llvm.abs.i16(i16 [[SUB]], i1 false) ; CHECK-NEXT: [[T:%.*]] = trunc i16 [[A]] to i8 ; CHECK-NEXT: ret i8 [[T]] ; %sx = sext i8 %x to i32 %sy = sext i8 %y to i32 %sub = sub nsw i32 %sx, %sy %a = call i32 @llvm.abs.i32(i32 %sub, i1 true) %t = trunc i32 %a to i8 ret i8 %t } define i8 @abs_sub_intmin_poison_false(i8 %x, i8 %y) { ; CHECK-LABEL: define i8 @abs_sub_intmin_poison_false( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) { ; CHECK-NEXT: [[SX:%.*]] = sext i8 [[X]] to i16 ; CHECK-NEXT: [[SY:%.*]] = sext i8 [[Y]] to i16 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i16 [[SX]], [[SY]] ; CHECK-NEXT: [[A:%.*]] = call i16 @llvm.abs.i16(i16 [[SUB]], i1 false) ; CHECK-NEXT: [[T:%.*]] = trunc i16 [[A]] to i8 ; CHECK-NEXT: ret i8 [[T]] ; %sx = sext i8 %x to i32 %sy = sext i8 %y to i32 %sub = sub nsw i32 %sx, %sy %a = call i32 @llvm.abs.i32(i32 %sub, i1 false) %t = trunc i32 %a to i8 ret i8 %t } define i8 @abs_unknown_operand(i32 %x) { ; CHECK-LABEL: define i8 @abs_unknown_operand( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: [[A:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false) ; CHECK-NEXT: [[T:%.*]] = trunc i32 [[A]] to i8 ; CHECK-NEXT: ret i8 [[T]] ; %a = call i32 @llvm.abs.i32(i32 %x, i1 false) %t = trunc i32 %a to i8 ret i8 %t } define i8 @abs_phi_self_loop(i1 %c, i8 %x) { ; CHECK-LABEL: define i8 @abs_phi_self_loop( ; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]]) { ; CHECK-NEXT: [[ENTRY:.*]]: ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[M:%.*]], %[[LOOP]] ] ; CHECK-NEXT: [[A:%.*]] = and i32 [[ACC]], 127 ; CHECK-NEXT: [[EXT:%.*]] = sext i8 [[X]] to i32 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[A]], [[EXT]] ; CHECK-NEXT: [[M]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false) ; CHECK-NEXT: br i1 [[C]], label %[[EXIT:.*]], label %[[LOOP]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: [[T:%.*]] = trunc i32 [[M]] to i8 ; CHECK-NEXT: ret i8 [[T]] ; entry: br label %loop loop: %acc = phi i32 [ 0, %entry ], [ %m, %loop ] %a = and i32 %acc, 127 %ext = sext i8 %x to i32 %sub = sub nsw i32 %a, %ext %m = call i32 @llvm.abs.i32(i32 %sub, i1 false) br i1 %c, label %exit, label %loop exit: %t = trunc i32 %m to i8 ret i8 %t } define i8 @abs_const_neg100_poison_true(i32 %x) { ; CHECK-LABEL: define i8 @abs_const_neg100_poison_true( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: ret i8 100 ; %a = call i32 @llvm.abs.i32(i32 -100, i1 true) %t = trunc i32 %a to i8 ret i8 %t } define i8 @abs_const_neg200_poison_false(i32 %x) { ; CHECK-LABEL: define i8 @abs_const_neg200_poison_false( ; CHECK-SAME: i32 [[X:%.*]]) { ; CHECK-NEXT: ret i8 -56 ; %a = call i32 @llvm.abs.i32(i32 -200, i1 false) %t = trunc i32 %a to i8 ret i8 %t } define i8 @abs_multi_use(i8 %x, i8 %y, ptr %p) { ; CHECK-LABEL: define i8 @abs_multi_use( ; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], ptr [[P:%.*]]) { ; CHECK-NEXT: [[SX:%.*]] = sext i8 [[X]] to i32 ; CHECK-NEXT: [[SY:%.*]] = sext i8 [[Y]] to i32 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[SX]], [[SY]] ; CHECK-NEXT: [[A:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false) ; CHECK-NEXT: store i32 [[A]], ptr [[P]], align 4 ; CHECK-NEXT: [[T:%.*]] = trunc i32 [[A]] to i8 ; CHECK-NEXT: ret i8 [[T]] ; %sx = sext i8 %x to i32 %sy = sext i8 %y to i32 %sub = sub nsw i32 %sx, %sy %a = call i32 @llvm.abs.i32(i32 %sub, i1 false) store i32 %a, ptr %p %t = trunc i32 %a to i8 ret i8 %t } define <4 x i8> @abs_select_sext_vec(<4 x i1> %c, <4 x i8> %x) { ; CHECK-LABEL: define <4 x i8> @abs_select_sext_vec( ; CHECK-SAME: <4 x i1> [[C:%.*]], <4 x i8> [[X:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i8> @llvm.abs.v4i8(<4 x i8> [[X]], i1 false) ; CHECK-NEXT: [[T:%.*]] = select <4 x i1> [[C]], <4 x i8> [[TMP1]], <4 x i8> splat (i8 5) ; CHECK-NEXT: ret <4 x i8> [[T]] ; %sx = sext <4 x i8> %x to <4 x i32> %sel = select <4 x i1> %c, <4 x i32> %sx, <4 x i32> splat (i32 5) %a = call <4 x i32> @llvm.abs.v4i32(<4 x i32> %sel, i1 true) %t = trunc <4 x i32> %a to <4 x i8> ret <4 x i8> %t }