diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -73,11 +73,12 @@ // a) (x & ((1 << MaskShAmt) - 1)) << ShiftShAmt // b) (x & (~(-1 << MaskShAmt))) << ShiftShAmt // c) (x & (-1 >> MaskShAmt)) << ShiftShAmt +// d) (x & ((-1 << MaskShAmt) >> MaskShAmt)) << ShiftShAmt // All these patterns can be simplified to just: // x << ShiftShAmt // iff: // a,b) (MaskShAmt+ShiftShAmt) u>= bitwidth(x) -// c) (ShiftShAmt-MaskShAmt) s>= 0 (i.e. ShiftShAmt u>= MaskShAmt) +// c,d) (ShiftShAmt-MaskShAmt) s>= 0 (i.e. ShiftShAmt u>= MaskShAmt) static Instruction * dropRedundantMaskingOfLeftShiftInput(BinaryOperator *OuterShift, const SimplifyQuery &SQ) { @@ -93,6 +94,9 @@ auto MaskB = m_Xor(m_Shl(m_AllOnes(), m_Value(MaskShAmt)), m_AllOnes()); // (-1 >> MaskShAmt) auto MaskC = m_Shr(m_AllOnes(), m_Value(MaskShAmt)); + // ((-1 << MaskShAmt) >> MaskShAmt) + auto MaskD = + m_Shr(m_Shl(m_AllOnes(), m_Value(MaskShAmt)), m_Deferred(MaskShAmt)); Value *X; if (match(Masked, m_c_And(m_CombineOr(MaskA, MaskB), m_Value(X)))) { @@ -109,7 +113,7 @@ APInt(BitWidth, BitWidth)))) return nullptr; // All good, we can do this fold. - } else if (match(Masked, m_c_And(MaskC, m_Value(X)))) { + } else if (match(Masked, m_c_And(m_CombineOr(MaskC, MaskD), m_Value(X)))) { // Can we simplify (ShiftShAmt-MaskShAmt) ? Value *ShAmtsDiff = SimplifyBinOp(Instruction::BinaryOps::Sub, ShiftShAmt, MaskShAmt, diff --git a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-d.ll b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-d.ll --- a/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-d.ll +++ b/llvm/test/Transforms/InstCombine/redundant-left-shift-input-masking-variant-d.ll @@ -23,7 +23,7 @@ ; CHECK-NEXT: call void @use32(i32 [[T0]]) ; CHECK-NEXT: call void @use32(i32 [[T1]]) ; CHECK-NEXT: call void @use32(i32 [[T2]]) -; CHECK-NEXT: [[T4:%.*]] = shl i32 [[T2]], [[NBITS]] +; CHECK-NEXT: [[T4:%.*]] = shl i32 [[X]], [[NBITS]] ; CHECK-NEXT: ret i32 [[T4]] ; %t0 = shl i32 -1, %nbits @@ -46,7 +46,7 @@ ; CHECK-NEXT: call void @use32(i32 [[T1]]) ; CHECK-NEXT: call void @use32(i32 [[T2]]) ; CHECK-NEXT: call void @use32(i32 [[T3]]) -; CHECK-NEXT: [[T4:%.*]] = shl i32 [[T2]], [[T3]] +; CHECK-NEXT: [[T4:%.*]] = shl i32 [[X]], [[T3]] ; CHECK-NEXT: ret i32 [[T4]] ; %t0 = shl i32 -1, %nbits @@ -75,7 +75,7 @@ ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[T1]]) ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[T2]]) ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[T3]]) -; CHECK-NEXT: [[T4:%.*]] = shl <3 x i32> [[T2]], [[T3]] +; CHECK-NEXT: [[T4:%.*]] = shl <3 x i32> [[X]], [[T3]] ; CHECK-NEXT: ret <3 x i32> [[T4]] ; %t0 = shl <3 x i32> , %nbits @@ -100,7 +100,7 @@ ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[T1]]) ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[T2]]) ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[T3]]) -; CHECK-NEXT: [[T4:%.*]] = shl <3 x i32> [[T2]], [[T3]] +; CHECK-NEXT: [[T4:%.*]] = shl <3 x i32> [[X]], [[T3]] ; CHECK-NEXT: ret <3 x i32> [[T4]] ; %t0 = shl <3 x i32> , %nbits @@ -124,7 +124,7 @@ ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[T1]]) ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[T2]]) ; CHECK-NEXT: call void @use3xi32(<3 x i32> [[NBITS]]) -; CHECK-NEXT: [[T4:%.*]] = shl <3 x i32> [[T2]], [[NBITS]] +; CHECK-NEXT: [[T4:%.*]] = shl <3 x i32> [[X]], [[NBITS]] ; CHECK-NEXT: ret <3 x i32> [[T4]] ; %t0 = shl <3 x i32> , %nbits @@ -152,7 +152,7 @@ ; CHECK-NEXT: call void @use32(i32 [[T0]]) ; CHECK-NEXT: call void @use32(i32 [[T1]]) ; CHECK-NEXT: call void @use32(i32 [[T2]]) -; CHECK-NEXT: [[T3:%.*]] = shl i32 [[T2]], [[NBITS]] +; CHECK-NEXT: [[T3:%.*]] = shl i32 [[X]], [[NBITS]] ; CHECK-NEXT: ret i32 [[T3]] ; %x = call i32 @gen32() @@ -170,20 +170,20 @@ ; CHECK-LABEL: @t6_commutativity1( ; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS0:%.*]] ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[T0]], [[NBITS0]] -; CHECK-NEXT: [[T2:%.*]] = shl i32 -1, [[NBITS0]] -; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T0]], [[NBITS1:%.*]] +; CHECK-NEXT: [[T2:%.*]] = shl i32 -1, [[NBITS1:%.*]] +; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T0]], [[NBITS1]] ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T3]], [[T1]] ; CHECK-NEXT: call void @use32(i32 [[T0]]) ; CHECK-NEXT: call void @use32(i32 [[T1]]) ; CHECK-NEXT: call void @use32(i32 [[T2]]) ; CHECK-NEXT: call void @use32(i32 [[T3]]) ; CHECK-NEXT: call void @use32(i32 [[T4]]) -; CHECK-NEXT: [[T5:%.*]] = shl i32 [[T4]], [[NBITS0]] +; CHECK-NEXT: [[T5:%.*]] = shl i32 [[T3]], [[NBITS0]] ; CHECK-NEXT: ret i32 [[T5]] ; %t0 = shl i32 -1, %nbits0 %t1 = lshr i32 %t0, %nbits0 - %t2 = shl i32 -1, %nbits0 + %t2 = shl i32 -1, %nbits1 %t3 = lshr i32 %t0, %nbits1 %t4 = and i32 %t3, %t1 ; both hands of 'and' could be mask.. call void @use32(i32 %t0) @@ -198,8 +198,8 @@ ; CHECK-LABEL: @t6_commutativity2( ; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS0:%.*]] ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[T0]], [[NBITS0]] -; CHECK-NEXT: [[T2:%.*]] = shl i32 -1, [[NBITS0]] -; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T0]], [[NBITS1:%.*]] +; CHECK-NEXT: [[T2:%.*]] = shl i32 -1, [[NBITS1:%.*]] +; CHECK-NEXT: [[T3:%.*]] = lshr i32 [[T0]], [[NBITS1]] ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T3]], [[T1]] ; CHECK-NEXT: call void @use32(i32 [[T0]]) ; CHECK-NEXT: call void @use32(i32 [[T1]]) @@ -211,7 +211,7 @@ ; %t0 = shl i32 -1, %nbits0 %t1 = lshr i32 %t0, %nbits0 - %t2 = shl i32 -1, %nbits0 + %t2 = shl i32 -1, %nbits1 %t3 = lshr i32 %t0, %nbits1 %t4 = and i32 %t3, %t1 ; both hands of 'and' could be mask.. call void @use32(i32 %t0) @@ -233,7 +233,7 @@ ; CHECK-NEXT: call void @use32(i32 [[T0]]) ; CHECK-NEXT: call void @use32(i32 [[T1]]) ; CHECK-NEXT: call void @use32(i32 [[T2]]) -; CHECK-NEXT: [[T3:%.*]] = shl nuw i32 [[T2]], [[NBITS]] +; CHECK-NEXT: [[T3:%.*]] = shl i32 [[X]], [[NBITS]] ; CHECK-NEXT: ret i32 [[T3]] ; %t0 = shl i32 -1, %nbits @@ -254,7 +254,7 @@ ; CHECK-NEXT: call void @use32(i32 [[T0]]) ; CHECK-NEXT: call void @use32(i32 [[T1]]) ; CHECK-NEXT: call void @use32(i32 [[T2]]) -; CHECK-NEXT: [[T3:%.*]] = shl nsw i32 [[T2]], [[NBITS]] +; CHECK-NEXT: [[T3:%.*]] = shl i32 [[X]], [[NBITS]] ; CHECK-NEXT: ret i32 [[T3]] ; %t0 = shl i32 -1, %nbits @@ -275,7 +275,7 @@ ; CHECK-NEXT: call void @use32(i32 [[T0]]) ; CHECK-NEXT: call void @use32(i32 [[T1]]) ; CHECK-NEXT: call void @use32(i32 [[T2]]) -; CHECK-NEXT: [[T3:%.*]] = shl nuw nsw i32 [[T2]], [[NBITS]] +; CHECK-NEXT: [[T3:%.*]] = shl i32 [[X]], [[NBITS]] ; CHECK-NEXT: ret i32 [[T3]] ; %t0 = shl i32 -1, %nbits @@ -316,10 +316,11 @@ ; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]] ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]] ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[X:%.*]] +; CHECK-NEXT: [[T3:%.*]] = add i32 [[NBITS]], -1 ; CHECK-NEXT: call void @use32(i32 [[T0]]) ; CHECK-NEXT: call void @use32(i32 [[T1]]) ; CHECK-NEXT: call void @use32(i32 [[T2]]) -; CHECK-NEXT: [[T4:%.*]] = shl i32 [[T2]], [[NBITS]] +; CHECK-NEXT: [[T4:%.*]] = shl i32 [[T2]], [[T3]] ; CHECK-NEXT: ret i32 [[T4]] ; %t0 = shl i32 -1, %nbits @@ -329,6 +330,6 @@ call void @use32(i32 %t0) call void @use32(i32 %t1) call void @use32(i32 %t2) - %t4 = shl i32 %t2, %nbits + %t4 = shl i32 %t2, %t3 ret i32 %t4 }