From 86bdc1efbecc3e3ff037701011b001b1194b4a06 Mon Sep 17 00:00:00 2001 From: Juergen Ributzka Date: Mon, 15 Sep 2014 20:47:16 +0000 Subject: [PATCH] [FastISel][AArch64] Improve floating-point compare support. Add support for the last two missing fcmp condition codes: UEQ and ONE. This fixes rdar://problem/18341575. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217823 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/AArch64/AArch64FastISel.cpp | 69 +++++- test/CodeGen/AArch64/arm64-fast-isel-fcmp.ll | 240 ++++++++++--------- 2 files changed, 190 insertions(+), 119 deletions(-) diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp index 05c22566dd5..0577a8d5981 100644 --- a/lib/Target/AArch64/AArch64FastISel.cpp +++ b/lib/Target/AArch64/AArch64FastISel.cpp @@ -1830,22 +1830,77 @@ bool AArch64FastISel::SelectIndirectBr(const Instruction *I) { bool AArch64FastISel::SelectCmp(const Instruction *I) { const CmpInst *CI = cast(I); - // We may not handle every CC for now. - AArch64CC::CondCode CC = getCompareCC(CI->getPredicate()); - if (CC == AArch64CC::AL) - return false; + // Try to optimize or fold the cmp. + CmpInst::Predicate Predicate = optimizeCmpPredicate(CI); + unsigned ResultReg = 0; + switch (Predicate) { + default: + break; + case CmpInst::FCMP_FALSE: + ResultReg = createResultReg(&AArch64::GPR32RegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::COPY), ResultReg) + .addReg(AArch64::WZR, getKillRegState(true)); + break; + case CmpInst::FCMP_TRUE: + ResultReg = fastEmit_i(MVT::i32, MVT::i32, ISD::Constant, 1); + break; + } + + if (ResultReg) { + updateValueMap(I, ResultReg); + return true; + } // Emit the cmp. if (!emitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned())) return false; + ResultReg = createResultReg(&AArch64::GPR32RegClass); + + // FCMP_UEQ and FCMP_ONE cannot be checked with a single instruction. These + // condition codes are inverted, because they are used by CSINC. + static unsigned CondCodeTable[2][2] = { + { AArch64CC::NE, AArch64CC::VC }, + { AArch64CC::PL, AArch64CC::LE } + }; + unsigned *CondCodes = nullptr; + switch (Predicate) { + default: + break; + case CmpInst::FCMP_UEQ: + CondCodes = &CondCodeTable[0][0]; + break; + case CmpInst::FCMP_ONE: + CondCodes = &CondCodeTable[1][0]; + break; + } + + if (CondCodes) { + unsigned TmpReg1 = createResultReg(&AArch64::GPR32RegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr), + TmpReg1) + .addReg(AArch64::WZR, getKillRegState(true)) + .addReg(AArch64::WZR, getKillRegState(true)) + .addImm(CondCodes[0]); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr), + ResultReg) + .addReg(TmpReg1, getKillRegState(true)) + .addReg(AArch64::WZR, getKillRegState(true)) + .addImm(CondCodes[1]); + + updateValueMap(I, ResultReg); + return true; + } + // Now set a register based on the comparison. + AArch64CC::CondCode CC = getCompareCC(Predicate); + assert((CC != AArch64CC::AL) && "Unexpected condition code."); AArch64CC::CondCode invertedCC = getInvertedCondCode(CC); - unsigned ResultReg = createResultReg(&AArch64::GPR32RegClass); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(AArch64::CSINCWr), ResultReg) - .addReg(AArch64::WZR) - .addReg(AArch64::WZR) + .addReg(AArch64::WZR, getKillRegState(true)) + .addReg(AArch64::WZR, getKillRegState(true)) .addImm(invertedCC); updateValueMap(I, ResultReg); diff --git a/test/CodeGen/AArch64/arm64-fast-isel-fcmp.ll b/test/CodeGen/AArch64/arm64-fast-isel-fcmp.ll index de101f2665e..111b6bd3d49 100644 --- a/test/CodeGen/AArch64/arm64-fast-isel-fcmp.ll +++ b/test/CodeGen/AArch64/arm64-fast-isel-fcmp.ll @@ -1,146 +1,162 @@ ; RUN: llc -O0 -fast-isel-abort -verify-machineinstrs -mtriple=arm64-apple-darwin < %s | FileCheck %s -define zeroext i1 @fcmp_float1(float %a) nounwind ssp { -entry: -; CHECK-LABEL: @fcmp_float1 -; CHECK: fcmp s0, #0.0 -; CHECK: cset w{{[0-9]+}}, ne - %cmp = fcmp une float %a, 0.000000e+00 - ret i1 %cmp +define zeroext i1 @fcmp_float1(float %a) { +; CHECK-LABEL: fcmp_float1 +; CHECK: fcmp s0, #0.0 +; CHECK-NEXT: cset {{w[0-9]+}}, ne + %1 = fcmp une float %a, 0.000000e+00 + ret i1 %1 } -define zeroext i1 @fcmp_float2(float %a, float %b) nounwind ssp { -entry: -; CHECK-LABEL: @fcmp_float2 -; CHECK: fcmp s0, s1 -; CHECK: cset w{{[0-9]+}}, ne - %cmp = fcmp une float %a, %b - ret i1 %cmp +define zeroext i1 @fcmp_float2(float %a, float %b) { +; CHECK-LABEL: fcmp_float2 +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, ne + %1 = fcmp une float %a, %b + ret i1 %1 } -define zeroext i1 @fcmp_double1(double %a) nounwind ssp { -entry: -; CHECK-LABEL: @fcmp_double1 -; CHECK: fcmp d0, #0.0 -; CHECK: cset w{{[0-9]+}}, ne - %cmp = fcmp une double %a, 0.000000e+00 - ret i1 %cmp +define zeroext i1 @fcmp_double1(double %a) { +; CHECK-LABEL: fcmp_double1 +; CHECK: fcmp d0, #0.0 +; CHECK-NEXT: cset {{w[0-9]+}}, ne + %1 = fcmp une double %a, 0.000000e+00 + ret i1 %1 } -define zeroext i1 @fcmp_double2(double %a, double %b) nounwind ssp { -entry: -; CHECK-LABEL: @fcmp_double2 -; CHECK: fcmp d0, d1 -; CHECK: cset w{{[0-9]+}}, ne - %cmp = fcmp une double %a, %b - ret i1 %cmp +define zeroext i1 @fcmp_double2(double %a, double %b) { +; CHECK-LABEL: fcmp_double2 +; CHECK: fcmp d0, d1 +; CHECK-NEXT: cset {{w[0-9]+}}, ne + %1 = fcmp une double %a, %b + ret i1 %1 } ; Check each fcmp condition -define float @fcmp_oeq(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_oeq -; CHECK: fcmp s0, s1 -; CHECK: cset w{{[0-9]+}}, eq - %cmp = fcmp oeq float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_false(float %a) { +; CHECK-LABEL: fcmp_false +; CHECK: mov {{w[0-9]+}}, wzr + %1 = fcmp ogt float %a, %a + ret i1 %1 } -define float @fcmp_ogt(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_ogt -; CHECK: fcmp s0, s1 -; CHECK: cset w{{[0-9]+}}, gt - %cmp = fcmp ogt float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_oeq(float %a, float %b) { +; CHECK-LABEL: fcmp_oeq +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, eq + %1 = fcmp oeq float %a, %b + ret i1 %1 } -define float @fcmp_oge(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_oge -; CHECK: fcmp s0, s1 -; CHECK: cset w{{[0-9]+}}, ge - %cmp = fcmp oge float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_ogt(float %a, float %b) { +; CHECK-LABEL: fcmp_ogt +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, gt + %1 = fcmp ogt float %a, %b + ret i1 %1 } -define float @fcmp_olt(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_olt -; CHECK: fcmp s0, s1 -; CHECK: cset w{{[0-9]+}}, mi - %cmp = fcmp olt float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_oge(float %a, float %b) { +; CHECK-LABEL: fcmp_oge +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, ge + %1 = fcmp oge float %a, %b + ret i1 %1 } -define float @fcmp_ole(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_ole -; CHECK: fcmp s0, s1 -; CHECK: cset w{{[0-9]+}}, ls - %cmp = fcmp ole float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_olt(float %a, float %b) { +; CHECK-LABEL: fcmp_olt +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, mi + %1 = fcmp olt float %a, %b + ret i1 %1 } -define float @fcmp_ord(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_ord -; CHECK: fcmp s0, s1 -; CHECK: cset {{w[0-9]+}}, vc - %cmp = fcmp ord float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_ole(float %a, float %b) { +; CHECK-LABEL: fcmp_ole +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, ls + %1 = fcmp ole float %a, %b + ret i1 %1 } -define float @fcmp_uno(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_uno -; CHECK: fcmp s0, s1 -; CHECK: cset {{w[0-9]+}}, vs - %cmp = fcmp uno float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_one(float %a, float %b) { +; CHECK-LABEL: fcmp_one +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset [[REG:w[0-9]+]], mi +; CHECK-NEXT: csinc {{w[0-9]+}}, [[REG]], wzr, le + %1 = fcmp one float %a, %b + ret i1 %1 } -define float @fcmp_ugt(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_ugt -; CHECK: fcmp s0, s1 -; CHECK: cset {{w[0-9]+}}, hi - %cmp = fcmp ugt float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_ord(float %a, float %b) { +; CHECK-LABEL: fcmp_ord +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, vc + %1 = fcmp ord float %a, %b + ret i1 %1 } -define float @fcmp_uge(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_uge -; CHECK: fcmp s0, s1 -; CHECK: cset {{w[0-9]+}}, pl - %cmp = fcmp uge float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_uno(float %a, float %b) { +; CHECK-LABEL: fcmp_uno +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, vs + %1 = fcmp uno float %a, %b + ret i1 %1 } -define float @fcmp_ult(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_ult -; CHECK: fcmp s0, s1 -; CHECK: cset {{w[0-9]+}}, lt - %cmp = fcmp ult float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_ueq(float %a, float %b) { +; CHECK-LABEL: fcmp_ueq +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset [[REG:w[0-9]+]], eq +; CHECK-NEXT: csinc {{w[0-9]+}}, [[REG]], wzr, vc + %1 = fcmp ueq float %a, %b + ret i1 %1 } -define float @fcmp_ule(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_ule -; CHECK: fcmp s0, s1 -; CHECK: cset {{w[0-9]+}}, le - %cmp = fcmp ule float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_ugt(float %a, float %b) { +; CHECK-LABEL: fcmp_ugt +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, hi + %1 = fcmp ugt float %a, %b + ret i1 %1 } -define float @fcmp_une(float %a, float %b) nounwind ssp { -; CHECK-LABEL: @fcmp_une -; CHECK: fcmp s0, s1 -; CHECK: cset {{w[0-9]+}}, ne - %cmp = fcmp une float %a, %b - %conv = uitofp i1 %cmp to float - ret float %conv +define zeroext i1 @fcmp_uge(float %a, float %b) { +; CHECK-LABEL: fcmp_uge +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, pl + %1 = fcmp uge float %a, %b + ret i1 %1 +} + +define zeroext i1 @fcmp_ult(float %a, float %b) { +; CHECK-LABEL: fcmp_ult +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, lt + %1 = fcmp ult float %a, %b + ret i1 %1 +} + +define zeroext i1 @fcmp_ule(float %a, float %b) { +; CHECK-LABEL: fcmp_ule +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, le + %1 = fcmp ule float %a, %b + ret i1 %1 +} + +define zeroext i1 @fcmp_une(float %a, float %b) { +; CHECK-LABEL: fcmp_une +; CHECK: fcmp s0, s1 +; CHECK-NEXT: cset {{w[0-9]+}}, ne + %1 = fcmp une float %a, %b + ret i1 %1 +} + +define zeroext i1 @fcmp_true(float %a) { +; CHECK-LABEL: fcmp_true +; CHECK: orr {{w[0-9]+}}, wzr, #0x1 + %1 = fcmp ueq float %a, %a + ret i1 %1 }