Skip to content

Commit e317ee2

Browse files
committed
Made suggested changes but couldn't generalize to div/rem as suggested
"If it is the case, you should generalize it to handle most of binops (excluding div/rem), then use simplifyBinOp and simplifyBinaryIntrinsic to check if min/max(c1 binop c2, c3) folds to c3."
1 parent 19f60a9 commit e317ee2

File tree

1 file changed

+43
-41
lines changed

1 file changed

+43
-41
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,75 +1172,75 @@ static Instruction *moveAddAfterMinMax(IntrinsicInst *II,
11721172
: BinaryOperator::CreateNUWAdd(NewMinMax, Add->getOperand(1));
11731173
}
11741174

1175-
//Try canonicalize min/max(x << shamt, c<<shamt) into max(x, c) << shamt
1176-
static Instruction *moveShiftAfterMinMax(IntrinsicInst *II, InstCombiner::BuilderTy &Builder) {
1175+
// Try canonicalize max(max(X,C1) binop C2, C3) -> max(X binop C2, C3)
1176+
static Instruction *moveShiftAfterMinMax(IntrinsicInst *II,
1177+
InstCombiner::BuilderTy &Builder) {
11771178
Intrinsic::ID MinMaxID = II->getIntrinsicID();
1178-
assert((MinMaxID == Intrinsic::smax || MinMaxID == Intrinsic::smin ||
1179-
MinMaxID == Intrinsic::umax || MinMaxID == Intrinsic::umin) &&
1180-
"Expected a min or max intrinsic");
1181-
1179+
assert(isa<MinMaxIntrinsic>(II) &&
1180+
"Expected a min or max intrinsic");
1181+
11821182
Value *Op0 = II->getArgOperand(0), *Op1 = II->getArgOperand(1);
11831183
Value *InnerMax;
11841184
const APInt *C;
1185-
if (!match(Op0, m_OneUse(m_BinOp(m_Value(InnerMax), m_APInt(C)))) ||
1185+
if (!match(Op0, m_OneUse(m_BinOp(m_Value(InnerMax), m_APInt(C)))) ||
11861186
!match(Op1, m_APInt(C)))
1187-
return nullptr;
1188-
1189-
auto* BinOpInst = cast<BinaryOperator>(Op0);
1187+
return nullptr;
1188+
1189+
auto *BinOpInst = cast<BinaryOperator>(Op0);
11901190
Instruction::BinaryOps BinOp = BinOpInst->getOpcode();
1191-
Value *X;
1191+
11921192
InnerMax = BinOpInst->getOperand(0);
1193-
// std::cout<< InnerMax->dump() <<std::endl;
1194-
if(!match(InnerMax,m_OneUse(m_Intrinsic<Intrinsic::umax>(m_Value(X),m_APInt(C))))){
1195-
if(!match(InnerMax,m_OneUse(m_Intrinsic<Intrinsic::smax>(m_Value(X),m_APInt(C))))){
1196-
if(!match(InnerMax,m_OneUse(m_Intrinsic<Intrinsic::umin>(m_Value(X),m_APInt(C))))){
1197-
if(!match(InnerMax,m_OneUse(m_Intrinsic<Intrinsic::smin>(m_Value(X),m_APInt(C))))){
1198-
return nullptr;
1199-
}}}}
1200-
1201-
auto *InnerMaxInst = cast<IntrinsicInst>(InnerMax);
12021193

1203-
bool IsSigned = MinMaxID == Intrinsic::smax || MinMaxID == Intrinsic::smin;
1204-
if((IsSigned && !BinOpInst->hasNoSignedWrap()) ||
1205-
(!IsSigned && !BinOpInst->hasNoUnsignedWrap()))
1206-
return nullptr;
1194+
auto *InnerMinMaxInst = dyn_cast<MinMaxIntrinsic>(BinOpInst->getOperand(0));
1195+
1196+
if (!InnerMinMaxInst || !InnerMinMaxInst->hasOneUse())
1197+
return nullptr;
1198+
1199+
bool IsSigned = InnerMinMaxInst->isSigned();
1200+
if (InnerMinMaxInst->getIntrinsicID() != MinMaxID)
1201+
return nullptr;
1202+
1203+
if ((IsSigned && !BinOpInst->hasNoSignedWrap()) ||
1204+
(!IsSigned && !BinOpInst->hasNoUnsignedWrap()))
1205+
return nullptr;
12071206

12081207
// Check if BinOp is a left shift
12091208
if (BinOp != Instruction::Shl) {
12101209
return nullptr;
12111210
}
12121211

1213-
APInt C2=llvm::dyn_cast<llvm::ConstantInt>(BinOpInst->getOperand(1))->getValue() ;
1214-
APInt C3=llvm::dyn_cast<llvm::ConstantInt>(II->getArgOperand(1))->getValue();
1215-
APInt C1=llvm::dyn_cast<llvm::ConstantInt>(InnerMaxInst->getOperand(1))->getValue();
1212+
APInt C2 =llvm::dyn_cast<llvm::ConstantInt>(BinOpInst->getOperand(1))->getValue();
1213+
APInt C3 =llvm::dyn_cast<llvm::ConstantInt>(II->getArgOperand(1))->getValue();
1214+
APInt C1 = llvm::dyn_cast<llvm::ConstantInt>(InnerMinMaxInst->getOperand(1))->getValue();
12161215

12171216
// Compute C1 * 2^C2
12181217
APInt Two = APInt(C2.getBitWidth(), 2);
1219-
APInt Pow2C2 = Two.shl(C2); // 2^C2
1218+
APInt Pow2C2 = Two.shl(C2); // 2^C2
12201219
APInt C1TimesPow2C2 = C1 * Pow2C2; // C1 * 2^C2
12211220

12221221
// Check C3 >= C1 * 2^C2
12231222
if (C3.ult(C1TimesPow2C2)) {
12241223
return nullptr;
12251224
}
12261225

1227-
//Create new x binop c2
1228-
Value *NewBinOp = Builder.CreateBinOp(BinOp, InnerMaxInst->getOperand(0), BinOpInst->getOperand(1) );
1229-
1230-
//Create new min/max intrinsic with new binop and c3
1231-
1232-
if(IsSigned){
1233-
cast<Instruction>(NewBinOp) -> setHasNoSignedWrap(true);
1234-
cast<Instruction>(NewBinOp) -> setHasNoUnsignedWrap(false);
1235-
}else{
1236-
cast<Instruction>(NewBinOp) -> setHasNoUnsignedWrap(true);
1237-
cast<Instruction>(NewBinOp) -> setHasNoSignedWrap(false);
1226+
// Create new x binop c2
1227+
Value *NewBinOp = Builder.CreateBinOp(BinOp, InnerMinMaxInst->getOperand(0),
1228+
BinOpInst->getOperand(1));
1229+
1230+
// Create new min/max intrinsic with new binop and c3
1231+
if (auto *NewBinInst = dyn_cast<Instruction>(NewBinOp))
1232+
if (IsSigned) {
1233+
cast<Instruction>(NewBinOp)->setHasNoSignedWrap(true);
1234+
cast<Instruction>(NewBinOp)->setHasNoUnsignedWrap(false);
1235+
} else {
1236+
cast<Instruction>(NewBinOp)->setHasNoUnsignedWrap(true);
1237+
cast<Instruction>(NewBinOp)->setHasNoSignedWrap(false);
12381238
}
1239-
12401239

12411240
// Get the intrinsic function for MinMaxID
12421241
Type *Ty = II->getType();
1243-
Function *MinMaxFn = Intrinsic::getDeclaration(II->getModule(), MinMaxID, {Ty});
1242+
Function *MinMaxFn =
1243+
Intrinsic::getDeclaration(II->getModule(), MinMaxID, {Ty});
12441244

12451245
// Create new min/max intrinsic: MinMaxID(NewBinOp, C3) (not inserted)
12461246
Value *Args[] = {NewBinOp, Op1};
@@ -1249,6 +1249,8 @@ static Instruction *moveShiftAfterMinMax(IntrinsicInst *II, InstCombiner::Builde
12491249
return NewMax;
12501250
}
12511251

1252+
1253+
12521254
/// Match a sadd_sat or ssub_sat which is using min/max to clamp the value.
12531255
Instruction *InstCombinerImpl::matchSAddSubSat(IntrinsicInst &MinMax1) {
12541256
Type *Ty = MinMax1.getType();

0 commit comments

Comments
 (0)