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.usub.with.overflow.i64(i64, i64) 5declare { i8, i1 } @llvm.usub.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: [[OVERFLOW:%.*]] = icmp ult i64 [[A:%.*]], [[B:%.*]] 12; CHECK-NEXT: ret i1 [[OVERFLOW]] 13; 14 %res = tail call { i64, i1 } @llvm.usub.with.overflow.i64(i64 %a, i64 %b) 15 %overflow = extractvalue { i64, i1 } %res, 1 16 ret i1 %overflow 17} 18 19define i1 @test_constant0(i8 %a) { 20; CHECK-LABEL: @test_constant0( 21; CHECK-NEXT: ret i1 false 22; 23 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 0) 24 %overflow = extractvalue { i8, i1 } %res, 1 25 ret i1 %overflow 26} 27 28define i1 @test_constant1(i8 %a) { 29; CHECK-LABEL: @test_constant1( 30; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp eq i8 [[A:%.*]], 0 31; CHECK-NEXT: ret i1 [[OVERFLOW]] 32; 33 %res = tail call { i8, i1 } @llvm.usub.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 ult i8 [[A:%.*]], 2 41; CHECK-NEXT: ret i1 [[OVERFLOW]] 42; 43 %res = tail call { i8, i1 } @llvm.usub.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 ult i8 [[A:%.*]], 3 51; CHECK-NEXT: ret i1 [[OVERFLOW]] 52; 53 %res = tail call { i8, i1 } @llvm.usub.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 ult i8 [[A:%.*]], 4 61; CHECK-NEXT: ret i1 [[OVERFLOW]] 62; 63 %res = tail call { i8, i1 } @llvm.usub.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 ult i8 [[A:%.*]], 127 72; CHECK-NEXT: ret i1 [[OVERFLOW]] 73; 74 %res = tail call { i8, i1 } @llvm.usub.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 sgt i8 [[A:%.*]], -1 82; CHECK-NEXT: ret i1 [[OVERFLOW]] 83; 84 %res = tail call { i8, i1 } @llvm.usub.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 ne i8 [[A:%.*]], -1 92; CHECK-NEXT: ret i1 [[OVERFLOW]] 93; 94 %res = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %a, i8 255) 95 %overflow = extractvalue { i8, i1 } %res, 1 96 ret i1 %overflow 97} 98 99define i1 @sub_eq0(i8 %x, i8 %y, i1 %b) { 100; CHECK-LABEL: @sub_eq0( 101; CHECK-NEXT: [[OV:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] 102; CHECK-NEXT: call void @use(i1 [[OV]]) 103; CHECK-NEXT: [[EQ0:%.*]] = icmp eq i8 [[X]], [[Y]] 104; CHECK-NEXT: ret i1 [[EQ0]] 105; 106 %us = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y) 107 %ov = extractvalue { i8, i1 } %us, 1 108 call void @use(i1 %ov) 109 %sub = extractvalue { i8, i1 } %us, 0 110 %eq0 = icmp eq i8 %sub, 0 111 ret i1 %eq0 112} 113 114define i1 @sub_ne0(i8 %x, i8 %y, i1 %b) { 115; CHECK-LABEL: @sub_ne0( 116; CHECK-NEXT: [[OV:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] 117; CHECK-NEXT: call void @use(i1 [[OV]]) 118; CHECK-NEXT: [[NE0:%.*]] = icmp ne i8 [[X]], [[Y]] 119; CHECK-NEXT: ret i1 [[NE0]] 120; 121 %us = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y) 122 %ov = extractvalue { i8, i1 } %us, 1 123 call void @use(i1 %ov) 124 %sub = extractvalue { i8, i1 } %us, 0 125 %ne0 = icmp ne i8 %sub, 0 126 ret i1 %ne0 127} 128 129; negative test - need zero 130 131define i1 @sub_eq1(i8 %x, i8 %y, i1 %b) { 132; CHECK-LABEL: @sub_eq1( 133; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 134; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1 135; CHECK-NEXT: call void @use(i1 [[OV]]) 136; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SS]], 0 137; CHECK-NEXT: [[EQ1:%.*]] = icmp eq i8 [[SUB]], 1 138; CHECK-NEXT: ret i1 [[EQ1]] 139; 140 %ss = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y) 141 %ov = extractvalue { i8, i1 } %ss, 1 142 call void @use(i1 %ov) 143 %sub = extractvalue { i8, i1 } %ss, 0 144 %eq1 = icmp eq i8 %sub, 1 145 ret i1 %eq1 146} 147 148; negative test - need equality pred 149 150define i1 @sub_sgt0(i8 %x, i8 %y, i1 %b) { 151; CHECK-LABEL: @sub_sgt0( 152; CHECK-NEXT: [[SS:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]]) 153; CHECK-NEXT: [[OV:%.*]] = extractvalue { i8, i1 } [[SS]], 1 154; CHECK-NEXT: call void @use(i1 [[OV]]) 155; CHECK-NEXT: [[SUB:%.*]] = extractvalue { i8, i1 } [[SS]], 0 156; CHECK-NEXT: [[SGT0:%.*]] = icmp sgt i8 [[SUB]], 0 157; CHECK-NEXT: ret i1 [[SGT0]] 158; 159 %ss = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %x, i8 %y) 160 %ov = extractvalue { i8, i1 } %ss, 1 161 call void @use(i1 %ov) 162 %sub = extractvalue { i8, i1 } %ss, 0 163 %sgt0 = icmp sgt i8 %sub, 0 164 ret i1 %sgt0 165} 166