diff options
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.cpp | 41 | ||||
-rw-r--r-- | test/CodeGen/ARM/sub-cmp-peephole.ll | 60 |
2 files changed, 94 insertions, 7 deletions
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index df8c017..f835a4e 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -2372,8 +2372,32 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, isSafe = true; break; } - // Condition code is after the operand before CPSR. - ARMCC::CondCodes CC = (ARMCC::CondCodes)Instr.getOperand(IO-1).getImm(); + // Condition code is after the operand before CPSR except for VSELs. + ARMCC::CondCodes CC; + bool IsInstrVSel = true; + switch (Instr.getOpcode()) { + default: + IsInstrVSel = false; + CC = (ARMCC::CondCodes)Instr.getOperand(IO - 1).getImm(); + break; + case ARM::VSELEQD: + case ARM::VSELEQS: + CC = ARMCC::EQ; + break; + case ARM::VSELGTD: + case ARM::VSELGTS: + CC = ARMCC::GT; + break; + case ARM::VSELGED: + case ARM::VSELGES: + CC = ARMCC::GE; + break; + case ARM::VSELVSS: + case ARM::VSELVSD: + CC = ARMCC::VS; + break; + } + if (Sub) { ARMCC::CondCodes NewCC = getSwappedCondition(CC); if (NewCC == ARMCC::AL) @@ -2384,11 +2408,14 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, // If it is safe to remove CmpInstr, the condition code of these // operands will be modified. if (SrcReg2 != 0 && Sub->getOperand(1).getReg() == SrcReg2 && - Sub->getOperand(2).getReg() == SrcReg) - OperandsToUpdate.push_back(std::make_pair(&((*I).getOperand(IO-1)), - NewCC)); - } - else + Sub->getOperand(2).getReg() == SrcReg) { + // VSel doesn't support condition code update. + if (IsInstrVSel) + return false; + OperandsToUpdate.push_back( + std::make_pair(&((*I).getOperand(IO - 1)), NewCC)); + } + } else switch (CC) { default: // CPSR can be used multiple times, we should continue. diff --git a/test/CodeGen/ARM/sub-cmp-peephole.ll b/test/CodeGen/ARM/sub-cmp-peephole.ll index 1b411e3..19727da 100644 --- a/test/CodeGen/ARM/sub-cmp-peephole.ll +++ b/test/CodeGen/ARM/sub-cmp-peephole.ll @@ -1,4 +1,7 @@ ; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s +; RUN: llc < %s -mtriple=arm-apple-darwin | FileCheck %s --check-prefix=V7 +; RUN: llc < %s -mtriple=armv8-none-linux-gnueabi | FileCheck %s -check-prefix=V8 + define i32 @f(i32 %a, i32 %b) nounwind ssp { entry: @@ -84,3 +87,60 @@ land.lhs.true: ; preds = %num2long.exit if.end11: ; preds = %num2long.exit ret i32 23 } + +define float @float_sel(i32 %a, i32 %b, float %x, float %y) { +entry: +; CHECK-LABEL: float_sel: +; CHECK-NOT: cmp +; V8-LABEL: float_sel: +; V8-NOT: cmp +; V8: vseleq.f32 + %sub = sub i32 %a, %b + %cmp = icmp eq i32 %sub, 0 + %ret = select i1 %cmp, float %x, float %y + ret float %ret +} + +define double @double_sel(i32 %a, i32 %b, double %x, double %y) { +entry: +; CHECK-LABEL: double_sel: +; CHECK-NOT: cmp +; V8-LABEL: double_sel: +; V8-NOT: cmp +; V8: vseleq.f64 + %sub = sub i32 %a, %b + %cmp = icmp eq i32 %sub, 0 + %ret = select i1 %cmp, double %x, double %y + ret double %ret +} + +@t = common global i32 0 +define double @double_sub(i32 %a, i32 %b, double %x, double %y) { +entry: +; CHECK-LABEL: double_sub: +; CHECK: subs +; CHECK-NOT: cmp +; V8-LABEL: double_sub: +; V8: vsel + %cmp = icmp sgt i32 %a, %b + %sub = sub i32 %a, %b + store i32 %sub, i32* @t + %ret = select i1 %cmp, double %x, double %y + ret double %ret +} + +define double @double_sub_swap(i32 %a, i32 %b, double %x, double %y) { +entry: +; V7-LABEL: double_sub_swap: +; V7-NOT: cmp +; V7: subs +; V8-LABEL: double_sub_swap: +; V8-NOT: subs +; V8: cmp +; V8: vsel + %cmp = icmp sgt i32 %a, %b + %sub = sub i32 %b, %a + %ret = select i1 %cmp, double %x, double %y + store i32 %sub, i32* @t + ret double %ret +} |