diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp index f66eb9dbee2dc..b2d6aa18732bc 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp @@ -640,6 +640,149 @@ unsigned SparcInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { return get(Opcode).getSize(); } +bool SparcInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg, + Register &SrcReg2, int64_t &CmpMask, + int64_t &CmpValue) const { + switch (MI.getOpcode()) { + default: + break; + case SP::CMPri: + SrcReg = MI.getOperand(0).getReg(); + SrcReg2 = 0; + CmpMask = ~0; + CmpValue = MI.getOperand(1).getImm(); + return (CmpValue == 0); + case SP::CMPrr: + SrcReg = MI.getOperand(0).getReg(); + SrcReg2 = MI.getOperand(1).getReg(); + CmpMask = ~0; + CmpValue = 0; + return SrcReg2 == SP::G0; + } + + return false; +} + +bool SparcInstrInfo::optimizeCompareInstr( + MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, + int64_t CmpValue, const MachineRegisterInfo *MRI) const { + + // Get the unique definition of SrcReg. + MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg); + if (!MI) + return false; + + // Only optimize if defining and comparing instruction in same block. + if (MI->getParent() != CmpInstr.getParent()) + return false; + + unsigned newOpcode; + switch (MI->getOpcode()) { + case SP::ANDNrr: + newOpcode = SP::ANDNCCrr; + break; + case SP::ANDNri: + newOpcode = SP::ANDNCCri; + break; + case SP::ANDrr: + newOpcode = SP::ANDCCrr; + break; + case SP::ANDri: + newOpcode = SP::ANDCCri; + break; + case SP::ORrr: + newOpcode = SP::ORCCrr; + break; + case SP::ORri: + newOpcode = SP::ORCCri; + break; + case SP::ORNCCrr: + newOpcode = SP::ORNCCrr; + break; + case SP::ORNri: + newOpcode = SP::ORNCCri; + break; + case SP::XORrr: + newOpcode = SP::XORCCrr; + break; + case SP::XNORri: + newOpcode = SP::XNORCCri; + break; + case SP::XNORrr: + newOpcode = SP::XNORCCrr; + break; + case SP::ADDrr: + newOpcode = SP::ADDCCrr; + break; + case SP::ADDri: + newOpcode = SP::ADDCCri; + break; + case SP::SUBrr: + newOpcode = SP::SUBCCrr; + break; + case SP::SUBri: + newOpcode = SP::SUBCCri; + break; + default: + return false; + } + + bool isSafe = false; + bool isRegUsed = false; + MachineBasicBlock::iterator I = MI; + MachineBasicBlock::iterator C = CmpInstr; + MachineBasicBlock::iterator E = CmpInstr.getParent()->end(); + const TargetRegisterInfo *TRI = &getRegisterInfo(); + + // If ICC is used or modified between MI and CmpInstr we cannot optimize. + while (++I != C) { + if (I->modifiesRegister(SP::ICC, TRI) || I->readsRegister(SP::ICC, TRI)) + return false; + if (I->readsRegister(SrcReg, TRI)) + isRegUsed = true; + } + + while (++I != E) { + // Only allow conditionals on equality. + if (I->readsRegister(SP::ICC, TRI)) { + bool IsICCBranch = (I->getOpcode() == SP::BCOND) || + (I->getOpcode() == SP::BPICC) || + (I->getOpcode() == SP::BPXCC); + bool IsICCMove = (I->getOpcode() == SP::MOVICCrr) || + (I->getOpcode() == SP::MOVICCri) || + (I->getOpcode() == SP::MOVXCCrr) || + (I->getOpcode() == SP::MOVXCCri); + bool IsICCConditional = IsICCBranch || IsICCMove; + if (!IsICCConditional || + (I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_E && + I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_NE)) + return false; + } else if (I->modifiesRegister(SP::ICC, TRI)) { + isSafe = true; + break; + } + } + + if (!isSafe) { + MachineBasicBlock *MBB = CmpInstr.getParent(); + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); + SI != SE; ++SI) + if ((*SI)->isLiveIn(SP::ICC)) + return false; + } + + // If the result is not needed use the %g0 register. + if (!isRegUsed && CmpInstr.getOperand(0).isKill()) + MI->getOperand(0).setReg(SP::G0); + + MI->setDesc(get(newOpcode)); + MI->addRegisterDefined(SP::ICC); + CmpInstr.eraseFromParent(); + + return true; +} + bool SparcInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { switch (MI.getOpcode()) { case TargetOpcode::LOAD_STACK_GUARD: { diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.h b/llvm/lib/Target/Sparc/SparcInstrInfo.h index 01d0204734943..dd0f9c7efebd4 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.h +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.h @@ -108,6 +108,14 @@ class SparcInstrInfo : public SparcGenInstrInfo { /// instruction may be. This returns the maximum number of bytes. unsigned getInstSizeInBytes(const MachineInstr &MI) const override; + bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, + Register &SrcReg2, int64_t &CmpMask, + int64_t &CmpValue) const override; + + bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, + Register SrcReg2, int64_t CmpMask, int64_t CmpValue, + const MachineRegisterInfo *MRI) const override; + // Lower pseudo instructions after register allocation. bool expandPostRAPseudo(MachineInstr &MI) const override; }; diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index bc192c2d5f523..233dea63b80e6 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -914,8 +914,17 @@ let Defs = [ICC], hasPostISelHook = true in let Uses = [ICC] in defm SUBC : F3_12np <"subx", 0b001100>; -def : Pat<(SPcmpicc i32:$lhs, i32:$rhs), (SUBCCrr $lhs, $rhs)>; -def : Pat<(SPcmpicc i32:$lhs, (i32 simm13:$rhs)), (SUBCCri $lhs, imm:$rhs)>; +// cmp (from Section A.3) is a specialized alias for subcc +let Defs = [ICC], rd = 0, isCompare = 1 in { + def CMPrr : F3_1<2, 0b010100, + (outs), (ins IntRegs:$rs1, IntRegs:$rs2), + "cmp $rs1, $rs2", + [(SPcmpicc i32:$rs1, i32:$rs2)]>; + def CMPri : F3_2<2, 0b010100, + (outs), (ins IntRegs:$rs1, simm13Op:$simm13), + "cmp $rs1, $simm13", + [(SPcmpicc i32:$rs1, (i32 simm13:$simm13))]>; +} // Section B.18 - Multiply Instructions, p. 113 let Defs = [Y] in { diff --git a/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll b/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll index e05c47bfee766..9dffe0a3ce456 100644 --- a/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll +++ b/llvm/test/CodeGen/SPARC/2011-01-11-CC.ll @@ -25,15 +25,13 @@ define i32 @test_addx(i64 %a, i64 %b, i64 %c) nounwind { ; V8-NEXT: retl ; V8-NEXT: nop ; V8-NEXT: .LBB0_4: ! %entry -; V8-NEXT: mov %g0, %o2 ; V8-NEXT: cmp %o3, %o5 ; V8-NEXT: bgu .LBB0_2 -; V8-NEXT: nop +; V8-NEXT: mov %g0, %o2 ; V8-NEXT: .LBB0_5: ! %entry -; V8-NEXT: mov %g0, %o0 ; V8-NEXT: cmp %o1, %o4 ; V8-NEXT: be .LBB0_3 -; V8-NEXT: nop +; V8-NEXT: mov %g0, %o0 ; V8-NEXT: .LBB0_6: ! %entry ; V8-NEXT: retl ; V8-NEXT: mov %o2, %o0 diff --git a/llvm/test/CodeGen/SPARC/atomicrmw-uinc-udec-wrap.ll b/llvm/test/CodeGen/SPARC/atomicrmw-uinc-udec-wrap.ll index d1f1c46d9b8b1..ac21cb2bf88de 100644 --- a/llvm/test/CodeGen/SPARC/atomicrmw-uinc-udec-wrap.ll +++ b/llvm/test/CodeGen/SPARC/atomicrmw-uinc-udec-wrap.ll @@ -292,8 +292,7 @@ define i64 @atomicrmw_udec_wrap_i64(ptr %ptr, i64 %val) { ; CHECK-NEXT: mov %g0, %l0 ; CHECK-NEXT: addcc %g3, -1, %o3 ; CHECK-NEXT: addxcc %g2, -1, %o2 -; CHECK-NEXT: or %g3, %g2, %l1 -; CHECK-NEXT: cmp %l1, 0 +; CHECK-NEXT: orcc %g3, %g2, %g0 ; CHECK-NEXT: move %icc, 1, %i5 ; CHECK-NEXT: cmp %g2, %i1 ; CHECK-NEXT: movgu %icc, 1, %g4 @@ -301,8 +300,7 @@ define i64 @atomicrmw_udec_wrap_i64(ptr %ptr, i64 %val) { ; CHECK-NEXT: movgu %icc, 1, %l0 ; CHECK-NEXT: cmp %g2, %i1 ; CHECK-NEXT: move %icc, %l0, %g4 -; CHECK-NEXT: or %i5, %g4, %i5 -; CHECK-NEXT: cmp %i5, 0 +; CHECK-NEXT: orcc %i5, %g4, %i5 ; CHECK-NEXT: movne %icc, %i1, %o2 ; CHECK-NEXT: movne %icc, %i2, %o3 ; CHECK-NEXT: std %g2, [%fp+-8] diff --git a/llvm/test/CodeGen/SPARC/ctlz.ll b/llvm/test/CodeGen/SPARC/ctlz.ll index f7dc309452b35..528b3c9a0b8e9 100644 --- a/llvm/test/CodeGen/SPARC/ctlz.ll +++ b/llvm/test/CodeGen/SPARC/ctlz.ll @@ -156,8 +156,7 @@ define i64 @i64_nopoison(i64 %x) nounwind { ; SPARC-LABEL: i64_nopoison: ; SPARC: ! %bb.0: ; SPARC-NEXT: save %sp, -96, %sp -; SPARC-NEXT: or %i1, %i0, %i2 -; SPARC-NEXT: cmp %i2, 0 +; SPARC-NEXT: orcc %i1, %i0, %g0 ; SPARC-NEXT: be .LBB2_4 ; SPARC-NEXT: nop ; SPARC-NEXT: ! %bb.1: ! %cond.false @@ -182,8 +181,7 @@ define i64 @i64_nopoison(i64 %x) nounwind { ; SPARC-POPC-LABEL: i64_nopoison: ; SPARC-POPC: ! %bb.0: ; SPARC-POPC-NEXT: save %sp, -96, %sp -; SPARC-POPC-NEXT: or %i1, %i0, %i2 -; SPARC-POPC-NEXT: cmp %i2, 0 +; SPARC-POPC-NEXT: orcc %i1, %i0, %g0 ; SPARC-POPC-NEXT: be .LBB2_4 ; SPARC-POPC-NEXT: nop ; SPARC-POPC-NEXT: ! %bb.1: ! %cond.false diff --git a/llvm/test/CodeGen/SPARC/cttz.ll b/llvm/test/CodeGen/SPARC/cttz.ll index 138f67dbf684a..49592fe4dac00 100644 --- a/llvm/test/CodeGen/SPARC/cttz.ll +++ b/llvm/test/CodeGen/SPARC/cttz.ll @@ -184,8 +184,7 @@ define i32 @i32_poison(i32 %x) nounwind { define i64 @i64_nopoison(i64 %x) nounwind { ; SPARC-LABEL: i64_nopoison: ; SPARC: ! %bb.0: -; SPARC-NEXT: or %o1, %o0, %o2 -; SPARC-NEXT: cmp %o2, 0 +; SPARC-NEXT: orcc %o1, %o0, %g0 ; SPARC-NEXT: be .LBB2_3 ; SPARC-NEXT: nop ; SPARC-NEXT: ! %bb.1: ! %cond.false @@ -219,8 +218,7 @@ define i64 @i64_nopoison(i64 %x) nounwind { ; ; SPARC-POPC-LABEL: i64_nopoison: ; SPARC-POPC: ! %bb.0: -; SPARC-POPC-NEXT: or %o1, %o0, %o2 -; SPARC-POPC-NEXT: cmp %o2, 0 +; SPARC-POPC-NEXT: orcc %o1, %o0, %g0 ; SPARC-POPC-NEXT: be .LBB2_3 ; SPARC-POPC-NEXT: nop ; SPARC-POPC-NEXT: ! %bb.1: ! %cond.false diff --git a/llvm/test/CodeGen/SPARC/optcompare.ll b/llvm/test/CodeGen/SPARC/optcompare.ll new file mode 100644 index 0000000000000..d05596da16f7e --- /dev/null +++ b/llvm/test/CodeGen/SPARC/optcompare.ll @@ -0,0 +1,250 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=sparc | FileCheck %s +; RUN: llc < %s -mtriple=sparcv9 | FileCheck %s -check-prefix=CHECK64 + +define i32 @test(i32 %a) #0 { +; CHECK-LABEL: test: +; CHECK: ! %bb.0: ! %entry +; CHECK-NEXT: andcc %o0, 1, %g0 +; CHECK-NEXT: bne .LBB0_2 +; CHECK-NEXT: nop +; CHECK-NEXT: ! %bb.1: ! %if.end +; CHECK-NEXT: retl +; CHECK-NEXT: mov 2, %o0 +; CHECK-NEXT: .LBB0_2: ! %if.then +; CHECK-NEXT: retl +; CHECK-NEXT: mov 1, %o0 +; +; CHECK64-LABEL: test: +; CHECK64: ! %bb.0: ! %entry +; CHECK64-NEXT: andcc %o0, 1, %g0 +; CHECK64-NEXT: bne %icc, .LBB0_2 +; CHECK64-NEXT: nop +; CHECK64-NEXT: ! %bb.1: ! %if.end +; CHECK64-NEXT: retl +; CHECK64-NEXT: mov 2, %o0 +; CHECK64-NEXT: .LBB0_2: ! %if.then +; CHECK64-NEXT: retl +; CHECK64-NEXT: mov 1, %o0 +entry: + %and = and i32 %a, 1 + %tobool = icmp eq i32 %and, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: + ret i32 1 + +if.end: + ret i32 2 +} + +; Same as above, with select. +define i32 @test_select(i32 %a) #0 { +; CHECK-LABEL: test_select: +; CHECK: ! %bb.0: +; CHECK-NEXT: andcc %o0, 1, %g0 +; CHECK-NEXT: be .LBB1_2 +; CHECK-NEXT: nop +; CHECK-NEXT: ! %bb.1: +; CHECK-NEXT: retl +; CHECK-NEXT: mov 2, %o0 +; CHECK-NEXT: .LBB1_2: +; CHECK-NEXT: retl +; CHECK-NEXT: mov 1, %o0 +; +; CHECK64-LABEL: test_select: +; CHECK64: ! %bb.0: +; CHECK64-NEXT: andcc %o0, 1, %g0 +; CHECK64-NEXT: mov 2, %o0 +; CHECK64-NEXT: retl +; CHECK64-NEXT: move %icc, 1, %o0 + %and = and i32 %a, 1 + %tobool = icmp eq i32 %and, 0 + %ret = select i1 %tobool, i32 1, i32 2 + ret i32 %ret +} + + +; No instruction can be changed to set ICC +define i32 @no_candidate(i32 %a) #0 { +; CHECK-LABEL: no_candidate: +; CHECK: ! %bb.0: ! %entry +; CHECK-NEXT: cmp %o0, 0 +; CHECK-NEXT: be .LBB2_2 +; CHECK-NEXT: nop +; CHECK-NEXT: ! %bb.1: ! %if.then +; CHECK-NEXT: retl +; CHECK-NEXT: mov 1, %o0 +; CHECK-NEXT: .LBB2_2: ! %if.end +; CHECK-NEXT: retl +; CHECK-NEXT: mov 2, %o0 +; +; CHECK64-LABEL: no_candidate: +; CHECK64: ! %bb.0: ! %entry +; CHECK64-NEXT: cmp %o0, 0 +; CHECK64-NEXT: be %icc, .LBB2_2 +; CHECK64-NEXT: nop +; CHECK64-NEXT: ! %bb.1: ! %if.then +; CHECK64-NEXT: retl +; CHECK64-NEXT: mov 1, %o0 +; CHECK64-NEXT: .LBB2_2: ! %if.end +; CHECK64-NEXT: retl +; CHECK64-NEXT: mov 2, %o0 +entry: + %tobool = icmp eq i32 %a, 0 + br i1 %tobool, label %if.end, label %if.then + +if.then: + ret i32 1 + +if.end: + ret i32 2 +} + +; Defining instruction and compare not in same block +define i32 @not_same_block(i32 %a) #0 { +; CHECK-LABEL: not_same_block: +; CHECK: ! %bb.0: ! %entry +; CHECK-NEXT: and %o0, 1, %o0 +; CHECK-NEXT: .LBB3_1: ! %if.then +; CHECK-NEXT: ! =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: cmp %o0, 0 +; CHECK-NEXT: bne .LBB3_1 +; CHECK-NEXT: nop +; CHECK-NEXT: ! %bb.2: ! %if.end +; CHECK-NEXT: retl +; CHECK-NEXT: mov 2, %o0 +; +; CHECK64-LABEL: not_same_block: +; CHECK64: ! %bb.0: ! %entry +; CHECK64-NEXT: and %o0, 1, %o0 +; CHECK64-NEXT: .LBB3_1: ! %if.then +; CHECK64-NEXT: ! =>This Inner Loop Header: Depth=1 +; CHECK64-NEXT: cmp %o0, 0 +; CHECK64-NEXT: bne %icc, .LBB3_1 +; CHECK64-NEXT: nop +; CHECK64-NEXT: ! %bb.2: ! %if.end +; CHECK64-NEXT: retl +; CHECK64-NEXT: mov 2, %o0 +entry: + %and = and i32 %a, 1 + br label %if.then + +if.then: + %tobool = icmp eq i32 %and, 0 + br i1 %tobool, label %if.end, label %if.then + ret i32 1 + +if.end: + ret i32 2 +} + +; Compare instruction is not checking equality +define i32 @not_equality(i32 %a) #0 { +; CHECK-LABEL: not_equality: +; CHECK: ! %bb.0: ! %entry +; CHECK-NEXT: and %o0, 1, %o1 +; CHECK-NEXT: cmp %o1, 0 +; CHECK-NEXT: bl .LBB4_2 +; CHECK-NEXT: nop +; CHECK-NEXT: ! %bb.1: ! %entry +; CHECK-NEXT: mov %o1, %o0 +; CHECK-NEXT: .LBB4_2: ! %entry +; CHECK-NEXT: retl +; CHECK-NEXT: nop +; +; CHECK64-LABEL: not_equality: +; CHECK64: ! %bb.0: ! %entry +; CHECK64-NEXT: and %o0, 1, %o1 +; CHECK64-NEXT: cmp %o1, 0 +; CHECK64-NEXT: movl %icc, %o0, %o1 +; CHECK64-NEXT: retl +; CHECK64-NEXT: mov %o1, %o0 +entry: + %and = and i32 %a, 1 + %cmp = icmp slt i32 %and, 0 + %cond = select i1 %cmp, i32 %a, i32 %and + ret i32 %cond +} + +; Instruction that modifies ICC (call) between defining +; and compare instruction. +define i32 @call_between(i32 %a) #0 { +; CHECK-LABEL: call_between: +; CHECK: ! %bb.0: ! %entry +; CHECK-NEXT: save %sp, -96, %sp +; CHECK-NEXT: and %i0, 1, %i1 +; CHECK-NEXT: call not_equality +; CHECK-NEXT: mov %i1, %o0 +; CHECK-NEXT: cmp %i1, 0 +; CHECK-NEXT: be .LBB5_2 +; CHECK-NEXT: nop +; CHECK-NEXT: ! %bb.1: ! %entry +; CHECK-NEXT: mov %i1, %i0 +; CHECK-NEXT: .LBB5_2: ! %entry +; CHECK-NEXT: ret +; CHECK-NEXT: restore +; +; CHECK64-LABEL: call_between: +; CHECK64: ! %bb.0: ! %entry +; CHECK64-NEXT: save %sp, -176, %sp +; CHECK64-NEXT: and %i0, 1, %i1 +; CHECK64-NEXT: call not_equality +; CHECK64-NEXT: mov %i1, %o0 +; CHECK64-NEXT: cmp %i1, 0 +; CHECK64-NEXT: move %icc, %i0, %i1 +; CHECK64-NEXT: ret +; CHECK64-NEXT: restore %g0, %i1, %o0 +entry: + %and = and i32 %a, 1 + call i32 @not_equality(i32 %and) + %cmp = icmp eq i32 %and, 0 + %cond = select i1 %cmp, i32 %a, i32 %and + ret i32 %cond +} + +; ICC is used in successor block. +define i32 @icc_live_out(i32 %a) #0 { +; CHECK-LABEL: icc_live_out: +; CHECK: ! %bb.0: ! %entry +; CHECK-NEXT: and %o0, 1, %o1 +; CHECK-NEXT: cmp %o1, 0 +; CHECK-NEXT: bne .LBB6_4 +; CHECK-NEXT: nop +; CHECK-NEXT: ! %bb.1: ! %case1 +; CHECK-NEXT: be .LBB6_3 +; CHECK-NEXT: nop +; CHECK-NEXT: ! %bb.2: ! %case1 +; CHECK-NEXT: mov %o1, %o0 +; CHECK-NEXT: .LBB6_3: ! %case1 +; CHECK-NEXT: retl +; CHECK-NEXT: nop +; CHECK-NEXT: .LBB6_4: ! %case2 +; CHECK-NEXT: retl +; CHECK-NEXT: mov 2, %o0 +; +; CHECK64-LABEL: icc_live_out: +; CHECK64: ! %bb.0: ! %entry +; CHECK64-NEXT: mov %o0, %o1 +; CHECK64-NEXT: and %o0, 1, %o0 +; CHECK64-NEXT: cmp %o0, 0 +; CHECK64-NEXT: bne %icc, .LBB6_2 +; CHECK64-NEXT: nop +; CHECK64-NEXT: ! %bb.1: ! %case1 +; CHECK64-NEXT: retl +; CHECK64-NEXT: move %icc, %o1, %o0 +; CHECK64-NEXT: .LBB6_2: ! %case2 +; CHECK64-NEXT: retl +; CHECK64-NEXT: mov 2, %o0 +entry: + %and = and i32 %a, 1 + %cmp = icmp eq i32 %and, 0 + br i1 %cmp, label %case1, label %case2 +case1: + %cond = select i1 %cmp, i32 %a, i32 %and + ret i32 %cond +case2: + ret i32 2 +} + +attributes #0 = { nounwind } diff --git a/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll b/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll index 1e5ab7922de08..e0c7032b1d9d4 100644 --- a/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll +++ b/llvm/test/CodeGen/SPARC/smulo-128-legalisation-lowering.ll @@ -130,8 +130,7 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) nounwind { ; SPARC-NEXT: xor %i0, %g4, %i0 ; SPARC-NEXT: xor %i5, %g4, %i4 ; SPARC-NEXT: or %i4, %i0, %i0 -; SPARC-NEXT: or %i0, %i1, %i0 -; SPARC-NEXT: cmp %i0, 0 +; SPARC-NEXT: orcc %i0, %i1, %g0 ; SPARC-NEXT: bne .LBB0_2 ; SPARC-NEXT: nop ; SPARC-NEXT: ! %bb.1: ! %start diff --git a/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll b/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll index 6d197c88bfecd..40e90d6bdd6af 100644 --- a/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll +++ b/llvm/test/CodeGen/SPARC/umulo-128-legalisation-lowering.ll @@ -116,32 +116,30 @@ define { i128, i8 } @muloti_test(i128 %l, i128 %r) nounwind { ; SPARC-NEXT: .LBB0_22: ! %start ; SPARC-NEXT: and %o4, %o3, %o2 ; SPARC-NEXT: cmp %l1, 0 -; SPARC-NEXT: and %o0, %l4, %l4 +; SPARC-NEXT: and %o0, %l4, %o0 ; SPARC-NEXT: bne .LBB0_24 ; SPARC-NEXT: mov %l3, %l1 ; SPARC-NEXT: ! %bb.23: ! %start ; SPARC-NEXT: mov %g0, %l1 ; SPARC-NEXT: .LBB0_24: ! %start -; SPARC-NEXT: or %o2, %o1, %o0 +; SPARC-NEXT: or %o2, %o1, %l4 ; SPARC-NEXT: cmp %l2, %l0 -; SPARC-NEXT: or %l4, %l6, %l4 +; SPARC-NEXT: or %o0, %l6, %l6 ; SPARC-NEXT: bcs .LBB0_26 ; SPARC-NEXT: mov %l3, %l0 ; SPARC-NEXT: ! %bb.25: ! %start ; SPARC-NEXT: mov %g0, %l0 ; SPARC-NEXT: .LBB0_26: ! %start -; SPARC-NEXT: or %o0, %l7, %l2 -; SPARC-NEXT: or %i5, %i4, %i4 -; SPARC-NEXT: cmp %i4, 0 -; SPARC-NEXT: or %l4, %l1, %l1 +; SPARC-NEXT: or %l4, %l7, %l2 +; SPARC-NEXT: orcc %i5, %i4, %g0 +; SPARC-NEXT: or %l6, %l1, %l1 ; SPARC-NEXT: bne .LBB0_28 ; SPARC-NEXT: mov %l3, %i4 ; SPARC-NEXT: ! %bb.27: ! %start ; SPARC-NEXT: mov %g0, %i4 ; SPARC-NEXT: .LBB0_28: ! %start ; SPARC-NEXT: or %l2, %g4, %i5 -; SPARC-NEXT: or %i1, %i0, %i0 -; SPARC-NEXT: cmp %i0, 0 +; SPARC-NEXT: orcc %i1, %i0, %g0 ; SPARC-NEXT: bne .LBB0_30 ; SPARC-NEXT: or %l1, %l0, %i0 ; SPARC-NEXT: ! %bb.29: ! %start