[llvm] 110340c - [PowerPC][GIsel] Materialize i64 constants.
Kai Nacke via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 15 13:23:27 PST 2022
Author: Kai Nacke
Date: 2022-12-15T21:22:58Z
New Revision: 110340c687ccdd894079e59e281bbee4191adbac
URL: https://github.com/llvm/llvm-project/commit/110340c687ccdd894079e59e281bbee4191adbac
DIFF: https://github.com/llvm/llvm-project/commit/110340c687ccdd894079e59e281bbee4191adbac.diff
LOG: [PowerPC][GIsel] Materialize i64 constants.
Adds support for i64 constant. It uses the same pattern-based
approach as in SDAG (see PPCISelDAGToDAG::selectI64ImmDirect(),
PPCISelDAGToDAG::selectI64Imm()). It does not support the
prefixed instructions.
Reviewed By: arsenm, tschuett
Differential Revision: https://reviews.llvm.org/D140119
Added:
llvm/test/CodeGen/PowerPC/GlobalISel/ppc-isel-constant.ll
Modified:
llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
index aeb33caaa3ede..a23fe7a451619 100644
--- a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
+++ b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
@@ -55,6 +55,13 @@ class PPCInstructionSelector : public InstructionSelector {
bool selectZExt(MachineInstr &I, MachineBasicBlock &MBB,
MachineRegisterInfo &MRI) const;
+ std::optional<bool> selectI64ImmDirect(MachineInstr &I,
+ MachineBasicBlock &MBB,
+ MachineRegisterInfo &MRI, Register Reg,
+ uint64_t Imm) const;
+ bool selectI64Imm(MachineInstr &I, MachineBasicBlock &MBB,
+ MachineRegisterInfo &MRI) const;
+
const PPCSubtarget &STI;
const PPCInstrInfo &TII;
const PPCRegisterInfo &TRI;
@@ -250,6 +257,379 @@ bool PPCInstructionSelector::selectZExt(MachineInstr &I, MachineBasicBlock &MBB,
return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
}
+// For any 32 < Num < 64, check if the Imm contains at least Num consecutive
+// zeros and return the number of bits by the left of these consecutive zeros.
+static uint32_t findContiguousZerosAtLeast(uint64_t Imm, unsigned Num) {
+ uint32_t HiTZ = countTrailingZeros<uint32_t>(Hi_32(Imm));
+ uint32_t LoLZ = countLeadingZeros<uint32_t>(Lo_32(Imm));
+ if ((HiTZ + LoLZ) >= Num)
+ return (32 + HiTZ);
+ return 0;
+}
+
+// Direct materialization of 64-bit constants by enumerated patterns.
+// Similar to PPCISelDAGToDAG::selectI64ImmDirect().
+std::optional<bool> PPCInstructionSelector::selectI64ImmDirect(MachineInstr &I,
+ MachineBasicBlock &MBB,
+ MachineRegisterInfo &MRI,
+ Register Reg,
+ uint64_t Imm) const {
+ unsigned TZ = countTrailingZeros<uint64_t>(Imm);
+ unsigned LZ = countLeadingZeros<uint64_t>(Imm);
+ unsigned TO = countTrailingOnes<uint64_t>(Imm);
+ unsigned LO = countLeadingOnes<uint64_t>(Imm);
+ uint32_t Hi32 = Hi_32(Imm);
+ uint32_t Lo32 = Lo_32(Imm);
+ uint32_t Shift = 0;
+
+ // Following patterns use 1 instructions to materialize the Imm.
+
+ // 1-1) Patterns : {zeros}{15-bit valve}
+ // {ones}{15-bit valve}
+ if (isInt<16>(Imm))
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), Reg)
+ .addImm(Imm)
+ .constrainAllUses(TII, TRI, RBI);
+ // 1-2) Patterns : {zeros}{15-bit valve}{16 zeros}
+ // {ones}{15-bit valve}{16 zeros}
+ if (TZ > 15 && (LZ > 32 || LO > 32))
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), Reg)
+ .addImm((Imm >> 16) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI);
+
+ // Following patterns use 2 instructions to materialize the Imm.
+
+ assert(LZ < 64 && "Unexpected leading zeros here.");
+ // Count of ones follwing the leading zeros.
+ unsigned FO = countLeadingOnes<uint64_t>(Imm << LZ);
+ // 2-1) Patterns : {zeros}{31-bit value}
+ // {ones}{31-bit value}
+ if (isInt<32>(Imm)) {
+ uint64_t ImmHi16 = (Imm >> 16) & 0xffff;
+ unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
+ .addImm((Imm >> 16) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm(Imm & 0xffff)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 2-2) Patterns : {zeros}{ones}{15-bit value}{zeros}
+ // {zeros}{15-bit value}{zeros}
+ // {zeros}{ones}{15-bit value}
+ // {ones}{15-bit value}{zeros}
+ // We can take advantage of LI's sign-extension semantics to generate leading
+ // ones, and then use RLDIC to mask off the ones in both sides after rotation.
+ if ((LZ + FO + TZ) > 48) {
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
+ .addImm((Imm >> TZ) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm(TZ)
+ .addImm(LZ)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 2-3) Pattern : {zeros}{15-bit value}{ones}
+ // Shift right the Imm by (48 - LZ) bits to construct a negtive 16 bits value,
+ // therefore we can take advantage of LI's sign-extension semantics, and then
+ // mask them off after rotation.
+ //
+ // +--LZ--||-15-bit-||--TO--+ +-------------|--16-bit--+
+ // |00000001bbbbbbbbb1111111| -> |00000000000001bbbbbbbbb1|
+ // +------------------------+ +------------------------+
+ // 63 0 63 0
+ // Imm (Imm >> (48 - LZ) & 0xffff)
+ // +----sext-----|--16-bit--+ +clear-|-----------------+
+ // |11111111111111bbbbbbbbb1| -> |00000001bbbbbbbbb1111111|
+ // +------------------------+ +------------------------+
+ // 63 0 63 0
+ // LI8: sext many leading zeros RLDICL: rotate left (48 - LZ), clear left LZ
+ if ((LZ + TO) > 48) {
+ // Since the immediates with (LZ > 32) have been handled by previous
+ // patterns, here we have (LZ <= 32) to make sure we will not shift right
+ // the Imm by a negative value.
+ assert(LZ <= 32 && "Unexpected shift value.");
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
+ .addImm(Imm >> (48 - LZ) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm(48 - LZ)
+ .addImm(LZ)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 2-4) Patterns : {zeros}{ones}{15-bit value}{ones}
+ // {ones}{15-bit value}{ones}
+ // We can take advantage of LI's sign-extension semantics to generate leading
+ // ones, and then use RLDICL to mask off the ones in left sides (if required)
+ // after rotation.
+ //
+ // +-LZ-FO||-15-bit-||--TO--+ +-------------|--16-bit--+
+ // |00011110bbbbbbbbb1111111| -> |000000000011110bbbbbbbbb|
+ // +------------------------+ +------------------------+
+ // 63 0 63 0
+ // Imm (Imm >> TO) & 0xffff
+ // +----sext-----|--16-bit--+ +LZ|---------------------+
+ // |111111111111110bbbbbbbbb| -> |00011110bbbbbbbbb1111111|
+ // +------------------------+ +------------------------+
+ // 63 0 63 0
+ // LI8: sext many leading zeros RLDICL: rotate left TO, clear left LZ
+ if ((LZ + FO + TO) > 48) {
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
+ .addImm((Imm >> TO) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm(TO)
+ .addImm(LZ)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 2-5) Pattern : {32 zeros}{****}{0}{15-bit value}
+ // If Hi32 is zero and the Lo16(in Lo32) can be presented as a positive 16 bit
+ // value, we can use LI for Lo16 without generating leading ones then add the
+ // Hi16(in Lo32).
+ if (LZ == 32 && ((Lo32 & 0x8000) == 0)) {
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
+ .addImm(Lo32 & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm(Lo32 >> 16)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 2-6) Patterns : {******}{49 zeros}{******}
+ // {******}{49 ones}{******}
+ // If the Imm contains 49 consecutive zeros/ones, it means that a total of 15
+ // bits remain on both sides. Rotate right the Imm to construct an int<16>
+ // value, use LI for int<16> value and then use RLDICL without mask to rotate
+ // it back.
+ //
+ // 1) findContiguousZerosAtLeast(Imm, 49)
+ // +------|--zeros-|------+ +---ones--||---15 bit--+
+ // |bbbbbb0000000000aaaaaa| -> |0000000000aaaaaabbbbbb|
+ // +----------------------+ +----------------------+
+ // 63 0 63 0
+ //
+ // 2) findContiguousZerosAtLeast(~Imm, 49)
+ // +------|--ones--|------+ +---ones--||---15 bit--+
+ // |bbbbbb1111111111aaaaaa| -> |1111111111aaaaaabbbbbb|
+ // +----------------------+ +----------------------+
+ // 63 0 63 0
+ if ((Shift = findContiguousZerosAtLeast(Imm, 49)) ||
+ (Shift = findContiguousZerosAtLeast(~Imm, 49))) {
+ uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LI8), TmpReg)
+ .addImm(RotImm & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm(Shift)
+ .addImm(0)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+
+ // Following patterns use 3 instructions to materialize the Imm.
+
+ // 3-1) Patterns : {zeros}{ones}{31-bit value}{zeros}
+ // {zeros}{31-bit value}{zeros}
+ // {zeros}{ones}{31-bit value}
+ // {ones}{31-bit value}{zeros}
+ // We can take advantage of LIS's sign-extension semantics to generate leading
+ // ones, add the remaining bits with ORI, and then use RLDIC to mask off the
+ // ones in both sides after rotation.
+ if ((LZ + FO + TZ) > 32) {
+ uint64_t ImmHi16 = (Imm >> (TZ + 16)) & 0xffff;
+ unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
+ .addImm(ImmHi16)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm((Imm >> TZ) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIC), Reg)
+ .addReg(Tmp2Reg, RegState::Kill)
+ .addImm(TZ)
+ .addImm(LZ)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 3-2) Pattern : {zeros}{31-bit value}{ones}
+ // Shift right the Imm by (32 - LZ) bits to construct a negative 32 bits
+ // value, therefore we can take advantage of LIS's sign-extension semantics,
+ // add the remaining bits with ORI, and then mask them off after rotation.
+ // This is similar to Pattern 2-3, please refer to the diagram there.
+ if ((LZ + TO) > 32) {
+ // Since the immediates with (LZ > 32) have been handled by previous
+ // patterns, here we have (LZ <= 32) to make sure we will not shift right
+ // the Imm by a negative value.
+ assert(LZ <= 32 && "Unexpected shift value.");
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg)
+ .addImm((Imm >> (48 - LZ)) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm((Imm >> (32 - LZ)) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
+ .addReg(Tmp2Reg, RegState::Kill)
+ .addImm(32 - LZ)
+ .addImm(LZ)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 3-3) Patterns : {zeros}{ones}{31-bit value}{ones}
+ // {ones}{31-bit value}{ones}
+ // We can take advantage of LIS's sign-extension semantics to generate leading
+ // ones, add the remaining bits with ORI, and then use RLDICL to mask off the
+ // ones in left sides (if required) after rotation.
+ // This is similar to Pattern 2-4, please refer to the diagram there.
+ if ((LZ + FO + TO) > 32) {
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::LIS8), TmpReg)
+ .addImm((Imm >> (TO + 16)) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm((Imm >> TO) & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
+ .addReg(Tmp2Reg, RegState::Kill)
+ .addImm(TO)
+ .addImm(LZ)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 3-4) Patterns : High word == Low word
+ if (Hi32 == Lo32) {
+ // Handle the first 32 bits.
+ uint64_t ImmHi16 = (Lo32 >> 16) & 0xffff;
+ unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
+ .addImm(ImmHi16)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm(Lo32 & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDIMI), Reg)
+ .addReg(Tmp2Reg)
+ .addReg(Tmp2Reg, RegState::Kill)
+ .addImm(32)
+ .addImm(0)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ // 3-5) Patterns : {******}{33 zeros}{******}
+ // {******}{33 ones}{******}
+ // If the Imm contains 33 consecutive zeros/ones, it means that a total of 31
+ // bits remain on both sides. Rotate right the Imm to construct an int<32>
+ // value, use LIS + ORI for int<32> value and then use RLDICL without mask to
+ // rotate it back.
+ // This is similar to Pattern 2-6, please refer to the diagram there.
+ if ((Shift = findContiguousZerosAtLeast(Imm, 33)) ||
+ (Shift = findContiguousZerosAtLeast(~Imm, 33))) {
+ uint64_t RotImm = APInt(64, Imm).rotr(Shift).getZExtValue();
+ uint64_t ImmHi16 = (RotImm >> 16) & 0xffff;
+ unsigned Opcode = ImmHi16 ? PPC::LIS8 : PPC::LI8;
+ Register TmpReg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ Register Tmp2Reg = MRI.createVirtualRegister(&PPC::G8RCRegClass);
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode), TmpReg)
+ .addImm(ImmHi16)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), Tmp2Reg)
+ .addReg(TmpReg, RegState::Kill)
+ .addImm(RotImm & 0xffff)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ return BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::RLDICL), Reg)
+ .addReg(Tmp2Reg, RegState::Kill)
+ .addImm(Shift)
+ .addImm(0)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+
+ // If we end up here then no instructions were inserted.
+ return std::nullopt;
+}
+
+// Derived from PPCISelDAGToDAG::selectI64Imm().
+// TODO: Add support for prefixed instructions.
+bool PPCInstructionSelector::selectI64Imm(MachineInstr &I,
+ MachineBasicBlock &MBB,
+ MachineRegisterInfo &MRI) const {
+ assert(I.getOpcode() == TargetOpcode::G_CONSTANT && "Unexpected G code");
+
+ Register DstReg = I.getOperand(0).getReg();
+ int64_t Imm = I.getOperand(1).getCImm()->getValue().getZExtValue();
+ // No more than 3 instructions are used if we can select the i64 immediate
+ // directly.
+ if (std::optional<bool> Res = selectI64ImmDirect(I, MBB, MRI, DstReg, Imm)) {
+ I.eraseFromParent();
+ return *Res;
+ }
+
+ // Calculate the last bits as required.
+ uint32_t Hi16 = (Lo_32(Imm) >> 16) & 0xffff;
+ uint32_t Lo16 = Lo_32(Imm) & 0xffff;
+
+ Register Reg =
+ (Hi16 || Lo16) ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;
+
+ // Handle the upper 32 bit value.
+ std::optional<bool> Res =
+ selectI64ImmDirect(I, MBB, MRI, Reg, Imm & 0xffffffff00000000);
+ if (!Res || !*Res)
+ return false;
+
+ // Add in the last bits as required.
+ if (Hi16) {
+ Register TmpReg =
+ Lo16 ? MRI.createVirtualRegister(&PPC::G8RCRegClass) : DstReg;
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORIS8), TmpReg)
+ .addReg(Reg, RegState::Kill)
+ .addImm(Hi16)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ Reg = TmpReg;
+ }
+ if (Lo16) {
+ if (!BuildMI(MBB, I, I.getDebugLoc(), TII.get(PPC::ORI8), DstReg)
+ .addReg(Reg, RegState::Kill)
+ .addImm(Lo16)
+ .constrainAllUses(TII, TRI, RBI))
+ return false;
+ }
+ I.eraseFromParent();
+ return true;
+}
+
bool PPCInstructionSelector::select(MachineInstr &I) {
auto &MBB = *I.getParent();
auto &MF = *MBB.getParent();
@@ -316,6 +696,8 @@ bool PPCInstructionSelector::select(MachineInstr &I) {
// G_SEXT will be selected in tb-gen pattern.
case TargetOpcode::G_ZEXT:
return selectZExt(I, MBB, MRI);
+ case TargetOpcode::G_CONSTANT:
+ return selectI64Imm(I, MBB, MRI);
}
return false;
}
diff --git a/llvm/test/CodeGen/PowerPC/GlobalISel/ppc-isel-constant.ll b/llvm/test/CodeGen/PowerPC/GlobalISel/ppc-isel-constant.ll
new file mode 100644
index 0000000000000..fa9fbe25a00db
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/GlobalISel/ppc-isel-constant.ll
@@ -0,0 +1,400 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple ppc64le-linux -ppc-asm-full-reg-names -global-isel -o - < %s \
+; RUN: | FileCheck %s
+
+; Function Attrs: nounwind readnone
+define i64 @cn15bit1() #0 {
+; CHECK-LABEL: cn15bit1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, 32767
+; CHECK-NEXT: blr
+entry:
+ ret i64 32767
+
+}
+
+; Function Attrs: nounwind readnone
+define i64 @cn15bit2() #0 {
+; CHECK-LABEL: cn15bit2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -32767
+; CHECK-NEXT: blr
+entry:
+ ret i64 -32767
+
+}
+
+
+; Function Attrs: nounwind readnone
+define i64 @cn1() #0 {
+; CHECK-LABEL: cn1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -1
+; CHECK-NEXT: rldic r3, r3, 0, 16
+; CHECK-NEXT: blr
+entry:
+ ret i64 281474976710655
+
+}
+
+; Function Attrs: nounwind readnone
+define i64 @cnb() #0 {
+; CHECK-LABEL: cnb:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -81
+; CHECK-NEXT: rldic r3, r3, 0, 16
+; CHECK-NEXT: blr
+entry:
+ ret i64 281474976710575
+
+}
+
+; Function Attrs: nounwind readnone
+define i64 @f2(i64 %x) #0 {
+; CHECK-LABEL: f2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -1
+; CHECK-NEXT: rldic r3, r3, 36, 0
+; CHECK-NEXT: blr
+entry:
+ ret i64 -68719476736
+
+}
+
+; Function Attrs: nounwind readnone
+define i64 @f2a(i64 %x) #0 {
+; CHECK-LABEL: f2a:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -337
+; CHECK-NEXT: rldic r3, r3, 30, 0
+; CHECK-NEXT: blr
+entry:
+ ret i64 -361850994688
+
+}
+
+; Function Attrs: nounwind readnone
+define i64 @f2n(i64 %x) #0 {
+; CHECK-LABEL: f2n:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -1
+; CHECK-NEXT: rldic r3, r3, 0, 28
+; CHECK-NEXT: blr
+entry:
+ ret i64 68719476735
+
+}
+
+; Function Attrs: nounwind readnone
+define i64 @f3(i64 %x) #0 {
+; CHECK-LABEL: f3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -1
+; CHECK-NEXT: rldic r3, r3, 0, 31
+; CHECK-NEXT: blr
+entry:
+ ret i64 8589934591
+
+}
+
+; Function Attrs: nounwind readnone
+define i64 @cn2n() #0 {
+; CHECK-LABEL: cn2n:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, -5121
+; CHECK-NEXT: ori r3, r3, 65534
+; CHECK-NEXT: rotldi r3, r3, 22
+; CHECK-NEXT: blr
+entry:
+ ret i64 -1407374887747585
+
+}
+
+define i64 @uint32_1() #0 {
+; CHECK-LABEL: uint32_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, 18176
+; CHECK-NEXT: oris r3, r3, 59509
+; CHECK-NEXT: blr
+entry:
+ ret i64 3900000000
+
+}
+
+define i32 @uint32_1_i32() #0 {
+; CHECK-LABEL: uint32_1_i32:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, -6027
+; CHECK-NEXT: ori r3, r3, 18176
+; CHECK-NEXT: blr
+entry:
+ ret i32 -394967296
+
+}
+
+define i64 @uint32_2() #0 {
+; CHECK-LABEL: uint32_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -1
+; CHECK-NEXT: rldic r3, r3, 0, 32
+; CHECK-NEXT: blr
+entry:
+ ret i64 4294967295
+
+}
+
+define i32 @uint32_2_i32() #0 {
+; CHECK-LABEL: uint32_2_i32:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -1
+; CHECK-NEXT: blr
+entry:
+ ret i32 -1
+
+}
+
+define i64 @uint32_3() #0 {
+; CHECK-LABEL: uint32_3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, 1
+; CHECK-NEXT: rldic r3, r3, 31, 32
+; CHECK-NEXT: blr
+entry:
+ ret i64 2147483648
+
+}
+
+define i64 @uint32_4() #0 {
+; CHECK-LABEL: uint32_4:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, -6027
+; CHECK-NEXT: ori r3, r3, 18177
+; CHECK-NEXT: rldic r3, r3, 5, 27
+; CHECK-NEXT: blr
+entry:
+ ret i64 124800000032
+
+}
+
+define i64 @cn_ones_1() #0 {
+; CHECK-LABEL: cn_ones_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -25633
+; CHECK-NEXT: rldicl r3, r3, 18, 30
+; CHECK-NEXT: blr
+entry:
+ ret i64 10460594175
+
+}
+
+define i64 @cn_ones_2() #0 {
+; CHECK-LABEL: cn_ones_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, -25638
+; CHECK-NEXT: ori r3, r3, 24575
+; CHECK-NEXT: rldicl r3, r3, 2, 30
+; CHECK-NEXT: blr
+entry:
+ ret i64 10459119615
+
+}
+
+define i64 @imm1() #0 {
+; CHECK-LABEL: imm1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, 8465
+; CHECK-NEXT: rldic r3, r3, 28, 22
+; CHECK-NEXT: blr
+entry:
+ ret i64 2272306135040 ;0x21110000000
+}
+
+define i64 @imm2() #0 {
+; CHECK-LABEL: imm2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -28536
+; CHECK-NEXT: rldicl r3, r3, 1, 32
+; CHECK-NEXT: blr
+entry:
+ ret i64 4294910225 ;0xFFFF2111
+}
+
+define i64 @imm3() #0 {
+; CHECK-LABEL: imm3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -32495
+; CHECK-NEXT: rldic r3, r3, 0, 32
+; CHECK-NEXT: blr
+entry:
+ ret i64 4294934801 ;0xFFFF8111
+}
+
+define i64 @imm4() #0 {
+; CHECK-LABEL: imm4:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, 33
+; CHECK-NEXT: ori r3, r3, 4352
+; CHECK-NEXT: rldimi r3, r3, 32, 0
+; CHECK-NEXT: blr
+entry:
+ ret i64 9307365931290880 ;0x21110000211100
+}
+
+define i64 @imm5() #0 {
+; CHECK-LABEL: imm5:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, 28685
+; CHECK-NEXT: rotldi r3, r3, 52
+; CHECK-NEXT: blr
+entry:
+ ret i64 58546795155816455 ;0xd0000000000007
+}
+
+define i64 @imm6() #0 {
+; CHECK-LABEL: imm6:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, -1
+; CHECK-NEXT: ori r3, r3, 28674
+; CHECK-NEXT: rotldi r3, r3, 52
+; CHECK-NEXT: blr
+entry:
+ ret i64 13510798882111479 ;0x2ffffffffffff7
+}
+
+define i64 @imm7() #0 {
+; CHECK-LABEL: imm7:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -3823
+; CHECK-NEXT: rldic r3, r3, 28, 20
+; CHECK-NEXT: blr
+entry:
+ ret i64 16565957296128 ;0xf1110000000
+}
+
+define i64 @imm8() #0 {
+; CHECK-LABEL: imm8:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -7919
+; CHECK-NEXT: rldic r3, r3, 22, 22
+; CHECK-NEXT: blr
+entry:
+ ret i64 4364831817728 ;0x3f844400000
+}
+
+define i64 @imm9() #0 {
+; CHECK-LABEL: imm9:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, -1
+; CHECK-NEXT: ori r3, r3, 28674
+; CHECK-NEXT: rotldi r3, r3, 52
+; CHECK-NEXT: blr
+entry:
+ ret i64 13510798882111479 ;0x2ffffffffffff7
+}
+
+define i64 @imm10() #0 {
+; CHECK-LABEL: imm10:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -3823
+; CHECK-NEXT: rldic r3, r3, 28, 20
+; CHECK-NEXT: blr
+entry:
+ ret i64 16565957296128 ;0xf1110000000
+}
+
+define i64 @imm11() #0 {
+; CHECK-LABEL: imm11:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -7919
+; CHECK-NEXT: rldic r3, r3, 22, 22
+; CHECK-NEXT: blr
+entry:
+ ret i64 4364831817728 ;0x3f844400000
+}
+
+define i64 @imm12() #0 {
+; CHECK-LABEL: imm12:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, -29
+; CHECK-NEXT: ori r3, r3, 64577
+; CHECK-NEXT: rldic r3, r3, 12, 20
+; CHECK-NEXT: blr
+entry:
+ ret i64 17584665923584 ;0xffe3fc41000
+}
+
+define i64 @imm13() #0 {
+; CHECK-LABEL: imm13:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -24847
+; CHECK-NEXT: rldicl r3, r3, 21, 27
+; CHECK-NEXT: blr
+entry:
+ ret i64 85333114879 ;0x13de3fffff
+}
+
+define i64 @imm13_2() #0 {
+; CHECK-LABEL: imm13_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -12424
+; CHECK-NEXT: rldicl r3, r3, 22, 26
+; CHECK-NEXT: blr
+entry:
+ ret i64 222772068351 ;0x33de3fffff
+}
+
+define i64 @imm14() #0 {
+; CHECK-LABEL: imm14:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -3960
+; CHECK-NEXT: rldicl r3, r3, 21, 24
+; CHECK-NEXT: blr
+entry:
+ ret i64 1091209003007 ;0xfe111fffff
+}
+
+define i64 @imm15() #0 {
+; CHECK-LABEL: imm15:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, -8065
+; CHECK-NEXT: rldic r3, r3, 24, 0
+; CHECK-NEXT: blr
+entry:
+ ret i64 -135308247040
+}
+
+define i64 @imm16() #0 {
+; CHECK-LABEL: imm16:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, -16392
+; CHECK-NEXT: ori r3, r3, 57217
+; CHECK-NEXT: rldic r3, r3, 16, 0
+; CHECK-NEXT: blr
+entry:
+ ret i64 -70399354142720
+}
+
+define i64 @imm17() #0 {
+; CHECK-LABEL: imm17:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: lis r3, 20344
+; CHECK-NEXT: ori r3, r3, 32847
+; CHECK-NEXT: rotldi r3, r3, 49
+; CHECK-NEXT: blr
+entry:
+ ret i64 44473046320324337 ;0x9e000000009ef1
+}
+
+define i64 @imm18() #0 {
+; CHECK-LABEL: imm18:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li r3, 1
+; CHECK-NEXT: rldic r3, r3, 33, 30
+; CHECK-NEXT: oris r3, r3, 39436
+; CHECK-NEXT: ori r3, r3, 61633
+; CHECK-NEXT: blr
+entry:
+ ret i64 11174473921
+}
+
+attributes #0 = { nounwind readnone }
More information about the llvm-commits
mailing list