[InstCombine] fold mul with decremented "shl -1" factor
This is a sibling to:
6064e92b0a
...but we canonicalize the shl+add to shl+xor,
so the pattern is different than I expected:
https://alive2.llvm.org/ce/z/8CX16e
I have not found any patterns that are safe
to propagate no-wrap, so that is not included
here.
This commit is contained in:
@@ -140,7 +140,7 @@ static Value *foldMulSelectToNegate(BinaryOperator &I,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Reduce integer multiplication patterns that contain a (1 << Z) factor.
|
||||
/// Reduce integer multiplication patterns that contain a (+/-1 << Z) factor.
|
||||
/// Callers are expected to call this twice to handle commuted patterns.
|
||||
static Value *foldMulShl1(BinaryOperator &Mul, bool CommuteOperands,
|
||||
InstCombiner::BuilderTy &Builder) {
|
||||
@@ -171,6 +171,17 @@ static Value *foldMulShl1(BinaryOperator &Mul, bool CommuteOperands,
|
||||
return Builder.CreateAdd(Shl, FrX, Mul.getName(), HasNUW, PropagateNSW);
|
||||
}
|
||||
|
||||
// Similar to above, but a decrement of the shifted value is disguised as
|
||||
// 'not' and becomes a sub:
|
||||
// X * (~(-1 << Z)) --> X * ((1 << Z) - 1) --> (X << Z) - X
|
||||
// This increases uses of X, so it may require a freeze, but that is still
|
||||
// expected to be an improvement because it removes the multiply.
|
||||
if (match(Y, m_OneUse(m_Not(m_OneUse(m_Shl(m_AllOnes(), m_Value(Z))))))) {
|
||||
Value *FrX = Builder.CreateFreeze(X, X->getName() + ".fr");
|
||||
Value *Shl = Builder.CreateShl(FrX, Z, "mulshl");
|
||||
return Builder.CreateAdd(Shl, FrX, Mul.getName());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -229,10 +229,10 @@ define i32 @shl1_increment_use(i32 %x, i32 %y) {
|
||||
|
||||
define i8 @shl1_decrement(i8 %x, i8 %y) {
|
||||
; CHECK-LABEL: @shl1_decrement(
|
||||
; CHECK-NEXT: [[POW2X:%.*]] = shl i8 -1, [[X:%.*]]
|
||||
; CHECK-NEXT: [[X1:%.*]] = xor i8 [[POW2X]], -1
|
||||
; CHECK-NEXT: [[M:%.*]] = mul i8 [[X1]], [[Y:%.*]]
|
||||
; CHECK-NEXT: ret i8 [[M]]
|
||||
; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]
|
||||
; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[M1:%.*]] = add i8 [[MULSHL]], [[Y_FR]]
|
||||
; CHECK-NEXT: ret i8 [[M1]]
|
||||
;
|
||||
%pow2x = shl i8 -1, %x
|
||||
%x1 = xor i8 %pow2x, -1
|
||||
@@ -243,10 +243,9 @@ define i8 @shl1_decrement(i8 %x, i8 %y) {
|
||||
define i8 @shl1_decrement_commute(i8 %x, i8 noundef %p) {
|
||||
; CHECK-LABEL: @shl1_decrement_commute(
|
||||
; CHECK-NEXT: [[Y:%.*]] = ashr i8 [[P:%.*]], 1
|
||||
; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i8 -1, [[X:%.*]]
|
||||
; CHECK-NEXT: [[X1:%.*]] = xor i8 [[NOTMASK]], -1
|
||||
; CHECK-NEXT: [[M:%.*]] = mul i8 [[Y]], [[X1]]
|
||||
; CHECK-NEXT: ret i8 [[M]]
|
||||
; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[M1:%.*]] = add i8 [[MULSHL]], [[Y]]
|
||||
; CHECK-NEXT: ret i8 [[M1]]
|
||||
;
|
||||
%y = ashr i8 %p, 1 ; thwart complexity-based canonicalization
|
||||
%pow2x = shl i8 1, %x
|
||||
@@ -257,10 +256,10 @@ define i8 @shl1_decrement_commute(i8 %x, i8 noundef %p) {
|
||||
|
||||
define i8 @shl1_nuw_decrement(i8 %x, i8 %y) {
|
||||
; CHECK-LABEL: @shl1_nuw_decrement(
|
||||
; CHECK-NEXT: [[POW2X:%.*]] = shl i8 -1, [[X:%.*]]
|
||||
; CHECK-NEXT: [[X1:%.*]] = xor i8 [[POW2X]], -1
|
||||
; CHECK-NEXT: [[M:%.*]] = mul nuw i8 [[X1]], [[Y:%.*]]
|
||||
; CHECK-NEXT: ret i8 [[M]]
|
||||
; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]
|
||||
; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[M1:%.*]] = add i8 [[MULSHL]], [[Y_FR]]
|
||||
; CHECK-NEXT: ret i8 [[M1]]
|
||||
;
|
||||
%pow2x = shl i8 -1, %x
|
||||
%x1 = xor i8 %pow2x, -1
|
||||
@@ -270,10 +269,10 @@ define i8 @shl1_nuw_decrement(i8 %x, i8 %y) {
|
||||
|
||||
define i8 @shl1_nsw_decrement(i8 %x, i8 %y) {
|
||||
; CHECK-LABEL: @shl1_nsw_decrement(
|
||||
; CHECK-NEXT: [[POW2X:%.*]] = shl nsw i8 -1, [[X:%.*]]
|
||||
; CHECK-NEXT: [[X1:%.*]] = xor i8 [[POW2X]], -1
|
||||
; CHECK-NEXT: [[M:%.*]] = mul nsw i8 [[X1]], [[Y:%.*]]
|
||||
; CHECK-NEXT: ret i8 [[M]]
|
||||
; CHECK-NEXT: [[Y_FR:%.*]] = freeze i8 [[Y:%.*]]
|
||||
; CHECK-NEXT: [[MULSHL:%.*]] = shl i8 [[Y_FR]], [[X:%.*]]
|
||||
; CHECK-NEXT: [[M1:%.*]] = add i8 [[MULSHL]], [[Y_FR]]
|
||||
; CHECK-NEXT: ret i8 [[M1]]
|
||||
;
|
||||
%pow2x = shl nsw i8 -1, %x
|
||||
%x1 = xor i8 %pow2x, -1
|
||||
|
||||
Reference in New Issue
Block a user