Index: llvm/test/Transforms/InstCombine/mul.ll =================================================================== --- llvm/test/Transforms/InstCombine/mul.ll +++ llvm/test/Transforms/InstCombine/mul.ll @@ -671,6 +671,89 @@ ret i32 %mul } +; https://alive2.llvm.org/ce/z/jJ8rZd +define i32 @PR57278_shl(i32 %a) { +; CHECK-LABEL: @PR57278_shl( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[A:%.*]], 2 +; CHECK-NEXT: [[ADD:%.*]] = or i32 [[SHL]], 3 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], 3 +; CHECK-NEXT: ret i32 [[MUL]] +; + %shl = shl nsw i32 %a, 2 + %add = or i32 %shl, 3 + %mul = mul nsw i32 %add, 3 + ret i32 %mul +} + +; Negative test: Have common bits set +define i32 @PR57278_shl_1(i32 %a) { +; CHECK-LABEL: @PR57278_shl_1( +; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[A:%.*]], 2 +; CHECK-NEXT: [[ADD:%.*]] = or i32 [[SHL]], 4 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ADD]], 3 +; CHECK-NEXT: ret i32 [[MUL]] +; + %shl = shl nsw i32 %a, 2 + %add = or i32 %shl, 4 + %mul = mul nsw i32 %add, 3 + ret i32 %mul +} + +; Keep nuw flag in this change, https://alive2.llvm.org/ce/z/awsQrx +define i32 @PR57278_mul(i32 %a) { +; CHECK-LABEL: @PR57278_mul( +; CHECK-NEXT: [[MUL0:%.*]] = mul nuw i32 [[A:%.*]], 12 +; CHECK-NEXT: [[ADD:%.*]] = or i32 [[MUL0]], 3 +; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[ADD]], 3 +; CHECK-NEXT: ret i32 [[MUL]] +; + %mul0 = mul nuw i32 %a, 12 + %add = or i32 %mul0, 3 + %mul = mul nuw i32 %add, 3 + ret i32 %mul +} + +; Negative test: Have common bits set +define i32 @PR57278_mul_1(i32 %a) { +; CHECK-LABEL: @PR57278_mul_1( +; CHECK-NEXT: [[MUL0:%.*]] = mul nuw i32 [[A:%.*]], 12 +; CHECK-NEXT: [[ADD:%.*]] = or i32 [[MUL0]], 4 +; CHECK-NEXT: [[MUL:%.*]] = mul nuw i32 [[ADD]], 3 +; CHECK-NEXT: ret i32 [[MUL]] +; + %mul0 = mul nuw i32 %a, 12 + %add = or i32 %mul0, 4 + %mul = mul nuw i32 %add, 3 + ret i32 %mul +} + +; https://alive2.llvm.org/ce/z/XYpv9q +define <2 x i32> @PR57278_shl_vec(<2 x i32> %v1) { +; CHECK-LABEL: @PR57278_shl_vec( +; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i32> [[V1:%.*]], +; CHECK-NEXT: [[ADD:%.*]] = or <2 x i32> [[SHL]], +; CHECK-NEXT: [[MUL:%.*]] = mul nuw <2 x i32> [[ADD]], +; CHECK-NEXT: ret <2 x i32> [[MUL]] +; + %shl = shl nuw <2 x i32> %v1, + %add = or <2 x i32> %shl, + %mul = mul nuw <2 x i32> %add, + ret <2 x i32> %mul +} + +define <2 x i32> @PR57278_shl_vec_poison(<2 x i32> %v1) { +; CHECK-LABEL: @PR57278_shl_vec_poison( +; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i32> [[V1:%.*]], +; CHECK-NEXT: [[ADD:%.*]] = or <2 x i32> [[SHL]], +; CHECK-NEXT: [[MUL:%.*]] = mul nuw <2 x i32> [[ADD]], +; CHECK-NEXT: ret <2 x i32> [[MUL]] +; + %shl = shl nuw <2 x i32> %v1, + %add = or <2 x i32> %shl, + %mul = mul nuw <2 x i32> %add, + ret <2 x i32> %mul +} + define <2 x i1> @test21(<2 x i1> %A, <2 x i1> %B) { ; CHECK-LABEL: @test21( ; CHECK-NEXT: [[C:%.*]] = and <2 x i1> [[A:%.*]], [[B:%.*]]