Unverified Commit 6f01cb91 authored by Justin Lebar's avatar Justin Lebar
Browse files

Handle `select` in programUndefinedIfPoison.

If both the true and false operands of a `select` are poison, then the `select`
is poison.

Differential Revision: https://reviews.llvm.org/D149427
parent 8df59132
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -6707,7 +6707,7 @@ bool llvm::isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC,
  return ::isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth, true);
}

/// Return true if undefined behavior would provable be executed on the path to
/// Return true if undefined behavior would provably be executed on the path to
/// OnPathTo if Root produced a posion result.  Note that this doesn't say
/// anything about whether OnPathTo is actually executed or whether Root is
/// actually poison.  This can be used to assess whether a new use of Root can
@@ -7041,6 +7041,15 @@ static bool programUndefinedIfUndefOrPoison(const Value *V,
          break;
        }
      }

      // Special handling for select, which returns poison if its operand 0 is
      // poison (handled in the loop above) *or* if both its true/false operands
      // are poison (handled here).
      if (I.getOpcode() == Instruction::Select &&
          YieldsPoison.count(I.getOperand(1)) &&
          YieldsPoison.count(I.getOperand(2))) {
        YieldsPoison.insert(&I);
      }
    }

    BB = BB->getSingleSuccessor();
+14 −0
Original line number Diff line number Diff line
@@ -982,6 +982,20 @@ TEST_F(ValueTrackingTest, programUndefinedIfPoison) {
  EXPECT_EQ(programUndefinedIfPoison(A), true);
}

TEST_F(ValueTrackingTest, programUndefinedIfPoisonSelect) {
  parseAssembly("declare i32 @any_num()"
                "define void @test(i1 %Cond) {\n"
                "  %A = call i32 @any_num()\n"
                "  %B = add i32 %A, 1\n"
                "  %C = select i1 %Cond, i32 %A, i32 %B\n"
                "  udiv i32 1, %C"
                "  ret void\n"
                "}\n");
  // If A is poison, B is also poison, and therefore C is poison regardless of
  // the value of %Cond.
  EXPECT_EQ(programUndefinedIfPoison(A), true);
}

TEST_F(ValueTrackingTest, programUndefinedIfUndefOrPoison) {
  parseAssembly("declare i32 @any_num()"
                "define void @test(i32 %mask) {\n"