[llvm] b80e1ac - [M68k] Improve codegen of overflow arithmetics
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 26 11:10:08 PST 2023
Author: Min-Yih Hsu
Date: 2023-12-26T11:08:11-08:00
New Revision: b80e1acc8cfb82158255de24fb2887acd72a4049
URL: https://github.com/llvm/llvm-project/commit/b80e1acc8cfb82158255de24fb2887acd72a4049
DIFF: https://github.com/llvm/llvm-project/commit/b80e1acc8cfb82158255de24fb2887acd72a4049.diff
LOG: [M68k] Improve codegen of overflow arithmetics
The codegen logic for overflow arithmetics (e.g. llvm.uadd.overflow)
was a mess; overflow multiplications were not even supported.
This patch clean up the legalization of overflow arithmetics and add
supports for common variants of overflow multiplications.
Added:
Modified:
llvm/lib/Target/M68k/M68kISelLowering.cpp
llvm/lib/Target/M68k/M68kInstrArithmetic.td
llvm/lib/Target/M68k/M68kInstrInfo.td
llvm/test/CodeGen/M68k/Arith/smul-with-overflow.ll
llvm/test/CodeGen/M68k/Arith/umul-with-overflow.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/M68k/M68kISelLowering.cpp b/llvm/lib/Target/M68k/M68kISelLowering.cpp
index 0830cc7feb220d..6ca5962965bdea 100644
--- a/llvm/lib/Target/M68k/M68kISelLowering.cpp
+++ b/llvm/lib/Target/M68k/M68kISelLowering.cpp
@@ -94,11 +94,10 @@ M68kTargetLowering::M68kTargetLowering(const M68kTargetMachine &TM,
setOperationAction(OP, MVT::i16, Expand);
}
- // FIXME It would be better to use a custom lowering
for (auto OP : {ISD::SMULO, ISD::UMULO}) {
- setOperationAction(OP, MVT::i8, Expand);
- setOperationAction(OP, MVT::i16, Expand);
- setOperationAction(OP, MVT::i32, Expand);
+ setOperationAction(OP, MVT::i8, Custom);
+ setOperationAction(OP, MVT::i16, Custom);
+ setOperationAction(OP, MVT::i32, Custom);
}
for (auto OP : {ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS})
@@ -1533,46 +1532,119 @@ bool M68kTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
return VT.bitsLE(MVT::i32) || Subtarget.atLeastM68020();
}
-SDValue M68kTargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const {
- // Lower the "add/sub/mul with overflow" instruction into a regular ins plus
- // a "setcc" instruction that checks the overflow flag. The "brcond" lowering
- // looks for this combo and may remove the "setcc" instruction if the "setcc"
- // has only one use.
+static bool isOverflowArithmetic(unsigned Opcode) {
+ switch (Opcode) {
+ case ISD::UADDO:
+ case ISD::SADDO:
+ case ISD::USUBO:
+ case ISD::SSUBO:
+ case ISD::UMULO:
+ case ISD::SMULO:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void lowerOverflowArithmetic(SDValue Op, SelectionDAG &DAG,
+ SDValue &Result, SDValue &CCR,
+ unsigned &CC) {
SDNode *N = Op.getNode();
+ EVT VT = N->getValueType(0);
SDValue LHS = N->getOperand(0);
SDValue RHS = N->getOperand(1);
- unsigned BaseOp = 0;
- unsigned Cond = 0;
SDLoc DL(Op);
+
+ unsigned TruncOp = 0;
+ auto PromoteMULO = [&](unsigned ExtOp) {
+ // We don't have 8-bit multiplications, so promote i8 version of U/SMULO
+ // to i16.
+ // Ideally this should be done by legalizer but sadly there is no promotion
+ // rule for U/SMULO at this moment.
+ if (VT == MVT::i8) {
+ LHS = DAG.getNode(ExtOp, DL, MVT::i16, LHS);
+ RHS = DAG.getNode(ExtOp, DL, MVT::i16, RHS);
+ VT = MVT::i16;
+ TruncOp = ISD::TRUNCATE;
+ }
+ };
+
+ bool NoOverflow = false;
+ unsigned BaseOp = 0;
switch (Op.getOpcode()) {
default:
llvm_unreachable("Unknown ovf instruction!");
case ISD::SADDO:
BaseOp = M68kISD::ADD;
- Cond = M68k::COND_VS;
+ CC = M68k::COND_VS;
break;
case ISD::UADDO:
BaseOp = M68kISD::ADD;
- Cond = M68k::COND_CS;
+ CC = M68k::COND_CS;
break;
case ISD::SSUBO:
BaseOp = M68kISD::SUB;
- Cond = M68k::COND_VS;
+ CC = M68k::COND_VS;
break;
case ISD::USUBO:
BaseOp = M68kISD::SUB;
- Cond = M68k::COND_CS;
+ CC = M68k::COND_CS;
+ break;
+ case ISD::UMULO:
+ PromoteMULO(ISD::ZERO_EXTEND);
+ NoOverflow = VT != MVT::i32;
+ BaseOp = NoOverflow ? ISD::MUL : M68kISD::UMUL;
+ CC = M68k::COND_VS;
+ break;
+ case ISD::SMULO:
+ PromoteMULO(ISD::SIGN_EXTEND);
+ NoOverflow = VT != MVT::i32;
+ BaseOp = NoOverflow ? ISD::MUL : M68kISD::SMUL;
+ CC = M68k::COND_VS;
break;
}
- // Also sets CCR.
- SDVTList VTs = DAG.getVTList(N->getValueType(0), MVT::i8);
+ SDVTList VTs;
+ if (NoOverflow)
+ VTs = DAG.getVTList(VT);
+ else
+ // Also sets CCR.
+ VTs = DAG.getVTList(VT, MVT::i8);
+
SDValue Arith = DAG.getNode(BaseOp, DL, VTs, LHS, RHS);
- SDValue SetCC = DAG.getNode(M68kISD::SETCC, DL, N->getValueType(1),
- DAG.getConstant(Cond, DL, MVT::i8),
- SDValue(Arith.getNode(), 1));
+ Result = Arith.getValue(0);
+ if (TruncOp)
+ // Right now the only place to truncate is from i16 to i8.
+ Result = DAG.getNode(TruncOp, DL, MVT::i8, Arith);
- return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Arith, SetCC);
+ if (NoOverflow)
+ CCR = DAG.getConstant(0, DL, N->getValueType(1));
+ else
+ CCR = Arith.getValue(1);
+}
+
+SDValue M68kTargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const {
+ SDNode *N = Op.getNode();
+ SDLoc DL(Op);
+
+ // Lower the "add/sub/mul with overflow" instruction into a regular ins plus
+ // a "setcc" instruction that checks the overflow flag.
+ SDValue Result, CCR;
+ unsigned CC;
+ lowerOverflowArithmetic(Op, DAG, Result, CCR, CC);
+
+ SDValue Overflow;
+ if (isa<ConstantSDNode>(CCR)) {
+ // It's likely a result of operations that will not overflow
+ // hence no setcc is needed.
+ Overflow = DAG.getZExtOrTrunc(CCR, DL, N->getValueType(1));
+ } else {
+ // Generate a M68kISD::SETCC.
+ Overflow = DAG.getNode(M68kISD::SETCC, DL, N->getValueType(1),
+ DAG.getConstant(CC, DL, MVT::i8), CCR);
+ }
+
+ return DAG.getNode(ISD::MERGE_VALUES, DL, N->getVTList(), Result, Overflow);
}
/// Create a BTST (Bit Test) node - Test bit \p BitNo in \p Src and set
@@ -2269,55 +2341,12 @@ SDValue M68kTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const {
Cond = Cmp;
addTest = false;
}
- } else if (CondOpcode == ISD::USUBO || CondOpcode == ISD::SSUBO ||
- CondOpcode == ISD::UADDO || CondOpcode == ISD::SADDO ||
- CondOpcode == ISD::UMULO || CondOpcode == ISD::SMULO) {
- SDValue LHS = Cond.getOperand(0);
- SDValue RHS = Cond.getOperand(1);
- unsigned MxOpcode;
- unsigned MxCond;
- SDVTList VTs;
- switch (CondOpcode) {
- case ISD::UADDO:
- MxOpcode = M68kISD::ADD;
- MxCond = M68k::COND_CS;
- break;
- case ISD::SADDO:
- MxOpcode = M68kISD::ADD;
- MxCond = M68k::COND_VS;
- break;
- case ISD::USUBO:
- MxOpcode = M68kISD::SUB;
- MxCond = M68k::COND_CS;
- break;
- case ISD::SSUBO:
- MxOpcode = M68kISD::SUB;
- MxCond = M68k::COND_VS;
- break;
- case ISD::UMULO:
- MxOpcode = M68kISD::UMUL;
- MxCond = M68k::COND_VS;
- break;
- case ISD::SMULO:
- MxOpcode = M68kISD::SMUL;
- MxCond = M68k::COND_VS;
- break;
- default:
- llvm_unreachable("unexpected overflowing operator");
- }
- if (CondOpcode == ISD::UMULO)
- VTs = DAG.getVTList(LHS.getValueType(), LHS.getValueType(), MVT::i32);
- else
- VTs = DAG.getVTList(LHS.getValueType(), MVT::i32);
-
- SDValue MxOp = DAG.getNode(MxOpcode, DL, VTs, LHS, RHS);
-
- if (CondOpcode == ISD::UMULO)
- Cond = MxOp.getValue(2);
- else
- Cond = MxOp.getValue(1);
-
- CC = DAG.getConstant(MxCond, DL, MVT::i8);
+ } else if (isOverflowArithmetic(CondOpcode)) {
+ // Result is unused here.
+ SDValue Result;
+ unsigned CCode;
+ lowerOverflowArithmetic(Cond, DAG, Result, Cond, CCode);
+ CC = DAG.getConstant(CCode, DL, MVT::i8);
addTest = false;
}
@@ -2466,61 +2495,15 @@ SDValue M68kTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
}
}
CondOpcode = Cond.getOpcode();
- if (CondOpcode == ISD::UADDO || CondOpcode == ISD::SADDO ||
- CondOpcode == ISD::USUBO || CondOpcode == ISD::SSUBO) {
- SDValue LHS = Cond.getOperand(0);
- SDValue RHS = Cond.getOperand(1);
- unsigned MxOpcode;
- unsigned MxCond;
- SDVTList VTs;
- // Keep this in sync with LowerXALUO, otherwise we might create redundant
- // instructions that can't be removed afterwards (i.e. M68kISD::ADD and
- // M68kISD::INC).
- switch (CondOpcode) {
- case ISD::UADDO:
- MxOpcode = M68kISD::ADD;
- MxCond = M68k::COND_CS;
- break;
- case ISD::SADDO:
- MxOpcode = M68kISD::ADD;
- MxCond = M68k::COND_VS;
- break;
- case ISD::USUBO:
- MxOpcode = M68kISD::SUB;
- MxCond = M68k::COND_CS;
- break;
- case ISD::SSUBO:
- MxOpcode = M68kISD::SUB;
- MxCond = M68k::COND_VS;
- break;
- case ISD::UMULO:
- MxOpcode = M68kISD::UMUL;
- MxCond = M68k::COND_VS;
- break;
- case ISD::SMULO:
- MxOpcode = M68kISD::SMUL;
- MxCond = M68k::COND_VS;
- break;
- default:
- llvm_unreachable("unexpected overflowing operator");
- }
+ if (isOverflowArithmetic(CondOpcode)) {
+ SDValue Result;
+ unsigned CCode;
+ lowerOverflowArithmetic(Cond, DAG, Result, Cond, CCode);
if (Inverted)
- MxCond = M68k::GetOppositeBranchCondition((M68k::CondCode)MxCond);
+ CCode = M68k::GetOppositeBranchCondition((M68k::CondCode)CCode);
+ CC = DAG.getConstant(CCode, DL, MVT::i8);
- if (CondOpcode == ISD::UMULO)
- VTs = DAG.getVTList(LHS.getValueType(), LHS.getValueType(), MVT::i8);
- else
- VTs = DAG.getVTList(LHS.getValueType(), MVT::i8);
-
- SDValue MxOp = DAG.getNode(MxOpcode, DL, VTs, LHS, RHS);
-
- if (CondOpcode == ISD::UMULO)
- Cond = MxOp.getValue(2);
- else
- Cond = MxOp.getValue(1);
-
- CC = DAG.getConstant(MxCond, DL, MVT::i8);
AddTest = false;
} else {
unsigned CondOpc;
diff --git a/llvm/lib/Target/M68k/M68kInstrArithmetic.td b/llvm/lib/Target/M68k/M68kInstrArithmetic.td
index 15d2049f62cb73..7f250f4e56ef26 100644
--- a/llvm/lib/Target/M68k/M68kInstrArithmetic.td
+++ b/llvm/lib/Target/M68k/M68kInstrArithmetic.td
@@ -590,8 +590,9 @@ class MxDiMuOp_DD<string MN, bits<4> CMD, bit SIGNED = false,
}
// $dreg <- $dreg op $dreg
-class MxDiMuOp_DD_Long<string MN, bits<10> CMD, bit SIGNED = false>
- : MxInst<(outs MxDRD32:$dst), (ins MxDRD32:$src, MxDRD32:$opd), MN#"\t$opd, $dst", []> {
+class MxDiMuOp_DD_Long<string MN, SDNode NODE, bits<10> CMD, bit SIGNED = false>
+ : MxInst<(outs MxDRD32:$dst), (ins MxDRD32:$src, MxDRD32:$opd), MN#"\t$opd, $dst",
+ [(set i32:$dst, CCR, (NODE i32:$src, i32:$opd))]> {
let Inst = (ascend
(descend CMD,
/*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)),
@@ -634,8 +635,8 @@ multiclass MxDiMuOp<string MN, bits<4> CMD, bit isComm = 0> {
defm DIV : MxDiMuOp<"div", 0x8>;
-def SDIVd32d32 : MxDiMuOp_DD_Long<"divs.l", 0x131, /*SIGNED*/true>;
-def UDIVd32d32 : MxDiMuOp_DD_Long<"divu.l", 0x131, /*SIGNED*/false>;
+def SDIVd32d32 : MxDiMuOp_DD_Long<"divs.l", sdiv, 0x131, /*SIGNED*/true>;
+def UDIVd32d32 : MxDiMuOp_DD_Long<"divu.l", udiv, 0x131, /*SIGNED*/false>;
// This is used to cast immediates to 16-bits for operations which don't
// support smaller immediate sizes.
@@ -685,13 +686,6 @@ def : Pat<(urem i16:$dst, i16:$opd),
(LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 8), 8),
MxSubRegIndex16Lo)>;
-
-// RR i32
-def : Pat<(sdiv i32:$dst, i32:$opd), (SDIVd32d32 $dst, $opd)>;
-
-def : Pat<(udiv i32:$dst, i32:$opd), (UDIVd32d32 $dst, $opd)>;
-
-
// RI i8
def : Pat<(sdiv i8:$dst, MximmSExt8:$opd),
(EXTRACT_SUBREG
@@ -737,8 +731,8 @@ def : Pat<(urem i16:$dst, MximmSExt16:$opd),
defm MUL : MxDiMuOp<"mul", 0xC, 1>;
-def SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", 0x130, /*SIGNED*/true>;
-def UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", 0x130, /*SIGNED*/false>;
+def SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", MxSMul, 0x130, /*SIGNED*/true>;
+def UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", MxUMul, 0x130, /*SIGNED*/false>;
// RR
def : Pat<(mul i16:$dst, i16:$opd),
diff --git a/llvm/lib/Target/M68k/M68kInstrInfo.td b/llvm/lib/Target/M68k/M68kInstrInfo.td
index dc66e103361a42..1e40c3c48990d4 100644
--- a/llvm/lib/Target/M68k/M68kInstrInfo.td
+++ b/llvm/lib/Target/M68k/M68kInstrInfo.td
@@ -55,15 +55,6 @@ def MxSDT_BiArithCCRInOut : SDTypeProfile<2, 3, [
/* CCR */ SDTCisSameAs<1, 4>
]>;
-// RES1, RES2, CCR <- op LHS, RHS
-def MxSDT_2BiArithCCROut : SDTypeProfile<3, 2, [
- /* RES 1 */ SDTCisInt<0>,
- /* RES 2 */ SDTCisSameAs<0, 1>,
- /* CCR */ SDTCisVT<1, i8>,
- /* LHS */ SDTCisSameAs<0, 2>,
- /* RHS */ SDTCisSameAs<0, 3>
-]>;
-
def MxSDT_CmpTest : SDTypeProfile<1, 2, [
/* CCR */ SDTCisVT<0, i8>,
/* Ops */ SDTCisSameAs<1, 2>
@@ -134,7 +125,7 @@ def MxAddX : SDNode<"M68kISD::ADDX", MxSDT_BiArithCCRInOut>;
def MxSubX : SDNode<"M68kISD::SUBX", MxSDT_BiArithCCRInOut>;
def MxSMul : SDNode<"M68kISD::SMUL", MxSDT_BiArithCCROut, [SDNPCommutative]>;
-def MxUMul : SDNode<"M68kISD::UMUL", MxSDT_2BiArithCCROut, [SDNPCommutative]>;
+def MxUMul : SDNode<"M68kISD::UMUL", MxSDT_BiArithCCROut, [SDNPCommutative]>;
def MxCmp : SDNode<"M68kISD::CMP", MxSDT_CmpTest>;
def MxBtst : SDNode<"M68kISD::BTST", MxSDT_CmpTest>;
diff --git a/llvm/test/CodeGen/M68k/Arith/smul-with-overflow.ll b/llvm/test/CodeGen/M68k/Arith/smul-with-overflow.ll
index 1d3371cce833a9..cd9349181a6314 100644
--- a/llvm/test/CodeGen/M68k/Arith/smul-with-overflow.ll
+++ b/llvm/test/CodeGen/M68k/Arith/smul-with-overflow.ll
@@ -3,7 +3,6 @@
declare i32 @printf(i8*, ...) nounwind
declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32)
-declare { i63, i1 } @llvm.smul.with.overflow.i63(i63, i63)
@ok = internal constant [4 x i8] c"%d\0A\00"
@no = internal constant [4 x i8] c"no\0A\00"
@@ -11,37 +10,23 @@ declare { i63, i1 } @llvm.smul.with.overflow.i63(i63, i63)
define fastcc i1 @test1(i32 %v1, i32 %v2) nounwind {
; CHECK-LABEL: test1:
; CHECK: ; %bb.0: ; %entry
-; CHECK-NEXT: suba.l #28, %sp
-; CHECK-NEXT: movem.l %d2-%d3, (20,%sp) ; 12-byte Folded Spill
-; CHECK-NEXT: move.l %d1, (12,%sp)
-; CHECK-NEXT: move.l #31, %d2
-; CHECK-NEXT: asr.l %d2, %d1
-; CHECK-NEXT: move.l %d1, (8,%sp)
-; CHECK-NEXT: move.l %d0, (4,%sp)
-; CHECK-NEXT: asr.l %d2, %d0
-; CHECK-NEXT: move.l %d0, (%sp)
-; CHECK-NEXT: jsr __muldi3 at PLT
-; CHECK-NEXT: move.l %d1, %d3
-; CHECK-NEXT: asr.l %d2, %d3
-; CHECK-NEXT: sub.l %d3, %d0
-; CHECK-NEXT: sne %d0
-; CHECK-NEXT: cmpi.b #0, %d0
-; CHECK-NEXT: beq .LBB0_1
+; CHECK-NEXT: suba.l #12, %sp
+; CHECK-NEXT: muls.l %d1, %d0
+; CHECK-NEXT: bvc .LBB0_1
; CHECK-NEXT: ; %bb.2: ; %overflow
; CHECK-NEXT: lea (no,%pc), %a0
; CHECK-NEXT: move.l %a0, (%sp)
; CHECK-NEXT: jsr printf at PLT
; CHECK-NEXT: move.b #0, %d0
-; CHECK-NEXT: bra .LBB0_3
+; CHECK-NEXT: adda.l #12, %sp
+; CHECK-NEXT: rts
; CHECK-NEXT: .LBB0_1: ; %normal
-; CHECK-NEXT: move.l %d1, (4,%sp)
+; CHECK-NEXT: move.l %d0, (4,%sp)
; CHECK-NEXT: lea (ok,%pc), %a0
; CHECK-NEXT: move.l %a0, (%sp)
; CHECK-NEXT: jsr printf at PLT
; CHECK-NEXT: move.b #1, %d0
-; CHECK-NEXT: .LBB0_3: ; %overflow
-; CHECK-NEXT: movem.l (20,%sp), %d2-%d3 ; 12-byte Folded Reload
-; CHECK-NEXT: adda.l #28, %sp
+; CHECK-NEXT: adda.l #12, %sp
; CHECK-NEXT: rts
entry:
%t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
@@ -61,37 +46,25 @@ overflow:
define fastcc i1 @test2(i32 %v1, i32 %v2) nounwind {
; CHECK-LABEL: test2:
; CHECK: ; %bb.0: ; %entry
-; CHECK-NEXT: suba.l #28, %sp
-; CHECK-NEXT: movem.l %d2-%d3, (20,%sp) ; 12-byte Folded Spill
-; CHECK-NEXT: move.l %d1, (12,%sp)
-; CHECK-NEXT: move.l #31, %d2
-; CHECK-NEXT: asr.l %d2, %d1
-; CHECK-NEXT: move.l %d1, (8,%sp)
-; CHECK-NEXT: move.l %d0, (4,%sp)
-; CHECK-NEXT: asr.l %d2, %d0
-; CHECK-NEXT: move.l %d0, (%sp)
-; CHECK-NEXT: jsr __muldi3 at PLT
-; CHECK-NEXT: move.l %d1, %d3
-; CHECK-NEXT: asr.l %d2, %d3
-; CHECK-NEXT: sub.l %d3, %d0
-; CHECK-NEXT: sne %d0
-; CHECK-NEXT: sub.b #1, %d0
-; CHECK-NEXT: bne .LBB1_3
+; CHECK-NEXT: suba.l #12, %sp
+; CHECK-NEXT: muls.l %d1, %d0
+; CHECK-NEXT: svs %d1
+; CHECK-NEXT: sub.b #1, %d1
+; CHECK-NEXT: bne .LBB1_2
; CHECK-NEXT: ; %bb.1: ; %overflow
; CHECK-NEXT: lea (no,%pc), %a0
; CHECK-NEXT: move.l %a0, (%sp)
; CHECK-NEXT: jsr printf at PLT
; CHECK-NEXT: move.b #0, %d0
-; CHECK-NEXT: bra .LBB1_2
-; CHECK-NEXT: .LBB1_3: ; %normal
-; CHECK-NEXT: move.l %d1, (4,%sp)
+; CHECK-NEXT: adda.l #12, %sp
+; CHECK-NEXT: rts
+; CHECK-NEXT: .LBB1_2: ; %normal
+; CHECK-NEXT: move.l %d0, (4,%sp)
; CHECK-NEXT: lea (ok,%pc), %a0
; CHECK-NEXT: move.l %a0, (%sp)
; CHECK-NEXT: jsr printf at PLT
; CHECK-NEXT: move.b #1, %d0
-; CHECK-NEXT: .LBB1_2: ; %overflow
-; CHECK-NEXT: movem.l (20,%sp), %d2-%d3 ; 12-byte Folded Reload
-; CHECK-NEXT: adda.l #28, %sp
+; CHECK-NEXT: adda.l #12, %sp
; CHECK-NEXT: rts
entry:
%t = call {i32, i1} @llvm.smul.with.overflow.i32(i32 %v1, i32 %v2)
@@ -129,7 +102,8 @@ define i32 @test4(i32 %a, i32 %b) nounwind readnone {
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.l (8,%sp), %d0
; CHECK-NEXT: add.l (4,%sp), %d0
-; CHECK-NEXT: lsl.l #2, %d0
+; CHECK-NEXT: move.l #4, %d1
+; CHECK-NEXT: muls.l %d1, %d0
; CHECK-NEXT: rts
entry:
%tmp0 = add i32 %b, %a
diff --git a/llvm/test/CodeGen/M68k/Arith/umul-with-overflow.ll b/llvm/test/CodeGen/M68k/Arith/umul-with-overflow.ll
index 16dc1036fd2840..ef7171dc386fea 100644
--- a/llvm/test/CodeGen/M68k/Arith/umul-with-overflow.ll
+++ b/llvm/test/CodeGen/M68k/Arith/umul-with-overflow.ll
@@ -6,15 +6,10 @@ declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
define i1 @a(i32 %x) nounwind {
; CHECK-LABEL: a:
; CHECK: ; %bb.0:
-; CHECK-NEXT: suba.l #20, %sp
-; CHECK-NEXT: move.l #3, (12,%sp)
-; CHECK-NEXT: move.l #0, (8,%sp)
-; CHECK-NEXT: move.l (24,%sp), (4,%sp)
-; CHECK-NEXT: move.l #0, (%sp)
-; CHECK-NEXT: jsr __muldi3 at PLT
-; CHECK-NEXT: cmpi.l #0, %d0
-; CHECK-NEXT: sne %d0
-; CHECK-NEXT: adda.l #20, %sp
+; CHECK-NEXT: move.l #3, %d0
+; CHECK-NEXT: move.l (4,%sp), %d1
+; CHECK-NEXT: mulu.l %d0, %d1
+; CHECK-NEXT: svs %d0
; CHECK-NEXT: rts
%res = call {i32, i1} @llvm.umul.with.overflow.i32(i32 %x, i32 3)
%obil = extractvalue {i32, i1} %res, 1
@@ -42,7 +37,8 @@ define i32 @test3(i32 %a, i32 %b) nounwind readnone {
; CHECK: ; %bb.0: ; %entry
; CHECK-NEXT: move.l (8,%sp), %d0
; CHECK-NEXT: add.l (4,%sp), %d0
-; CHECK-NEXT: lsl.l #2, %d0
+; CHECK-NEXT: move.l #4, %d1
+; CHECK-NEXT: mulu.l %d1, %d0
; CHECK-NEXT: rts
entry:
%tmp0 = add i32 %b, %a
More information about the llvm-commits
mailing list