1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare { i64, i1 } @llvm.smul.with.overflow.i64(i64, i64) 5declare { i8, i1 } @llvm.smul.with.overflow.i8(i8, i8) 6declare { i1, i1 } @llvm.smul.with.overflow.i1(i1, i1) 7declare { <2 x i1>, <2 x i1> } @llvm.smul.with.overflow.v2i1(<2 x i1>, <2 x i1>) 8 9define i1 @test_generic(i64 %a, i64 %b) { 10; CHECK-LABEL: @test_generic( 11; CHECK-NEXT: [[RES:%.*]] = tail call { i64, i1 } @llvm.smul.with.overflow.i64(i64 [[A:%.*]], i64 [[B:%.*]]) 12; CHECK-NEXT: [[OVERFLOW:%.*]] = extractvalue { i64, i1 } [[RES]], 1 13; CHECK-NEXT: ret i1 [[OVERFLOW]] 14; 15 %res = tail call { i64, i1 } @llvm.smul.with.overflow.i64(i64 %a, i64 %b) 16 %overflow = extractvalue { i64, i1 } %res, 1 17 ret i1 %overflow 18} 19 20define i1 @test_constant0(i8 %a) { 21; CHECK-LABEL: @test_constant0( 22; CHECK-NEXT: ret i1 false 23; 24 %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 0) 25 %overflow = extractvalue { i8, i1 } %res, 1 26 ret i1 %overflow 27} 28 29define i1 @test_constant1(i8 %a) { 30; CHECK-LABEL: @test_constant1( 31; CHECK-NEXT: ret i1 false 32; 33 %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 1) 34 %overflow = extractvalue { i8, i1 } %res, 1 35 ret i1 %overflow 36} 37 38define i1 @test_constant2(i8 %a) { 39; CHECK-LABEL: @test_constant2( 40; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[A:%.*]], 64 41; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp slt i8 [[TMP1]], 0 42; CHECK-NEXT: ret i1 [[OVERFLOW]] 43; 44 %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 2) 45 %overflow = extractvalue { i8, i1 } %res, 1 46 ret i1 %overflow 47} 48 49define i1 @test_constant3(i8 %a) { 50; CHECK-LABEL: @test_constant3( 51; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[A:%.*]], -43 52; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i8 [[TMP1]], -85 53; CHECK-NEXT: ret i1 [[OVERFLOW]] 54; 55 %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 3) 56 %overflow = extractvalue { i8, i1 } %res, 1 57 ret i1 %overflow 58} 59 60define i1 @test_constant4(i8 %a) { 61; CHECK-LABEL: @test_constant4( 62; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[A:%.*]], -32 63; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i8 [[TMP1]], -64 64; CHECK-NEXT: ret i1 [[OVERFLOW]] 65; 66 %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 4) 67 %overflow = extractvalue { i8, i1 } %res, 1 68 ret i1 %overflow 69} 70 71 72define i1 @test_constant127(i8 %a) { 73; CHECK-LABEL: @test_constant127( 74; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[A:%.*]], -2 75; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i8 [[TMP1]], -3 76; CHECK-NEXT: ret i1 [[OVERFLOW]] 77; 78 %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 127) 79 %overflow = extractvalue { i8, i1 } %res, 1 80 ret i1 %overflow 81} 82 83define i1 @test_constant128(i8 %a) { 84; CHECK-LABEL: @test_constant128( 85; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ugt i8 [[A:%.*]], 1 86; CHECK-NEXT: ret i1 [[OVERFLOW]] 87; 88 %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 128) 89 %overflow = extractvalue { i8, i1 } %res, 1 90 ret i1 %overflow 91} 92 93define i1 @test_constant255(i8 %a) { 94; CHECK-LABEL: @test_constant255( 95; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], -128 96; CHECK-NEXT: ret i1 [[OVERFLOW]] 97; 98 %res = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 255) 99 %overflow = extractvalue { i8, i1 } %res, 1 100 ret i1 %overflow 101} 102 103define i1 @i1_res(i1 %x, i1 %y) { 104; CHECK-LABEL: @i1_res( 105; CHECK-NEXT: [[R:%.*]] = and i1 [[X:%.*]], [[Y:%.*]] 106; CHECK-NEXT: ret i1 [[R]] 107; 108 %m = call {i1, i1} @llvm.smul.with.overflow.i1(i1 %x, i1 %y) 109 %r = extractvalue {i1, i1} %m, 0 110 ret i1 %r 111} 112 113define <2 x i1> @v2i1_res(<2 x i1> %x, <2 x i1> %y) { 114; CHECK-LABEL: @v2i1_res( 115; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[X:%.*]], [[Y:%.*]] 116; CHECK-NEXT: ret <2 x i1> [[R]] 117; 118 %m = call {<2 x i1>, <2 x i1>} @llvm.smul.with.overflow.v2i1(<2 x i1> %x, <2 x i1> %y) 119 %r = extractvalue {<2 x i1>, <2 x i1>} %m, 0 120 ret <2 x i1> %r 121} 122 123define i1 @i1_res_by_one(i1 %x) { 124; CHECK-LABEL: @i1_res_by_one( 125; CHECK-NEXT: ret i1 [[X:%.*]] 126; 127 %m = call {i1, i1} @llvm.smul.with.overflow.i1(i1 %x, i1 1) 128 %r = extractvalue {i1, i1} %m, 0 129 ret i1 %r 130} 131 132define <2 x i1> @v2i1_res_by_one(<2 x i1> %x) { 133; CHECK-LABEL: @v2i1_res_by_one( 134; CHECK-NEXT: ret <2 x i1> [[X:%.*]] 135; 136 %m = call {<2 x i1>, <2 x i1>} @llvm.smul.with.overflow.v2i1(<2 x i1> %x, <2 x i1> <i1 1, i1 1>) 137 %r = extractvalue {<2 x i1>, <2 x i1>} %m, 0 138 ret <2 x i1> %r 139} 140 141define i1 @i1_ov(i1 %x, i1 %y) { 142; CHECK-LABEL: @i1_ov( 143; CHECK-NEXT: [[OV:%.*]] = and i1 [[X:%.*]], [[Y:%.*]] 144; CHECK-NEXT: ret i1 [[OV]] 145; 146 %m = call {i1, i1} @llvm.smul.with.overflow.i1(i1 %x, i1 %y) 147 %ov = extractvalue {i1, i1} %m, 1 148 ret i1 %ov 149} 150 151define <2 x i1> @v2i1_ov(<2 x i1> %x, <2 x i1> %y) { 152; CHECK-LABEL: @v2i1_ov( 153; CHECK-NEXT: [[OV:%.*]] = and <2 x i1> [[X:%.*]], [[Y:%.*]] 154; CHECK-NEXT: ret <2 x i1> [[OV]] 155; 156 %m = call {<2 x i1>, <2 x i1>} @llvm.smul.with.overflow.v2i1(<2 x i1> %x, <2 x i1> %y) 157 %ov = extractvalue {<2 x i1>, <2 x i1>} %m, 1 158 ret <2 x i1> %ov 159} 160 161define i1 @i1_ov_by_one(i1 %x) { 162; CHECK-LABEL: @i1_ov_by_one( 163; CHECK-NEXT: ret i1 [[X:%.*]] 164; 165 %m = call {i1, i1} @llvm.smul.with.overflow.i1(i1 %x, i1 1) 166 %ov = extractvalue {i1, i1} %m, 1 167 ret i1 %ov 168} 169 170define <2 x i1> @v2i1_ov_by_one(<2 x i1> %x) { 171; CHECK-LABEL: @v2i1_ov_by_one( 172; CHECK-NEXT: ret <2 x i1> [[X:%.*]] 173; 174 %m = call {<2 x i1>, <2 x i1>} @llvm.smul.with.overflow.v2i1(<2 x i1> %x, <2 x i1> <i1 1, i1 1>) 175 %ov = extractvalue {<2 x i1>, <2 x i1>} %m, 1 176 ret <2 x i1> %ov 177} 178