mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-01 17:32:36 +00:00
Add support for comparing integer non-legal types.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@143559 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
81550dc0a8
commit
e07cd5e40a
@ -174,7 +174,8 @@ class ARMFastISel : public FastISel {
|
||||
private:
|
||||
bool isTypeLegal(Type *Ty, MVT &VT);
|
||||
bool isLoadTypeLegal(Type *Ty, MVT &VT);
|
||||
bool ARMEmitCmp(const Value *Src1Value, const Value *Src2Value);
|
||||
bool ARMEmitCmp(const Value *Src1Value, const Value *Src2Value,
|
||||
bool isZExt);
|
||||
bool ARMEmitLoad(EVT VT, unsigned &ResultReg, Address &Addr);
|
||||
bool ARMEmitStore(EVT VT, unsigned SrcReg, Address &Addr);
|
||||
bool ARMComputeAddress(const Value *Obj, Address &Addr);
|
||||
@ -1119,7 +1120,7 @@ bool ARMFastISel::SelectBranch(const Instruction *I) {
|
||||
if (ARMPred == ARMCC::AL) return false;
|
||||
|
||||
// Emit the compare.
|
||||
if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1)))
|
||||
if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
|
||||
return false;
|
||||
|
||||
unsigned BrOpc = isThumb ? ARM::t2Bcc : ARM::Bcc;
|
||||
@ -1189,19 +1190,19 @@ bool ARMFastISel::SelectBranch(const Instruction *I) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARMFastISel::ARMEmitCmp(const Value *Src1Value, const Value *Src2Value) {
|
||||
MVT VT;
|
||||
bool ARMFastISel::ARMEmitCmp(const Value *Src1Value, const Value *Src2Value,
|
||||
bool isZExt) {
|
||||
Type *Ty = Src1Value->getType();
|
||||
if (!isTypeLegal(Ty, VT))
|
||||
return false;
|
||||
EVT SrcVT = TLI.getValueType(Ty, true);
|
||||
if (!SrcVT.isSimple()) return false;
|
||||
|
||||
bool isFloat = (Ty->isFloatTy() || Ty->isDoubleTy());
|
||||
if (isFloat && !Subtarget->hasVFP2())
|
||||
return false;
|
||||
|
||||
unsigned CmpOpc;
|
||||
switch (VT.SimpleTy) {
|
||||
// TODO: Add support for non-legal types (i.e., i1, i8, i16).
|
||||
bool needsExt = false;
|
||||
switch (SrcVT.getSimpleVT().SimpleTy) {
|
||||
default: return false;
|
||||
// TODO: Verify compares.
|
||||
case MVT::f32:
|
||||
@ -1210,19 +1211,36 @@ bool ARMFastISel::ARMEmitCmp(const Value *Src1Value, const Value *Src2Value) {
|
||||
case MVT::f64:
|
||||
CmpOpc = ARM::VCMPED;
|
||||
break;
|
||||
case MVT::i1:
|
||||
case MVT::i8:
|
||||
case MVT::i16:
|
||||
needsExt = true;
|
||||
// Intentional fall-through.
|
||||
case MVT::i32:
|
||||
CmpOpc = isThumb ? ARM::t2CMPrr : ARM::CMPrr;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned Src1 = getRegForValue(Src1Value);
|
||||
if (Src1 == 0) return false;
|
||||
unsigned SrcReg1 = getRegForValue(Src1Value);
|
||||
if (SrcReg1 == 0) return false;
|
||||
|
||||
unsigned Src2 = getRegForValue(Src2Value);
|
||||
if (Src2 == 0) return false;
|
||||
unsigned SrcReg2 = getRegForValue(Src2Value);
|
||||
if (SrcReg2 == 0) return false;
|
||||
|
||||
// We have i1, i8, or i16, we need to either zero extend or sign extend.
|
||||
if (needsExt) {
|
||||
unsigned ResultReg;
|
||||
EVT DestVT = MVT::i32;
|
||||
ResultReg = ARMEmitIntExt(SrcVT, SrcReg1, DestVT, isZExt);
|
||||
if (ResultReg == 0) return false;
|
||||
SrcReg1 = ResultReg;
|
||||
ResultReg = ARMEmitIntExt(SrcVT, SrcReg2, DestVT, isZExt);
|
||||
if (ResultReg == 0) return false;
|
||||
SrcReg2 = ResultReg;
|
||||
}
|
||||
|
||||
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CmpOpc))
|
||||
.addReg(Src1).addReg(Src2));
|
||||
.addReg(SrcReg1).addReg(SrcReg2));
|
||||
|
||||
// For floating point we need to move the result to a comparison register
|
||||
// that we can then use for branches.
|
||||
@ -1243,7 +1261,7 @@ bool ARMFastISel::SelectCmp(const Instruction *I) {
|
||||
if (ARMPred == ARMCC::AL) return false;
|
||||
|
||||
// Emit the compare.
|
||||
if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1)))
|
||||
if (!ARMEmitCmp(CI->getOperand(0), CI->getOperand(1), CI->isUnsigned()))
|
||||
return false;
|
||||
|
||||
// Now set a register based on the comparison. Explicitly set the predicates
|
||||
@ -1962,7 +1980,6 @@ bool ARMFastISel::SelectCall(const Instruction *I) {
|
||||
static_cast<MachineInstr *>(MIB)->setPhysRegsDeadExcept(UsedRegs, TRI);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool ARMFastISel::SelectTrunc(const Instruction *I) {
|
||||
|
47
test/CodeGen/ARM/fast-isel-icmp.ll
Normal file
47
test/CodeGen/ARM/fast-isel-icmp.ll
Normal file
@ -0,0 +1,47 @@
|
||||
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-apple-darwin | FileCheck %s --check-prefix=ARM
|
||||
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-darwin | FileCheck %s --check-prefix=THUMB
|
||||
|
||||
define i32 @icmp_i16_unsigned(i16 %a, i16 %b) nounwind {
|
||||
entry:
|
||||
; ARM: icmp_i16_unsigned
|
||||
; ARM: uxth r0, r0
|
||||
; ARM: uxth r1, r1
|
||||
; ARM: cmp r0, r1
|
||||
; THUMB: icmp_i16_unsigned
|
||||
; THUMB: uxth r0, r0
|
||||
; THUMB: uxth r1, r1
|
||||
; THUMB: cmp r0, r1
|
||||
%cmp = icmp ult i16 %a, %b
|
||||
%conv2 = zext i1 %cmp to i32
|
||||
ret i32 %conv2
|
||||
}
|
||||
|
||||
define i32 @icmp_i8_signed(i8 %a, i8 %b) nounwind {
|
||||
entry:
|
||||
; ARM: icmp_i8_signed
|
||||
; ARM: sxtb r0, r0
|
||||
; ARM: sxtb r1, r1
|
||||
; ARM: cmp r0, r1
|
||||
; THUMB: icmp_i8_signed
|
||||
; THUMB: sxtb r0, r0
|
||||
; THUMB: sxtb r1, r1
|
||||
; THUMB: cmp r0, r1
|
||||
%cmp = icmp sgt i8 %a, %b
|
||||
%conv2 = zext i1 %cmp to i32
|
||||
ret i32 %conv2
|
||||
}
|
||||
|
||||
define i32 @icmp_i1_unsigned(i1 %a, i1 %b) nounwind {
|
||||
entry:
|
||||
; ARM: icmp_i1_unsigned
|
||||
; ARM: and r0, r0, #1
|
||||
; ARM: and r1, r1, #1
|
||||
; ARM: cmp r0, r1
|
||||
; THUMB: icmp_i1_unsigned
|
||||
; THUMB: and r0, r0, #1
|
||||
; THUMB: and r1, r1, #1
|
||||
; THUMB: cmp r0, r1
|
||||
%cmp = icmp ult i1 %a, %b
|
||||
%conv2 = zext i1 %cmp to i32
|
||||
ret i32 %conv2
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user