OSDN Git Service

Preserve the order of READ_REGISTER and WRITE_REGISTER
authorHal Finkel <hfinkel@anl.gov>
Mon, 18 May 2015 16:42:10 +0000 (16:42 +0000)
committerHal Finkel <hfinkel@anl.gov>
Mon, 18 May 2015 16:42:10 +0000 (16:42 +0000)
At the present time, we don't have a way to represent general dependency
relationships, so everything is represented using memory dependency. In order
to preserve the data dependency of a READ_REGISTER on WRITE_REGISTER, we need
to model WRITE_REGISTER as writing (which we had been doing) and model
READ_REGISTER as reading (which we had not been doing). Fix this, and also the
way that the chain operands were generated at the SDAG level.

Patch by Nicholas Paul Johnson, thanks! Test case by me.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237584 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Intrinsics.td
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
test/Transforms/EarlyCSE/read-reg.ll [new file with mode: 0644]

index 1442b64..6d98e69 100644 (file)
@@ -266,7 +266,7 @@ def int_framerecover : Intrinsic<[llvm_ptr_ty],
                                  [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty],
                                  [IntrNoMem]>;
 def int_read_register  : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty],
-                                   [IntrNoMem], "llvm.read_register">;
+                                   [IntrReadMem], "llvm.read_register">;
 def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty],
                                    [], "llvm.write_register">;
 
index 3c5d32f..48bf226 100644 (file)
@@ -4045,16 +4045,20 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
     return nullptr;
   case Intrinsic::read_register: {
     Value *Reg = I.getArgOperand(0);
+    SDValue Chain = getRoot();
     SDValue RegName =
         DAG.getMDNode(cast<MDNode>(cast<MetadataAsValue>(Reg)->getMetadata()));
     EVT VT = TLI.getValueType(I.getType());
-    setValue(&I, DAG.getNode(ISD::READ_REGISTER, sdl, VT, RegName));
+    Res = DAG.getNode(ISD::READ_REGISTER, sdl,
+      DAG.getVTList(VT, MVT::Other), Chain, RegName);
+    setValue(&I, Res);
+    DAG.setRoot(Res.getValue(1));
     return nullptr;
   }
   case Intrinsic::write_register: {
     Value *Reg = I.getArgOperand(0);
     Value *RegValue = I.getArgOperand(1);
-    SDValue Chain = getValue(RegValue).getOperand(0);
+    SDValue Chain = getRoot();
     SDValue RegName =
         DAG.getMDNode(cast<MDNode>(cast<MetadataAsValue>(Reg)->getMetadata()));
     DAG.setRoot(DAG.getNode(ISD::WRITE_REGISTER, sdl, MVT::Other, Chain,
index 175434e..22f592a 100644 (file)
@@ -1926,12 +1926,12 @@ SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) {
 SDNode
 *SelectionDAGISel::Select_READ_REGISTER(SDNode *Op) {
   SDLoc dl(Op);
-  MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(Op->getOperand(0));
+  MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(Op->getOperand(1));
   const MDString *RegStr = dyn_cast<MDString>(MD->getMD()->getOperand(0));
   unsigned Reg =
       TLI->getRegisterByName(RegStr->getString().data(), Op->getValueType(0));
   SDValue New = CurDAG->getCopyFromReg(
-                        CurDAG->getEntryNode(), dl, Reg, Op->getValueType(0));
+                        Op->getOperand(0), dl, Reg, Op->getValueType(0));
   New->setNodeId(-1);
   return New.getNode();
 }
@@ -1944,7 +1944,7 @@ SDNode
   unsigned Reg = TLI->getRegisterByName(RegStr->getString().data(),
                                         Op->getOperand(2).getValueType());
   SDValue New = CurDAG->getCopyToReg(
-                        CurDAG->getEntryNode(), dl, Reg, Op->getOperand(2));
+                        Op->getOperand(0), dl, Reg, Op->getOperand(2));
   New->setNodeId(-1);
   return New.getNode();
 }
diff --git a/test/Transforms/EarlyCSE/read-reg.ll b/test/Transforms/EarlyCSE/read-reg.ll
new file mode 100644 (file)
index 0000000..83a2999
--- /dev/null
@@ -0,0 +1,34 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+target datalayout = "E-m:e-i64:64-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+; Function Attrs: nounwind
+define i64 @f(i64 %x) #0 {
+entry:
+  %0 = call i64 @llvm.read_register.i64(metadata !0)
+  call void bitcast (void (...)* @foo to void ()*)()
+  %1 = call i64 @llvm.read_register.i64(metadata !0)
+  %add = add nsw i64 %0, %1
+  ret i64 %add
+}
+
+; CHECK-LABEL: @f
+; CHECK: call i64 @llvm.read_register.i64
+; CHECK: call i64 @llvm.read_register.i64
+
+; Function Attrs: nounwind readnone
+declare i64 @llvm.read_register.i64(metadata) #1
+
+; Function Attrs: nounwind
+declare void @llvm.write_register.i64(metadata, i64) #2
+
+declare void @foo(...)
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readnone }
+attributes #2 = { nounwind }
+
+!llvm.named.register.r1 = !{!0}
+
+!0 = !{!"r1"}
+