-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[InstCombine] Widen Sel width after Cmp to generate Max/Min intrinsics. #118932
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
4bf3009
3d11a3c
9b4de8e
69569af
c6d09f1
d81963f
ca733bd
089ab55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -8781,40 +8781,12 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred, | |||||
return matchFastFloatClamp(Pred, CmpLHS, CmpRHS, TrueVal, FalseVal, LHS, RHS); | ||||||
} | ||||||
|
||||||
/// Helps to match a select pattern in case of a type mismatch. | ||||||
/// | ||||||
/// The function processes the case when type of true and false values of a | ||||||
/// select instruction differs from type of the cmp instruction operands because | ||||||
/// of a cast instruction. The function checks if it is legal to move the cast | ||||||
/// operation after "select". If yes, it returns the new second value of | ||||||
/// "select" (with the assumption that cast is moved): | ||||||
/// 1. As operand of cast instruction when both values of "select" are same cast | ||||||
/// instructions. | ||||||
/// 2. As restored constant (by applying reverse cast operation) when the first | ||||||
/// value of the "select" is a cast operation and the second value is a | ||||||
/// constant. | ||||||
/// NOTE: We return only the new second value because the first value could be | ||||||
/// accessed as operand of cast instruction. | ||||||
static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2, | ||||||
Instruction::CastOps *CastOp) { | ||||||
auto *Cast1 = dyn_cast<CastInst>(V1); | ||||||
if (!Cast1) | ||||||
return nullptr; | ||||||
|
||||||
*CastOp = Cast1->getOpcode(); | ||||||
static Value *lookThroughCastConst(CmpInst *CmpI, CastInst *Cast1, Constant *C, | ||||||
Instruction::CastOps *CastOp) { | ||||||
Type *SrcTy = Cast1->getSrcTy(); | ||||||
if (auto *Cast2 = dyn_cast<CastInst>(V2)) { | ||||||
// If V1 and V2 are both the same cast from the same type, look through V1. | ||||||
if (*CastOp == Cast2->getOpcode() && SrcTy == Cast2->getSrcTy()) | ||||||
return Cast2->getOperand(0); | ||||||
return nullptr; | ||||||
} | ||||||
|
||||||
auto *C = dyn_cast<Constant>(V2); | ||||||
if (!C) | ||||||
return nullptr; | ||||||
|
||||||
const DataLayout &DL = CmpI->getDataLayout(); | ||||||
|
||||||
*CastOp = Cast1->getOpcode(); | ||||||
Constant *CastedTo = nullptr; | ||||||
switch (*CastOp) { | ||||||
case Instruction::ZExt: | ||||||
|
@@ -8890,6 +8862,62 @@ static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2, | |||||
return CastedTo; | ||||||
} | ||||||
|
||||||
/// Helps to match a select pattern in case of a type mismatch. | ||||||
/// | ||||||
/// The function processes the case when type of true and false values of a | ||||||
/// select instruction differs from type of the cmp instruction operands because | ||||||
/// of a cast instruction. The function checks if it is legal to move the cast | ||||||
/// operation after "select". If yes, it returns the new second value of | ||||||
/// "select" (with the assumption that cast is moved): | ||||||
/// 1. As operand of cast instruction when both values of "select" are same cast | ||||||
/// instructions. | ||||||
/// 2. As restored constant (by applying reverse cast operation) when the first | ||||||
/// value of the "select" is a cast operation and the second value is a | ||||||
/// constant. It is implemented in lookThroughCastConst(). | ||||||
/// 3. As one operand is cast instruction and the other is not. The operands in | ||||||
/// sel(cmp) are in different type integer. | ||||||
/// NOTE: We return only the new second value because the first value could be | ||||||
/// accessed as operand of cast instruction. | ||||||
static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2, | ||||||
Instruction::CastOps *CastOp) { | ||||||
auto *Cast1 = dyn_cast<CastInst>(V1); | ||||||
if (!Cast1) | ||||||
return nullptr; | ||||||
|
||||||
*CastOp = Cast1->getOpcode(); | ||||||
Type *SrcTy = Cast1->getSrcTy(); | ||||||
if (auto *Cast2 = dyn_cast<CastInst>(V2)) { | ||||||
// If V1 and V2 are both the same cast from the same type, look through V1. | ||||||
if (*CastOp == Cast2->getOpcode() && SrcTy == Cast2->getSrcTy()) | ||||||
return Cast2->getOperand(0); | ||||||
return nullptr; | ||||||
} | ||||||
|
||||||
auto *C = dyn_cast<Constant>(V2); | ||||||
if (C) | ||||||
return lookThroughCastConst(CmpI, Cast1, C, CastOp); | ||||||
|
||||||
Value *CastedTo = nullptr; | ||||||
if (*CastOp == Instruction::Trunc) { | ||||||
if (match(CmpI->getOperand(1), m_ZExtOrSExt(m_Specific(V2))) && | ||||||
V2->getType() == Cast1->getType()) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still think this check is unnecessary. Can you replace it with an assertion? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry @dtcxzyw , I don't understand which check you think is unnecessary? Could you please explain me more? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We always pass two arms of a select into this function. If I am not missing something, the type of |
||||||
// Here we have the following case: | ||||||
// %y_ext = sext iK %y to iN | ||||||
// %cond = cmp iN %x, %y_ext | ||||||
// %tr = trunc iN %x to iK | ||||||
// %narrowsel = select i1 %cond, iK %tr, iK %y | ||||||
// | ||||||
// We can always move trunc after select operation: | ||||||
// %y_ext = sext iK %y to iN | ||||||
// %cond = cmp iN %x, %y_ext | ||||||
// %widesel = select i1 %cond, iN %x, iN%y_ext | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
// %tr = trunc iN %widesel to iK | ||||||
CastedTo = CmpI->getOperand(1); | ||||||
} | ||||||
} | ||||||
|
||||||
return CastedTo; | ||||||
} | ||||||
SelectPatternResult llvm::matchSelectPattern(Value *V, Value *&LHS, Value *&RHS, | ||||||
Instruction::CastOps *CastOp, | ||||||
unsigned Depth) { | ||||||
|
Uh oh!
There was an error while loading. Please reload this page.