[llvm-branch-commits] [llvm] a427f15 - GlobalISel: Add isKnownToBeAPowerOfTwo helper function
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Jan 5 10:03:18 PST 2021
Author: Matt Arsenault
Date: 2021-01-05T12:59:08-05:00
New Revision: a427f15d6070fd50457c553a097e031139b40886
URL: https://github.com/llvm/llvm-project/commit/a427f15d6070fd50457c553a097e031139b40886
DIFF: https://github.com/llvm/llvm-project/commit/a427f15d6070fd50457c553a097e031139b40886.diff
LOG: GlobalISel: Add isKnownToBeAPowerOfTwo helper function
Added:
Modified:
llvm/include/llvm/CodeGen/GlobalISel/Utils.h
llvm/lib/CodeGen/GlobalISel/Utils.cpp
llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
index 446aaf8c3551..9bd5180f7222 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -23,6 +23,7 @@
namespace llvm {
class AnalysisUsage;
+class GISelKnownBits;
class MachineFunction;
class MachineInstr;
class MachineOperand;
@@ -194,6 +195,12 @@ Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const Register Op1,
Optional<APInt> ConstantFoldExtOp(unsigned Opcode, const Register Op1,
uint64_t Imm, const MachineRegisterInfo &MRI);
+/// Test if the given value is known to have exactly one bit set. This
diff ers
+/// from computeKnownBits in that it doesn't necessarily determine which bit is
+/// set.
+bool isKnownToBeAPowerOfTwo(Register Val, const MachineRegisterInfo &MRI,
+ GISelKnownBits *KnownBits = nullptr);
+
/// Returns true if \p Val can be assumed to never be a NaN. If \p SNaN is true,
/// this returns if \p Val can be assumed to never be a signaling NaN.
bool isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index c19ee2e3860f..aeacd4fb797d 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -14,6 +14,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/Optional.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
+#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
@@ -551,6 +552,58 @@ Optional<APInt> llvm::ConstantFoldExtOp(unsigned Opcode, const Register Op1,
return None;
}
+bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
+ GISelKnownBits *KB) {
+ Optional<DefinitionAndSourceRegister> DefSrcReg =
+ getDefSrcRegIgnoringCopies(Reg, MRI);
+ if (!DefSrcReg)
+ return false;
+
+ const MachineInstr &MI = *DefSrcReg->MI;
+ const LLT Ty = MRI.getType(Reg);
+
+ switch (MI.getOpcode()) {
+ case TargetOpcode::G_CONSTANT: {
+ unsigned BitWidth = Ty.getScalarSizeInBits();
+ const ConstantInt *CI = MI.getOperand(1).getCImm();
+ return CI->getValue().zextOrTrunc(BitWidth).isPowerOf2();
+ }
+ case TargetOpcode::G_SHL: {
+ // A left-shift of a constant one will have exactly one bit set because
+ // shifting the bit off the end is undefined.
+
+ // TODO: Constant splat
+ if (auto ConstLHS = getConstantVRegVal(MI.getOperand(1).getReg(), MRI)) {
+ if (*ConstLHS == 1)
+ return true;
+ }
+
+ break;
+ }
+ case TargetOpcode::G_LSHR: {
+ if (auto ConstLHS = getConstantVRegVal(MI.getOperand(1).getReg(), MRI)) {
+ if (ConstLHS->isSignMask())
+ return true;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ // TODO: Are all operands of a build vector constant powers of two?
+ if (!KB)
+ return false;
+
+ // More could be done here, though the above checks are enough
+ // to handle some common cases.
+
+ // Fall back to computeKnownBits to catch other known cases.
+ KnownBits Known = KB->getKnownBits(Reg);
+ return (Known.countMaxPopulation() == 1) && (Known.countMinPopulation() == 1);
+}
+
void llvm::getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU) {
AU.addPreserved<StackProtector>();
}
diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
index 7888f461957e..b1e0548cdced 100644
--- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp
@@ -528,6 +528,87 @@ TEST_F(AMDGPUGISelMITest, TestTargetKnownAlign) {
EXPECT_EQ(Align(4), Info.computeKnownAlignment(CopyImplicitBufferPtr));
}
+TEST_F(AMDGPUGISelMITest, TestIsKnownToBeAPowerOfTwo) {
+
+ StringRef MIRString = R"MIR(
+ %zero:_(s32) = G_CONSTANT i32 0
+ %one:_(s32) = G_CONSTANT i32 1
+ %two:_(s32) = G_CONSTANT i32 2
+ %three:_(s32) = G_CONSTANT i32 3
+ %five:_(s32) = G_CONSTANT i32 5
+ %copy_zero:_(s32) = COPY %zero
+ %copy_one:_(s32) = COPY %one
+ %copy_two:_(s32) = COPY %two
+ %copy_three:_(s32) = COPY %three
+
+ %trunc_two:_(s1) = G_TRUNC %two
+ %trunc_three:_(s1) = G_TRUNC %three
+ %trunc_five:_(s1) = G_TRUNC %five
+
+ %copy_trunc_two:_(s1) = COPY %trunc_two
+ %copy_trunc_three:_(s1) = COPY %trunc_three
+ %copy_trunc_five:_(s1) = COPY %trunc_five
+
+ %ptr:_(p1) = G_IMPLICIT_DEF
+ %shift_amt:_(s32) = G_LOAD %ptr :: (load 4, addrspace 1)
+
+ %shl_1:_(s32) = G_SHL %one, %shift_amt
+ %copy_shl_1:_(s32) = COPY %shl_1
+
+ %shl_2:_(s32) = G_SHL %two, %shift_amt
+ %copy_shl_2:_(s32) = COPY %shl_2
+
+ %not_sign_mask:_(s32) = G_LOAD %ptr :: (load 4, addrspace 1)
+ %sign_mask:_(s32) = G_CONSTANT i32 -2147483648
+
+ %lshr_not_sign_mask:_(s32) = G_LSHR %not_sign_mask, %shift_amt
+ %copy_lshr_not_sign_mask:_(s32) = COPY %lshr_not_sign_mask
+
+ %lshr_sign_mask:_(s32) = G_LSHR %sign_mask, %shift_amt
+ %copy_lshr_sign_mask:_(s32) = COPY %lshr_sign_mask
+
+ %or_pow2:_(s32) = G_OR %zero, %two
+ %copy_or_pow2:_(s32) = COPY %or_pow2
+
+)MIR";
+ setUp(MIRString);
+ if (!TM)
+ return;
+
+ GISelKnownBits KB(*MF);
+
+ Register CopyZero = Copies[Copies.size() - 12];
+ Register CopyOne = Copies[Copies.size() - 11];
+ Register CopyTwo = Copies[Copies.size() - 10];
+ Register CopyThree = Copies[Copies.size() - 9];
+ Register CopyTruncTwo = Copies[Copies.size() - 8];
+ Register CopyTruncThree = Copies[Copies.size() - 7];
+ Register CopyTruncFive = Copies[Copies.size() - 6];
+
+ Register CopyShl1 = Copies[Copies.size() - 5];
+ Register CopyShl2 = Copies[Copies.size() - 4];
+
+ Register CopyLShrNotSignMask = Copies[Copies.size() - 3];
+ Register CopyLShrSignMask = Copies[Copies.size() - 2];
+ Register CopyOrPow2 = Copies[Copies.size() - 1];
+
+ EXPECT_FALSE(isKnownToBeAPowerOfTwo(CopyZero, *MRI, &KB));
+ EXPECT_TRUE(isKnownToBeAPowerOfTwo(CopyOne, *MRI, &KB));
+ EXPECT_TRUE(isKnownToBeAPowerOfTwo(CopyTwo, *MRI, &KB));
+ EXPECT_FALSE(isKnownToBeAPowerOfTwo(CopyThree, *MRI, &KB));
+
+ EXPECT_FALSE(isKnownToBeAPowerOfTwo(CopyTruncTwo, *MRI, &KB));
+ EXPECT_TRUE(isKnownToBeAPowerOfTwo(CopyTruncThree, *MRI, &KB));
+ EXPECT_TRUE(isKnownToBeAPowerOfTwo(CopyTruncFive, *MRI, &KB));
+
+ EXPECT_TRUE(isKnownToBeAPowerOfTwo(CopyShl1, *MRI, &KB));
+ EXPECT_FALSE(isKnownToBeAPowerOfTwo(CopyShl2, *MRI, &KB));
+
+ EXPECT_FALSE(isKnownToBeAPowerOfTwo(CopyLShrNotSignMask, *MRI, &KB));
+ EXPECT_TRUE(isKnownToBeAPowerOfTwo(CopyLShrSignMask, *MRI, &KB));
+ EXPECT_TRUE(isKnownToBeAPowerOfTwo(CopyOrPow2, *MRI, &KB));
+}
+
TEST_F(AArch64GISelMITest, TestMetadata) {
StringRef MIRString = " %imp:_(p0) = G_IMPLICIT_DEF\n"
" %load:_(s8) = G_LOAD %imp(p0) :: (load 1)\n"
More information about the llvm-branch-commits
mailing list