185 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; sext(A s< B) + zext(A s> B) => scmp(A, B)5define i8 @signed_add(i32 %a, i32 %b) {6; CHECK-LABEL: define i8 @signed_add(7; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {8; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]])9; CHECK-NEXT: ret i8 [[R]]10;11 %lt = icmp slt i32 %a, %b12 %lt8 = sext i1 %lt to i813 %gt = icmp sgt i32 %a, %b14 %gt8 = zext i1 %gt to i815 %r = add i8 %lt8, %gt816 ret i8 %r17}18 19; Unsigned version20define i8 @unsigned_add(i32 %a, i32 %b) {21; CHECK-LABEL: define i8 @unsigned_add(22; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {23; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]])24; CHECK-NEXT: ret i8 [[R]]25;26 %lt = icmp ult i32 %a, %b27 %lt8 = sext i1 %lt to i828 %gt = icmp ugt i32 %a, %b29 %gt8 = zext i1 %gt to i830 %r = add i8 %lt8, %gt831 ret i8 %r32}33 34; Commuted operands35define i8 @signed_add_commuted1(i32 %a, i32 %b) {36; CHECK-LABEL: define i8 @signed_add_commuted1(37; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {38; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[B]], i32 [[A]])39; CHECK-NEXT: ret i8 [[R]]40;41 %lt = icmp slt i32 %a, %b42 %lt8 = zext i1 %lt to i843 %gt = icmp sgt i32 %a, %b44 %gt8 = sext i1 %gt to i845 %r = add i8 %lt8, %gt846 ret i8 %r47}48 49define i8 @signed_add_commuted2(i32 %a, i32 %b) {50; CHECK-LABEL: define i8 @signed_add_commuted2(51; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {52; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]])53; CHECK-NEXT: ret i8 [[R]]54;55 %lt = icmp sgt i32 %b, %a56 %lt8 = sext i1 %lt to i857 %gt = icmp sgt i32 %a, %b58 %gt8 = zext i1 %gt to i859 %r = add i8 %lt8, %gt860 ret i8 %r61}62 63; zext(A s> B) - zext(A s< B) => scmp(A, B)64define i8 @signed_sub(i32 %a, i32 %b) {65; CHECK-LABEL: define i8 @signed_sub(66; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {67; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[A]], i32 [[B]])68; CHECK-NEXT: ret i8 [[R]]69;70 %lt = icmp slt i32 %a, %b71 %lt8 = zext i1 %lt to i872 %gt = icmp sgt i32 %a, %b73 %gt8 = zext i1 %gt to i874 %r = sub i8 %gt8, %lt875 ret i8 %r76}77 78; Unsigned version79define i8 @unsigned_sub(i32 %a, i32 %b) {80; CHECK-LABEL: define i8 @unsigned_sub(81; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {82; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]])83; CHECK-NEXT: ret i8 [[R]]84;85 %lt = icmp ult i32 %a, %b86 %lt8 = zext i1 %lt to i887 %gt = icmp ugt i32 %a, %b88 %gt8 = zext i1 %gt to i889 %r = sub i8 %gt8, %lt890 ret i8 %r91}92 93; Negative test: incorrect predicates94define i8 @signed_add_neg1(i32 %a, i32 %b) {95; CHECK-LABEL: define i8 @signed_add_neg1(96; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {97; CHECK-NEXT: [[LT:%.*]] = icmp sgt i32 [[A]], [[B]]98; CHECK-NEXT: [[LT8:%.*]] = sext i1 [[LT]] to i899; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[A]], [[B]]100; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8101; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8]], [[GT8]]102; CHECK-NEXT: ret i8 [[R]]103;104 %lt = icmp sgt i32 %a, %b105 %lt8 = sext i1 %lt to i8106 %gt = icmp sgt i32 %a, %b107 %gt8 = zext i1 %gt to i8108 %r = add i8 %lt8, %gt8109 ret i8 %r110}111 112define i8 @signed_add_neg2(i32 %a, i32 %b) {113; CHECK-LABEL: define i8 @signed_add_neg2(114; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {115; CHECK-NEXT: [[LT:%.*]] = icmp slt i32 [[A]], [[B]]116; CHECK-NEXT: [[LT8:%.*]] = sext i1 [[LT]] to i8117; CHECK-NEXT: [[GT:%.*]] = icmp ne i32 [[A]], [[B]]118; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8119; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8]], [[GT8]]120; CHECK-NEXT: ret i8 [[R]]121;122 %lt = icmp slt i32 %a, %b123 %lt8 = sext i1 %lt to i8124 %gt = icmp ne i32 %a, %b125 %gt8 = zext i1 %gt to i8126 %r = add i8 %lt8, %gt8127 ret i8 %r128}129 130; Negative test: mismatched signedness of predicates131define i8 @signed_add_neg3(i32 %a, i32 %b) {132; CHECK-LABEL: define i8 @signed_add_neg3(133; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {134; CHECK-NEXT: [[LT:%.*]] = icmp slt i32 [[A]], [[B]]135; CHECK-NEXT: [[LT8:%.*]] = sext i1 [[LT]] to i8136; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[A]], [[B]]137; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8138; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8]], [[GT8]]139; CHECK-NEXT: ret i8 [[R]]140;141 %lt = icmp slt i32 %a, %b142 %lt8 = sext i1 %lt to i8143 %gt = icmp ugt i32 %a, %b144 %gt8 = zext i1 %gt to i8145 %r = add i8 %lt8, %gt8146 ret i8 %r147}148 149; Negative test: zext instead of sext or vice-versa (NOT commuted operands)150define i8 @signed_add_neg4(i32 %a, i32 %b) {151; CHECK-LABEL: define i8 @signed_add_neg4(152; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {153; CHECK-NEXT: [[LT:%.*]] = icmp slt i32 [[A]], [[B]]154; CHECK-NEXT: [[LT8:%.*]] = sext i1 [[LT]] to i8155; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[A]], [[B]]156; CHECK-NEXT: [[GT8:%.*]] = sext i1 [[GT]] to i8157; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[LT8]], [[GT8]]158; CHECK-NEXT: ret i8 [[R]]159;160 %lt = icmp slt i32 %a, %b161 %lt8 = sext i1 %lt to i8162 %gt = icmp sgt i32 %a, %b163 %gt8 = sext i1 %gt to i8164 %r = add i8 %lt8, %gt8165 ret i8 %r166}167 168define i8 @signed_add_neg5(i32 %a, i32 %b) {169; CHECK-LABEL: define i8 @signed_add_neg5(170; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {171; CHECK-NEXT: [[LT:%.*]] = icmp slt i32 [[A]], [[B]]172; CHECK-NEXT: [[LT8:%.*]] = zext i1 [[LT]] to i8173; CHECK-NEXT: [[GT:%.*]] = icmp sgt i32 [[A]], [[B]]174; CHECK-NEXT: [[GT8:%.*]] = zext i1 [[GT]] to i8175; CHECK-NEXT: [[R:%.*]] = add nuw nsw i8 [[LT8]], [[GT8]]176; CHECK-NEXT: ret i8 [[R]]177;178 %lt = icmp slt i32 %a, %b179 %lt8 = zext i1 %lt to i8180 %gt = icmp sgt i32 %a, %b181 %gt8 = zext i1 %gt to i8182 %r = add i8 %lt8, %gt8183 ret i8 %r184}185