Skip to content

Commit

Permalink
Revert "Teach the AArch64 backend to materialize immediates using a p…
Browse files Browse the repository at this point in the history
…air of ORR-immediate"

This reverts commit 8d433a0 due to test failures on
CodeGen/AArch64/GlobalISel/store-merging.ll
  • Loading branch information
resistor committed Feb 5, 2023
1 parent 3fad47a commit 80fe772
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 192 deletions.
143 changes: 0 additions & 143 deletions llvm/lib/Target/AArch64/AArch64ExpandImm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,141 +239,6 @@ static bool trySequenceOfOnes(uint64_t UImm,
return true;
}

static uint64_t GetRunOfOnesStartingAt(uint64_t V, uint64_t StartPosition) {
uint64_t NumOnes = llvm::countTrailingOnes(V >> StartPosition);

uint64_t UnshiftedOnes;
if (NumOnes == 64) {
UnshiftedOnes = ~0ULL;
} else {
UnshiftedOnes = (1ULL << NumOnes) - 1;
}
return UnshiftedOnes << StartPosition;
}

static uint64_t rotl(uint64_t n, uint64_t d) {
if (d == 0)
return n;
return (n << d) | (n >> (64 - d));
}

static uint64_t rotr(uint64_t n, uint64_t d) {
if (d == 0)
return n;
return (n >> d) | (n << (64 - d));
}

static uint64_t MaximallyReplicateSubImmediate(uint64_t V, uint64_t Subset) {
uint64_t Result = Subset;

// 64, 32, 16, 8, 4, 2
for (uint64_t i = 0; i < 6; ++i) {
uint64_t Rotation = 1 << (6 - i);
uint64_t Closure = Result | rotl(Result, Rotation);
if (Closure != (Closure & V)) {
break;
}
Result = Closure;
}

return Result;
}

// Find the logical immediate that covers the most bits in RemainingBits,
// allowing for additional bits to be set that were set in OriginalBits.
static uint64_t maximalLogicalImmWithin(uint64_t RemainingBits,
uint64_t OriginalBits) {
// Find the first set bit.
uint32_t Position = llvm::countTrailingZeros(RemainingBits);

// Get the first run of set bits.
uint64_t FirstRun = GetRunOfOnesStartingAt(OriginalBits, Position);

// Replicate the run as many times as possible, as long as the bits are set in
// RemainingBits.
uint64_t MaximalImm = MaximallyReplicateSubImmediate(OriginalBits, FirstRun);

return MaximalImm;
}

static std::optional<std::pair<uint64_t, uint64_t>>
decomposeIntoOrrOfLogicalImmediates(uint64_t UImm) {
if (UImm == 0 || ~UImm == 0)
return std::nullopt;

// Make sure we don't have a run of ones split around the rotation boundary.
uint32_t InitialTrailingOnes = llvm::countTrailingOnes(UImm);
uint64_t RotatedBits = rotr(UImm, InitialTrailingOnes);

// Find the largest logical immediate that fits within the full immediate.
uint64_t MaximalImm1 = maximalLogicalImmWithin(RotatedBits, RotatedBits);

// Remove all bits that are set by this mask.
uint64_t RemainingBits = RotatedBits & ~MaximalImm1;

// Find the largest logical immediate covering the remaining bits, allowing
// for additional bits to be set that were also set in the original immediate.
uint64_t MaximalImm2 = maximalLogicalImmWithin(RemainingBits, RotatedBits);

// If any bits still haven't been covered, then give up.
if (RemainingBits & ~MaximalImm2)
return std::nullopt;

// Make sure to un-rotate the immediates.
return std::make_pair(rotl(MaximalImm1, InitialTrailingOnes),
rotl(MaximalImm2, InitialTrailingOnes));
}

// Attempt to expand an immediate as the ORR of a pair of logical immediates.
static bool tryOrrOfLogicalImmediates(uint64_t UImm,
SmallVectorImpl<ImmInsnModel> &Insn) {
auto MaybeDecomposition = decomposeIntoOrrOfLogicalImmediates(UImm);
if (MaybeDecomposition == std::nullopt)
return false;
uint64_t Imm1 = MaybeDecomposition->first;
uint64_t Imm2 = MaybeDecomposition->second;

uint64_t Encoding1, Encoding2;
bool Imm1Success = AArch64_AM::processLogicalImmediate(Imm1, 64, Encoding1);
bool Imm2Success = AArch64_AM::processLogicalImmediate(Imm2, 64, Encoding2);

if (Imm1Success && Imm2Success) {
// Create the ORR-immediate instructions.
Insn.push_back({AArch64::ORRXri, 0, Encoding1});
Insn.push_back({AArch64::ORRXri, 1, Encoding2});
return true;
}

return false;
}

// Attempt to expand an immediate as the AND of a pair of logical immediates.
// This is done by applying DeMorgan's law, under which logical immediates
// are closed.
static bool tryAndOfLogicalImmediates(uint64_t UImm,
SmallVectorImpl<ImmInsnModel> &Insn) {
// Apply DeMorgan's law to turn this into an ORR problem.
auto MaybeDecomposition = decomposeIntoOrrOfLogicalImmediates(~UImm);
if (MaybeDecomposition == std::nullopt)
return false;
uint64_t Imm1 = MaybeDecomposition->first;
uint64_t Imm2 = MaybeDecomposition->second;

uint64_t Encoding1, Encoding2;
bool Imm1Success = AArch64_AM::processLogicalImmediate(~Imm1, 64, Encoding1);
bool Imm2Success = AArch64_AM::processLogicalImmediate(~Imm2, 64, Encoding2);

if (Imm1Success && Imm2Success) {
// Materialize Imm1, the LHS of the AND
Insn.push_back({AArch64::ORRXri, 0, Encoding1});
// AND Imm1 with Imm2
Insn.push_back({AArch64::ANDXri, 1, Encoding2});
return true;
}

return false;
}

/// \brief Expand a MOVi32imm or MOVi64imm pseudo instruction to a
/// MOVZ or MOVN of width BitSize followed by up to 3 MOVK instructions.
static inline void expandMOVImmSimple(uint64_t Imm, unsigned BitSize,
Expand Down Expand Up @@ -507,14 +372,6 @@ void AArch64_IMM::expandMOVImm(uint64_t Imm, unsigned BitSize,
}
}

// Attempt to use a sequence of two ORR-immediate instructions.
if (tryOrrOfLogicalImmediates(Imm, Insn))
return;

// Attempt to use a sequence of ORR-immediate followed by AND-immediate.
if (tryAndOfLogicalImmediates(Imm, Insn))
return;

// FIXME: Add more two-instruction sequences.

// Three instruction sequences.
Expand Down
38 changes: 4 additions & 34 deletions llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,40 +148,10 @@ bool AArch64ExpandPseudo::expandMOVImm(MachineBasicBlock &MBB,

case AArch64::ORRWri:
case AArch64::ORRXri:
if (I->Op1 == 0) {
MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
.add(MI.getOperand(0))
.addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
.addImm(I->Op2));
} else {
Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
MIBS.push_back(
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
.addReg(DstReg, RegState::Define |
getDeadRegState(DstIsDead && LastItem) |
RenamableState)
.addReg(DstReg)
.addImm(I->Op2));
}
break;
case AArch64::ANDXri:
if (I->Op1 == 0) {
MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
.add(MI.getOperand(0))
.addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
.addImm(I->Op2));
} else {
Register DstReg = MI.getOperand(0).getReg();
bool DstIsDead = MI.getOperand(0).isDead();
MIBS.push_back(
BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
.addReg(DstReg, RegState::Define |
getDeadRegState(DstIsDead && LastItem) |
RenamableState)
.addReg(DstReg)
.addImm(I->Op2));
}
MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
.add(MI.getOperand(0))
.addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
.addImm(I->Op2));
break;
case AArch64::MOVNWi:
case AArch64::MOVNXi:
Expand Down
49 changes: 34 additions & 15 deletions llvm/test/CodeGen/AArch64/arm64-movi.ll
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,14 @@ define i64 @movz_skip1_movk() nounwind {
ret i64 147695335379508
}

; FIXME: Prefer "mov w0, #2863311530; lsl x0, x0, #4"
; or "mov x0, #-6148914691236517206; and x0, x0, #45812984480"
define i64 @orr_lsl_pattern() nounwind {
; CHECK-LABEL: orr_lsl_pattern:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x0, #-6148914691236517206
; CHECK-NEXT: and x0, x0, #0x1fffffffe0
; CHECK-NEXT: mov x0, #43680
; CHECK-NEXT: movk x0, #43690, lsl #16
; CHECK-NEXT: movk x0, #10, lsl #32
; CHECK-NEXT: ret
ret i64 45812984480
}
Expand Down Expand Up @@ -319,11 +322,13 @@ define i64 @orr_movk15() nounwind {
ret i64 549621596159
}

; FIXME: prefer "mov x0, #2147483646; orr x0, x0, #36028659580010496"
define i64 @orr_movk16() nounwind {
; CHECK-LABEL: orr_movk16:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x0, #2147483646
; CHECK-NEXT: orr x0, x0, #0x7fffe0007fffe0
; CHECK-NEXT: mov x0, #36028659580010496
; CHECK-NEXT: movk x0, #65534
; CHECK-NEXT: movk x0, #32767, lsl #16
; CHECK-NEXT: ret
ret i64 36028661727494142
}
Expand All @@ -346,11 +351,13 @@ define i64 @orr_movk18() nounwind {
ret i64 137438953409
}

; FIXME: prefer "mov x0, #72340172838076673; and x0, x0, #2199023255296"
define i64 @orr_and() nounwind {
; CHECK-LABEL: orr_and:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x0, #72340172838076673
; CHECK-NEXT: and x0, x0, #0xffffffffff00
; CHECK-NEXT: mov x0, #256
; CHECK-NEXT: movk x0, #257, lsl #16
; CHECK-NEXT: movk x0, #257, lsl #32
; CHECK-NEXT: ret
ret i64 1103823438080
}
Expand Down Expand Up @@ -388,47 +395,59 @@ define i64 @movn_eor() nounwind {
ret i64 3689348814437076172
}

; FIXME: prefer "mov x0, #536866816; orr x0, x0, #0x3fff800000000000"
define i64 @orr_orr_64() nounwind {
; CHECK-LABEL: orr_orr_64:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x0, #536866816
; CHECK-NEXT: orr x0, x0, #0x3fff800000000000
; CHECK-NEXT: mov x0, #4611545280939032576
; CHECK-NEXT: movk x0, #61440
; CHECK-NEXT: movk x0, #8191, lsl #16
; CHECK-NEXT: ret
ret i64 4611545281475899392
}

; FIXME: prefer "mov x0, #558551907040256; orr x0, x0, #0x1000100010001000"
define i64 @orr_orr_32() nounwind {
; CHECK-LABEL: orr_orr_32:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x0, #558551907040256
; CHECK-NEXT: orr x0, x0, #0x1c001c001c001c00
; CHECK-NEXT: mov x0, #-287953294993589248
; CHECK-NEXT: movk x0, #7169, lsl #16
; CHECK-NEXT: movk x0, #7169, lsl #48
; CHECK-NEXT: ret
ret i64 2018171185438784512
}

; FIXME: prefer "mov x0, #281479271743489; orr x0, x0, #0x1000100010001000"
define i64 @orr_orr_16() nounwind {
; CHECK-LABEL: orr_orr_16:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x0, #1152939097061330944
; CHECK-NEXT: orr x0, x0, #0x1000100010001
; CHECK-NEXT: mov x0, #4097
; CHECK-NEXT: movk x0, #4097, lsl #16
; CHECK-NEXT: movk x0, #4097, lsl #32
; CHECK-NEXT: movk x0, #4097, lsl #48
; CHECK-NEXT: ret
ret i64 1153220576333074433
}

; FIXME: prefer "mov x0, #144680345676153346; orr x0, x0, #0x1818181818181818"
define i64 @orr_orr_8() nounwind {
; CHECK-LABEL: orr_orr_8:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x0, #144680345676153346
; CHECK-NEXT: orr x0, x0, #0x1818181818181818
; CHECK-NEXT: mov x0, #6682
; CHECK-NEXT: movk x0, #6682, lsl #16
; CHECK-NEXT: movk x0, #6682, lsl #32
; CHECK-NEXT: movk x0, #6682, lsl #48
; CHECK-NEXT: ret
ret i64 1880844493789993498
}

; FIXME: prefer "mov x0, #-6148914691236517206; orr x0, x0, #0x0FFFFF0000000000"
define i64 @orr_64_orr_8() nounwind {
; CHECK-LABEL: orr_64_orr_8:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x0, #-6148914691236517206
; CHECK-NEXT: orr x0, x0, #0xfffff0000000000
; CHECK-NEXT: movk x0, #65450, lsl #32
; CHECK-NEXT: movk x0, #45055, lsl #48
; CHECK-NEXT: ret
ret i64 -5764607889538110806
}

0 comments on commit 80fe772

Please sign in to comment.