This is an archive of the discontinued LLVM Phabricator instance.

[ValueTracking] Allow min/max detection to see through casts.
ClosedPublic

Authored by jmolloy on May 13 2015, 7:34 AM.

Details

Reviewers
reames
majnemer
Summary

This teaches the min/max idiom detector in ValueTracking to see through
casts such as SExt/ZExt/Trunc. SCEV can already do this, so we're bringing
non-SCEV analyses up to the same level.

The returned LHS/RHS will not match the type of the original SelectInst
any more, so a CastOp is returned too to inform the caller how to
convert to the SelectInst's type.

UIToFP/FPToSI are not yet handled - that would require this function to be able to return floating point min/max, which I intend to do in the future.

No in-tree users yet; this will be used by InstCombine in a followup and will be tested there.

Diff Detail

Repository
rL LLVM

Event Timeline

jmolloy updated this revision to Diff 25685.May 13 2015, 7:34 AM
jmolloy retitled this revision from to [ValueTracking] Allow min/max detection to see through casts..
jmolloy updated this object.
jmolloy edited the test plan for this revision. (Show Details)
jmolloy added a reviewer: reames.
jmolloy set the repository for this revision to rL LLVM.
jmolloy added a reviewer: majnemer.
jmolloy added a subscriber: Unknown Object (MLST).
reames edited edge metadata.May 13 2015, 9:40 AM

No obvious problems spotted, but I'd like to see the updated diff after comments applied so that I can be more confident of the change before signing off.

lib/Analysis/ValueTracking.cpp
3211

Missing context here makes it hard to review change. Please upload full diff.

3279

I find it odd that these routines don't already exist. Have you looked at various subclasses of Constant and ConstantExpr?

If they don't already exist, I'd prefer to see them placed as members on Constant or an appropriate class.

3344

This loop usage is a bit confusing. It would probably be clearer to extract out a helper function and call it twice.

majnemer added inline comments.May 13 2015, 11:47 PM
lib/Analysis/ValueTracking.cpp
3279

Right, how is this different from ConstantExpr::getTrunc ?

3290–3292

No need for the extra indentation here, just stick return nullptr at the end of the function.

3295

Likewise, why can't this be ConstantExpr::getSExt

3311

Likewise, why can't this be ConstantExpr::getZExt

3327

It'd be nice if V was const qualified.

3344

Agreed.

jmolloy updated this revision to Diff 25762.May 14 2015, 2:55 AM
jmolloy edited edge metadata.

Hi Philip, David,

Thanks for your review! I've updated the diff. I looked for public versions of those helper functions but couldn't find them - I didn't think to check ConstantExpr! :(

All comments addressed. The only thing I'm not too keen on is the const_cast, I feel like raptors will come and attack me whenever it's used. But without it the "const" goes viral and takes over everything, including the return values "LHS" and "RHS".

James

majnemer edited edge metadata.May 14 2015, 10:48 AM

Hi Philip, David,

Thanks for your review! I've updated the diff. I looked for public versions of those helper functions but couldn't find them - I didn't think to check ConstantExpr! :(

All comments addressed. The only thing I'm not too keen on is the const_cast, I feel like raptors will come and attack me whenever it's used. But without it the "const" goes viral and takes over everything, including the return values "LHS" and "RHS".

James

In that case, let's just skip the const.

lib/Analysis/ValueTracking.cpp
3291–3293

Would it be equally correct to phrase this like:

if (ICI->isSigned())
  if (Constant *Trunc = ConstantExpr::getTrunc(Op2, Castee->getType());
    return Trunc;

?

3297–3299

!ICI->isSigned() will return true for NE/EQ. Perhaps:

if (ICI->isUnsigned())
  if (Constant *Trunc = ConstantExpr::getTrunc(Op2, Castee->getType());
    return Trunc;
3302–3304

You may want to wrap the call to getIntegerCast with if (!ICI->isEquality()) so you won't create the cast if the comparison is == or !=.

3328–3332

I think it'd be more clear if you switched those cast<Instruction> over to cast<CastInst>.

jmolloy updated this revision to Diff 25798.May 14 2015, 12:04 PM
jmolloy edited edge metadata.

Hi David,

Those comments make sense. Thanks!

I've changed !isSigned() to isUnsigned(), but instead of checking for !equality everywhere I've just added a quick bailout right at the start.

Cheers,

James

jmolloy updated this revision to Diff 25799.May 14 2015, 12:30 PM

.... and now with conflict markers removed ...

jmolloy updated this revision to Diff 25800.May 14 2015, 12:34 PM
majnemer added inline comments.May 14 2015, 3:38 PM
include/llvm/Analysis/ValueTracking.h
294

Please clang-format this.

lib/Analysis/ValueTracking.cpp
3279–3303

TrueVal and FalseVal are not accurate names and the switch/case structure is a little superfluous. Castee->getType() is just Op1->getSrcTy().

I think the following is equivalent:

static Constant *lookThroughCast(ICmpInst *ICI, Value *V1, Value *V2,
                                 Instruction::CastOps *CastOp) {
  auto *CI = dyn_cast<CastInst>(V1);
  auto *C = dyn_cast<Constant>(V2);
  if (!CI || !C)
    return nullptr;

  *CastOp = CI->getOpcode();

  if ((isa<SExtInst>(CI) && ICI->isSigned()) ||
      (isa<ZExtInst>(CI) && ICI->isUnsigned()))
    return ConstantExpr::getTrunc(C, CI->getSrcTy());

  if (isa<TruncInst>(CI))
    return ConstantExpr::getIntegerCast(C, CI->getSrcTy(), ICI->isSigned());

  return nullptr;
}
3321–3322

I don't think this will compile, CI isn't defined.

3330

No need to make this else if.

jmolloy updated this revision to Diff 25850.May 15 2015, 2:52 AM

Hi David,

Apologies for the broken code; I have a bunch of patches downstream in my git history and messed up slightly with the rebase.

I've tested this patch in isolation and it compiles and works fine. Thanks for all the suggestions so far, I'm slightly embarrassed that you've essentially rewritten this entire patch for me but your version looks far superior!

Cheers,

James

majnemer accepted this revision.May 15 2015, 8:56 AM
majnemer edited edge metadata.

LGTM

This revision is now accepted and ready to land.May 15 2015, 8:56 AM
jmolloy closed this revision.Jul 17 2015, 2:21 AM