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