137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//=- AArch64ConditionOptimizer.cpp - Remove useless comparisons for AArch64 -=//
237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//                     The LLVM Compiler Infrastructure
437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// This file is distributed under the University of Illinois Open Source
637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// License. See LICENSE.TXT for details.
737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//===----------------------------------------------------------------------===//
937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
1037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// This pass tries to make consecutive compares of values use same operands to
1137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// allow CSE pass to remove duplicated instructions.  For this it analyzes
1237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// branches and adjusts comparisons with immediate values by converting:
1337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//  * GE -> GT
1437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//  * GT -> GE
1537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//  * LT -> LE
1637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//  * LE -> LT
1737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// and adjusting immediate values appropriately.  It basically corrects two
1837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// immediate values towards each other to make them equal.
1937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
2037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Consider the following example in C:
2137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
2237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//   if ((a < 5 && ...) || (a > 5 && ...)) {
2337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//        ~~~~~             ~~~~~
2437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//          ^                 ^
2537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//          x                 y
2637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
2737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Here both "x" and "y" expressions compare "a" with "5".  When "x" evaluates
2837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// to "false", "y" can just check flags set by the first comparison.  As a
2937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// result of the canonicalization employed by
3037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// SelectionDAGBuilder::visitSwitchCase, DAGCombine, and other target-specific
3137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// code, assembly ends up in the form that is not CSE friendly:
3237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
3337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     ...
3437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     cmp      w8, #4
3537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     b.gt     .LBB0_3
3637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     ...
3737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//   .LBB0_3:
3837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     cmp      w8, #6
3937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     b.lt     .LBB0_6
4037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     ...
4137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
4237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Same assembly after the pass:
4337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
4437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     ...
4537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     cmp      w8, #5
4637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     b.ge     .LBB0_3
4737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     ...
4837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//   .LBB0_3:
4937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     cmp      w8, #5     // <-- CSE pass removes this instruction
5037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     b.le     .LBB0_6
5137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//     ...
5237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
5337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Currently only SUBS and ADDS followed by b.?? are supported.
5437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
5537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// TODO: maybe handle TBNZ/TBZ the same way as CMP when used instead for "a < 0"
5637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// TODO: handle other conditional instructions (e.g. CSET)
5737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// TODO: allow second branching to be anything if it doesn't require adjusting
5837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//
5937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines//===----------------------------------------------------------------------===//
6037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
6137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "AArch64.h"
6237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/ADT/DepthFirstIterator.h"
6337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/ADT/SmallVector.h"
6437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/ADT/Statistic.h"
6537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/CodeGen/LiveIntervalAnalysis.h"
6637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/CodeGen/MachineDominators.h"
6737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/CodeGen/MachineFunction.h"
6837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/CodeGen/MachineFunctionPass.h"
6937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/CodeGen/MachineInstrBuilder.h"
7037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/CodeGen/Passes.h"
7137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/Support/CommandLine.h"
7237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/Support/Debug.h"
7337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/Support/raw_ostream.h"
7437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/Target/TargetInstrInfo.h"
7537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include "llvm/Target/TargetSubtargetInfo.h"
7637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include <cstdlib>
7737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#include <tuple>
7837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
7937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesusing namespace llvm;
8037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
8137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#define DEBUG_TYPE "aarch64-condopt"
8237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
8337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesSTATISTIC(NumConditionsAdjusted, "Number of conditions adjusted");
8437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
8537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesnamespace {
8637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesclass AArch64ConditionOptimizer : public MachineFunctionPass {
8737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  const TargetInstrInfo *TII;
8837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  MachineDominatorTree *DomTree;
8937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
9037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinespublic:
9137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Stores immediate, compare instruction opcode and branch condition (in this
9237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // order) of adjusted comparison.
9337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  typedef std::tuple<int, int, AArch64CC::CondCode> CmpInfo;
9437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
9537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  static char ID;
9637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  AArch64ConditionOptimizer() : MachineFunctionPass(ID) {}
9737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override;
9837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  MachineInstr *findSuitableCompare(MachineBasicBlock *MBB);
9937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  CmpInfo adjustCmp(MachineInstr *CmpMI, AArch64CC::CondCode Cmp);
10037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  void modifyCmp(MachineInstr *CmpMI, const CmpInfo &Info);
10137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  bool adjustTo(MachineInstr *CmpMI, AArch64CC::CondCode Cmp, MachineInstr *To,
10237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                int ToImm);
10337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  bool runOnMachineFunction(MachineFunction &MF) override;
10437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  const char *getPassName() const override {
10537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return "AArch64 Condition Optimizer";
10637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
10737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines};
10837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines} // end anonymous namespace
10937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
11037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hineschar AArch64ConditionOptimizer::ID = 0;
11137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
11237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesnamespace llvm {
11337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesvoid initializeAArch64ConditionOptimizerPass(PassRegistry &);
11437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
11537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
11637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesINITIALIZE_PASS_BEGIN(AArch64ConditionOptimizer, "aarch64-condopt",
11737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                      "AArch64 CondOpt Pass", false, false)
11837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesINITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
11937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesINITIALIZE_PASS_DEPENDENCY(LiveIntervals)
12037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesINITIALIZE_PASS_END(AArch64ConditionOptimizer, "aarch64-condopt",
12137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                    "AArch64 CondOpt Pass", false, false)
12237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
12337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesFunctionPass *llvm::createAArch64ConditionOptimizerPass() {
12437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return new AArch64ConditionOptimizer();
12537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
12637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
12737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesvoid AArch64ConditionOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {
12837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  AU.addRequired<MachineDominatorTree>();
12937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  AU.addPreserved<MachineDominatorTree>();
13037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  AU.addRequired<LiveIntervals>();
13137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  AU.addPreserved<LiveIntervals>();
13237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  MachineFunctionPass::getAnalysisUsage(AU);
13337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
13437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
13537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Finds compare instruction that corresponds to supported types of branching.
13637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Returns the instruction or nullptr on failures or detecting unsupported
13737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// instructions.
13837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesMachineInstr *AArch64ConditionOptimizer::findSuitableCompare(
13937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    MachineBasicBlock *MBB) {
14037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  MachineBasicBlock::iterator I = MBB->getFirstTerminator();
14137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (I == MBB->end())
14237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return nullptr;
14337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
14437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (I->getOpcode() != AArch64::Bcc)
14537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return nullptr;
14637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
14737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Now find the instruction controlling the terminator.
14837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  for (MachineBasicBlock::iterator B = MBB->begin(); I != B;) {
14937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    --I;
15037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    assert(!I->isTerminator() && "Spurious terminator");
15137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    switch (I->getOpcode()) {
15237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // cmp is an alias for subs with a dead destination register.
15337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::SUBSWri:
15437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::SUBSXri:
15537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // cmn is an alias for adds with a dead destination register.
15637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::ADDSWri:
15737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::ADDSXri:
15837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      if (I->getOperand(0).isDead())
15937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        return I;
16037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
16137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      DEBUG(dbgs() << "Destination of cmp is not dead, " << *I << '\n');
16237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      return nullptr;
16337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
16437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // Prevent false positive case like:
16537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // cmp      w19, #0
16637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // cinc     w0, w19, gt
16737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // ...
16837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // fcmp     d8, #0.0
16937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // b.gt     .LBB0_5
17037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::FCMPDri:
17137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::FCMPSri:
17237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::FCMPESri:
17337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::FCMPEDri:
17437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
17537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::SUBSWrr:
17637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::SUBSXrr:
17737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::ADDSWrr:
17837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::ADDSXrr:
17937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::FCMPSrr:
18037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::FCMPDrr:
18137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::FCMPESrr:
18237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    case AArch64::FCMPEDrr:
18337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // Skip comparison instructions without immediate operands.
18437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      return nullptr;
18537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
18637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
18737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  DEBUG(dbgs() << "Flags not defined in BB#" << MBB->getNumber() << '\n');
18837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return nullptr;
18937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
19037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
19137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Changes opcode adds <-> subs considering register operand width.
19237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic int getComplementOpc(int Opc) {
19337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  switch (Opc) {
19437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  case AArch64::ADDSWri: return AArch64::SUBSWri;
19537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  case AArch64::ADDSXri: return AArch64::SUBSXri;
19637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  case AArch64::SUBSWri: return AArch64::ADDSWri;
19737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  case AArch64::SUBSXri: return AArch64::ADDSXri;
19837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  default:
19937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    llvm_unreachable("Unexpected opcode");
20037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
20137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
20237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
20337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Changes form of comparison inclusive <-> exclusive.
20437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic AArch64CC::CondCode getAdjustedCmp(AArch64CC::CondCode Cmp) {
20537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  switch (Cmp) {
20637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  case AArch64CC::GT: return AArch64CC::GE;
20737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  case AArch64CC::GE: return AArch64CC::GT;
20837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  case AArch64CC::LT: return AArch64CC::LE;
20937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  case AArch64CC::LE: return AArch64CC::LT;
21037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  default:
21137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    llvm_unreachable("Unexpected condition code");
21237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
21337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
21437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
21537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Transforms GT -> GE, GE -> GT, LT -> LE, LE -> LT by updating comparison
21637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// operator and condition code.
21737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesAArch64ConditionOptimizer::CmpInfo AArch64ConditionOptimizer::adjustCmp(
21837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    MachineInstr *CmpMI, AArch64CC::CondCode Cmp) {
21937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  int Opc = CmpMI->getOpcode();
22037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
22137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // CMN (compare with negative immediate) is an alias to ADDS (as
22237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // "operand - negative" == "operand + positive")
22337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  bool Negative = (Opc == AArch64::ADDSWri || Opc == AArch64::ADDSXri);
22437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
22537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  int Correction = (Cmp == AArch64CC::GT) ? 1 : -1;
22637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Negate Correction value for comparison with negative immediate (CMN).
22737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (Negative) {
22837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    Correction = -Correction;
22937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
23037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
23137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  const int OldImm = (int)CmpMI->getOperand(2).getImm();
23237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  const int NewImm = std::abs(OldImm + Correction);
23337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
23437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Handle +0 -> -1 and -0 -> +1 (CMN with 0 immediate) transitions by
23537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // adjusting compare instruction opcode.
23637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (OldImm == 0 && ((Negative && Correction == 1) ||
23737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                      (!Negative && Correction == -1))) {
23837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    Opc = getComplementOpc(Opc);
23937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
24037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
24137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return CmpInfo(NewImm, Opc, getAdjustedCmp(Cmp));
24237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
24337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
24437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Applies changes to comparison instruction suggested by adjustCmp().
24537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesvoid AArch64ConditionOptimizer::modifyCmp(MachineInstr *CmpMI,
24637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    const CmpInfo &Info) {
24737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  int Imm;
24837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  int Opc;
24937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  AArch64CC::CondCode Cmp;
25037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  std::tie(Imm, Opc, Cmp) = Info;
25137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
25237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  MachineBasicBlock *const MBB = CmpMI->getParent();
25337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
25437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Change immediate in comparison instruction (ADDS or SUBS).
25537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  BuildMI(*MBB, CmpMI, CmpMI->getDebugLoc(), TII->get(Opc))
25637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      .addOperand(CmpMI->getOperand(0))
25737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      .addOperand(CmpMI->getOperand(1))
25837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      .addImm(Imm)
25937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      .addOperand(CmpMI->getOperand(3));
26037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  CmpMI->eraseFromParent();
26137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
26237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // The fact that this comparison was picked ensures that it's related to the
26337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // first terminator instruction.
26437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  MachineInstr *BrMI = MBB->getFirstTerminator();
26537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
26637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Change condition in branch instruction.
26737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  BuildMI(*MBB, BrMI, BrMI->getDebugLoc(), TII->get(AArch64::Bcc))
26837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      .addImm(Cmp)
26937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      .addOperand(BrMI->getOperand(1));
27037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  BrMI->eraseFromParent();
27137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
27237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  MBB->updateTerminator();
27337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
27437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  ++NumConditionsAdjusted;
27537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
27637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
27737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Parse a condition code returned by AnalyzeBranch, and compute the CondCode
27837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// corresponding to TBB.
27937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Returns true if parsing was successful, otherwise false is returned.
28037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesstatic bool parseCond(ArrayRef<MachineOperand> Cond, AArch64CC::CondCode &CC) {
28137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // A normal br.cond simply has the condition code.
28237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (Cond[0].getImm() != -1) {
28337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    assert(Cond.size() == 1 && "Unknown Cond array format");
28437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
28537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return true;
28637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
28737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return false;
28837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
28937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
29037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// Adjusts one cmp instruction to another one if result of adjustment will allow
29137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// CSE.  Returns true if compare instruction was changed, otherwise false is
29237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines// returned.
29337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool AArch64ConditionOptimizer::adjustTo(MachineInstr *CmpMI,
29437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  AArch64CC::CondCode Cmp, MachineInstr *To, int ToImm)
29537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines{
29637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  CmpInfo Info = adjustCmp(CmpMI, Cmp);
29737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (std::get<0>(Info) == ToImm && std::get<1>(Info) == To->getOpcode()) {
29837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    modifyCmp(CmpMI, Info);
29937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return true;
30037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
30137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return false;
30237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
30337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
30437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesbool AArch64ConditionOptimizer::runOnMachineFunction(MachineFunction &MF) {
30537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  DEBUG(dbgs() << "********** AArch64 Conditional Compares **********\n"
30637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines               << "********** Function: " << MF.getName() << '\n');
307ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  TII = MF.getSubtarget().getInstrInfo();
30837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  DomTree = &getAnalysis<MachineDominatorTree>();
30937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
31037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  bool Changed = false;
31137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
31237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Visit blocks in dominator tree pre-order. The pre-order enables multiple
31337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // cmp-conversions from the same head block.
31437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // Note that updateDomTree() modifies the children of the DomTree node
31537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // currently being visited. The df_iterator supports that; it doesn't look at
31637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  // child_begin() / child_end() until after a node has been visited.
31737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  for (MachineDomTreeNode *I : depth_first(DomTree)) {
31837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    MachineBasicBlock *HBB = I->getBlock();
31937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
32037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    SmallVector<MachineOperand, 4> HeadCond;
32137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
32237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (TII->AnalyzeBranch(*HBB, TBB, FBB, HeadCond)) {
32337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      continue;
32437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
32537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
32637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // Equivalence check is to skip loops.
32737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (!TBB || TBB == HBB) {
32837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      continue;
32937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
33037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
33137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    SmallVector<MachineOperand, 4> TrueCond;
33237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    MachineBasicBlock *TBB_TBB = nullptr, *TBB_FBB = nullptr;
33337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (TII->AnalyzeBranch(*TBB, TBB_TBB, TBB_FBB, TrueCond)) {
33437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      continue;
33537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
33637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
33737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    MachineInstr *HeadCmpMI = findSuitableCompare(HBB);
33837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (!HeadCmpMI) {
33937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      continue;
34037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
34137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
34237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    MachineInstr *TrueCmpMI = findSuitableCompare(TBB);
34337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (!TrueCmpMI) {
34437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      continue;
34537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
34637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
34737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    AArch64CC::CondCode HeadCmp;
34837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (HeadCond.empty() || !parseCond(HeadCond, HeadCmp)) {
34937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      continue;
35037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
35137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
35237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    AArch64CC::CondCode TrueCmp;
35337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (TrueCond.empty() || !parseCond(TrueCond, TrueCmp)) {
35437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      continue;
35537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
35637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
35737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    const int HeadImm = (int)HeadCmpMI->getOperand(2).getImm();
35837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    const int TrueImm = (int)TrueCmpMI->getOperand(2).getImm();
35937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
36037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    DEBUG(dbgs() << "Head branch:\n");
36137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    DEBUG(dbgs() << "\tcondition: "
36237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines          << AArch64CC::getCondCodeName(HeadCmp) << '\n');
36337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    DEBUG(dbgs() << "\timmediate: " << HeadImm << '\n');
36437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
36537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    DEBUG(dbgs() << "True branch:\n");
36637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    DEBUG(dbgs() << "\tcondition: "
36737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines          << AArch64CC::getCondCodeName(TrueCmp) << '\n');
36837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    DEBUG(dbgs() << "\timmediate: " << TrueImm << '\n');
36937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
37037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    if (((HeadCmp == AArch64CC::GT && TrueCmp == AArch64CC::LT) ||
37137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines         (HeadCmp == AArch64CC::LT && TrueCmp == AArch64CC::GT)) &&
37237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        std::abs(TrueImm - HeadImm) == 2) {
37337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // This branch transforms machine instructions that correspond to
37437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      //
37537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // 1) (a > {TrueImm} && ...) || (a < {HeadImm} && ...)
37637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // 2) (a < {TrueImm} && ...) || (a > {HeadImm} && ...)
37737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      //
37837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // into
37937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      //
38037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // 1) (a >= {NewImm} && ...) || (a <= {NewImm} && ...)
38137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // 2) (a <= {NewImm} && ...) || (a >= {NewImm} && ...)
38237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
38337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);
38437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);
38537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&
38637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines          std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {
38737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        modifyCmp(HeadCmpMI, HeadCmpInfo);
38837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        modifyCmp(TrueCmpMI, TrueCmpInfo);
38937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        Changed = true;
39037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      }
39137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    } else if (((HeadCmp == AArch64CC::GT && TrueCmp == AArch64CC::GT) ||
39237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                (HeadCmp == AArch64CC::LT && TrueCmp == AArch64CC::LT)) &&
39337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                std::abs(TrueImm - HeadImm) == 1) {
39437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // This branch transforms machine instructions that correspond to
39537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      //
39637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // 1) (a > {TrueImm} && ...) || (a > {HeadImm} && ...)
39737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // 2) (a < {TrueImm} && ...) || (a < {HeadImm} && ...)
39837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      //
39937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // into
40037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      //
40137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // 1) (a <= {NewImm} && ...) || (a >  {NewImm} && ...)
40237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // 2) (a <  {NewImm} && ...) || (a >= {NewImm} && ...)
40337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
40437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // GT -> GE transformation increases immediate value, so picking the
40537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // smaller one; LT -> LE decreases immediate value so invert the choice.
40637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      bool adjustHeadCond = (HeadImm < TrueImm);
40737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      if (HeadCmp == AArch64CC::LT) {
40837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines          adjustHeadCond = !adjustHeadCond;
40937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      }
41037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
41137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      if (adjustHeadCond) {
41237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);
41337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      } else {
41437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines        Changed |= adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm);
41537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      }
41637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
41737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // Other transformation cases almost never occur due to generation of < or >
41837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    // comparisons instead of <= and >=.
41937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
42037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
42137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return Changed;
42237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
423