Index: llvm/include/llvm/CodeGen/GlobalISel/Utils.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/Utils.h +++ llvm/include/llvm/CodeGen/GlobalISel/Utils.h @@ -258,6 +258,12 @@ bool isConstTrueVal(const TargetLowering &TLI, int64_t Val, bool IsVector, bool IsFP); +/// \returns true if \p Val is a true value extended from \p OrigTy to \p ExtTy. +/// \p IsFP is true if the value is floating point. +/// \p IsSignExtended is true if the extension should be signed. +bool isExtendedTrueVal(const TargetLowering &TLI, int64_t Val, const LLT &ExtTy, + const LLT &OrigTy, bool IsFP, bool IsSignExtended); + /// Returns an integer representing true, as defined by the /// TargetBooleanContents. int64_t getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP); Index: llvm/lib/CodeGen/GlobalISel/Utils.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -734,6 +734,31 @@ llvm_unreachable("Invalid boolean contents"); } +bool llvm::isExtendedTrueVal(const TargetLowering &TLI, int64_t Val, + const LLT &ExtTy, const LLT &OrigTy, bool IsFP, + bool IsSignExtended) { + assert(ExtTy.isVector() == OrigTy.isVector() && + "Expected either both scalars or both vectors?"); + assert(OrigTy.getSizeInBits() <= ExtTy.getSizeInBits() && + "Extended type cannot be smaller than original type?"); + auto S1 = LLT::scalar(1); + if (ExtTy == S1) + return Val == 1; + switch (TLI.getBooleanContents(ExtTy.isVector(), IsFP)) { + case TargetLowering::ZeroOrOneBooleanContent: + // An extended value of 1 is always true... + if (!IsSignExtended || OrigTy != S1) + return Val == 1; + // ... Unless we're sign extending from a s1, in which case, we'll have a + // -1. + return Val == -1; + case TargetLowering::UndefinedBooleanContent: + case TargetLowering::ZeroOrNegativeOneBooleanContent: + return Val == -1 && IsSignExtended; + } + llvm_unreachable("Invalid boolean contents"); +} + int64_t llvm::getICmpTrueVal(const TargetLowering &TLI, bool IsVector, bool IsFP) { switch (TLI.getBooleanContents(IsVector, IsFP)) { Index: llvm/unittests/CodeGen/GlobalISel/GISelUtilsTest.cpp =================================================================== --- llvm/unittests/CodeGen/GlobalISel/GISelUtilsTest.cpp +++ llvm/unittests/CodeGen/GlobalISel/GISelUtilsTest.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "GISelMITest.h" #include "llvm/CodeGen/GlobalISel/Utils.h" #include "gtest/gtest.h" @@ -241,4 +242,56 @@ EXPECT_EQ(V4P1, getLCMType(P1, V2S64)); } +TEST_F(AArch64GISelMITest, ExtendedTrueTest) { + setUp(); + if (!TM) + return; + const auto &TLI = *B.getMF().getSubtarget().getTargetLowering(); + bool BooleanChoices[2] = {true, false}; + + // Test extended true/false for s1. This should only return true for 1, + // regardless of any other inputs, because we only have one bit. + for (auto IsFP : BooleanChoices) { + for (auto IsSignExtended : BooleanChoices) { + EXPECT_TRUE(isExtendedTrueVal(TLI, 1, /*ExtTy = */ S1, /* OrigTy = */ S1, + IsFP, IsSignExtended)); + EXPECT_FALSE(isExtendedTrueVal(TLI, -1, S1, S1, IsFP, IsSignExtended)); + EXPECT_FALSE(isExtendedTrueVal(TLI, 0, S1, S1, IsFP, IsSignExtended)); + } + } + + bool SExt = true; + bool ZExt = false; + + // AArch64 uses ZeroOrOneBooleanContent for scalars, and + // ZeroOrNegativeOneBooleanContent for vectors. + for (auto IsFP : BooleanChoices) { + // Scalar types. + // Zexting a N-bit 1 to any greater size == 1 + // Sexting a N-bit 1 to any greater size == 1, for N > 1. + EXPECT_TRUE(isExtendedTrueVal(TLI, 1, S64, S32, IsFP, ZExt)); + EXPECT_TRUE(isExtendedTrueVal(TLI, 1, S64, S32, IsFP, SExt)); + + EXPECT_FALSE(isExtendedTrueVal(TLI, -1, S64, S32, IsFP, ZExt)); + EXPECT_FALSE(isExtendedTrueVal(TLI, -1, S64, S32, IsFP, SExt)); + + // Zexting a 1-bit 1 to any greater size == 1 + // Sexting a 1-bit 1 to any greater size == -1 + EXPECT_TRUE(isExtendedTrueVal(TLI, -1, S64, S1, IsFP, SExt)); + EXPECT_TRUE(isExtendedTrueVal(TLI, 1, S64, S1, IsFP, ZExt)); + + EXPECT_FALSE(isExtendedTrueVal(TLI, -1, S64, S1, IsFP, ZExt)); + EXPECT_FALSE(isExtendedTrueVal(TLI, 1, S64, S1, IsFP, SExt)); + + // Vector types. Only true when we have a -1, which must have come from + // a sign extension. + EXPECT_TRUE(isExtendedTrueVal(TLI, -1, V2S64, V2S32, IsFP, SExt)); + + EXPECT_FALSE(isExtendedTrueVal(TLI, 1, V2S64, V2S32, IsFP, SExt)); + EXPECT_FALSE(isExtendedTrueVal(TLI, 567, V2S64, V2S32, IsFP, SExt)); + EXPECT_FALSE(isExtendedTrueVal(TLI, -1, V2S64, V2S32, IsFP, ZExt)); + EXPECT_FALSE(isExtendedTrueVal(TLI, 1, V2S64, V2S32, IsFP, ZExt)); + } } + +} // namespace