412 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s3 4; If nothing is known we can't change anything5define i8 @ucmp_0(i32 %x, i32 %y) {6; CHECK-LABEL: @ucmp_0(7; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])8; CHECK-NEXT: ret i8 [[TMP1]]9;10 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)11 ret i8 %112}13 14define i8 @scmp_0(i32 %x, i32 %y) {15; CHECK-LABEL: @scmp_0(16; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])17; CHECK-NEXT: ret i8 [[TMP1]]18;19 %1 = call i8 @llvm.scmp(i32 %x, i32 %y)20 ret i8 %121}22 23; If we know that range of LHS < range of RHS then return -124define i8 @ucmp_1(i32 %x, i32 %y) {25 ; X is within [4, 8)26; CHECK-LABEL: @ucmp_1(27; CHECK-NEXT: [[COND1:%.*]] = icmp samesign uge i32 [[X:%.*]], 428; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])29; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[X]], 830; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])31; CHECK-NEXT: [[COND3:%.*]] = icmp uge i32 [[Y:%.*]], 832; CHECK-NEXT: call void @llvm.assume(i1 [[COND3]])33; CHECK-NEXT: ret i8 -134;35 %cond1 = icmp uge i32 %x, 436 call void @llvm.assume(i1 %cond1)37 %cond2 = icmp ult i32 %x, 838 call void @llvm.assume(i1 %cond2)39 ; Y is within [8, UNSIGNED_MAX)40 %cond3 = icmp uge i32 %y, 841 call void @llvm.assume(i1 %cond3)42 43 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)44 ret i8 %145}46 47define i8 @scmp_1(i32 %x, i32 %y) {48 ; X is within [-5, 3)49; CHECK-LABEL: @scmp_1(50; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[X:%.*]], -551; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])52; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[X]], 353; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])54; CHECK-NEXT: [[COND3:%.*]] = icmp sge i32 [[Y:%.*]], 355; CHECK-NEXT: call void @llvm.assume(i1 [[COND3]])56; CHECK-NEXT: ret i8 -157;58 %cond1 = icmp sge i32 %x, -559 call void @llvm.assume(i1 %cond1)60 %cond2 = icmp slt i32 %x, 361 call void @llvm.assume(i1 %cond2)62 ; Y is within [3, SIGNED_MAX)63 %cond3 = icmp sge i32 %y, 364 call void @llvm.assume(i1 %cond3)65 66 %1 = call i8 @llvm.scmp(i32 %x, i32 %y)67 ret i8 %168}69 70; If we know that range of LHS > range of RHS then return 171define i8 @ucmp_2(i32 %x, i32 %y) {72 ; X is within [4, UNSIGNED_MAX)73; CHECK-LABEL: @ucmp_2(74; CHECK-NEXT: [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 475; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])76; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 477; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])78; CHECK-NEXT: ret i8 179;80 %cond1 = icmp uge i32 %x, 481 call void @llvm.assume(i1 %cond1)82 ; Y is within [0, 4)83 %cond2 = icmp ult i32 %y, 484 call void @llvm.assume(i1 %cond2)85 86 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)87 ret i8 %188}89 90define i8 @scmp_2(i32 %x, i32 %y) {91 ; X is within [4, SIGNED_MAX)92; CHECK-LABEL: @scmp_2(93; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 494; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])95; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 496; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])97; CHECK-NEXT: ret i8 198;99 %cond1 = icmp sge i32 %x, 4100 call void @llvm.assume(i1 %cond1)101 ; Y is within [SIGNED_MIN, 4)102 %cond2 = icmp slt i32 %y, 4103 call void @llvm.assume(i1 %cond2)104 105 %1 = call i8 @llvm.scmp(i32 %x, i32 %y)106 ret i8 %1107}108 109; If we know that LHS and RHS are both constants then return 0110define i8 @ucmp_5(i32 %x, i32 %y) {111; CHECK-LABEL: @ucmp_5(112; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[X:%.*]], 4113; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])114; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[Y:%.*]], 4115; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])116; CHECK-NEXT: ret i8 0117;118 %cond1 = icmp eq i32 %x, 4119 call void @llvm.assume(i1 %cond1)120 %cond2 = icmp eq i32 %y, 4121 call void @llvm.assume(i1 %cond2)122 123 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)124 ret i8 %1125}126 127define i8 @scmp_5(i32 %x, i32 %y) {128; CHECK-LABEL: @scmp_5(129; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[X:%.*]], -5130; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])131; CHECK-NEXT: [[COND2:%.*]] = icmp eq i32 [[Y:%.*]], -5132; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])133; CHECK-NEXT: ret i8 0134;135 %cond1 = icmp eq i32 %x, -5136 call void @llvm.assume(i1 %cond1)137 %cond2 = icmp eq i32 %y, -5138 call void @llvm.assume(i1 %cond2)139 140 %1 = call i8 @llvm.scmp(i32 %x, i32 %y)141 ret i8 %1142}143 144; We can infer ranges based on the location where a UCMP/SCMP result is used145define i8 @scmp_6(i32 noundef %x) {146; CHECK-LABEL: @scmp_6(147; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 10148; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 -1, i8 5149; CHECK-NEXT: ret i8 [[TMP2]]150;151 %1 = icmp slt i32 %x, 10152 %2 = call i8 @llvm.scmp(i32 %x, i32 10)153 %3 = select i1 %1, i8 %2, i8 5154 ret i8 %3155}156 157; Negative test: ranges overlap158define i8 @ucmp_3(i32 %x, i32 %y) {159 ; X is within [4, UNSIGNED_MAX)160; CHECK-LABEL: @ucmp_3(161; CHECK-NEXT: [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4162; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])163; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 6164; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])165; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])166; CHECK-NEXT: ret i8 [[TMP1]]167;168 %cond1 = icmp uge i32 %x, 4169 call void @llvm.assume(i1 %cond1)170 ; Y is within [0, 6)171 %cond2 = icmp ult i32 %y, 6172 call void @llvm.assume(i1 %cond2)173 174 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)175 ret i8 %1176}177 178define i8 @scmp_3(i32 %x, i32 %y) {179 ; X is within [2, SIGNED_MAX)180; CHECK-LABEL: @scmp_3(181; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 2182; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])183; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 4184; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])185; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])186; CHECK-NEXT: ret i8 [[TMP1]]187;188 %cond1 = icmp sge i32 %x, 2189 call void @llvm.assume(i1 %cond1)190 ; Y is within [SIGNED_MIN, 4)191 %cond2 = icmp slt i32 %y, 4192 call void @llvm.assume(i1 %cond2)193 194 %1 = call i8 @llvm.scmp(i32 %x, i32 %y)195 ret i8 %1196}197 198; Negative test: mismatched signedness of range-establishing comparisons and199; of the intrinsic200define i8 @ucmp_4(i32 %x, i32 %y) {201 ; X is within [4, SIGNED_MAX)202; CHECK-LABEL: @ucmp_4(203; CHECK-NEXT: [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 4204; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])205; CHECK-NEXT: [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 4206; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])207; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])208; CHECK-NEXT: ret i8 [[TMP1]]209;210 %cond1 = icmp sge i32 %x, 4211 call void @llvm.assume(i1 %cond1)212 ; Y is within [0, 4)213 %cond2 = icmp slt i32 %y, 4214 call void @llvm.assume(i1 %cond2)215 216 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)217 ret i8 %1218}219 220define i8 @scmp_4(i32 %x, i32 %y) {221 ; X is within [4, UNSIGNED_MAX)222; CHECK-LABEL: @scmp_4(223; CHECK-NEXT: [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4224; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])225; CHECK-NEXT: [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 4226; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])227; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])228; CHECK-NEXT: ret i8 [[TMP1]]229;230 %cond1 = icmp uge i32 %x, 4231 call void @llvm.assume(i1 %cond1)232 ; Y is within [0, 4)233 %cond2 = icmp ult i32 %y, 4234 call void @llvm.assume(i1 %cond2)235 236 %1 = call i8 @llvm.scmp(i32 %x, i32 %y)237 ret i8 %1238}239 240; Negative test: ranges are the same, but we can't be sure the values are equal241define i8 @ucmp_6(i32 %x, i32 %y) {242 ; Both X and Y are within [0, 10]243; CHECK-LABEL: @ucmp_6(244; CHECK-NEXT: [[COND1:%.*]] = icmp ule i32 [[X:%.*]], 10245; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])246; CHECK-NEXT: [[COND2:%.*]] = icmp ule i32 [[Y:%.*]], 10247; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])248; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])249; CHECK-NEXT: ret i8 [[TMP1]]250;251 %cond1 = icmp ule i32 %x, 10252 call void @llvm.assume(i1 %cond1)253 %cond2 = icmp ule i32 %y, 10254 call void @llvm.assume(i1 %cond2)255 256 %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)257 ret i8 %1258}259 260define i8 @ucmp_switch(i32 %x, i32 %y) {261; CHECK-LABEL: @ucmp_switch(262; CHECK-NEXT: [[CMP:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])263; CHECK-NEXT: switch i8 [[CMP]], label [[DEFAULT_UNREACHABLE:%.*]] [264; CHECK-NEXT: i8 1, label [[BB_1:%.*]]265; CHECK-NEXT: i8 -1, label [[BB_NEG1:%.*]]266; CHECK-NEXT: i8 0, label [[BB_0:%.*]]267; CHECK-NEXT: ]268; CHECK: bb.neg2:269; CHECK-NEXT: ret i8 -2270; CHECK: bb.neg1:271; CHECK-NEXT: ret i8 -1272; CHECK: bb.0:273; CHECK-NEXT: ret i8 0274; CHECK: bb.1:275; CHECK-NEXT: ret i8 1276; CHECK: bb.2:277; CHECK-NEXT: ret i8 2278; CHECK: default.unreachable:279; CHECK-NEXT: unreachable280; CHECK: default:281; CHECK-NEXT: ret i8 123282;283 %cmp = call i8 @llvm.ucmp(i32 %x, i32 %y)284 switch i8 %cmp, label %default [285 i8 -2, label %bb.neg2286 i8 -1, label %bb.neg1287 i8 0, label %bb.0288 i8 1, label %bb.1289 i8 2, label %bb.2290 ]291 292bb.neg2:293 ret i8 -2294 295bb.neg1:296 ret i8 -1297 298bb.0:299 ret i8 0300 301bb.1:302 ret i8 1303 304bb.2:305 ret i8 2306 307default:308 ret i8 123309}310 311define i8 @ucmp_switch_callsite_range(i32 %x, i32 %y) {312; CHECK-LABEL: @ucmp_switch_callsite_range(313; CHECK-NEXT: [[CMP:%.*]] = call range(i8 -2, 3) i8 @llvm.ucmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])314; CHECK-NEXT: switch i8 [[CMP]], label [[DEFAULT_UNREACHABLE:%.*]] [315; CHECK-NEXT: i8 1, label [[BB_1:%.*]]316; CHECK-NEXT: i8 -1, label [[BB_NEG1:%.*]]317; CHECK-NEXT: i8 0, label [[BB_0:%.*]]318; CHECK-NEXT: ]319; CHECK: bb.neg2:320; CHECK-NEXT: ret i8 -2321; CHECK: bb.neg1:322; CHECK-NEXT: ret i8 -1323; CHECK: bb.0:324; CHECK-NEXT: ret i8 0325; CHECK: bb.1:326; CHECK-NEXT: ret i8 1327; CHECK: bb.2:328; CHECK-NEXT: ret i8 2329; CHECK: default.unreachable:330; CHECK-NEXT: unreachable331; CHECK: default:332; CHECK-NEXT: ret i8 123333;334 %cmp = call range(i8 -2, 3) i8 @llvm.ucmp(i32 %x, i32 %y)335 switch i8 %cmp, label %default [336 i8 -2, label %bb.neg2337 i8 -1, label %bb.neg1338 i8 0, label %bb.0339 i8 1, label %bb.1340 i8 2, label %bb.2341 ]342 343bb.neg2:344 ret i8 -2345 346bb.neg1:347 ret i8 -1348 349bb.0:350 ret i8 0351 352bb.1:353 ret i8 1354 355bb.2:356 ret i8 2357 358default:359 ret i8 123360}361 362define i8 @scmp_switch(i32 %x, i32 %y) {363; CHECK-LABEL: @scmp_switch(364; CHECK-NEXT: [[CMP:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])365; CHECK-NEXT: switch i8 [[CMP]], label [[DEFAULT_UNREACHABLE:%.*]] [366; CHECK-NEXT: i8 1, label [[BB_1:%.*]]367; CHECK-NEXT: i8 -1, label [[BB_NEG1:%.*]]368; CHECK-NEXT: i8 0, label [[BB_0:%.*]]369; CHECK-NEXT: ]370; CHECK: bb.neg2:371; CHECK-NEXT: ret i8 -2372; CHECK: bb.neg1:373; CHECK-NEXT: ret i8 -1374; CHECK: bb.0:375; CHECK-NEXT: ret i8 0376; CHECK: bb.1:377; CHECK-NEXT: ret i8 1378; CHECK: bb.2:379; CHECK-NEXT: ret i8 2380; CHECK: default.unreachable:381; CHECK-NEXT: unreachable382; CHECK: default:383; CHECK-NEXT: ret i8 123384;385 %cmp = call i8 @llvm.scmp(i32 %x, i32 %y)386 switch i8 %cmp, label %default [387 i8 -2, label %bb.neg2388 i8 -1, label %bb.neg1389 i8 0, label %bb.0390 i8 1, label %bb.1391 i8 2, label %bb.2392 ]393 394bb.neg2:395 ret i8 -2396 397bb.neg1:398 ret i8 -1399 400bb.0:401 ret i8 0402 403bb.1:404 ret i8 1405 406bb.2:407 ret i8 2408 409default:410 ret i8 123411}412