[ConstantRange] Add initial support for binaryXor.

The initial implementation just delegates to APInt's implementation of
XOR for single element ranges and conservatively returns the full set
otherwise.

Reviewers: nikic, spatel, lebedev.ri

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D76453
diff --git a/llvm/unittests/IR/ConstantRangeTest.cpp b/llvm/unittests/IR/ConstantRangeTest.cpp
index 2e5ab82..4d19dd5 100644
--- a/llvm/unittests/IR/ConstantRangeTest.cpp
+++ b/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -2317,4 +2317,20 @@
   EXPECT_EQ(64u, IntToPtr.getBitWidth());
   EXPECT_TRUE(IntToPtr.isFullSet());
 }
+
+TEST_F(ConstantRangeTest, binaryXor) {
+  // Single element ranges.
+  ConstantRange R16(APInt(8, 16));
+  ConstantRange R20(APInt(8, 20));
+  EXPECT_EQ(*R16.binaryXor(R16).getSingleElement(), APInt(8, 0));
+  EXPECT_EQ(*R16.binaryXor(R20).getSingleElement(), APInt(8, 16 ^ 20));
+
+  // Ranges with more than a single element. Handled conservatively for now.
+  ConstantRange R16_35(APInt(8, 16), APInt(8, 35));
+  ConstantRange R0_99(APInt(8, 0), APInt(8, 99));
+  EXPECT_TRUE(R16_35.binaryXor(R16_35).isFullSet());
+  EXPECT_TRUE(R16_35.binaryXor(R0_99).isFullSet());
+  EXPECT_TRUE(R0_99.binaryXor(R16_35).isFullSet());
+}
+
 }  // anonymous namespace