Skip to content

Commit 22a280d

Browse files
authored
LICM: teach hoistMinMax about samesign (#122730)
Follow up on 4a0d53a (PatternMatch: migrate to CmpPredicate) to get rid of one of the FIXMEs it introduced by replacing a predicate comparison with CmpPredicate::getMatching.
1 parent e3cd88a commit 22a280d

File tree

2 files changed

+69
-9
lines changed

2 files changed

+69
-9
lines changed

llvm/lib/Transforms/Scalar/LICM.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,16 +2453,17 @@ static bool hoistMinMax(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
24532453
if (!MatchICmpAgainstInvariant(Cond1, P1, LHS1, RHS1) ||
24542454
!MatchICmpAgainstInvariant(Cond2, P2, LHS2, RHS2))
24552455
return false;
2456-
// FIXME: Use CmpPredicate::getMatching here.
2457-
if (P1 != static_cast<CmpInst::Predicate>(P2) || LHS1 != LHS2)
2456+
auto MatchingPred = CmpPredicate::getMatching(P1, P2);
2457+
if (!MatchingPred || LHS1 != LHS2)
24582458
return false;
24592459

24602460
// Everything is fine, we can do the transform.
2461-
bool UseMin = ICmpInst::isLT(P1) || ICmpInst::isLE(P1);
2461+
bool UseMin = ICmpInst::isLT(*MatchingPred) || ICmpInst::isLE(*MatchingPred);
24622462
assert(
2463-
(UseMin || ICmpInst::isGT(P1) || ICmpInst::isGE(P1)) &&
2463+
(UseMin || ICmpInst::isGT(*MatchingPred) ||
2464+
ICmpInst::isGE(*MatchingPred)) &&
24642465
"Relational predicate is either less (or equal) or greater (or equal)!");
2465-
Intrinsic::ID id = ICmpInst::isSigned(P1)
2466+
Intrinsic::ID id = ICmpInst::isSigned(*MatchingPred)
24662467
? (UseMin ? Intrinsic::smin : Intrinsic::smax)
24672468
: (UseMin ? Intrinsic::umin : Intrinsic::umax);
24682469
auto *Preheader = L.getLoopPreheader();
@@ -2475,11 +2476,12 @@ static bool hoistMinMax(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo,
24752476
if (isa<SelectInst>(I))
24762477
RHS2 = Builder.CreateFreeze(RHS2, RHS2->getName() + ".fr");
24772478
Value *NewRHS = Builder.CreateBinaryIntrinsic(
2478-
id, RHS1, RHS2, nullptr, StringRef("invariant.") +
2479-
(ICmpInst::isSigned(P1) ? "s" : "u") +
2480-
(UseMin ? "min" : "max"));
2479+
id, RHS1, RHS2, nullptr,
2480+
StringRef("invariant.") +
2481+
(ICmpInst::isSigned(*MatchingPred) ? "s" : "u") +
2482+
(UseMin ? "min" : "max"));
24812483
Builder.SetInsertPoint(&I);
2482-
ICmpInst::Predicate P = P1;
2484+
ICmpInst::Predicate P = *MatchingPred;
24832485
if (Inverse)
24842486
P = ICmpInst::getInversePredicate(P);
24852487
Value *NewCond = Builder.CreateICmp(P, LHS1, NewRHS);

llvm/test/Transforms/LICM/min_max.ll

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,35 @@ exit:
242242
ret i32 %iv
243243
}
244244

245+
define i32 @test_sgt_samesign(i32 %start, i32 %inv_1, i32 %inv_2) {
246+
; CHECK-LABEL: @test_sgt_samesign(
247+
; CHECK-NEXT: entry:
248+
; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
249+
; CHECK-NEXT: br label [[LOOP:%.*]]
250+
; CHECK: loop:
251+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
252+
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sgt i32 [[IV]], [[INVARIANT_SMAX]]
253+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
254+
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
255+
; CHECK: exit:
256+
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
257+
; CHECK-NEXT: ret i32 [[IV_LCSSA]]
258+
;
259+
entry:
260+
br label %loop
261+
262+
loop:
263+
%iv = phi i32 [%start, %entry], [%iv.next, %loop]
264+
%cmp_1 = icmp samesign ugt i32 %iv, %inv_1
265+
%cmp_2 = icmp sgt i32 %iv, %inv_2
266+
%loop_cond = and i1 %cmp_1, %cmp_2
267+
%iv.next = add i32 %iv, 1
268+
br i1 %loop_cond, label %loop, label %exit
269+
270+
exit:
271+
ret i32 %iv
272+
}
273+
245274
; turn to %iv >=s smax(inv_1, inv_2) and hoist it out of loop.
246275
define i32 @test_sge(i32 %start, i32 %inv_1, i32 %inv_2) {
247276
; CHECK-LABEL: @test_sge(
@@ -272,6 +301,35 @@ exit:
272301
ret i32 %iv
273302
}
274303

304+
define i32 @test_sge_samesign(i32 %start, i32 %inv_1, i32 %inv_2) {
305+
; CHECK-LABEL: @test_sge_samesign(
306+
; CHECK-NEXT: entry:
307+
; CHECK-NEXT: [[INVARIANT_SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INV_1:%.*]], i32 [[INV_2:%.*]])
308+
; CHECK-NEXT: br label [[LOOP:%.*]]
309+
; CHECK: loop:
310+
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
311+
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp sge i32 [[IV]], [[INVARIANT_SMAX]]
312+
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
313+
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
314+
; CHECK: exit:
315+
; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i32 [ [[IV]], [[LOOP]] ]
316+
; CHECK-NEXT: ret i32 [[IV_LCSSA]]
317+
;
318+
entry:
319+
br label %loop
320+
321+
loop:
322+
%iv = phi i32 [%start, %entry], [%iv.next, %loop]
323+
%cmp_1 = icmp sge i32 %iv, %inv_1
324+
%cmp_2 = icmp samesign uge i32 %iv, %inv_2
325+
%loop_cond = and i1 %cmp_1, %cmp_2
326+
%iv.next = add i32 %iv, 1
327+
br i1 %loop_cond, label %loop, label %exit
328+
329+
exit:
330+
ret i32 %iv
331+
}
332+
275333
; Turn OR to AND and handle accordingly.
276334
define i32 @test_ult_inv(i32 %start, i32 %inv_1, i32 %inv_2) {
277335
; CHECK-LABEL: @test_ult_inv(

0 commit comments

Comments
 (0)