169 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4declare { i64, i1 } @llvm.ssub.with.overflow.i64(i64, i64)5declare { i8, i1 } @llvm.ssub.with.overflow.i8(i8, i8)6 7declare void @use(i1)8 9define i1 @test_generic(i64 %a, i64 %b) {10; CHECK-LABEL: @test_generic(11; CHECK-NEXT: [[RES:%.*]] = tail call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]])12; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 113; CHECK-NEXT: ret i1 [[OVERFLOW]]14;15 %res = tail call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)16 %overflow = extractvalue { i64, i1 } %res, 117 ret i1 %overflow18}19 20define i1 @test_constant0(i8 %a) {21; CHECK-LABEL: @test_constant0(22; CHECK-NEXT: ret i1 false23;24 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 0)25 %overflow = extractvalue { i8, i1 } %res, 126 ret i1 %overflow27}28 29define i1 @test_constant1(i8 %a) {30; CHECK-LABEL: @test_constant1(31; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], -12832; CHECK-NEXT: ret i1 [[OVERFLOW]]33;34 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 1)35 %overflow = extractvalue { i8, i1 } %res, 136 ret i1 %overflow37}38 39define i1 @test_constant2(i8 %a) {40; CHECK-LABEL: @test_constant2(41; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -12642; CHECK-NEXT: ret i1 [[OVERFLOW]]43;44 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 2)45 %overflow = extractvalue { i8, i1 } %res, 146 ret i1 %overflow47}48 49define i1 @test_constant3(i8 %a) {50; CHECK-LABEL: @test_constant3(51; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -12552; CHECK-NEXT: ret i1 [[OVERFLOW]]53;54 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 3)55 %overflow = extractvalue { i8, i1 } %res, 156 ret i1 %overflow57}58 59define i1 @test_constant4(i8 %a) {60; CHECK-LABEL: @test_constant4(61; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -12462; CHECK-NEXT: ret i1 [[OVERFLOW]]63;64 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 4)65 %overflow = extractvalue { i8, i1 } %res, 166 ret i1 %overflow67}68 69 70define i1 @test_constant127(i8 %a) {71; CHECK-LABEL: @test_constant127(72; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], -173; CHECK-NEXT: ret i1 [[OVERFLOW]]74;75 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 127)76 %overflow = extractvalue { i8, i1 } %res, 177 ret i1 %overflow78}79 80define i1 @test_constant128(i8 %a) {81; CHECK-LABEL: @test_constant128(82; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp sgt i8 [[A:%.*]], -183; CHECK-NEXT: ret i1 [[OVERFLOW]]84;85 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 128)86 %overflow = extractvalue { i8, i1 } %res, 187 ret i1 %overflow88}89 90define i1 @test_constant255(i8 %a) {91; CHECK-LABEL: @test_constant255(92; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], 12793; CHECK-NEXT: ret i1 [[OVERFLOW]]94;95 %res = tail call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %a, i8 255)96 %overflow = extractvalue { i8, i1 } %res, 197 ret i1 %overflow98}99 100define i1 @sub_eq0(i8 %x, i8 %y, i1 %b) {101; CHECK-LABEL: @sub_eq0(102; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])103; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1104; CHECK-NEXT: call void @use(i1 [[OV]])105; CHECK-NEXT: [[EQ0:%.*]] = icmp eq i8 [[X]], [[Y]]106; CHECK-NEXT: ret i1 [[EQ0]]107;108 %ss = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y)109 %ov = extractvalue { i8, i1 } %ss, 1110 call void @use(i1 %ov)111 %sub = extractvalue { i8, i1 } %ss, 0112 %eq0 = icmp eq i8 %sub, 0113 ret i1 %eq0114}115 116define i1 @sub_ne0(i8 %x, i8 %y, i1 %b) {117; CHECK-LABEL: @sub_ne0(118; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])119; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1120; CHECK-NEXT: call void @use(i1 [[OV]])121; CHECK-NEXT: [[NE0:%.*]] = icmp ne i8 [[X]], [[Y]]122; CHECK-NEXT: ret i1 [[NE0]]123;124 %ss = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y)125 %ov = extractvalue { i8, i1 } %ss, 1126 call void @use(i1 %ov)127 %sub = extractvalue { i8, i1 } %ss, 0128 %ne0 = icmp ne i8 %sub, 0129 ret i1 %ne0130}131 132; negative test - need zero133 134define i1 @sub_eq1(i8 %x, i8 %y, i1 %b) {135; CHECK-LABEL: @sub_eq1(136; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])137; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1138; CHECK-NEXT: call void @use(i1 [[OV]])139; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SS]], 0140; CHECK-NEXT: [[EQ1:%.*]] = icmp eq i8 [[SUB]], 1141; CHECK-NEXT: ret i1 [[EQ1]]142;143 %ss = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y)144 %ov = extractvalue { i8, i1 } %ss, 1145 call void @use(i1 %ov)146 %sub = extractvalue { i8, i1 } %ss, 0147 %eq1 = icmp eq i8 %sub, 1148 ret i1 %eq1149}150 151; negative test - need equality pred152 153define i1 @sub_sgt0(i8 %x, i8 %y, i1 %b) {154; CHECK-LABEL: @sub_sgt0(155; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])156; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1157; CHECK-NEXT: call void @use(i1 [[OV]])158; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SS]], 0159; CHECK-NEXT: [[SGT0:%.*]] = icmp sgt i8 [[SUB]], 0160; CHECK-NEXT: ret i1 [[SGT0]]161;162 %ss = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 %x, i8 %y)163 %ov = extractvalue { i8, i1 } %ss, 1164 call void @use(i1 %ov)165 %sub = extractvalue { i8, i1 } %ss, 0166 %sgt0 = icmp sgt i8 %sub, 0167 ret i1 %sgt0168}169