Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -1226,6 +1226,11 @@ Value *X; if (match(Op0, m_Exact(m_Shr(m_Value(X), m_Specific(Op1))))) return X; + + // shl nuw i8 C, %x -> C iff C has sign bit set. + if (isNUW && match(Op0, m_Negative())) + return Op0; + return nullptr; } Index: test/Transforms/InstCombine/set-lowbits-mask-canonicalize.ll =================================================================== --- test/Transforms/InstCombine/set-lowbits-mask-canonicalize.ll +++ test/Transforms/InstCombine/set-lowbits-mask-canonicalize.ll @@ -39,9 +39,7 @@ define i32 @shl_add_nuw(i32 %NBits) { ; CHECK-LABEL: @shl_add_nuw( -; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]] -; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: ret i32 [[RET]] +; CHECK-NEXT: ret i32 0 ; %setbit = shl i32 1, %NBits %ret = add nuw i32 %setbit, -1 @@ -50,9 +48,7 @@ define i32 @shl_add_nsw_nuw(i32 %NBits) { ; CHECK-LABEL: @shl_add_nsw_nuw( -; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]] -; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: ret i32 [[RET]] +; CHECK-NEXT: ret i32 0 ; %setbit = shl i32 1, %NBits %ret = add nuw nsw i32 %setbit, -1 @@ -85,9 +81,7 @@ define i32 @shl_nsw_add_nuw(i32 %NBits) { ; CHECK-LABEL: @shl_nsw_add_nuw( -; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]] -; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: ret i32 [[RET]] +; CHECK-NEXT: ret i32 0 ; %setbit = shl nsw i32 1, %NBits %ret = add nuw i32 %setbit, -1 @@ -96,9 +90,7 @@ define i32 @shl_nsw_add_nsw_nuw(i32 %NBits) { ; CHECK-LABEL: @shl_nsw_add_nsw_nuw( -; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]] -; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: ret i32 [[RET]] +; CHECK-NEXT: ret i32 0 ; %setbit = shl nsw i32 1, %NBits %ret = add nuw nsw i32 %setbit, -1 @@ -131,9 +123,7 @@ define i32 @shl_nuw_add_nuw(i32 %NBits) { ; CHECK-LABEL: @shl_nuw_add_nuw( -; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]] -; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: ret i32 [[RET]] +; CHECK-NEXT: ret i32 0 ; %setbit = shl nuw i32 1, %NBits %ret = add nuw i32 %setbit, -1 @@ -142,9 +132,7 @@ define i32 @shl_nuw_add_nsw_nuw(i32 %NBits) { ; CHECK-LABEL: @shl_nuw_add_nsw_nuw( -; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]] -; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: ret i32 [[RET]] +; CHECK-NEXT: ret i32 0 ; %setbit = shl nuw i32 1, %NBits %ret = add nuw nsw i32 %setbit, -1 @@ -177,9 +165,7 @@ define i32 @shl_nsw_nuw_add_nuw(i32 %NBits) { ; CHECK-LABEL: @shl_nsw_nuw_add_nuw( -; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]] -; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: ret i32 [[RET]] +; CHECK-NEXT: ret i32 0 ; %setbit = shl nuw nsw i32 1, %NBits %ret = add nuw i32 %setbit, -1 @@ -188,9 +174,7 @@ define i32 @shl_nsw_nuw_add_nsw_nuw(i32 %NBits) { ; CHECK-LABEL: @shl_nsw_nuw_add_nsw_nuw( -; CHECK-NEXT: [[NOTMASK:%.*]] = shl nuw nsw i32 -1, [[NBITS:%.*]] -; CHECK-NEXT: [[RET:%.*]] = xor i32 [[NOTMASK]], -1 -; CHECK-NEXT: ret i32 [[RET]] +; CHECK-NEXT: ret i32 0 ; %setbit = shl nuw nsw i32 1, %NBits %ret = add nuw nsw i32 %setbit, -1 Index: test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll =================================================================== --- test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll +++ test/Transforms/InstSimplify/constantfold-shl-nuw-C-to-C.ll @@ -9,8 +9,7 @@ define i8 @shl_nuw (i8 %x) { ; CHECK-LABEL: @shl_nuw( -; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 -1, [[X:%.*]] -; CHECK-NEXT: ret i8 [[RET]] +; CHECK-NEXT: ret i8 -1 ; %ret = shl nuw i8 -1, %x ; nuw here means that %x can only be 0 @@ -19,8 +18,7 @@ define i8 @shl_nuw_nsw (i8 %x) { ; CHECK-LABEL: @shl_nuw_nsw( -; CHECK-NEXT: [[RET:%.*]] = shl nuw nsw i8 -1, [[X:%.*]] -; CHECK-NEXT: ret i8 [[RET]] +; CHECK-NEXT: ret i8 -1 ; %ret = shl nuw nsw i8 -1, %x ; nuw here means that %x can only be 0 @@ -29,8 +27,7 @@ define i8 @shl_128 (i8 %x) { ; CHECK-LABEL: @shl_128( -; CHECK-NEXT: [[RET:%.*]] = shl nuw i8 -128, [[X:%.*]] -; CHECK-NEXT: ret i8 [[RET]] +; CHECK-NEXT: ret i8 -128 ; %ret = shl nuw i8 128, %x ; 128 == 1<<7 == just the sign bit is set @@ -75,8 +72,7 @@ define <2 x i8> @shl_vec(<2 x i8> %x) { ; CHECK-LABEL: @shl_vec( -; CHECK-NEXT: [[RET:%.*]] = shl nuw <2 x i8> , [[X:%.*]] -; CHECK-NEXT: ret <2 x i8> [[RET]] +; CHECK-NEXT: ret <2 x i8> ; %ret = shl nuw <2 x i8> , %x ret <2 x i8> %ret @@ -84,8 +80,7 @@ define <3 x i8> @shl_vec_undef(<3 x i8> %x) { ; CHECK-LABEL: @shl_vec_undef( -; CHECK-NEXT: [[RET:%.*]] = shl nuw <3 x i8> , [[X:%.*]] -; CHECK-NEXT: ret <3 x i8> [[RET]] +; CHECK-NEXT: ret <3 x i8> ; %ret = shl nuw <3 x i8> , %x ret <3 x i8> %ret @@ -93,8 +88,7 @@ define <2 x i8> @shl_vec_nonsplat(<2 x i8> %x) { ; CHECK-LABEL: @shl_vec_nonsplat( -; CHECK-NEXT: [[RET:%.*]] = shl nuw <2 x i8> , [[X:%.*]] -; CHECK-NEXT: ret <2 x i8> [[RET]] +; CHECK-NEXT: ret <2 x i8> ; %ret = shl nuw <2 x i8> , %x ret <2 x i8> %ret