Skip to content

[InstCombine] wrong folding of shufflevector with a binary operator #114355

Open
@bongjunj

Description

@bongjunj

Constant *NewC = ConstantVector::get(NewVecC);
// It may not be safe to execute a binop on a vector with poison elements
// because the entire instruction can be folded to undef or create poison
// that did not exist in the original code.
// TODO: The shift case should not be necessary.
if (Inst.isIntDivRem() || (Inst.isShift() && ConstOp1))
NewC = getSafeVectorConstantForBinop(Opcode, NewC, ConstOp1);
// Op(shuffle(V1, Mask), C) -> shuffle(Op(V1, NewC), Mask)
// Op(C, shuffle(V1, Mask)) -> shuffle(Op(NewC, V1), Mask)
Value *NewLHS = ConstOp1 ? V1 : NewC;
Value *NewRHS = ConstOp1 ? NewC : V1;
return createBinOpShuffle(NewLHS, NewRHS, Mask);

Alive2 report: https://alive2.llvm.org/ce/z/FA_YTY

----------------------------------------
define <2 x i16> @test_srem_orig.2(i16 %a, i1 %cmp) {
#0:
  %splatinsert = insertelement <2 x i16> { 65535, poison }, i16 %a, i32 0
  %splat = shufflevector <2 x i16> %splatinsert, <2 x i16> undef, 0, 0
  %t1 = select i1 %cmp, <2 x i16> { 65535, poison }, <2 x i16> %splat
  %#1 = xor <2 x i16> %t1, { 2, 2 }
  ret <2 x i16> %#1
}
=>
define <2 x i16> @test_srem_orig.2(i16 %a, i1 %cmp) {
#0:
  %splatinsert = insertelement <2 x i16> poison, i16 %a, i64 0
  %#1 = xor <2 x i16> %splatinsert, { 2, poison }
  %#2 = shufflevector <2 x i16> %#1, <2 x i16> poison, 0, 0
  %#3 = select i1 %cmp, <2 x i16> { 65533, poison }, <2 x i16> %#2
  ret <2 x i16> %#3
}
Transformation doesn't verify!

ERROR: Target's return value is more undefined

Example:
i16 %a = #x0000 (0)
i1 %cmp = undef

Source:
<2 x i16> %splatinsert = < #x0000 (0), poison >
<2 x i16> %splat = < #x0000 (0), #x0000 (0) >
<2 x i16> %t1 = < #x0000 (0)	[based on undef value], #x0000 (0) >
<2 x i16> %#1 = < #x0002 (2), #x0002 (2) >

Target:
<2 x i16> %splatinsert = < #x0000 (0), poison >
<2 x i16> %#1 = < #x0002 (2), poison >
<2 x i16> %#2 = < #x0002 (2), #x0002 (2) >
<2 x i16> %#3 = < #x0002 (2), #x0002 (2) >
Source value: < #x0002 (2), #x0002 (2) >
Target value: < #x0002 (2), #x0002 (2) >


----------------------------------------
define <2 x i16> @test_srem_orig.3(i16 %a, i1 %cmp) {
#0:
  %splatinsert = insertelement <2 x i16> poison, i16 %a, i32 0
  %splat = shufflevector <2 x i16> %splatinsert, <2 x i16> poison, 0, 0
  %t1 = select i1 %cmp, <2 x i16> { undef, 65535 }, <2 x i16> %splat
  %t2 = srem <2 x i16> %t1, { 2, 2 }
  ret <2 x i16> %t2
}
=>
define <2 x i16> @test_srem_orig.3(i16 %a, i1 %cmp) {
#0:
  %splatinsert = insertelement <2 x i16> poison, i16 %a, i64 0
  %#1 = srem <2 x i16> %splatinsert, { 2, 1 }
  %#2 = shufflevector <2 x i16> %#1, <2 x i16> poison, 0, 0
  %t2 = select i1 %cmp, <2 x i16> { 0, 65535 }, <2 x i16> %#2
  ret <2 x i16> %t2
}
Transformation doesn't verify!

ERROR: Target's return value is more undefined

Example:
i16 %a = #x0001 (1)
i1 %cmp = undef

Source:
<2 x i16> %splatinsert = < #x0001 (1), poison >
<2 x i16> %splat = < #x0001 (1), #x0001 (1) >
<2 x i16> %t1 = < #x0001 (1)	[based on undef value], #x0001 (1) >
<2 x i16> %t2 = < #x0001 (1), #x0001 (1) >

Target:
<2 x i16> %splatinsert = < #x0001 (1), poison >
<2 x i16> %#1 = < #x0001 (1), poison >
<2 x i16> %#2 = < #x0001 (1), #x0001 (1) >
<2 x i16> %t2 = < #x0001 (1), #x0001 (1) >
Source value: < #x0001 (1), #x0001 (1) >
Target value: < #x0001 (1), #x0001 (1) >

Summary:
  0 correct transformations
  2 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions