diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 75ce59f1f80..b1a25dd4639 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -559,6 +559,39 @@ static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::SELECT, DL, FalseTy, SetCC, False, True); } + // If both operands are integer constants there's a possibility that we + // can do some interesting optimizations. + SDValue True = N->getOperand(1); + ConstantSDNode *TrueC = dyn_cast(True); + + if (!TrueC || !True.getValueType().isInteger()) + return SDValue(); + + // We'll also ignore MVT::i64 operands as this optimizations proves + // to be ineffective because of the required sign extensions as the result + // of a SETCC operator is always MVT::i32 for non-vector types. + if (True.getValueType() == MVT::i64) + return SDValue(); + + int64_t Diff = TrueC->getSExtValue() - FalseC->getSExtValue(); + + // 1) (a < x) ? y : y-1 + // slti $reg1, a, x + // addiu $reg2, $reg1, y-1 + if (Diff == 1) + return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, False); + + // 2) (a < x) ? y-1 : y + // slti $reg1, a, x + // xor $reg1, $reg1, 1 + // addiu $reg2, $reg1, y-1 + if (Diff == -1) { + ISD::CondCode CC = cast(SetCC.getOperand(2))->get(); + SetCC = DAG.getSetCC(DL, SetCC.getValueType(), SetCC.getOperand(0), + SetCC.getOperand(1), ISD::getSetCCInverse(CC, true)); + return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, True); + } + // Couldn't optimize. return SDValue(); } diff --git a/test/CodeGen/Mips/cmov.ll b/test/CodeGen/Mips/cmov.ll index c24c5ac26ae..f2009fa5afb 100644 --- a/test/CodeGen/Mips/cmov.ll +++ b/test/CodeGen/Mips/cmov.ll @@ -74,7 +74,7 @@ entry: define i32 @slti0(i32 %a) { entry: %cmp = icmp sgt i32 %a, 32766 - %cond = select i1 %cmp, i32 3, i32 4 + %cond = select i1 %cmp, i32 3, i32 5 ret i32 %cond } @@ -84,7 +84,7 @@ entry: define i32 @slti1(i32 %a) { entry: %cmp = icmp sgt i32 %a, 32767 - %cond = select i1 %cmp, i32 3, i32 4 + %cond = select i1 %cmp, i32 3, i32 5 ret i32 %cond } @@ -95,7 +95,7 @@ entry: define i32 @slti2(i32 %a) { entry: %cmp = icmp sgt i32 %a, -32769 - %cond = select i1 %cmp, i32 3, i32 4 + %cond = select i1 %cmp, i32 3, i32 5 ret i32 %cond } @@ -105,7 +105,7 @@ entry: define i32 @slti3(i32 %a) { entry: %cmp = icmp sgt i32 %a, -32770 - %cond = select i1 %cmp, i32 3, i32 4 + %cond = select i1 %cmp, i32 3, i32 5 ret i32 %cond } @@ -162,7 +162,7 @@ entry: define i32 @sltiu0(i32 %a) { entry: %cmp = icmp ugt i32 %a, 32766 - %cond = select i1 %cmp, i32 3, i32 4 + %cond = select i1 %cmp, i32 3, i32 5 ret i32 %cond } @@ -172,7 +172,7 @@ entry: define i32 @sltiu1(i32 %a) { entry: %cmp = icmp ugt i32 %a, 32767 - %cond = select i1 %cmp, i32 3, i32 4 + %cond = select i1 %cmp, i32 3, i32 5 ret i32 %cond } @@ -183,7 +183,7 @@ entry: define i32 @sltiu2(i32 %a) { entry: %cmp = icmp ugt i32 %a, -32769 - %cond = select i1 %cmp, i32 3, i32 4 + %cond = select i1 %cmp, i32 3, i32 5 ret i32 %cond } @@ -193,6 +193,49 @@ entry: define i32 @sltiu3(i32 %a) { entry: %cmp = icmp ugt i32 %a, -32770 - %cond = select i1 %cmp, i32 3, i32 4 + %cond = select i1 %cmp, i32 3, i32 5 ret i32 %cond } + +; Check if +; (select (setxx a, N), x, x-1) or +; (select (setxx a, N), x-1, x) +; doesn't generate conditional moves +; for constant operands whose difference is |1| + +define i32 @slti4(i32 %a) nounwind readnone { + %1 = icmp slt i32 %a, 7 + %2 = select i1 %1, i32 4, i32 3 + ret i32 %2 +} + +; O32-LABEL: slti4: +; O32-DAG: slti [[R1:\$[0-9]+]], $4, 7 +; O32-DAG: addiu [[R2:\$[0-9]+]], [[R1]], 3 +; O32-NOT: movn +; O32:.size slti4 + +define i32 @slti5(i32 %a) nounwind readnone { + %1 = icmp slt i32 %a, 7 + %2 = select i1 %1, i32 -3, i32 -4 + ret i32 %2 +} + +; O32-LABEL: slti5: +; O32-DAG: slti [[R1:\$[0-9]+]], $4, 7 +; O32-DAG: addiu [[R3:\$[0-9]+]], [[R2:\$[a-z0-9]+]], -4 +; O32-NOT: movn +; O32:.size slti5 + +define i32 @slti6(i32 %a) nounwind readnone { + %1 = icmp slt i32 %a, 7 + %2 = select i1 %1, i32 3, i32 4 + ret i32 %2 +} + +; O32-LABEL: slti6: +; O32-DAG: slti [[R1:\$[0-9]+]], $4, 7 +; O32-DAG: xori [[R1]], [[R1]], 1 +; O32-DAG: addiu [[R2:\$[0-9]+]], [[R1]], 3 +; O32-NOT: movn +; O32:.size slti6 \ No newline at end of file diff --git a/test/CodeGen/Mips/sel1c.ll b/test/CodeGen/Mips/sel1c.ll index 4c4784de6aa..edd2e3e43b7 100644 --- a/test/CodeGen/Mips/sel1c.ll +++ b/test/CodeGen/Mips/sel1c.ll @@ -10,7 +10,7 @@ entry: %0 = load i32* @i, align 4 %1 = load i32* @j, align 4 %cmp = icmp eq i32 %0, %1 - %cond = select i1 %cmp, i32 1, i32 2 + %cond = select i1 %cmp, i32 1, i32 3 store i32 %cond, i32* @k, align 4 ret void ; cond-b-short: bteqz $BB0_{{[0-9]+}} # 16 bit inst diff --git a/test/CodeGen/Mips/sel2c.ll b/test/CodeGen/Mips/sel2c.ll index 25dfaa9ba87..4b211245f46 100644 --- a/test/CodeGen/Mips/sel2c.ll +++ b/test/CodeGen/Mips/sel2c.ll @@ -10,7 +10,7 @@ entry: %0 = load i32* @i, align 4 %1 = load i32* @j, align 4 %cmp = icmp ne i32 %0, %1 - %cond = select i1 %cmp, i32 1, i32 2 + %cond = select i1 %cmp, i32 1, i32 3 store i32 %cond, i32* @k, align 4 ; cond-b-short: btnez $BB0_{{[0-9]+}} # 16 bit inst ret void