Commit 9309756d by Sagar Thakur Committed by Jim Stichnoth

[Subzero][MIPS] Implement conditional branches with 64-bit integer compares

R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2384433002 . Patch from Sagar Thakur <sagar.thakur@imgtec.com>.
parent 269eed47
......@@ -2239,63 +2239,207 @@ void TargetMIPS32::lowerBr(const InstBr *Instr) {
Operand *Src1 = CompareInst->getSrc(1);
const Type Src0Ty = Src0->getType();
assert(Src0Ty == Src1->getType());
Variable *Src0R = nullptr;
Variable *Src1R = nullptr;
Variable *Src0HiR = nullptr;
Variable *Src1HiR = nullptr;
if (Src0Ty == IceType_i64) {
UnimplementedLoweringError(this, Instr);
return;
Src0R = legalizeToReg(loOperand(Src0));
Src1R = legalizeToReg(loOperand(Src1));
Src0HiR = legalizeToReg(hiOperand(Src0));
Src1HiR = legalizeToReg(hiOperand(Src1));
} else {
Src0R = legalizeToReg(Src0);
Src1R = legalizeToReg(Src1);
}
auto *Src0R = legalizeToReg(Src0);
auto *Src1R = legalizeToReg(Src1);
auto *DestT = makeReg(Src0Ty);
auto *DestT = makeReg(IceType_i32);
switch (CompareInst->getCondition()) {
default:
break;
llvm_unreachable("unexpected condition");
return;
case InstIcmp::Eq: {
_br(TargetTrue, TargetFalse, Src0R, Src1R, CondMIPS32::Cond::NE);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_xor(T2, Src0R, Src1R);
_or(T3, T1, T2);
_mov(DestT, T3);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_br(TargetTrue, TargetFalse, Src0R, Src1R, CondMIPS32::Cond::NE);
}
return;
}
case InstIcmp::Ne: {
_br(TargetTrue, TargetFalse, Src0R, Src1R, CondMIPS32::Cond::EQ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_xor(T2, Src0R, Src1R);
_or(T3, T1, T2);
_mov(DestT, T3);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
} else {
_br(TargetTrue, TargetFalse, Src0R, Src1R, CondMIPS32::Cond::EQ);
}
return;
}
case InstIcmp::Ugt: {
_sltu(DestT, Src1R, Src0R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
auto *T4 = I32Reg();
auto *T5 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_sltu(T2, Src1HiR, Src0HiR);
_xori(T3, T2, 1);
_sltu(T4, Src1R, Src0R);
_xori(T5, T4, 1);
_movz(T3, T5, T1);
_mov(DestT, T3);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_sltu(DestT, Src1R, Src0R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
}
return;
}
case InstIcmp::Uge: {
_sltu(DestT, Src0R, Src1R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_sltu(T2, Src0HiR, Src1HiR);
_sltu(T3, Src0R, Src1R);
_movz(T2, T3, T1);
_mov(DestT, T2);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_sltu(DestT, Src0R, Src1R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
}
return;
}
case InstIcmp::Ult: {
_sltu(DestT, Src0R, Src1R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
auto *T4 = I32Reg();
auto *T5 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_sltu(T2, Src0HiR, Src1HiR);
_xori(T3, T2, 1);
_sltu(T4, Src0R, Src1R);
_xori(T5, T4, 1);
_movz(T3, T5, T1);
_mov(DestT, T3);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_sltu(DestT, Src0R, Src1R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
}
return;
}
case InstIcmp::Ule: {
_sltu(DestT, Src1R, Src0R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_sltu(T2, Src1HiR, Src0HiR);
_sltu(T3, Src1R, Src0R);
_movz(T2, T3, T1);
_mov(DestT, T2);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_sltu(DestT, Src1R, Src0R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
}
return;
}
case InstIcmp::Sgt: {
_slt(DestT, Src1R, Src0R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
auto *T4 = I32Reg();
auto *T5 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_slt(T2, Src1HiR, Src0HiR);
_xori(T3, T2, 1);
_sltu(T4, Src1R, Src0R);
_xori(T5, T4, 1);
_movz(T3, T5, T1);
_mov(DestT, T3);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_slt(DestT, Src1R, Src0R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
}
return;
}
case InstIcmp::Sge: {
_slt(DestT, Src0R, Src1R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_slt(T2, Src0HiR, Src1HiR);
_sltu(T3, Src0R, Src1R);
_movz(T2, T3, T1);
_mov(DestT, T2);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_slt(DestT, Src0R, Src1R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
}
return;
}
case InstIcmp::Slt: {
_slt(DestT, Src0R, Src1R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
auto *T4 = I32Reg();
auto *T5 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_slt(T2, Src0HiR, Src1HiR);
_xori(T3, T2, 1);
_sltu(T4, Src0R, Src1R);
_xori(T5, T4, 1);
_movz(T3, T5, T1);
_mov(DestT, T3);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_slt(DestT, Src0R, Src1R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::EQZ);
}
return;
}
case InstIcmp::Sle: {
_slt(DestT, Src1R, Src0R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
break;
if (Src0Ty == IceType_i64) {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
auto *T3 = I32Reg();
_xor(T1, Src0HiR, Src1HiR);
_slt(T2, Src1HiR, Src0HiR);
_sltu(T3, Src1R, Src0R);
_movz(T2, T3, T1);
_mov(DestT, T2);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
} else {
_slt(DestT, Src1R, Src0R);
_br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ);
}
return;
}
}
}
......@@ -2913,7 +3057,7 @@ void TargetMIPS32::lower64Icmp(const InstIcmp *Instr) {
switch (Condition) {
default:
llvm_unreachable("unexpected condition");
break;
return;
case InstIcmp::Eq: {
auto *T1 = I32Reg();
auto *T2 = I32Reg();
......
......@@ -1361,6 +1361,30 @@ if.end3: ; preds = %if.then2, %if.end
; ARM32: bl {{.*}} <func>
; ARM32: bx
; MIPS32-LABEL: icmpEq64
; MIPS32: xor [[T1:.*]],{{.*}},{{.*}}
; MIPS32: xor [[T2:.*]],{{.*}},{{.*}}
; MIPS32: or [[T3:.*]],[[T1]],[[T2]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sltiu [[T4:.*]],[[T3]],1
; MIPS32-OM1: sw [[T4]],[[MEM:.*]]
; MIPS32-OM1: lb [[T5:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T5]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: xor [[T1:.*]],{{.*}},{{.*}}
; MIPS32: xor [[T2:.*]],{{.*}},{{.*}}
; MIPS32: or [[T3:.*]],[[T1]],[[T2]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sltiu [[T4:.*]],[[T3]],1
; MIPS32-OM1: sw [[T4]],[[MEM:.*]]
; MIPS32-OM1: lb [[T5:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T5]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
declare void @func()
define internal void @icmpNe64(i64 %a, i64 %b, i64 %c, i64 %d) {
......@@ -1431,6 +1455,30 @@ if.end3: ; preds = %if.end, %if.then2
; ARM32-O2: beq
; ARM32: bl
; MIPS32-LABEL: icmpNe64
; MIPS32: xor [[T1:.*]],{{.*}},{{.*}}
; MIPS32: xor [[T2:.*]],{{.*}},{{.*}}
; MIPS32: or [[T3:.*]],[[T1]],[[T2]]
; MIPS32-O2: beqz [[T3]],{{.*}}
; MIPS32-OM1: sltu [[T4:.*]],zero,[[T3]]
; MIPS32-OM1: sw [[T4]],[[MEM:.*]]
; MIPS32-OM1: lb [[T5:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T5]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: xor [[T1:.*]],{{.*}},{{.*}}
; MIPS32: xor [[T2:.*]],{{.*}},{{.*}}
; MIPS32: or [[T3:.*]],[[T1]],[[T2]]
; MIPS32-O2: beqz [[T3]],{{.*}}
; MIPS32-OM1: sltu [[T4:.*]],zero,[[T3]]
; MIPS32-OM1: sw [[T4]],[[MEM:.*]]
; MIPS32-OM1: lb [[T5:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T5]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
define internal void @icmpGt64(i64 %a, i64 %b, i64 %c, i64 %d) {
entry:
%cmp = icmp ugt i64 %a, %b
......@@ -1485,6 +1533,38 @@ if.end3: ; preds = %if.then2, %if.end
; ARM32-O2: bge
; ARM32: bl
; MIPS32-LABEL: icmpGt64
; MIPS32: xor [[T1:.*]],[[A_HI:.*]],[[B_HI:.*]]
; MIPS32-O2: sltu [[T2:.*]],[[B_HI]],[[A_HI]]
; MIPS32-O2: xori [[T3:.*]],[[T2]],0x1
; MIPS32-O2: sltu [[T4:.*]],{{.*}},{{.*}}
; MIPS32-O2: xori [[T5:.*]],[[T4]],0x1
; MIPS32-OM1: sltu [[T3:.*]],[[B_HI]],[[A_HI]]
; MIPS32-OM1: sltu [[T5:.*]],{{.*}},{{.*}}
; MIPS32: movz [[T3]],[[T5]],[[T1]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sw [[T3]],[[MEM:.*]]
; MIPS32-OM1: lb [[T6:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T6]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: xor [[T1:.*]],[[A_HI:.*]],[[B_HI:.*]]
; MIPS32-O2: slt [[T2:.*]],[[B_HI]],[[A_HI]]
; MIPS32-O2: xori [[T3:.*]],[[T2]],0x1
; MIPS32-O2: sltu [[T4:.*]],{{.*}},{{.*}}
; MIPS32-O2: xori [[T5:.*]],[[T4]],0x1
; MIPS32-OM1: slt [[T3:.*]],[[B_HI]],[[A_HI]]
; MIPS32-OM1: sltu [[T5:.*]],{{.*}},{{.*}}
; MIPS32: movz [[T3]],[[T5]],[[T1]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sw [[T3]],[[MEM:.*]]
; MIPS32-OM1: lb [[T6:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T6]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
define internal void @icmpGe64(i64 %a, i64 %b, i64 %c, i64 %d) {
entry:
%cmp = icmp uge i64 %a, %b
......@@ -1539,6 +1619,38 @@ if.end3: ; preds = %if.end, %if.then2
; ARM32-O2: blt
; ARM32: bl
; MIPS32-LABEL: icmpGe64
; MIPS32: xor [[T1:.*]],[[A_HI:.*]],[[B_HI:.*]]
; MIPS32-OM1: sltu [[T2:.*]],[[A_HI]],[[B_HI]]
; MIPS32-OM1: xori [[T3:.*]],[[T2]],0x1
; MIPS32-OM1: sltu [[T4:.*]],{{.*}},{{.*}}
; MIPS32-OM1: xori [[T5:.*]],[[T4]],0x1
; MIPS32-O2: sltu [[T3:.*]],[[A_HI]],[[B_HI]]
; MIPS32-O2: sltu [[T5:.*]],{{.*}},{{.*}}
; MIPS32: movz [[T3]],[[T5]],[[T1]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sw [[T3]],[[MEM:.*]]
; MIPS32-OM1: lb [[T6:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T6]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: xor [[T1:.*]],[[A_HI:.*]],[[B_HI:.*]]
; MIPS32-OM1: slt [[T2:.*]],[[A_HI]],[[B_HI]]
; MIPS32-OM1: xori [[T3:.*]],[[T2]],0x1
; MIPS32-OM1: sltu [[T4:.*]],{{.*}},{{.*}}
; MIPS32-OM1: xori [[T5:.*]],[[T4]],0x1
; MIPS32-O2: slt [[T3:.*]],[[A_HI]],[[B_HI]]
; MIPS32-O2: sltu [[T5:.*]],{{.*}},{{.*}}
; MIPS32: movz [[T3]],[[T5]],[[T1]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sw [[T3]],[[MEM:.*]]
; MIPS32-OM1: lb [[T6:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T6]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
define internal void @icmpLt64(i64 %a, i64 %b, i64 %c, i64 %d) {
entry:
%cmp = icmp ult i64 %a, %b
......@@ -1593,6 +1705,38 @@ if.end3: ; preds = %if.then2, %if.end
; ARM32-O2: bge
; ARM32: bl
; MIPS32-LABEL: icmpLt64
; MIPS32: xor [[T1:.*]],[[A_HI:.*]],[[B_HI:.*]]
; MIPS32-O2: sltu [[T2:.*]],[[A_HI]],[[B_HI]]
; MIPS32-O2: xori [[T3:.*]],[[T2]],0x1
; MIPS32-O2: sltu [[T4:.*]],{{.*}},{{.*}}
; MIPS32-O2: xori [[T5:.*]],[[T4]],0x1
; MIPS32-OM1: sltu [[T3:.*]],[[A_HI]],[[B_HI]]
; MIPS32-OM1: sltu [[T5:.*]],{{.*}},{{.*}}
; MIPS32: movz [[T3]],[[T5]],[[T1]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sw [[T3]],[[MEM:.*]]
; MIPS32-OM1: lb [[T6:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T6]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: xor [[T1:.*]],[[A_HI:.*]],[[B_HI:.*]]
; MIPS32-O2: slt [[T2:.*]],[[A_HI]],[[B_HI]]
; MIPS32-O2: xori [[T3:.*]],[[T2]],0x1
; MIPS32-O2: sltu [[T4:.*]],{{.*}},{{.*}}
; MIPS32-O2: xori [[T5:.*]],[[T4]],0x1
; MIPS32-OM1: slt [[T3:.*]],[[A_HI]],[[B_HI]]
; MIPS32-OM1: sltu [[T5:.*]],{{.*}},{{.*}}
; MIPS32: movz [[T3]],[[T5]],[[T1]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sw [[T3]],[[MEM:.*]]
; MIPS32-OM1: lb [[T6:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T6]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
define internal void @icmpLe64(i64 %a, i64 %b, i64 %c, i64 %d) {
entry:
%cmp = icmp ule i64 %a, %b
......@@ -1647,6 +1791,38 @@ if.end3: ; preds = %if.end, %if.then2
; ARM32-O2: blt
; ARM32: bl
; MIPS32-LABEL: icmpLe64
; MIPS32: xor [[T1:.*]],[[A_HI:.*]],[[B_HI:.*]]
; MIPS32-OM1: sltu [[T2:.*]],[[B_HI]],[[A_HI]]
; MIPS32-OM1: xori [[T3:.*]],[[T2]],0x1
; MIPS32-OM1: sltu [[T4:.*]],{{.*}},{{.*}}
; MIPS32-OM1: xori [[T5:.*]],[[T4]],0x1
; MIPS32-O2: sltu [[T3:.*]],[[B_HI]],[[A_HI]]
; MIPS32-O2: sltu [[T5:.*]],{{.*}},{{.*}}
; MIPS32: movz [[T3]],[[T5]],[[T1]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sw [[T3]],[[MEM:.*]]
; MIPS32-OM1: lb [[T6:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T6]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: xor [[T1:.*]],[[A_HI:.*]],[[B_HI:.*]]
; MIPS32-OM1: slt [[T2:.*]],[[B_HI]],[[A_HI]]
; MIPS32-OM1: xori [[T3:.*]],[[T2]],0x1
; MIPS32-OM1: sltu [[T4:.*]],{{.*}},{{.*}}
; MIPS32-OM1: xori [[T5:.*]],[[T4]],0x1
; MIPS32-O2: slt [[T3:.*]],[[B_HI]],[[A_HI]]
; MIPS32-O2: sltu [[T5:.*]],{{.*}},{{.*}}
; MIPS32: movz [[T3]],[[T5]],[[T1]]
; MIPS32-O2: bnez [[T3]],{{.*}}
; MIPS32-OM1: sw [[T3]],[[MEM:.*]]
; MIPS32-OM1: lb [[T6:.*]],[[MEM]]
; MIPS32-OM1: beqz [[T6]],{{.*}}
; MIPS32-OM1: b {{.*}}
; MIPS32: jal {{.*}}
; MIPS32-OM1: b {{.*}}
define internal i32 @icmpEq64Bool(i64 %a, i64 %b) {
entry:
%cmp = icmp eq i64 %a, %b
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment