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