summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@google.com>2016-02-16 18:18:36 +0000
committerDerek Schuff <dschuff@google.com>2016-02-16 18:18:36 +0000
commitaadc89c25d664d8c52b7a96b1db1d581cd435358 (patch)
tree1bcfd5585267ea813c4d88d9ef15b04dbb5d5659
parentcc4c8718ed09b783a03f93500b96aea41f8273b4 (diff)
downloadbcm5719-llvm-aadc89c25d664d8c52b7a96b1db1d581cd435358.tar.gz
bcm5719-llvm-aadc89c25d664d8c52b7a96b1db1d581cd435358.zip
[WebAssembly] Insert COPY_LOCAL between CopyToReg and FrameIndex DAG nodes
CopyToReg nodes don't support FrameIndex operands. Other targets select the FI to some LEA-like instruction, but since we don't have that, we need to insert some kind of instruction that can take an FI operand and produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy copy_local between Op and its FI operand. This results in a redundant copy which we should optimize away later (maybe in the post-FI-lowering peephole pass). Differential Revision: http://reviews.llvm.org/D17213 llvm-svn: 260987
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp26
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h1
-rw-r--r--llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt31
-rw-r--r--llvm/test/CodeGen/WebAssembly/userstack.ll21
4 files changed, 55 insertions, 24 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 436494efd23..2027e8ba678 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -114,6 +114,7 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);
setOperationAction(ISD::FrameIndex, MVT::i32, Custom);
+ setOperationAction(ISD::CopyToReg, MVT::Other, Custom);
// Expand these forms; we pattern-match the forms that we can handle in isel.
for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
@@ -544,9 +545,34 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
case ISD::FRAMEADDR: // TODO: Make this return the userspace frame address
fail(DL, DAG, "WebAssembly hasn't implemented __builtin_frame_address");
return SDValue();
+ case ISD::CopyToReg:
+ return LowerCopyToReg(Op, DAG);
}
}
+SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDValue Src = Op.getOperand(2);
+ if (isa<FrameIndexSDNode>(Src.getNode())) {
+ // CopyToReg nodes don't support FrameIndex operands. Other targets select
+ // the FI to some LEA-like instruction, but since we don't have that, we
+ // need to insert some kind of instruction that can take an FI operand and
+ // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
+ // copy_local between Op and its FI operand.
+ SDLoc DL(Op);
+ EVT VT = Src.getValueType();
+ SDValue Copy(
+ DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_LOCAL_I32
+ : WebAssembly::COPY_LOCAL_I64,
+ DL, VT, Src),
+ 0);
+ return DAG.getCopyToReg(Op.getOperand(0), DL,
+ cast<RegisterSDNode>(Op.getOperand(1))->getReg(),
+ Copy);
+ }
+ return SDValue();
+}
+
SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
SelectionDAG &DAG) const {
int FI = cast<FrameIndexSDNode>(Op)->getIndex();
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
index a2fbfeadeb8..4aed2b1ec82 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
@@ -83,6 +83,7 @@ class WebAssemblyTargetLowering final : public TargetLowering {
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerCopyToReg(SDValue Op, SelectionDAG &DAG) const;
};
namespace WebAssembly {
diff --git a/llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt b/llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt
index 108ba6a8f3a..480c2c920d5 100644
--- a/llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt
+++ b/llvm/lib/Target/WebAssembly/known_gcc_test_failures.txt
@@ -1,32 +1,9 @@
# Tests which are known to fail from the GCC torture test suite.
-# InstrEmitter.cpp:302: unsigned int llvm::InstrEmitter::getVR(llvm::SDValue, DenseMap<llvm::SDValue, unsigned int> &): Assertion `I != VRBaseMap.end() && "Node emitted out of order - late"' failed.
-20000801-2.c
-20000815-1.c
-20011126-2.c
-20030916-1.c
-20050826-2.c
-20090113-1.c
-920501-6.c
-930518-1.c
-980707-1.c
-990127-1.c
-loop-15.c
-loop-ivopts-2.c
-pr20466-1.c
-pr28778.c
-pr33870-1.c
-pr33870.c
-pr38051.c
-pr39100.c
-pr49390.c
-pr53645-2.c
-pr53645.c
-pr59643.c
-
# WebAssemblyCFGStackify.cpp:458: void PlaceMarkers(llvm::MachineFunction &, const llvm::MachineLoopInfo &, const llvm::WebAssemblyInstrInfo &, llvm::MachineDominatorTree &, llvm::WebAssemblyFunctionInfo &): Assertion `Stack.back() == &MBB && "Loop top should be balanced"' failed.
20090113-2.c
20090113-3.c
+loop-15.c
930628-1.c
@@ -53,6 +30,12 @@ pr38151.c
# include/llvm/CodeGen/SelectionDAGNodes.h:800: llvm::SDNode::SDNode(unsigned int, unsigned int, llvm::DebugLoc, llvm::SDVTList, ArrayRef<llvm::SDValue>): Assertion `NumOperands == Ops.size() && "NumOperands wasn't wide enough for its operands!"' failed.
pr28982b.c
+# SelectionDAGNodes.h:943: llvm::SDValue::SDValue(llvm::SDNode *, unsigned int): Assertion `(!Node || ResNo < Node->getNumValues()) && "Invalid result number for the given node!"' failed.
+pr53645.c
+pr53645-2.c
+
+# multiple-entry loops are not supported yet.
+pr38051.c
# Computed gotos are not supported (Cannot select BlockAddress/BRIND)
20040302-1.c
diff --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll
index 435e1dd0b84..b5e711f6efb 100644
--- a/llvm/test/CodeGen/WebAssembly/userstack.ll
+++ b/llvm/test/CodeGen/WebAssembly/userstack.ll
@@ -160,4 +160,25 @@ define void @dynamic_static_alloca(i32 %alloc) {
ret void
}
+; The use of the alloca in a phi causes a CopyToReg DAG node to be generated,
+; which has to have special handling because CopyToReg can't have a FI operand
+; CHECK-LABEL: copytoreg_fi:
+define void @copytoreg_fi(i1 %cond, i32* %b) {
+entry:
+ ; CHECK: i32.const [[L2:.+]]=, 16
+ ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, [[L2]]
+ %addr = alloca i32
+ ; CHECK: i32.const [[OFF:.+]]=, 12
+ ; CHECK-NEXT: i32.add [[ADDR:.+]]=, [[SP]], [[OFF]]
+ ; CHECK-NEXT: copy_local [[COPY:.+]]=, [[ADDR]]
+ br label %body
+body:
+ %a = phi i32* [%addr, %entry], [%b, %body]
+ store i32 1, i32* %a
+ ; CHECK: i32.store {{.*}}, 0([[COPY]]),
+ br i1 %cond, label %body, label %exit
+exit:
+ ret void
+}
+
; TODO: test over-aligned alloca
OpenPOWER on IntegriCloud