diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1497,6 +1497,21 @@ } } + // Returns true, if the binary operator restricts undef operands, i.e. may no fold into + // undef for undef operands, like 'and undef, %x' != undef. + auto OpDoesRestrictUndef = [](BinaryOperator::BinaryOps Opcode) { + // Conservatively check opcodes that are guaranteed to fold to undef, + // for an undef operand. + switch (Opcode) { + case Instruction::Add: + case Instruction::Sub: + case Instruction::Shl: + return false; + default: + return true; + } + }; + // If one argument is a shuffle within one vector and the other is a constant, // try moving the shuffle after the binary operation. This canonicalization // intends to move shuffles closer to other shuffles and binops closer to @@ -1539,6 +1554,9 @@ break; } NewVecC[ShMask[I]] = CElt; + } else if (OpDoesRestrictUndef(Opcode)) { + MayChange = false; + break; } // If this is a widening shuffle, we must be able to extend with undef // elements. If the original binop does not produce an undef in the high diff --git a/llvm/test/Transforms/InstCombine/vec_shuffle.ll b/llvm/test/Transforms/InstCombine/vec_shuffle.ll --- a/llvm/test/Transforms/InstCombine/vec_shuffle.ll +++ b/llvm/test/Transforms/InstCombine/vec_shuffle.ll @@ -1004,10 +1004,13 @@ ret <2 x i32> %r } +; AND does not fold to undef for undef operands, we cannot move it +; across a shuffle with undef masks. define <4 x i16> @and_constant_mask_undef(<4 x i16> %add) { ; CHECK-LABEL: @and_constant_mask_undef( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[AND:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> undef, <4 x i32> +; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x i16> [[ADD:%.*]], <4 x i16> undef, <4 x i32> +; CHECK-NEXT: [[AND:%.*]] = and <4 x i16> [[SHUFFLE]], ; CHECK-NEXT: ret <4 x i16> [[AND]] ; entry: