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.umul.with.overflow.i64(i64, i64) 5declare { i8, i1 } @llvm.umul.with.overflow.i8(i8, i8) 6declare { i1, i1 } @llvm.umul.with.overflow.i1(i1, i1) 7declare { <2 x i1>, <2 x i1> } @llvm.umul.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.umul.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.umul.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.umul.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.umul.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: [[OVERFLOW:%.*]] = icmp slt i8 [[A:%.*]], 0 41; CHECK-NEXT: ret i1 [[OVERFLOW]] 42; 43 %res = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 2) 44 %overflow = extractvalue { i8, i1 } %res, 1 45 ret i1 %overflow 46} 47 48define i1 @test_constant3(i8 %a) { 49; CHECK-LABEL: @test_constant3( 50; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ugt i8 [[A:%.*]], 85 51; CHECK-NEXT: ret i1 [[OVERFLOW]] 52; 53 %res = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 3) 54 %overflow = extractvalue { i8, i1 } %res, 1 55 ret i1 %overflow 56} 57 58define i1 @test_constant4(i8 %a) { 59; CHECK-LABEL: @test_constant4( 60; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ugt i8 [[A:%.*]], 63 61; CHECK-NEXT: ret i1 [[OVERFLOW]] 62; 63 %res = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 4) 64 %overflow = extractvalue { i8, i1 } %res, 1 65 ret i1 %overflow 66} 67 68 69define i1 @test_constant127(i8 %a) { 70; CHECK-LABEL: @test_constant127( 71; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ugt i8 [[A:%.*]], 2 72; CHECK-NEXT: ret i1 [[OVERFLOW]] 73; 74 %res = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 127) 75 %overflow = extractvalue { i8, i1 } %res, 1 76 ret i1 %overflow 77} 78 79define i1 @test_constant128(i8 %a) { 80; CHECK-LABEL: @test_constant128( 81; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ugt i8 [[A:%.*]], 1 82; CHECK-NEXT: ret i1 [[OVERFLOW]] 83; 84 %res = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 128) 85 %overflow = extractvalue { i8, i1 } %res, 1 86 ret i1 %overflow 87} 88 89define i1 @test_constant255(i8 %a) { 90; CHECK-LABEL: @test_constant255( 91; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ugt i8 [[A:%.*]], 1 92; CHECK-NEXT: ret i1 [[OVERFLOW]] 93; 94 %res = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 255) 95 %overflow = extractvalue { i8, i1 } %res, 1 96 ret i1 %overflow 97} 98 99define i1 @i1_res(i1 %x, i1 %y) { 100; CHECK-LABEL: @i1_res( 101; CHECK-NEXT: [[M:%.*]] = and i1 [[X:%.*]], [[Y:%.*]] 102; CHECK-NEXT: ret i1 [[M]] 103; 104 %m = call {i1, i1} @llvm.umul.with.overflow.i1(i1 %x, i1 %y) 105 %r = extractvalue {i1, i1} %m, 0 106 ret i1 %r 107} 108 109define <2 x i1> @v2i1_res(<2 x i1> %x, <2 x i1> %y) { 110; CHECK-LABEL: @v2i1_res( 111; CHECK-NEXT: [[M:%.*]] = and <2 x i1> [[X:%.*]], [[Y:%.*]] 112; CHECK-NEXT: ret <2 x i1> [[M]] 113; 114 %m = call {<2 x i1>, <2 x i1>} @llvm.umul.with.overflow.v2i1(<2 x i1> %x, <2 x i1> %y) 115 %r = extractvalue {<2 x i1>, <2 x i1>} %m, 0 116 ret <2 x i1> %r 117} 118 119define i1 @i1_res_by_one(i1 %x) { 120; CHECK-LABEL: @i1_res_by_one( 121; CHECK-NEXT: ret i1 [[X:%.*]] 122; 123 %m = call {i1, i1} @llvm.umul.with.overflow.i1(i1 %x, i1 1) 124 %r = extractvalue {i1, i1} %m, 0 125 ret i1 %r 126} 127 128define <2 x i1> @v2i1_res_by_one(<2 x i1> %x) { 129; CHECK-LABEL: @v2i1_res_by_one( 130; CHECK-NEXT: ret <2 x i1> [[X:%.*]] 131; 132 %m = call {<2 x i1>, <2 x i1>} @llvm.umul.with.overflow.v2i1(<2 x i1> %x, <2 x i1> <i1 1, i1 1>) 133 %r = extractvalue {<2 x i1>, <2 x i1>} %m, 0 134 ret <2 x i1> %r 135} 136 137define i1 @i1_ov(i1 %x, i1 %y) { 138; CHECK-LABEL: @i1_ov( 139; CHECK-NEXT: ret i1 false 140; 141 %m = call {i1, i1} @llvm.umul.with.overflow.i1(i1 %x, i1 %y) 142 %ov = extractvalue {i1, i1} %m, 1 143 ret i1 %ov 144} 145 146define <2 x i1> @v2i1_ov(<2 x i1> %x, <2 x i1> %y) { 147; CHECK-LABEL: @v2i1_ov( 148; CHECK-NEXT: ret <2 x i1> zeroinitializer 149; 150 %m = call {<2 x i1>, <2 x i1>} @llvm.umul.with.overflow.v2i1(<2 x i1> %x, <2 x i1> %y) 151 %ov = extractvalue {<2 x i1>, <2 x i1>} %m, 1 152 ret <2 x i1> %ov 153} 154 155define i1 @i1_ov_by_one(i1 %x) { 156; CHECK-LABEL: @i1_ov_by_one( 157; CHECK-NEXT: ret i1 false 158; 159 %m = call {i1, i1} @llvm.umul.with.overflow.i1(i1 %x, i1 1) 160 %ov = extractvalue {i1, i1} %m, 1 161 ret i1 %ov 162} 163 164define <2 x i1> @v2i1_ov_by_one(<2 x i1> %x) { 165; CHECK-LABEL: @v2i1_ov_by_one( 166; CHECK-NEXT: ret <2 x i1> zeroinitializer 167; 168 %m = call {<2 x i1>, <2 x i1>} @llvm.umul.with.overflow.v2i1(<2 x i1> %x, <2 x i1> <i1 1, i1 1>) 169 %ov = extractvalue {<2 x i1>, <2 x i1>} %m, 1 170 ret <2 x i1> %ov 171} 172