Skip to content

Commit 84fb88f

Browse files
author
git apple-llvm automerger
committed
Merge commit 'a7101379d75e' from llvm.org/release/17.x into stable/20230725
2 parents 7368f51 + a710137 commit 84fb88f

File tree

2 files changed

+160
-41
lines changed

2 files changed

+160
-41
lines changed

llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -470,58 +470,48 @@ static bool processBinOp(BinaryOperator *BinOp, LazyValueInfo *LVI);
470470
// because it is negation-invariant.
471471
static bool processAbsIntrinsic(IntrinsicInst *II, LazyValueInfo *LVI) {
472472
Value *X = II->getArgOperand(0);
473-
bool IsIntMinPoison = cast<ConstantInt>(II->getArgOperand(1))->isOne();
474-
475473
Type *Ty = X->getType();
476-
Constant *IntMin =
477-
ConstantInt::get(Ty, APInt::getSignedMinValue(Ty->getScalarSizeInBits()));
478-
LazyValueInfo::Tristate Result;
474+
if (!Ty->isIntegerTy())
475+
return false;
476+
477+
bool IsIntMinPoison = cast<ConstantInt>(II->getArgOperand(1))->isOne();
478+
APInt IntMin = APInt::getSignedMinValue(Ty->getScalarSizeInBits());
479+
ConstantRange Range = LVI->getConstantRangeAtUse(
480+
II->getOperandUse(0), /*UndefAllowed*/ IsIntMinPoison);
479481

480482
// Is X in [0, IntMin]? NOTE: INT_MIN is fine!
481-
Result = LVI->getPredicateAt(CmpInst::Predicate::ICMP_ULE, X, IntMin, II,
482-
/*UseBlockValue=*/true);
483-
if (Result == LazyValueInfo::True) {
483+
if (Range.icmp(CmpInst::ICMP_ULE, IntMin)) {
484484
++NumAbs;
485485
II->replaceAllUsesWith(X);
486486
II->eraseFromParent();
487487
return true;
488488
}
489489

490490
// Is X in [IntMin, 0]? NOTE: INT_MIN is fine!
491-
Constant *Zero = ConstantInt::getNullValue(Ty);
492-
Result = LVI->getPredicateAt(CmpInst::Predicate::ICMP_SLE, X, Zero, II,
493-
/*UseBlockValue=*/true);
494-
assert(Result != LazyValueInfo::False && "Should have been handled already.");
495-
496-
if (Result == LazyValueInfo::Unknown) {
497-
// Argument's range crosses zero.
498-
bool Changed = false;
499-
if (!IsIntMinPoison) {
500-
// Can we at least tell that the argument is never INT_MIN?
501-
Result = LVI->getPredicateAt(CmpInst::Predicate::ICMP_NE, X, IntMin, II,
502-
/*UseBlockValue=*/true);
503-
if (Result == LazyValueInfo::True) {
504-
++NumNSW;
505-
++NumSubNSW;
506-
II->setArgOperand(1, ConstantInt::getTrue(II->getContext()));
507-
Changed = true;
508-
}
509-
}
510-
return Changed;
511-
}
491+
if (Range.getSignedMax().isNonPositive()) {
492+
IRBuilder<> B(II);
493+
Value *NegX = B.CreateNeg(X, II->getName(), /*HasNUW=*/false,
494+
/*HasNSW=*/IsIntMinPoison);
495+
++NumAbs;
496+
II->replaceAllUsesWith(NegX);
497+
II->eraseFromParent();
512498

513-
IRBuilder<> B(II);
514-
Value *NegX = B.CreateNeg(X, II->getName(), /*HasNUW=*/false,
515-
/*HasNSW=*/IsIntMinPoison);
516-
++NumAbs;
517-
II->replaceAllUsesWith(NegX);
518-
II->eraseFromParent();
499+
// See if we can infer some no-wrap flags.
500+
if (auto *BO = dyn_cast<BinaryOperator>(NegX))
501+
processBinOp(BO, LVI);
519502

520-
// See if we can infer some no-wrap flags.
521-
if (auto *BO = dyn_cast<BinaryOperator>(NegX))
522-
processBinOp(BO, LVI);
503+
return true;
504+
}
523505

524-
return true;
506+
// Argument's range crosses zero.
507+
// Can we at least tell that the argument is never INT_MIN?
508+
if (!IsIntMinPoison && !Range.contains(IntMin)) {
509+
++NumNSW;
510+
++NumSubNSW;
511+
II->setArgOperand(1, ConstantInt::getTrue(II->getContext()));
512+
return true;
513+
}
514+
return false;
525515
}
526516

527517
// See if this min/max intrinsic always picks it's one specific operand.

llvm/test/Transforms/CorrelatedValuePropagation/abs.ll

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
33

44
declare void @llvm.assume(i1)
5+
declare i32 @llvm.abs.i32(i32, i1)
56
declare i8 @llvm.abs.i8(i8, i1)
67
declare i1 @llvm.abs.i1(i1, i1)
78

@@ -379,11 +380,139 @@ define i8 @test27(i8 %x) {
379380

380381
define i1 @pr59887(i1 %x, i1 %c) {
381382
; CHECK-LABEL: @pr59887(
382-
; CHECK-NEXT: [[ABS:%.*]] = call i1 @llvm.abs.i1(i1 [[X:%.*]], i1 false)
383-
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C:%.*]], i1 [[ABS]], i1 false
383+
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C:%.*]], i1 [[X:%.*]], i1 false
384384
; CHECK-NEXT: ret i1 [[RES]]
385385
;
386386
%abs = call i1 @llvm.abs.i1(i1 %x, i1 false)
387387
%res = select i1 %c, i1 %abs, i1 false
388388
ret i1 %res
389389
}
390+
391+
; Because of `undef`, We can't delete `abs`.
392+
; We can't replace the `abs` argument with true either.
393+
define i32 @pr68381_undef_abs_false(i1 %c0, i1 %c1, i8 %v1) {
394+
; CHECK-LABEL: @pr68381_undef_abs_false(
395+
; CHECK-NEXT: start:
396+
; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
397+
; CHECK: bb0:
398+
; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32
399+
; CHECK-NEXT: br label [[BB1]]
400+
; CHECK: bb1:
401+
; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ]
402+
; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]
403+
; CHECK: bb2:
404+
; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false)
405+
; CHECK-NEXT: ret i32 [[Z]]
406+
;
407+
start:
408+
br i1 %c0, label %bb0, label %bb1
409+
410+
bb0:
411+
%v1_i32 = zext i8 %v1 to i32
412+
br label %bb1
413+
414+
bb1:
415+
%x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ]
416+
br i1 %c1, label %bb0, label %bb2
417+
418+
bb2:
419+
%z = call i32 @llvm.abs.i32(i32 %x, i1 false)
420+
ret i32 %z
421+
}
422+
423+
; Because of `and`, we can delete `abs`.
424+
define i32 @pr68381_undef_abs_false_and(i1 %c0, i1 %c1, i8 %v1) {
425+
; CHECK-LABEL: @pr68381_undef_abs_false_and(
426+
; CHECK-NEXT: start:
427+
; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
428+
; CHECK: bb0:
429+
; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32
430+
; CHECK-NEXT: br label [[BB1]]
431+
; CHECK: bb1:
432+
; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ]
433+
; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]
434+
; CHECK: bb2:
435+
; CHECK-NEXT: [[Y:%.*]] = and i32 [[X]], 255
436+
; CHECK-NEXT: ret i32 [[Y]]
437+
;
438+
start:
439+
br i1 %c0, label %bb0, label %bb1
440+
441+
bb0:
442+
%v1_i32 = zext i8 %v1 to i32
443+
br label %bb1
444+
445+
bb1:
446+
%x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ]
447+
br i1 %c1, label %bb0, label %bb2
448+
449+
bb2:
450+
%y = and i32 %x, 255
451+
%z = call i32 @llvm.abs.i32(i32 %y, i1 false)
452+
ret i32 %z
453+
}
454+
455+
; Because of `undef`, we can't replace `abs` with `sub`.
456+
define i32 @pr68381_undef_abs_false_sub(i1 %c0, i1 %c1, i32 %v1, i32 %v2) {
457+
; CHECK-LABEL: @pr68381_undef_abs_false_sub(
458+
; CHECK-NEXT: start:
459+
; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
460+
; CHECK: bb0:
461+
; CHECK-NEXT: [[V3:%.*]] = add i32 [[V1:%.*]], [[V2:%.*]]
462+
; CHECK-NEXT: [[LIM:%.*]] = icmp sle i32 [[V3]], -1
463+
; CHECK-NEXT: call void @llvm.assume(i1 [[LIM]])
464+
; CHECK-NEXT: br label [[BB1]]
465+
; CHECK: bb1:
466+
; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V3]], [[BB0]] ], [ undef, [[START:%.*]] ]
467+
; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]
468+
; CHECK: bb2:
469+
; CHECK-NEXT: [[Z:%.*]] = call i32 @llvm.abs.i32(i32 [[X]], i1 false)
470+
; CHECK-NEXT: ret i32 [[Z]]
471+
;
472+
start:
473+
br i1 %c0, label %bb0, label %bb1
474+
475+
bb0:
476+
%v3 = add i32 %v1, %v2
477+
%lim = icmp sle i32 %v3, -1
478+
call void @llvm.assume(i1 %lim)
479+
br label %bb1
480+
481+
bb1:
482+
%x = phi i32 [ %v3, %bb0 ], [ undef, %start ]
483+
br i1 %c1, label %bb0, label %bb2
484+
485+
bb2:
486+
%z = call i32 @llvm.abs.i32(i32 %x, i1 false)
487+
ret i32 %z
488+
}
489+
490+
; We can delete `abs`.
491+
define i32 @pr68381_undef_abs_true(i1 %c0, i1 %c1, i8 %v1) {
492+
; CHECK-LABEL: @pr68381_undef_abs_true(
493+
; CHECK-NEXT: start:
494+
; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
495+
; CHECK: bb0:
496+
; CHECK-NEXT: [[V1_I32:%.*]] = zext i8 [[V1:%.*]] to i32
497+
; CHECK-NEXT: br label [[BB1]]
498+
; CHECK: bb1:
499+
; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[V1_I32]], [[BB0]] ], [ undef, [[START:%.*]] ]
500+
; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB0]], label [[BB2:%.*]]
501+
; CHECK: bb2:
502+
; CHECK-NEXT: ret i32 [[X]]
503+
;
504+
start:
505+
br i1 %c0, label %bb0, label %bb1
506+
507+
bb0:
508+
%v1_i32 = zext i8 %v1 to i32
509+
br label %bb1
510+
511+
bb1:
512+
%x = phi i32 [ %v1_i32, %bb0 ], [ undef, %start ]
513+
br i1 %c1, label %bb0, label %bb2
514+
515+
bb2:
516+
%z = call i32 @llvm.abs.i32(i32 %x, i1 true)
517+
ret i32 %z
518+
}

0 commit comments

Comments
 (0)