1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt %s -instsimplify -S | FileCheck %s 3 4; Here we subtract two values, check that subtraction did not overflow AND 5; that the result is non-zero. This can be simplified just to a comparison 6; between the base and offset. 7 8declare void @use8(i8) 9declare void @use64(i64) 10declare void @use1(i1) 11 12declare void @llvm.assume(i1) 13 14; If we are checking that we either did not get null or got no overflow, 15; this is tautological and is always true. 16 17define i1 @commutativity0(i8 %base, i8 %offset) { 18; CHECK-LABEL: @commutativity0( 19; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 20; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 21; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]] 22; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]]) 23; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 24; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]]) 25; CHECK-NEXT: ret i1 true 26; 27 %adjusted = sub i8 %base, %offset 28 call void @use8(i8 %adjusted) 29 %no_underflow = icmp uge i8 %base, %offset 30 call void @use1(i1 %no_underflow) 31 %not_null = icmp ne i8 %adjusted, 0 32 call void @use1(i1 %not_null) 33 %r = or i1 %not_null, %no_underflow 34 ret i1 %r 35} 36define i1 @commutativity1(i8 %base, i8 %offset) { 37; CHECK-LABEL: @commutativity1( 38; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 39; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 40; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]] 41; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]]) 42; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 43; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]]) 44; CHECK-NEXT: ret i1 true 45; 46 %adjusted = sub i8 %base, %offset 47 call void @use8(i8 %adjusted) 48 %no_underflow = icmp ule i8 %offset, %base ; swapped 49 call void @use1(i1 %no_underflow) 50 %not_null = icmp ne i8 %adjusted, 0 51 call void @use1(i1 %not_null) 52 %r = or i1 %not_null, %no_underflow 53 ret i1 %r 54} 55define i1 @commutativity2(i8 %base, i8 %offset) { 56; CHECK-LABEL: @commutativity2( 57; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 58; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 59; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]] 60; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]]) 61; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 62; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]]) 63; CHECK-NEXT: ret i1 true 64; 65 %adjusted = sub i8 %base, %offset 66 call void @use8(i8 %adjusted) 67 %no_underflow = icmp uge i8 %base, %offset 68 call void @use1(i1 %no_underflow) 69 %not_null = icmp ne i8 %adjusted, 0 70 call void @use1(i1 %not_null) 71 %r = or i1 %no_underflow, %not_null ; swapped 72 ret i1 %r 73} 74 75define i1 @commutativity3(i8 %base, i8 %offset) { 76; CHECK-LABEL: @commutativity3( 77; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 78; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 79; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[OFFSET]], [[BASE]] 80; CHECK-NEXT: call void @use1(i1 [[NO_UNDERFLOW]]) 81; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 82; CHECK-NEXT: call void @use1(i1 [[NOT_NULL]]) 83; CHECK-NEXT: ret i1 true 84; 85 %adjusted = sub i8 %base, %offset 86 call void @use8(i8 %adjusted) 87 %no_underflow = icmp ule i8 %offset, %base ; swapped 88 call void @use1(i1 %no_underflow) 89 %not_null = icmp ne i8 %adjusted, 0 90 call void @use1(i1 %not_null) 91 %r = or i1 %no_underflow, %not_null ; swapped 92 ret i1 %r 93} 94 95;------------------------------------------------------------------------------- 96 97define i1 @exaustive_t0_no_underflow(i8 %base, i8 %offset) { 98; CHECK-LABEL: @exaustive_t0_no_underflow( 99; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 100; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 101; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]] 102; CHECK-NEXT: ret i1 [[NO_UNDERFLOW]] 103; 104 %adjusted = sub i8 %base, %offset 105 call void @use8(i8 %adjusted) 106 %not_null = icmp ne i8 %adjusted, 0 107 %no_underflow = icmp ult i8 %base, %offset 108 %r = and i1 %no_underflow, %not_null 109 ret i1 %r 110} 111 112define i1 @exaustive_t1_not_null(i8 %base, i8 %offset) { 113; CHECK-LABEL: @exaustive_t1_not_null( 114; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 115; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 116; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 117; CHECK-NEXT: ret i1 [[NOT_NULL]] 118; 119 %adjusted = sub i8 %base, %offset 120 call void @use8(i8 %adjusted) 121 %not_null = icmp ne i8 %adjusted, 0 122 %no_underflow = icmp ult i8 %base, %offset 123 %r = or i1 %no_underflow, %not_null 124 ret i1 %r 125} 126 127define i1 @exaustive_t2_false(i8 %base, i8 %offset) { 128; CHECK-LABEL: @exaustive_t2_false( 129; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 130; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 131; CHECK-NEXT: ret i1 false 132; 133 %adjusted = sub i8 %base, %offset 134 call void @use8(i8 %adjusted) 135 %not_null = icmp eq i8 %adjusted, 0 136 %no_underflow = icmp ult i8 %base, %offset 137 %r = and i1 %no_underflow, %not_null 138 ret i1 %r 139} 140 141define i1 @exaustive_t3_bad(i8 %base, i8 %offset) { 142; CHECK-LABEL: @exaustive_t3_bad( 143; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 144; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 145; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0 146; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ult i8 [[BASE]], [[OFFSET]] 147; CHECK-NEXT: [[R:%.*]] = or i1 [[NO_UNDERFLOW]], [[NOT_NULL]] 148; CHECK-NEXT: ret i1 [[R]] 149; 150 %adjusted = sub i8 %base, %offset 151 call void @use8(i8 %adjusted) 152 %not_null = icmp eq i8 %adjusted, 0 153 %no_underflow = icmp ult i8 %base, %offset 154 %r = or i1 %no_underflow, %not_null 155 ret i1 %r 156} 157 158define i1 @exaustive_t4_no_underflow(i8 %base, i8 %offset) { 159; CHECK-LABEL: @exaustive_t4_no_underflow( 160; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 161; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 162; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]] 163; CHECK-NEXT: ret i1 [[NO_UNDERFLOW]] 164; 165 %adjusted = sub i8 %base, %offset 166 call void @use8(i8 %adjusted) 167 %not_null = icmp ne i8 %adjusted, 0 168 %no_underflow = icmp ugt i8 %base, %offset 169 %r = and i1 %no_underflow, %not_null 170 ret i1 %r 171} 172 173define i1 @exaustive_t5_not_null(i8 %base, i8 %offset) { 174; CHECK-LABEL: @exaustive_t5_not_null( 175; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 176; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 177; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 178; CHECK-NEXT: ret i1 [[NOT_NULL]] 179; 180 %adjusted = sub i8 %base, %offset 181 call void @use8(i8 %adjusted) 182 %not_null = icmp ne i8 %adjusted, 0 183 %no_underflow = icmp ugt i8 %base, %offset 184 %r = or i1 %no_underflow, %not_null 185 ret i1 %r 186} 187 188define i1 @exaustive_t6_false(i8 %base, i8 %offset) { 189; CHECK-LABEL: @exaustive_t6_false( 190; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 191; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 192; CHECK-NEXT: ret i1 false 193; 194 %adjusted = sub i8 %base, %offset 195 call void @use8(i8 %adjusted) 196 %not_null = icmp eq i8 %adjusted, 0 197 %no_underflow = icmp ugt i8 %base, %offset 198 %r = and i1 %no_underflow, %not_null 199 ret i1 %r 200} 201 202define i1 @exaustive_t7_bad(i8 %base, i8 %offset) { 203; CHECK-LABEL: @exaustive_t7_bad( 204; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 205; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 206; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0 207; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ugt i8 [[BASE]], [[OFFSET]] 208; CHECK-NEXT: [[R:%.*]] = or i1 [[NO_UNDERFLOW]], [[NOT_NULL]] 209; CHECK-NEXT: ret i1 [[R]] 210; 211 %adjusted = sub i8 %base, %offset 212 call void @use8(i8 %adjusted) 213 %not_null = icmp eq i8 %adjusted, 0 214 %no_underflow = icmp ugt i8 %base, %offset 215 %r = or i1 %no_underflow, %not_null 216 ret i1 %r 217} 218 219define i1 @exaustive_t8_bad(i8 %base, i8 %offset) { 220; CHECK-LABEL: @exaustive_t8_bad( 221; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 222; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 223; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 224; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]] 225; CHECK-NEXT: [[R:%.*]] = and i1 [[NO_UNDERFLOW]], [[NOT_NULL]] 226; CHECK-NEXT: ret i1 [[R]] 227; 228 %adjusted = sub i8 %base, %offset 229 call void @use8(i8 %adjusted) 230 %not_null = icmp ne i8 %adjusted, 0 231 %no_underflow = icmp ule i8 %base, %offset 232 %r = and i1 %no_underflow, %not_null 233 ret i1 %r 234} 235 236define i1 @exaustive_t9_true(i8 %base, i8 %offset) { 237; CHECK-LABEL: @exaustive_t9_true( 238; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 239; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 240; CHECK-NEXT: ret i1 true 241; 242 %adjusted = sub i8 %base, %offset 243 call void @use8(i8 %adjusted) 244 %not_null = icmp ne i8 %adjusted, 0 245 %no_underflow = icmp ule i8 %base, %offset 246 %r = or i1 %no_underflow, %not_null 247 ret i1 %r 248} 249 250define i1 @exaustive_t10_not_null(i8 %base, i8 %offset) { 251; CHECK-LABEL: @exaustive_t10_not_null( 252; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 253; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 254; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0 255; CHECK-NEXT: ret i1 [[NOT_NULL]] 256; 257 %adjusted = sub i8 %base, %offset 258 call void @use8(i8 %adjusted) 259 %not_null = icmp eq i8 %adjusted, 0 260 %no_underflow = icmp ule i8 %base, %offset 261 %r = and i1 %no_underflow, %not_null 262 ret i1 %r 263} 264 265define i1 @exaustive_t11_no_underflow(i8 %base, i8 %offset) { 266; CHECK-LABEL: @exaustive_t11_no_underflow( 267; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 268; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 269; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp ule i8 [[BASE]], [[OFFSET]] 270; CHECK-NEXT: ret i1 [[NO_UNDERFLOW]] 271; 272 %adjusted = sub i8 %base, %offset 273 call void @use8(i8 %adjusted) 274 %not_null = icmp eq i8 %adjusted, 0 275 %no_underflow = icmp ule i8 %base, %offset 276 %r = or i1 %no_underflow, %not_null 277 ret i1 %r 278} 279 280define i1 @exaustive_t12_bad(i8 %base, i8 %offset) { 281; CHECK-LABEL: @exaustive_t12_bad( 282; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 283; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 284; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne i8 [[ADJUSTED]], 0 285; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]] 286; CHECK-NEXT: [[R:%.*]] = and i1 [[NO_UNDERFLOW]], [[NOT_NULL]] 287; CHECK-NEXT: ret i1 [[R]] 288; 289 %adjusted = sub i8 %base, %offset 290 call void @use8(i8 %adjusted) 291 %not_null = icmp ne i8 %adjusted, 0 292 %no_underflow = icmp uge i8 %base, %offset 293 %r = and i1 %no_underflow, %not_null 294 ret i1 %r 295} 296 297define i1 @exaustive_t13_true(i8 %base, i8 %offset) { 298; CHECK-LABEL: @exaustive_t13_true( 299; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 300; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 301; CHECK-NEXT: ret i1 true 302; 303 %adjusted = sub i8 %base, %offset 304 call void @use8(i8 %adjusted) 305 %not_null = icmp ne i8 %adjusted, 0 306 %no_underflow = icmp uge i8 %base, %offset 307 %r = or i1 %no_underflow, %not_null 308 ret i1 %r 309} 310 311define i1 @exaustive_t14_not_null(i8 %base, i8 %offset) { 312; CHECK-LABEL: @exaustive_t14_not_null( 313; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 314; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 315; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq i8 [[ADJUSTED]], 0 316; CHECK-NEXT: ret i1 [[NOT_NULL]] 317; 318 %adjusted = sub i8 %base, %offset 319 call void @use8(i8 %adjusted) 320 %not_null = icmp eq i8 %adjusted, 0 321 %no_underflow = icmp uge i8 %base, %offset 322 %r = and i1 %no_underflow, %not_null 323 ret i1 %r 324} 325 326define i1 @exaustive_t15_no_underflow(i8 %base, i8 %offset) { 327; CHECK-LABEL: @exaustive_t15_no_underflow( 328; CHECK-NEXT: [[ADJUSTED:%.*]] = sub i8 [[BASE:%.*]], [[OFFSET:%.*]] 329; CHECK-NEXT: call void @use8(i8 [[ADJUSTED]]) 330; CHECK-NEXT: [[NO_UNDERFLOW:%.*]] = icmp uge i8 [[BASE]], [[OFFSET]] 331; CHECK-NEXT: ret i1 [[NO_UNDERFLOW]] 332; 333 %adjusted = sub i8 %base, %offset 334 call void @use8(i8 %adjusted) 335 %not_null = icmp eq i8 %adjusted, 0 336 %no_underflow = icmp uge i8 %base, %offset 337 %r = or i1 %no_underflow, %not_null 338 ret i1 %r 339} 340