Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[InstSimplify] add no-wrap parameters to simplifyMul and add more tes…
…ts; NFC

This gives mul the same capabilities as add/sub.
A potential improvement with nsw was noted in:
1720ec6
  • Loading branch information
rotateright committed Jan 18, 2023
1 parent ecade80 commit 1378e7d
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 35 deletions.
52 changes: 27 additions & 25 deletions llvm/include/llvm/Analysis/InstructionSimplify.h
Expand Up @@ -143,17 +143,36 @@ struct SimplifyQuery {
// deprecated.
// Please use the SimplifyQuery versions in new code.

/// Given operand for an FNeg, fold the result or return null.
Value *simplifyFNegInst(Value *Op, FastMathFlags FMF, const SimplifyQuery &Q);

/// Given operands for an Add, fold the result or return null.
Value *simplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
Value *simplifyAddInst(Value *LHS, Value *RHS, bool IsNSW, bool IsNUW,
const SimplifyQuery &Q);

/// Given operands for a Sub, fold the result or return null.
Value *simplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
Value *simplifySubInst(Value *LHS, Value *RHS, bool IsNSW, bool IsNUW,
const SimplifyQuery &Q);

/// Given operands for a Mul, fold the result or return null.
Value *simplifyMulInst(Value *LHS, Value *RHS, bool IsNSW, bool IsNUW,
const SimplifyQuery &Q);

/// Given operands for an SDiv, fold the result or return null.
Value *simplifySDivInst(Value *LHS, Value *RHS, bool IsExact,
const SimplifyQuery &Q);

/// Given operands for a UDiv, fold the result or return null.
Value *simplifyUDivInst(Value *LHS, Value *RHS, bool IsExact,
const SimplifyQuery &Q);

/// Given operands for an SRem, fold the result or return null.
Value *simplifySRemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);

/// Given operands for a URem, fold the result or return null.
Value *simplifyURemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);

/// Given operand for an FNeg, fold the result or return null.
Value *simplifyFNegInst(Value *Op, FastMathFlags FMF, const SimplifyQuery &Q);


/// Given operands for an FAdd, fold the result or return null.
Value *
simplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
Expand Down Expand Up @@ -184,30 +203,13 @@ Value *simplifyFMAFMul(Value *LHS, Value *RHS, FastMathFlags FMF,
fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
RoundingMode Rounding = RoundingMode::NearestTiesToEven);

/// Given operands for a Mul, fold the result or return null.
Value *simplifyMulInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);

/// Given operands for an SDiv, fold the result or return null.
Value *simplifySDivInst(Value *LHS, Value *RHS, bool IsExact,
const SimplifyQuery &Q);

/// Given operands for a UDiv, fold the result or return null.
Value *simplifyUDivInst(Value *LHS, Value *RHS, bool IsExact,
const SimplifyQuery &Q);

/// Given operands for an FDiv, fold the result or return null.
Value *
simplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
const SimplifyQuery &Q,
fp::ExceptionBehavior ExBehavior = fp::ebIgnore,
RoundingMode Rounding = RoundingMode::NearestTiesToEven);

/// Given operands for an SRem, fold the result or return null.
Value *simplifySRemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);

/// Given operands for a URem, fold the result or return null.
Value *simplifyURemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);

/// Given operands for an FRem, fold the result or return null.
Value *
simplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
Expand All @@ -216,15 +218,15 @@ simplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
RoundingMode Rounding = RoundingMode::NearestTiesToEven);

/// Given operands for a Shl, fold the result or return null.
Value *simplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
Value *simplifyShlInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
const SimplifyQuery &Q);

/// Given operands for a LShr, fold the result or return null.
Value *simplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
Value *simplifyLShrInst(Value *Op0, Value *Op1, bool IsExact,
const SimplifyQuery &Q);

/// Given operands for a AShr, fold the result or return nulll.
Value *simplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
Value *simplifyAShrInst(Value *Op0, Value *Op1, bool IsExact,
const SimplifyQuery &Q);

/// Given operands for an And, fold the result or return null.
Expand Down
16 changes: 10 additions & 6 deletions llvm/lib/Analysis/InstructionSimplify.cpp
Expand Up @@ -922,8 +922,8 @@ Value *llvm::simplifySubInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,

/// Given operands for a Mul, see if we can fold the result.
/// If not, this returns null.
static Value *simplifyMulInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
unsigned MaxRecurse) {
static Value *simplifyMulInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
const SimplifyQuery &Q, unsigned MaxRecurse) {
if (Constant *C = foldOrCommuteConstant(Instruction::Mul, Op0, Op1, Q))
return C;

Expand Down Expand Up @@ -980,8 +980,9 @@ static Value *simplifyMulInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
return nullptr;
}

Value *llvm::simplifyMulInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
return ::simplifyMulInst(Op0, Op1, Q, RecursionLimit);
Value *llvm::simplifyMulInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
const SimplifyQuery &Q) {
return ::simplifyMulInst(Op0, Op1, IsNSW, IsNUW, Q, RecursionLimit);
}

/// Check for common or similar folds of integer division or integer remainder.
Expand Down Expand Up @@ -5707,7 +5708,8 @@ static Value *simplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
return simplifySubInst(LHS, RHS, /* IsNSW */ false, /* IsNUW */ false, Q,
MaxRecurse);
case Instruction::Mul:
return simplifyMulInst(LHS, RHS, Q, MaxRecurse);
return simplifyMulInst(LHS, RHS, /* IsNSW */ false, /* IsNUW */ false, Q,
MaxRecurse);
case Instruction::SDiv:
return simplifySDivInst(LHS, RHS, /* IsExact */ false, Q, MaxRecurse);
case Instruction::UDiv:
Expand Down Expand Up @@ -6582,7 +6584,9 @@ static Value *simplifyInstructionWithOperands(Instruction *I,
case Instruction::FMul:
return simplifyFMulInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q);
case Instruction::Mul:
return simplifyMulInst(NewOps[0], NewOps[1], Q);
return simplifyMulInst(NewOps[0], NewOps[1],
Q.IIQ.hasNoSignedWrap(cast<BinaryOperator>(I)),
Q.IIQ.hasNoUnsignedWrap(cast<BinaryOperator>(I)), Q);
case Instruction::SDiv:
return simplifySDivInst(NewOps[0], NewOps[1],
Q.IIQ.isExact(cast<BinaryOperator>(I)), Q);
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
Expand Up @@ -187,7 +187,9 @@ static Value *foldMulShl1(BinaryOperator &Mul, bool CommuteOperands,

Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
if (Value *V = simplifyMulInst(Op0, Op1, SQ.getWithInstruction(&I)))
if (Value *V =
simplifyMulInst(Op0, Op1, I.hasNoSignedWrap(), I.hasNoUnsignedWrap(),
SQ.getWithInstruction(&I)))
return replaceInstUsesWith(I, V);

if (SimplifyAssociativeOrCommutative(I))
Expand Down
33 changes: 30 additions & 3 deletions llvm/test/Transforms/InstSimplify/mul.ll
Expand Up @@ -50,26 +50,53 @@ define i32 @poison(i32 %x) {
ret i32 %v
}

define i1 @mul_i1(i1 %x, i1 %y) {
; CHECK-LABEL: @mul_i1(
; CHECK-NEXT: [[R:%.*]] = mul i1 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[R]]
;
%r = mul i1 %x, %y
ret i1 %r
}

define i1 @mul_i1_nsw(i1 %x, i1 %y) {
; CHECK-LABEL: @mul_i1_nsw(
; CHECK-NEXT: [[R:%.*]] = mul nsw i1 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[R]]
;
%r = mul nsw i1 %x, %y
ret i1 %r
}

define i1 @mul_i1_nuw(i1 %x, i1 %y) {
; CHECK-LABEL: @mul_i1_nuw(
; CHECK-NEXT: [[R:%.*]] = mul nuw i1 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: ret i1 [[R]]
;
%r = mul nuw i1 %x, %y
ret i1 %r
}

define i1 @square_i1(i1 %x) {
; CHECK-LABEL: @square_i1(
; CHECK-NEXT: ret i1 [[X:%.*]]
;
%r = mul i1 %x, %x
ret i1 %x
ret i1 %r
}

define i1 @square_i1_nsw(i1 %x) {
; CHECK-LABEL: @square_i1_nsw(
; CHECK-NEXT: ret i1 [[X:%.*]]
;
%r = mul nsw i1 %x, %x
ret i1 %x
ret i1 %r
}

define i1 @square_i1_nuw(i1 %x) {
; CHECK-LABEL: @square_i1_nuw(
; CHECK-NEXT: ret i1 [[X:%.*]]
;
%r = mul nuw i1 %x, %x
ret i1 %x
ret i1 %r
}

0 comments on commit 1378e7d

Please sign in to comment.