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<ConstantSDNode>(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<CondCodeSDNode>(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();
}
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
}
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
}
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
}
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
}
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
}
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
}
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
}
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