Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -1500,9 +1500,12 @@ if (Constant *C = dyn_cast(V)) { if (C->isNullValue()) return OrZero; - if (ConstantInt *CI = dyn_cast(C)) + + if (auto *CI = dyn_cast(C)) return CI->getValue().isPowerOf2(); - // TODO: Handle vector constants. + + if (auto *Splat = dyn_cast_or_null(C->getSplatValue())) + return Splat->getValue().isPowerOf2(); } // 1 << X is clearly a power of two if the one is not shifted off the end. If Index: test/Transforms/InstCombine/div.ll =================================================================== --- test/Transforms/InstCombine/div.ll +++ test/Transforms/InstCombine/div.ll @@ -374,7 +374,7 @@ define <2 x i32> @test36vec(<2 x i32> %A) { ; CHECK-LABEL: @test36vec( ; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> %A, -; CHECK-NEXT: [[SHL:%.*]] = shl nsw <2 x i32> , %A +; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw <2 x i32> , %A ; CHECK-NEXT: [[MUL:%.*]] = sdiv exact <2 x i32> [[AND]], [[SHL]] ; CHECK-NEXT: ret <2 x i32> [[MUL]] ; Index: test/Transforms/InstCombine/rem.ll =================================================================== --- test/Transforms/InstCombine/rem.ll +++ test/Transforms/InstCombine/rem.ll @@ -25,22 +25,18 @@ ret i32 %B } -; FIXME: This could be an 'and' just like above. - define <2 x i32> @vec_power_of_2_constant_splat_divisor(<2 x i32> %A) { ; CHECK-LABEL: @vec_power_of_2_constant_splat_divisor( -; CHECK-NEXT: [[B:%.*]] = urem <2 x i32> %A, +; CHECK-NEXT: [[B:%.*]] = and <2 x i32> %A, ; CHECK-NEXT: ret <2 x i32> [[B]] ; %B = urem <2 x i32> %A, ret <2 x i32> %B } -; FIXME: And it shouldn't matter whether we have ConstantVector or ConstantDataVector. - define <2 x i19> @weird_vec_power_of_2_constant_splat_divisor(<2 x i19> %A) { ; CHECK-LABEL: @weird_vec_power_of_2_constant_splat_divisor( -; CHECK-NEXT: [[B:%.*]] = urem <2 x i19> %A, +; CHECK-NEXT: [[B:%.*]] = and <2 x i19> %A, ; CHECK-NEXT: ret <2 x i19> [[B]] ; %B = urem <2 x i19> %A, Index: test/Transforms/InstCombine/shift.ll =================================================================== --- test/Transforms/InstCombine/shift.ll +++ test/Transforms/InstCombine/shift.ll @@ -700,11 +700,9 @@ ret i32 %div2 } -; FIXME: Vector lshr should be treated the same as scalar. - define <2 x i32> @test42vec(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @test42vec( -; CHECK-NEXT: [[DIV:%.*]] = lshr <2 x i32> , %b +; CHECK-NEXT: [[DIV:%.*]] = lshr exact <2 x i32> , %b ; CHECK-NEXT: [[DIV2:%.*]] = udiv <2 x i32> %a, [[DIV]] ; CHECK-NEXT: ret <2 x i32> [[DIV2]] ;