Index: lib/Target/ARM/Thumb2SizeReduction.cpp =================================================================== --- lib/Target/ARM/Thumb2SizeReduction.cpp +++ lib/Target/ARM/Thumb2SizeReduction.cpp @@ -122,6 +122,7 @@ { ARM::t2SUBSrr,ARM::tSUBrr, 0, 0, 0, 1, 0, 2,0, 0,0,0 }, { ARM::t2SXTB, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0,1,0 }, { ARM::t2SXTH, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0,1,0 }, + { ARM::t2TEQrr, ARM::tEOR, 0, 0, 0, 1, 0, 2,0, 0,1,0 }, { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0,0,0 }, { ARM::t2UXTB, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0,1,0 }, { ARM::t2UXTH, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0,1,0 }, @@ -717,6 +718,16 @@ return true; return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop); } + case ARM::t2TEQrr: { + unsigned PredReg = 0; + // Can only convert to eors if we're not in an IT block. + if (getInstrPredicate(*MI, PredReg) != ARMCC::AL) + break; + // TODO if Operand 0 is not killed but Operand 1 is, then we could write + // to Op1 instead. + if (MI->getOperand(0).isKill()) + return ReduceToNarrow(MBB, MI, Entry, LiveCPSR, IsSelfLoop); + } } return false; } @@ -903,9 +914,23 @@ // Add the 16-bit instruction. DebugLoc dl = MI->getDebugLoc(); MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, NewMCID); - MIB.add(MI->getOperand(0)); - if (NewMCID.hasOptionalDef()) - MIB.add(HasCC ? t1CondCodeOp(CCDead) : condCodeOp()); + + // TEQ is special in that it doesn't define a register but we're converting + // it into an EOR which does. So add the first operand as a def and then + // again as a use. + if (MCID.getOpcode() == ARM::t2TEQrr) { + MachineOperand MO = MI->getOperand(0); + MO.setIsKill(false); + MO.setIsDef(true); + MIB.add(MO); + if (NewMCID.hasOptionalDef()) + MIB.add(HasCC ? t1CondCodeOp(CCDead) : condCodeOp()); + MIB.add(MI->getOperand(0)); + } else { + MIB.add(MI->getOperand(0)); + if (NewMCID.hasOptionalDef()) + MIB.add(HasCC ? t1CondCodeOp(CCDead) : condCodeOp()); + } // Transfer the rest of operands. unsigned NumOps = MCID.getNumOperands(); Index: test/CodeGen/Thumb2/teq-size-reduce.ll =================================================================== --- /dev/null +++ test/CodeGen/Thumb2/teq-size-reduce.ll @@ -0,0 +1,101 @@ +; RUN: llc -mtriple=thumbv7m %s -o - | FileCheck %s +; RUN: llc -mtriple=thumbv8m.main %s -o - | FileCheck %s + +%list_head = type { %list_head*, %list_data* } +%list_data = type { i16, i16 } + +; CHECK-LABEL: reg_reg_it_block +; CHECK: ldrh [[A:r[0-9]+]], +; CHECK-NOT: teq +; CHECK: eors [[A]], r1 +; CHECK: ittt +; CHECK: teq +define %list_head* @reg_reg_it_block(%list_head* %a, i16 zeroext %b) { +entry: + br label %while.begin + +while.begin: + %list.addr.i = phi %list_head* [ %ld.5, %while.body.end ], [ %a, %entry ] + %info.i = getelementptr inbounds %list_head, %list_head* %list.addr.i, i32 0, i32 1 + %ld.0 = load %list_data*, %list_data** %info.i, align 4 + %data16.i = getelementptr inbounds %list_data, %list_data* %ld.0, i32 0, i32 0 + %ld.1 = load i16, i16* %data16.i, align 2 + %xor.1 = xor i16 %ld.1, %b + %cmp.i = icmp eq i16 %xor.1, 0 + br i1 %cmp.i, label %exit, label %while.body.a + +while.body.a: + %next.i = getelementptr inbounds %list_head, %list_head* %list.addr.i, i32 0, i32 0 + %ld.2 = load %list_head*, %list_head** %next.i, align 4 + %cmp.i.1 = icmp eq %list_head* %ld.2, null + br i1 %cmp.i.1, label %exit, label %it.block + +it.block: + %info.i.1 = getelementptr inbounds %list_head, %list_head* %ld.2, i32 0, i32 1 + %ld.3 = load %list_data*, %list_data** %info.i.1, align 4 + %data16.i.1 = getelementptr inbounds %list_data, %list_data* %ld.3, i32 0, i32 0 + %ld.4 = load i16, i16* %data16.i.1, align 2 + %xor.2 = xor i16 %ld.4, %b + %cmp.i.2 = icmp eq i16 %xor.2, 0 + br i1 %cmp.i.2, label %exit, label %while.body.end + +while.body.end: + %next.i.1 = getelementptr inbounds %list_head, %list_head* %ld.2, i32 0, i32 0 + %ld.5 = load %list_head*, %list_head** %next.i.1, align 4 + %cmp.i.3 = icmp eq %list_head* %ld.5, null + br i1 %cmp.i.3, label %exit, label %while.begin + +exit: + %res = phi %list_head* [ %list.addr.i, %while.begin ], + [ %ld.2, %while.body.a ], + [ %ld.2, %it.block ], + [ %ld.5, %while.body.end ] + ret %list_head* %res +} + +; CHECK-LABEL: op_not_killed +; CHECK: teq +; CHECK: teq +define i16 @op_not_killed(%list_head* %a, i16 zeroext %b) { +entry: + br label %while.begin + +while.begin: + %list.addr.i = phi %list_head* [ %ld.5, %while.body.end ], [ %a, %entry ] + %info.i = getelementptr inbounds %list_head, %list_head* %list.addr.i, i32 0, i32 1 + %ld.0 = load %list_data*, %list_data** %info.i, align 4 + %data16.i = getelementptr inbounds %list_data, %list_data* %ld.0, i32 0, i32 0 + %ld.1 = load i16, i16* %data16.i, align 2 + %xor.1 = xor i16 %ld.1, %b + %cmp.i = icmp eq i16 %xor.1, 0 + br i1 %cmp.i, label %exit, label %while.body.a + +while.body.a: + %next.i = getelementptr inbounds %list_head, %list_head* %list.addr.i, i32 0, i32 0 + %ld.2 = load %list_head*, %list_head** %next.i, align 4 + %cmp.i.1 = icmp eq %list_head* %ld.2, null + br i1 %cmp.i.1, label %exit, label %it.block + +it.block: + %info.i.1 = getelementptr inbounds %list_head, %list_head* %ld.2, i32 0, i32 1 + %ld.3 = load %list_data*, %list_data** %info.i.1, align 4 + %data16.i.1 = getelementptr inbounds %list_data, %list_data* %ld.3, i32 0, i32 0 + %ld.4 = load i16, i16* %data16.i.1, align 2 + %xor.2 = xor i16 %ld.4, %b + %cmp.i.2 = icmp eq i16 %xor.2, 0 + br i1 %cmp.i.2, label %exit, label %while.body.end + +while.body.end: + %next.i.1 = getelementptr inbounds %list_head, %list_head* %ld.2, i32 0, i32 0 + %ld.5 = load %list_head*, %list_head** %next.i.1, align 4 + %cmp.i.3 = icmp eq %list_head* %ld.5, null + br i1 %cmp.i.3, label %exit, label %while.begin + +exit: + %res = phi i16 [ %ld.1, %while.begin ], + [ %ld.1, %while.body.a ], + [ %ld.4, %it.block ], + [ %ld.4, %while.body.end ] + ret i16 %res +} + Index: test/CodeGen/Thumb2/thumb2-teq2.ll =================================================================== --- test/CodeGen/Thumb2/thumb2-teq2.ll +++ test/CodeGen/Thumb2/thumb2-teq2.ll @@ -14,7 +14,7 @@ define i32 @f4(i32 %a, i32 %b) { ; CHECK: f4 -; CHECK: teq.w {{.*}}, r1 +; CHECK: eors {{.*}}, r1 %tmp = xor i32 %a, %b %tmp1 = icmp eq i32 0, %tmp %ret = select i1 %tmp1, i32 42, i32 24