llvm.org GIT mirror llvm / c41364c
[X86] Factor the core code out of LowerXALUO into a helper function. Use it in LowerBRCOND and LowerSELECT to avoid some duplicated code. This makes it easier to keep the LowerBRCOND and LowerSELECT code in sync with LowerXALUO so they always pick the same operation for overflowing instructions. This is inspired by the helper functions used by ARM and AArch64 for the same purpose. The test change is because LowerSELECT was not in sync with LowerXALUO with regard to INC/DEC for SADDO/SSUBO. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350198 91177308-0d34-0410-b5e6-96231b3b80d8 Craig Topper 9 months ago
2 changed file(s) with 101 addition(s) and 148 deletion(s). Raw diff Collapse all Expand all
1958719587 return getSETCC(CC, Cmp.getValue(1), DL, DAG);
1958819588 }
1958919589
19590 // This function returns three things: the arithmetic computation itself
19591 // (Value), an EFLAGS result (Overflow), and a condition code (Cond). The
19592 // flag and the condition code define the case in which the arithmetic
19593 // computation overflows.
19594 static std::pair
19595 getX86XALUOOp(X86::CondCode &Cond, SDValue Op, SelectionDAG &DAG) {
19596 assert(Op.getResNo() == 0 && "Unexpected result number!");
19597 SDValue Value, Overflow;
19598 SDValue LHS = Op.getOperand(0);
19599 SDValue RHS = Op.getOperand(1);
19600 unsigned BaseOp = 0;
19601 SDLoc DL(Op);
19602 switch (Op.getOpcode()) {
19603 default: llvm_unreachable("Unknown ovf instruction!");
19604 case ISD::SADDO:
19605 // A subtract of one will be selected as a INC. Note that INC doesn't
19606 // set CF, so we can't do this for UADDO.
19607 if (isOneConstant(RHS)) {
19608 BaseOp = X86ISD::INC;
19609 Cond = X86::COND_O;
19610 break;
19611 }
19612 BaseOp = X86ISD::ADD;
19613 Cond = X86::COND_O;
19614 break;
19615 case ISD::UADDO:
19616 BaseOp = X86ISD::ADD;
19617 Cond = X86::COND_B;
19618 break;
19619 case ISD::SSUBO:
19620 // A subtract of one will be selected as a DEC. Note that DEC doesn't
19621 // set CF, so we can't do this for USUBO.
19622 if (isOneConstant(RHS)) {
19623 BaseOp = X86ISD::DEC;
19624 Cond = X86::COND_O;
19625 break;
19626 }
19627 BaseOp = X86ISD::SUB;
19628 Cond = X86::COND_O;
19629 break;
19630 case ISD::USUBO:
19631 BaseOp = X86ISD::SUB;
19632 Cond = X86::COND_B;
19633 break;
19634 case ISD::SMULO:
19635 BaseOp = Op.getValueType() == MVT::i8 ? X86ISD::SMUL8 : X86ISD::SMUL;
19636 Cond = X86::COND_O;
19637 break;
19638 case ISD::UMULO: { // i64, i8 = umulo lhs, rhs --> i64, i64, i32 umul lhs,rhs
19639 if (Op.getValueType() == MVT::i8) {
19640 BaseOp = X86ISD::UMUL8;
19641 Cond = X86::COND_O;
19642 break;
19643 }
19644 SDVTList VTs = DAG.getVTList(Op.getValueType(), Op.getValueType(),
19645 MVT::i32);
19646 Value = DAG.getNode(X86ISD::UMUL, DL, VTs, LHS, RHS);
19647 Overflow = Value.getValue(2);
19648 Cond = X86::COND_O;
19649 break;
19650 }
19651 }
19652
19653 if (BaseOp) {
19654 // Also sets EFLAGS.
19655 SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i32);
19656 Value = DAG.getNode(BaseOp, DL, VTs, LHS, RHS);
19657 Overflow = Value.getValue(1);
19658 }
19659
19660 return std::make_pair(Value, Overflow);
19661 }
19662
19663 static SDValue LowerXALUO(SDValue Op, SelectionDAG &DAG) {
19664 // Lower the "add/sub/mul with overflow" instruction into a regular ins plus
19665 // a "setcc" instruction that checks the overflow flag. The "brcond" lowering
19666 // looks for this combo and may remove the "setcc" instruction if the "setcc"
19667 // has only one use.
19668 SDLoc DL(Op);
19669 X86::CondCode Cond;
19670 SDValue Value, Overflow;
19671 std::tie(Value, Overflow) = getX86XALUOOp(Cond, Op, DAG);
19672
19673 SDValue SetCC = getSETCC(Cond, Overflow, DL, DAG);
19674 return DAG.getNode(ISD::MERGE_VALUES, DL, Op->getVTList(), Value, SetCC);
19675 }
19676
1959019677 /// Return true if opcode is a X86 logical comparison.
1959119678 static bool isX86LogicalCmp(SDValue Op) {
1959219679 unsigned Opc = Op.getOpcode();
1984919936 CondOpcode == ISD::UADDO || CondOpcode == ISD::SADDO ||
1985019937 ((CondOpcode == ISD::UMULO || CondOpcode == ISD::SMULO) &&
1985119938 Cond.getOperand(0).getValueType() != MVT::i8)) {
19852 SDValue LHS = Cond.getOperand(0);
19853 SDValue RHS = Cond.getOperand(1);
19854 unsigned X86Opcode;
19855 unsigned X86Cond;
19856 SDVTList VTs;
19857 switch (CondOpcode) {
19858 case ISD::UADDO: X86Opcode = X86ISD::ADD; X86Cond = X86::COND_B; break;
19859 case ISD::SADDO: X86Opcode = X86ISD::ADD; X86Cond = X86::COND_O; break;
19860 case ISD::USUBO: X86Opcode = X86ISD::SUB; X86Cond = X86::COND_B; break;
19861 case ISD::SSUBO: X86Opcode = X86ISD::SUB; X86Cond = X86::COND_O; break;
19862 case ISD::UMULO: X86Opcode = X86ISD::UMUL; X86Cond = X86::COND_O; break;
19863 case ISD::SMULO: X86Opcode = X86ISD::SMUL; X86Cond = X86::COND_O; break;
19864 default: llvm_unreachable("unexpected overflowing operator");
19865 }
19866 if (CondOpcode == ISD::UMULO)
19867 VTs = DAG.getVTList(LHS.getValueType(), LHS.getValueType(),
19868 MVT::i32);
19869 else
19870 VTs = DAG.getVTList(LHS.getValueType(), MVT::i32);
19871
19872 SDValue X86Op = DAG.getNode(X86Opcode, DL, VTs, LHS, RHS);
19873
19874 if (CondOpcode == ISD::UMULO)
19875 Cond = X86Op.getValue(2);
19876 else
19877 Cond = X86Op.getValue(1);
19939 SDValue Value;
19940 X86::CondCode X86Cond;
19941 std::tie(Value, Cond) = getX86XALUOOp(X86Cond, Cond.getValue(0), DAG);
1987819942
1987919943 CC = DAG.getConstant(X86Cond, DL, MVT::i8);
1988019944 AddTest = false;
2055620620 CondOpcode == ISD::USUBO || CondOpcode == ISD::SSUBO ||
2055720621 ((CondOpcode == ISD::UMULO || CondOpcode == ISD::SMULO) &&
2055820622 Cond.getOperand(0).getValueType() != MVT::i8)) {
20559 SDValue LHS = Cond.getOperand(0);
20560 SDValue RHS = Cond.getOperand(1);
20561 unsigned X86Opcode;
20562 unsigned X86Cond;
20563 SDVTList VTs;
20564 // Keep this in sync with LowerXALUO, otherwise we might create redundant
20565 // instructions that can't be removed afterwards (i.e. X86ISD::ADD and
20566 // X86ISD::INC).
20567 switch (CondOpcode) {
20568 case ISD::UADDO: X86Opcode = X86ISD::ADD; X86Cond = X86::COND_B; break;
20569 case ISD::SADDO:
20570 if (isOneConstant(RHS)) {
20571 X86Opcode = X86ISD::INC; X86Cond = X86::COND_O;
20572 break;
20573 }
20574 X86Opcode = X86ISD::ADD; X86Cond = X86::COND_O; break;
20575 case ISD::USUBO: X86Opcode = X86ISD::SUB; X86Cond = X86::COND_B; break;
20576 case ISD::SSUBO:
20577 if (isOneConstant(RHS)) {
20578 X86Opcode = X86ISD::DEC; X86Cond = X86::COND_O;
20579 break;
20580 }
20581 X86Opcode = X86ISD::SUB; X86Cond = X86::COND_O; break;
20582 case ISD::UMULO: X86Opcode = X86ISD::UMUL; X86Cond = X86::COND_O; break;
20583 case ISD::SMULO: X86Opcode = X86ISD::SMUL; X86Cond = X86::COND_O; break;
20584 default: llvm_unreachable("unexpected overflowing operator");
20585 }
20623 SDValue Value;
20624 X86::CondCode X86Cond;
20625 std::tie(Value, Cond) = getX86XALUOOp(X86Cond, Cond.getValue(0), DAG);
20626
2058620627 if (Inverted)
20587 X86Cond = X86::GetOppositeBranchCondition((X86::CondCode)X86Cond);
20588 if (CondOpcode == ISD::UMULO)
20589 VTs = DAG.getVTList(LHS.getValueType(), LHS.getValueType(),
20590 MVT::i32);
20591 else
20592 VTs = DAG.getVTList(LHS.getValueType(), MVT::i32);
20593
20594 SDValue X86Op = DAG.getNode(X86Opcode, dl, VTs, LHS, RHS);
20595
20596 if (CondOpcode == ISD::UMULO)
20597 Cond = X86Op.getValue(2);
20598 else
20599 Cond = X86Op.getValue(1);
20628 X86Cond = X86::GetOppositeBranchCondition(X86Cond);
2060020629
2060120630 CC = DAG.getConstant(X86Cond, dl, MVT::i8);
2060220631 addTest = false;
2491724946 return DAG.getNode(ISD::OR, DL, VT,
2491824947 DAG.getVectorShuffle(VT, DL, Res02, Res13, {0, 4, 2, 6}),
2491924948 DAG.getVectorShuffle(VT, DL, Res02, Res13, {1, 5, 3, 7}));
24920 }
24921
24922 static SDValue LowerXALUO(SDValue Op, SelectionDAG &DAG) {
24923 // Lower the "add/sub/mul with overflow" instruction into a regular ins plus
24924 // a "setcc" instruction that checks the overflow flag. The "brcond" lowering
24925 // looks for this combo and may remove the "setcc" instruction if the "setcc"
24926 // has only one use.
24927 SDNode *N = Op.getNode();
24928 SDValue LHS = N->getOperand(0);
24929 SDValue RHS = N->getOperand(1);
24930 unsigned BaseOp = 0;
24931 X86::CondCode Cond;
24932 SDLoc DL(Op);
24933 switch (Op.getOpcode()) {
24934 default: llvm_unreachable("Unknown ovf instruction!");
24935 case ISD::SADDO:
24936 // A subtract of one will be selected as a INC. Note that INC doesn't
24937 // set CF, so we can't do this for UADDO.
24938 if (isOneConstant(RHS)) {
24939 BaseOp = X86ISD::INC;
24940 Cond = X86::COND_O;
24941 break;
24942 }
24943 BaseOp = X86ISD::ADD;
24944 Cond = X86::COND_O;
24945 break;
24946 case ISD::UADDO:
24947 BaseOp = X86ISD::ADD;
24948 Cond = X86::COND_B;
24949 break;
24950 case ISD::SSUBO:
24951 // A subtract of one will be selected as a DEC. Note that DEC doesn't
24952 // set CF, so we can't do this for USUBO.
24953 if (isOneConstant(RHS)) {
24954 BaseOp = X86ISD::DEC;
24955 Cond = X86::COND_O;
24956 break;
24957 }
24958 BaseOp = X86ISD::SUB;
24959 Cond = X86::COND_O;
24960 break;
24961 case ISD::USUBO:
24962 BaseOp = X86ISD::SUB;
24963 Cond = X86::COND_B;
24964 break;
24965 case ISD::SMULO:
24966 BaseOp = N->getValueType(0) == MVT::i8 ? X86ISD::SMUL8 : X86ISD::SMUL;
24967 Cond = X86::COND_O;
24968 break;
24969 case ISD::UMULO: { // i64, i8 = umulo lhs, rhs --> i64, i64, i32 umul lhs,rhs
24970 if (N->getValueType(0) == MVT::i8) {
24971 BaseOp = X86ISD::UMUL8;
24972 Cond = X86::COND_O;
24973 break;
24974 }
24975 SDVTList VTs = DAG.getVTList(N->getValueType(0), N->getValueType(0),
24976 MVT::i32);
24977 SDValue Sum = DAG.getNode(X86ISD::UMUL, DL, VTs, LHS, RHS);
24978
24979 SDValue SetCC = getSETCC(X86::COND_O, SDValue(Sum.getNode(), 2), DL, DAG);
24980
24981 return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Sum, SetCC);
24982 }
24983 }
24984
24985 // Also sets EFLAGS.
24986 SDVTList VTs = DAG.getVTList(N->getValueType(0), MVT::i32);
24987 SDValue Sum = DAG.getNode(BaseOp, DL, VTs, LHS, RHS);
24988
24989 SDValue SetCC = getSETCC(Cond, SDValue(Sum.getNode(), 1), DL, DAG);
24990
24991 return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Sum, SetCC);
2499224949 }
2499324950
2499424951 /// Returns true if the operand type is exactly twice the native width, and
10771077 ret {i64, i1} %t
10781078 }
10791079
1080 ; FIXME: We're selecting both an INC and an ADD here. One of them becomes an LEA.
1080 ; Make sure we select an INC for both the data use and the flag use.
10811081 define i32 @incovfselectstore(i32 %v1, i32 %v2, i32* %x) {
10821082 ; SDAG-LABEL: incovfselectstore:
10831083 ; SDAG: ## %bb.0:
10841084 ; SDAG-NEXT: movl %esi, %eax
1085 ; SDAG-NEXT: ## kill: def $edi killed $edi def $rdi
1086 ; SDAG-NEXT: leal 1(%rdi), %ecx
1087 ; SDAG-NEXT: movl %edi, %esi
1088 ; SDAG-NEXT: addl $1, %esi
1085 ; SDAG-NEXT: movl %edi, %ecx
1086 ; SDAG-NEXT: incl %ecx
10891087 ; SDAG-NEXT: cmovol %edi, %eax
10901088 ; SDAG-NEXT: movl %ecx, (%rdx)
10911089 ; SDAG-NEXT: retq
11061104 ret i32 %ret
11071105 }
11081106
1109 ; FIXME: We're selecting both a DEC and a SUB here. DEC becomes an LEA and
1110 ; SUB becomes a CMP.
1107 ; Make sure we select a DEC for both the data use and the flag use.
11111108 define i32 @decovfselectstore(i32 %v1, i32 %v2, i32* %x) {
11121109 ; SDAG-LABEL: decovfselectstore:
11131110 ; SDAG: ## %bb.0:
11141111 ; SDAG-NEXT: movl %esi, %eax
1115 ; SDAG-NEXT: ## kill: def $edi killed $edi def $rdi
1116 ; SDAG-NEXT: leal -1(%rdi), %ecx
1117 ; SDAG-NEXT: cmpl $1, %edi
1112 ; SDAG-NEXT: movl %edi, %ecx
1113 ; SDAG-NEXT: decl %ecx
11181114 ; SDAG-NEXT: cmovol %edi, %eax
11191115 ; SDAG-NEXT: movl %ecx, (%rdx)
11201116 ; SDAG-NEXT: retq