llvm.org GIT mirror
[LVI] Make LVI smarter about comparisons with non-constants Make LVI smarter about comparisons with a non-constant. For example, a s< b constraints a to be in [INT_MIN, INT_MAX) range. This is a part of https://llvm.org/bugs/show_bug.cgi?id=28620 fix. Reviewed By: sanjoy Differential Revision: https://reviews.llvm.org/D23205 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278122 91177308-0d34-0410-b5e6-96231b3b80d8 Artur Pilipenko 3 years ago
2 changed file(s) with 153 addition(s) and 24 deletion(s).
 1196 1196 Result = LVILatticeVal::getNot(cast(RHS)); 1197 1197 return true; 1198 1198 } 1199 1200 // Recognize the range checking idiom that InstCombine produces. 1201 // (X+C1) u< C2 --> [-C1, C2-C1) 1202 ConstantInt *Offset = nullptr; 1203 if (Predicate == ICmpInst::ICMP_ULT) 1204 match(LHS, m_Add(m_Specific(Val), m_ConstantInt(Offset))); 1205 1206 ConstantInt *CI = dyn_cast(RHS); 1207 if (CI && (LHS == Val || Offset)) { 1208 // Calculate the range of values that are allowed by the comparison 1209 ConstantRange CmpRange(CI->getValue()); 1210 1211 // If we're interested in the false dest, invert the condition 1212 CmpInst::Predicate Pred = 1213 isTrueDest ? Predicate : CmpInst::getInversePredicate(Predicate); 1214 ConstantRange TrueValues = 1215 ConstantRange::makeAllowedICmpRegion(Pred, CmpRange); 1216 1217 if (Offset) // Apply the offset from above. 1218 TrueValues = TrueValues.subtract(Offset->getValue()); 1219 1220 Result = LVILatticeVal::getRange(std::move(TrueValues)); 1221 return true; 1222 }⏎ 1199 }⏎ 1200 1201 if (!Val->getType()->isIntegerTy()) 1202 return false; 1203 1204 // Use ConstantRange::makeAllowedICmpRegion in order to determine the possible 1205 // range of Val guaranteed by the condition. Recognize comparisons in the from 1206 // of: 1207 // icmp Val, ... 1208 // icmp ult (add Val, Offset), ... 1209 // The latter is the range checking idiom that InstCombine produces. Subtract 1210 // the offset from the allowed range for RHS in this case. 1211 1212 // Val or (add Val, Offset) can be on either hand of the comparison 1213 if (LHS != Val && !match(LHS, m_Add(m_Specific(Val), m_ConstantInt()))) { 1214 std::swap(LHS, RHS); 1215 Predicate = CmpInst::getSwappedPredicate(Predicate); 1216 } 1217 1218 ConstantInt *Offset = nullptr; 1219 if (Predicate == ICmpInst::ICMP_ULT) 1220 match(LHS, m_Add(m_Specific(Val), m_ConstantInt(Offset))); 1221 1222 if (LHS == Val || Offset) { 1223 // Calculate the range of values that are allowed by the comparison 1224 ConstantRange RHSRange(RHS->getType()->getIntegerBitWidth(), 1225 /*isFullSet=*/true); 1226 if (ConstantInt *CI = dyn_cast(RHS)) 1227 RHSRange = ConstantRange(CI->getValue()); 1228 1229 // If we're interested in the false dest, invert the condition 1230 CmpInst::Predicate Pred = 1231 isTrueDest ? Predicate : CmpInst::getInversePredicate(Predicate); 1232 ConstantRange TrueValues = 1233 ConstantRange::makeAllowedICmpRegion(Pred, RHSRange); 1234 1235 if (Offset) // Apply the offset from above. 1236 TrueValues = TrueValues.subtract(Offset->getValue()); 1237 1238 Result = LVILatticeVal::getRange(std::move(TrueValues)); 1239 return true; 1223 1240 } 1224 1241 1225 1242 return false;
 202 202 next: 203 203 ret i1 %test 204 204 } 205 206 define i32 @test12(i32 %a, i32 %b) { 207 ; CHECK-LABEL: @test12( 208 ; CHECK: then: 209 ; CHECK-NEXT: br i1 false, label %end, label %else 210 %cmp = icmp ult i32 %a, %b 211 br i1 %cmp, label %then, label %else 212 213 then: 214 %dead = icmp eq i32 %a, -1 215 br i1 %dead, label %end, label %else 216 217 else: 218 ret i32 1 219 220 end: 221 ret i32 2 222 } 223 224 define i32 @test12_swap(i32 %a, i32 %b) { 225 ; CHECK-LABEL: @test12_swap( 226 ; CHECK: then: 227 ; CHECK-NEXT: br i1 false, label %end, label %else 228 %cmp = icmp ugt i32 %b, %a 229 br i1 %cmp, label %then, label %else 230 231 then: 232 %dead = icmp eq i32 %a, -1 233 br i1 %dead, label %end, label %else 234 235 else: 236 ret i32 1 237 238 end: 239 ret i32 2 240 } 241 242 define i32 @test12_neg(i32 %a, i32 %b) { 243 ; The same as @test12 but the second check is on the false path 244 ; CHECK-LABEL: @test12_neg( 245 ; CHECK: else: 246 ; CHECK-NEXT: %alive = icmp eq i32 %a, -1 247 %cmp = icmp ult i32 %a, %b 248 br i1 %cmp, label %then, label %else 249 250 else: 251 %alive = icmp eq i32 %a, -1 252 br i1 %alive, label %end, label %then 253 254 then: 255 ret i32 1 256 257 end: 258 ret i32 2 259 } 260 261 define i32 @test12_signed(i32 %a, i32 %b) { 262 ; The same as @test12 but with signed comparison 263 ; CHECK-LABEL: @test12_signed( 264 ; CHECK: then: 265 ; CHECK-NEXT: br i1 false, label %end, label %else 266 %cmp = icmp slt i32 %a, %b 267 br i1 %cmp, label %then, label %else 268 269 then: 270 %dead = icmp eq i32 %a, 2147483647 271 br i1 %dead, label %end, label %else 272 273 else: 274 ret i32 1 275 276 end: 277 ret i32 2 278 } 279 280 define i32 @test13(i32 %a, i32 %b) { 281 ; CHECK-LABEL: @test13( 282 ; CHECK: then: 283 ; CHECK-NEXT: br i1 false, label %end, label %else 284 %a.off = add i32 %a, -8 285 %cmp = icmp ult i32 %a.off, %b 286 br i1 %cmp, label %then, label %else 287 288 then: 289 %dead = icmp eq i32 %a, 7 290 br i1 %dead, label %end, label %else 291 292 else: 293 ret i32 1 294 295 end: 296 ret i32 2 297 } 298 299 define i32 @test13_swap(i32 %a, i32 %b) { 300 ; CHECK-LABEL: @test13_swap( 301 ; CHECK: then: 302 ; CHECK-NEXT: br i1 false, label %end, label %else 303 %a.off = add i32 %a, -8 304 %cmp = icmp ugt i32 %b, %a.off 305 br i1 %cmp, label %then, label %else 306 307 then: 308 %dead = icmp eq i32 %a, 7 309 br i1 %dead, label %end, label %else 310 311 else: 312 ret i32 1 313 314 end: 315 ret i32 2 316 }