[llvm] r208435 - Add custom lowering for add/sub with overflow intrinsics to ARM
Reid Kleckner
rnk at google.com
Fri May 9 15:00:11 PDT 2014
Fixed in r208448 by adding a triple with an OS in it.
On Fri, May 9, 2014 at 2:50 PM, Reid Kleckner <rnk at google.com> wrote:
> This test is failing for me locally and on Takumi's bot:
>
> http://bb.pgr.jp/builders/ninja-x64-msvc-RA-centos6/builds/2593/steps/test_all/logs/LLVM%20%3A%3A%20CodeGen__ARM__intrinsics-overflow.ll
>
> -- Testing: 10688 tests, 32 threads --
> FAIL: LLVM :: CodeGen/ARM/intrinsics-overflow.ll (1128 of 10688)
> ******************** TEST 'LLVM :: CodeGen/ARM/intrinsics-overflow.ll'
> FAILED ********************
> Script:
> --
> D:/src/llvm/build/./bin\llc.EXE <
> D:\src\llvm\test\CodeGen\ARM\intrinsics-overflow.ll -march=arm
> -mcpu=generic | D:/src/llvm/build/./bin\FileCheck.EXE
> D:\src\llvm\test\CodeGen\ARM\intrinsics-overflow.ll
> --
> Exit Code: 2
>
> Command Output (stdout):
> --
> Command 0: "D:/src/llvm/build/./bin\llc.EXE" "-march=arm" "-mcpu=generic"
> Command 0 Result: 1
> Command 0 Output:
>
>
> Command 0 Stderr:
> LLVM ERROR: CPU: 'generic' does not support ARM mode execution!
> Stack dump:
> 0. Program arguments: D:/src/llvm/build/./bin\llc.EXE -march=arm
> -mcpu=generic
>
>
> Command 1: "D:/src/llvm/build/./bin\FileCheck.EXE"
> "D:\src\llvm\test\CodeGen\ARM\intrinsics-overflow.ll"
> Command 1 Result: 2
> Command 1 Output:
>
>
> Command 1 Stderr:
> FileCheck error: '-' is empty.
>
>
>
> --
>
>
>
> On Fri, May 9, 2014 at 10:02 AM, Louis Gerbarg <lgg at apple.com> wrote:
>
>> Author: louis
>> Date: Fri May 9 12:02:49 2014
>> New Revision: 208435
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=208435&view=rev
>> Log:
>> Add custom lowering for add/sub with overflow intrinsics to ARM
>>
>> This patch adds support to ARM for custom lowering of the
>> llvm.{u|s}add.with.overflow.i32 intrinsics for i32/i64. This is
>> particularly useful
>> for handling idiomatic saturating math functions as generated by
>> InstCombineCompare.
>>
>> Test cases included.
>>
>> rdar://14853450
>>
>> Added:
>> llvm/trunk/test/CodeGen/ARM/intrinsics-overflow.ll
>> Modified:
>> llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>> llvm/trunk/lib/Target/ARM/ARMISelLowering.h
>>
>> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=208435&r1=208434&r2=208435&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
>> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri May 9 12:02:49 2014
>> @@ -639,6 +639,11 @@ ARMTargetLowering::ARMTargetLowering(Tar
>> }
>> }
>>
>> + setOperationAction(ISD::SADDO, MVT::i32, Custom);
>> + setOperationAction(ISD::UADDO, MVT::i32, Custom);
>> + setOperationAction(ISD::SSUBO, MVT::i32, Custom);
>> + setOperationAction(ISD::USUBO, MVT::i32, Custom);
>> +
>> // i64 operation support.
>> setOperationAction(ISD::MUL, MVT::i64, Expand);
>> setOperationAction(ISD::MULHU, MVT::i32, Expand);
>> @@ -3222,11 +3227,96 @@ ARMTargetLowering::duplicateCmp(SDValue
>> return DAG.getNode(ARMISD::FMSTAT, DL, MVT::Glue, Cmp);
>> }
>>
>> +std::pair<SDValue, SDValue>
>> +ARMTargetLowering::getARMXALUOOp(SDValue Op, SelectionDAG &DAG,
>> + SDValue &ARMcc) const {
>> + assert(Op.getValueType() == MVT::i32 && "Unsupported value type");
>> +
>> + SDValue Value, OverflowCmp;
>> + SDValue LHS = Op.getOperand(0);
>> + SDValue RHS = Op.getOperand(1);
>> +
>> +
>> + // FIXME: We are currently always generating CMPs because we don't
>> support
>> + // generating CMN through the backend. This is not as good as the
>> natural
>> + // CMP case because it causes a register dependency and cannot be
>> folded
>> + // later.
>> +
>> + switch (Op.getOpcode()) {
>> + default:
>> + llvm_unreachable("Unknown overflow instruction!");
>> + case ISD::SADDO:
>> + ARMcc = DAG.getConstant(ARMCC::VC, MVT::i32);
>> + Value = DAG.getNode(ISD::ADD, SDLoc(Op), Op.getValueType(), LHS,
>> RHS);
>> + OverflowCmp = DAG.getNode(ARMISD::CMP, SDLoc(Op), MVT::Glue, Value,
>> LHS);
>> + break;
>> + case ISD::UADDO:
>> + ARMcc = DAG.getConstant(ARMCC::HS, MVT::i32);
>> + Value = DAG.getNode(ISD::ADD, SDLoc(Op), Op.getValueType(), LHS,
>> RHS);
>> + OverflowCmp = DAG.getNode(ARMISD::CMP, SDLoc(Op), MVT::Glue, Value,
>> LHS);
>> + break;
>> + case ISD::SSUBO:
>> + ARMcc = DAG.getConstant(ARMCC::VC, MVT::i32);
>> + Value = DAG.getNode(ISD::SUB, SDLoc(Op), Op.getValueType(), LHS,
>> RHS);
>> + OverflowCmp = DAG.getNode(ARMISD::CMP, SDLoc(Op), MVT::Glue, LHS,
>> RHS);
>> + break;
>> + case ISD::USUBO:
>> + ARMcc = DAG.getConstant(ARMCC::HS, MVT::i32);
>> + Value = DAG.getNode(ISD::SUB, SDLoc(Op), Op.getValueType(), LHS,
>> RHS);
>> + OverflowCmp = DAG.getNode(ARMISD::CMP, SDLoc(Op), MVT::Glue, LHS,
>> RHS);
>> + break;
>> + } // switch (...)
>> +
>> + return std::make_pair(Value, OverflowCmp);
>> +}
>> +
>> +
>> +SDValue
>> +ARMTargetLowering::LowerXALUO(SDValue Op, SelectionDAG &DAG) const {
>> + // Let legalize expand this if it isn't a legal type yet.
>> + if (!DAG.getTargetLoweringInfo().isTypeLegal(Op.getValueType()))
>> + return SDValue();
>> +
>> + SDValue Value, OverflowCmp;
>> + SDValue ARMcc;
>> + std::tie(Value, OverflowCmp) = getARMXALUOOp(Op, DAG, ARMcc);
>> + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
>> + // We use 0 and 1 as false and true values.
>> + SDValue TVal = DAG.getConstant(1, MVT::i32);
>> + SDValue FVal = DAG.getConstant(0, MVT::i32);
>> + EVT VT = Op.getValueType();
>> +
>> + SDValue Overflow = DAG.getNode(ARMISD::CMOV, SDLoc(Op), VT, TVal, FVal,
>> + ARMcc, CCR, OverflowCmp);
>> +
>> + SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i32);
>> + return DAG.getNode(ISD::MERGE_VALUES, SDLoc(Op), VTs, Value, Overflow);
>> +}
>> +
>> +
>> SDValue ARMTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG)
>> const {
>> SDValue Cond = Op.getOperand(0);
>> SDValue SelectTrue = Op.getOperand(1);
>> SDValue SelectFalse = Op.getOperand(2);
>> SDLoc dl(Op);
>> + unsigned Opc = Cond.getOpcode();
>> +
>> + if (Cond.getResNo() == 1 &&
>> + (Opc == ISD::SADDO || Opc == ISD::UADDO || Opc == ISD::SSUBO ||
>> + Opc == ISD::USUBO)) {
>> + if (!DAG.getTargetLoweringInfo().isTypeLegal(Cond->getValueType(0)))
>> + return SDValue();
>> +
>> + SDValue Value, OverflowCmp;
>> + SDValue ARMcc;
>> + std::tie(Value, OverflowCmp) = getARMXALUOOp(Cond, DAG, ARMcc);
>> + SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
>> + EVT VT = Op.getValueType();
>> +
>> + return DAG.getNode(ARMISD::CMOV, SDLoc(Op), VT, SelectTrue,
>> SelectFalse,
>> + ARMcc, CCR, OverflowCmp);
>> +
>> + }
>>
>> // Convert:
>> //
>> @@ -6139,6 +6229,11 @@ SDValue ARMTargetLowering::LowerOperatio
>> case ISD::ADDE:
>> case ISD::SUBC:
>> case ISD::SUBE: return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
>> + case ISD::SADDO:
>> + case ISD::UADDO:
>> + case ISD::SSUBO:
>> + case ISD::USUBO:
>> + return LowerXALUO(Op, DAG);
>> case ISD::ATOMIC_LOAD:
>> case ISD::ATOMIC_STORE: return LowerAtomicLoadStore(Op, DAG);
>> case ISD::FSINCOS: return LowerFSINCOS(Op, DAG);
>>
>> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=208435&r1=208434&r2=208435&view=diff
>>
>> ==============================================================================
>> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
>> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Fri May 9 12:02:49 2014
>> @@ -416,6 +416,7 @@ namespace llvm {
>> void addTypeForNEON(MVT VT, MVT PromotedLdStVT, MVT
>> PromotedBitwiseVT);
>> void addDRTypeForNEON(MVT VT);
>> void addQRTypeForNEON(MVT VT);
>> + std::pair<SDValue, SDValue> getARMXALUOOp(SDValue Op, SelectionDAG
>> &DAG, SDValue &ARMcc) const;
>>
>> typedef SmallVector<std::pair<unsigned, SDValue>, 8>
>> RegsToPassVector;
>> void PassF64ArgInRegs(SDLoc dl, SelectionDAG &DAG,
>> @@ -453,6 +454,7 @@ namespace llvm {
>> TLSModel::Model model) const;
>> SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG)
>> const;
>> SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
>> + SDValue LowerXALUO(SDValue Op, SelectionDAG &DAG) const;
>> SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;
>> SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
>> SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
>>
>> Added: llvm/trunk/test/CodeGen/ARM/intrinsics-overflow.ll
>> URL:
>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/intrinsics-overflow.ll?rev=208435&view=auto
>>
>> ==============================================================================
>> --- llvm/trunk/test/CodeGen/ARM/intrinsics-overflow.ll (added)
>> +++ llvm/trunk/test/CodeGen/ARM/intrinsics-overflow.ll Fri May 9
>> 12:02:49 2014
>> @@ -0,0 +1,57 @@
>> +; RUN: llc < %s -march=arm -mcpu=generic | FileCheck %s
>> +
>> +define i32 @uadd_overflow(i32 %a, i32 %b) #0 {
>> + %sadd = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %a, i32
>> %b)
>> + %1 = extractvalue { i32, i1 } %sadd, 1
>> + %2 = zext i1 %1 to i32
>> + ret i32 %2
>> +
>> + ; CHECK-LABEL: uadd_overflow:
>> + ; CHECK: add r[[R2:[0-9]+]], r[[R0:[0-9]+]], r[[R1:[0-9]+]]
>> + ; CHECK: mov r[[R1]], #1
>> + ; CHECK: cmp r[[R2]], r[[R0]]
>> + ; CHECK: movhs r[[R1]], #0
>> +}
>> +
>> +
>> +define i32 @sadd_overflow(i32 %a, i32 %b) #0 {
>> + %sadd = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %a, i32
>> %b)
>> + %1 = extractvalue { i32, i1 } %sadd, 1
>> + %2 = zext i1 %1 to i32
>> + ret i32 %2
>> +
>> + ; CHECK-LABEL: sadd_overflow:
>> + ; CHECK: add r[[R2:[0-9]+]], r[[R0:[0-9]+]], r[[R1:[0-9]+]]
>> + ; CHECK: mov r[[R1]], #1
>> + ; CHECK: cmp r[[R2]], r[[R0]]
>> + ; CHECK: movvc r[[R1]], #0
>> +}
>> +
>> +define i32 @usub_overflow(i32 %a, i32 %b) #0 {
>> + %sadd = tail call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %a, i32
>> %b)
>> + %1 = extractvalue { i32, i1 } %sadd, 1
>> + %2 = zext i1 %1 to i32
>> + ret i32 %2
>> +
>> + ; CHECK-LABEL: usub_overflow:
>> + ; CHECK: mov r[[R2]], #1
>> + ; CHECK: cmp r[[R0]], r[[R1]]
>> + ; CHECK: movhs r[[R2]], #0
>> +}
>> +
>> +define i32 @ssub_overflow(i32 %a, i32 %b) #0 {
>> + %sadd = tail call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %a, i32
>> %b)
>> + %1 = extractvalue { i32, i1 } %sadd, 1
>> + %2 = zext i1 %1 to i32
>> + ret i32 %2
>> +
>> + ; CHECK-LABEL: ssub_overflow:
>> + ; CHECK: mov r[[R2]], #1
>> + ; CHECK: cmp r[[R0]], r[[R1]]
>> + ; CHECK: movvc r[[R2]], #0
>> +}
>> +
>> +declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) #1
>> +declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) #2
>> +declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) #3
>> +declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) #4
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140509/19621d4f/attachment.html>
More information about the llvm-commits
mailing list