Fix sign extension for MIPS64 in makeLibCall function
authorPetar Jovanovic <petar.jovanovic@imgtec.com>
Mon, 23 Mar 2015 12:28:13 +0000 (12:28 +0000)
committerPetar Jovanovic <petar.jovanovic@imgtec.com>
Mon, 23 Mar 2015 12:28:13 +0000 (12:28 +0000)
Fixing sign extension in makeLibCall for MIPS64. In MIPS64 architecture all
32 bit arguments (int, unsigned int, float 32 (soft float)) must be sign
extended. This fixes test "MultiSource/Applications/oggenc/".

Patch by Strahinja Petrovic.

Differential Revision: http://reviews.llvm.org/D7791

llvm-svn: 232943

llvm/include/llvm/Target/TargetLowering.h
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
llvm/lib/Target/Mips/MipsISelLowering.cpp
llvm/lib/Target/Mips/MipsISelLowering.h
llvm/test/CodeGen/Mips/mips64-f128.ll
llvm/test/CodeGen/Mips/mips64signextendsesf.ll [new file with mode: 0644]

index fa827a1..dd23d8c 100644 (file)
@@ -1080,6 +1080,11 @@ public:
     return false;
   }
 
+  /// Returns true if arguments should be sign-extended in lib calls.
+  virtual bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const {
+    return IsSigned;
+ }
+
   /// Returns true if the given (atomic) load should be expanded by the
   /// IR-level AtomicExpand pass into a load-linked instruction
   /// (through emitLoadLinked()).
index 0a3c926..c382fe0 100644 (file)
@@ -96,18 +96,19 @@ TargetLowering::makeLibCall(SelectionDAG &DAG,
   for (unsigned i = 0; i != NumOps; ++i) {
     Entry.Node = Ops[i];
     Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext());
-    Entry.isSExt = isSigned;
-    Entry.isZExt = !isSigned;
+    Entry.isSExt = shouldSignExtendTypeInLibCall(Ops[i].getValueType(), isSigned);
+    Entry.isZExt = !shouldSignExtendTypeInLibCall(Ops[i].getValueType(), isSigned);
     Args.push_back(Entry);
   }
   SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC), getPointerTy());
 
   Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext());
   TargetLowering::CallLoweringInfo CLI(DAG);
+  bool signExtend = shouldSignExtendTypeInLibCall(RetVT, isSigned);
   CLI.setDebugLoc(dl).setChain(DAG.getEntryNode())
     .setCallee(getLibcallCallingConv(LC), RetTy, Callee, std::move(Args), 0)
     .setNoReturn(doesNotReturn).setDiscardResult(!isReturnValueUsed)
-    .setSExtResult(isSigned).setZExtResult(!isSigned);
+    .setSExtResult(signExtend).setZExtResult(!signExtend);
   return LowerCallTo(CLI);
 }
 
index f7a7baa..2eebd76 100644 (file)
@@ -3032,6 +3032,15 @@ MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv,
   return CCInfo.CheckReturn(Outs, RetCC_Mips);
 }
 
+bool
+MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const {
+  if (Subtarget.hasMips3() && Subtarget.abiUsesSoftFloat()) {
+    if (Type == MVT::i32)
+      return true;
+  }
+  return IsSigned;
+}
+
 SDValue
 MipsTargetLowering::LowerReturn(SDValue Chain,
                                 CallingConv::ID CallConv, bool IsVarArg,
index 748b1ad..02efba8 100644 (file)
@@ -475,6 +475,8 @@ namespace llvm {
                         const SmallVectorImpl<SDValue> &OutVals,
                         SDLoc dl, SelectionDAG &DAG) const override;
 
+    bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override;
+
     // Inline asm support
     ConstraintType
       getConstraintType(const std::string &Constraint) const override;
index 9dd41e3..0217c7c 100644 (file)
@@ -545,7 +545,7 @@ entry:
 
 ; ALL-LABEL: load_LD_float:
 ; ALL: ld   $[[R0:[0-9]+]], %got_disp(gf1)
-; ALL: lwu  $4, 0($[[R0]])
+; ALL: lw   $4, 0($[[R0]])
 ; ALL: ld   $25, %call16(__extendsftf2)
 ; ALL: jalr $25
 
diff --git a/llvm/test/CodeGen/Mips/mips64signextendsesf.ll b/llvm/test/CodeGen/Mips/mips64signextendsesf.ll
new file mode 100644 (file)
index 0000000..a76388d
--- /dev/null
@@ -0,0 +1,214 @@
+; RUN: llc -march=mips64 -mcpu=mips64r2 -soft-float -O2 < %s | FileCheck %s
+
+define void @foosf() #0 {
+entry:
+  %in = alloca float, align 4
+  %out = alloca float, align 4
+  store volatile float 0xBFD59E1380000000, float* %in, align 4
+  %in.0.in.0. = load volatile float, float* %in, align 4
+  %rintf = tail call float @rintf(float %in.0.in.0.) #1
+  store volatile float %rintf, float* %out, align 4
+  ret void
+
+; CHECK-LABEL:      foosf
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare float @rintf(float)
+
+define float @foosf1(float* nocapture readonly %a) #0 {
+entry:
+  %0 = load float, float* %a, align 4
+  %call = tail call float @roundf(float %0) #2
+  ret float %call
+
+; CHECK-LABEL:      foosf1
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare float @roundf(float) #1
+
+define float @foosf2(float* nocapture readonly %a) #0 {
+entry:
+  %0 = load float, float* %a, align 4
+  %call = tail call float @truncf(float %0) #2
+  ret float %call
+
+; CHECK-LABEL:      foosf2
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare float @truncf(float) #1
+
+define float @foosf3(float* nocapture readonly %a) #0 {
+entry:
+  %0 = load float, float* %a, align 4
+  %call = tail call float @floorf(float %0) #2
+  ret float %call
+
+; CHECK-LABEL:      foosf3
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare float @floorf(float) #1
+
+define float @foosf4(float* nocapture readonly %a) #0 {
+entry:
+  %0 = load float, float* %a, align 4
+  %call = tail call float @nearbyintf(float %0) #2
+  ret float %call
+
+; CHECK-LABEL:      foosf4
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare float @nearbyintf(float) #1
+
+define float @foosf5(float* nocapture readonly %a) #0 {
+entry:
+  %0 = load float, float* %a, align 4
+  %mul = fmul float %0, undef
+  ret float %mul
+
+; CHECK-LABEL:      foosf5
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+define float @foosf6(float* nocapture readonly %a) #0 {
+entry:
+  %0 = load float, float* %a, align 4
+  %sub = fsub float %0, undef
+  ret float %sub
+
+; CHECK-LABEL:      foosf6
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+define float @foosf7(float* nocapture readonly %a) #0 {
+entry:
+  %0 = load float, float* %a, align 4
+  %add = fadd float %0, undef
+  ret float %add
+
+; CHECK-LABEL:      foosf7
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+define float @foosf8(float* nocapture readonly %a) #0 {
+entry:
+  %b = alloca float, align 4
+  %b.0.b.0. = load volatile float, float* %b, align 4
+  %0 = load float, float* %a, align 4
+  %div = fdiv float %b.0.b.0., %0
+  ret float %div
+
+; CHECK-LABEL:      foosf8
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+define float @foosf9() #0 {
+entry:
+  %b = alloca float, align 4
+  %b.0.b.0. = load volatile float, float* %b, align 4
+  %conv = fpext float %b.0.b.0. to double
+  %b.0.b.0.3 = load volatile float, float* %b, align 4
+  %conv1 = fpext float %b.0.b.0.3 to double
+  %call = tail call double @pow(double %conv, double %conv1) #1
+  %conv2 = fptrunc double %call to float
+  ret float %conv2
+
+; CHECK-LABEL:      foosf9
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare double @pow(double, double) #0
+
+define float @foosf10() #0 {
+entry:
+  %a = alloca float, align 4
+  %a.0.a.0. = load volatile float, float* %a, align 4
+  %conv = fpext float %a.0.a.0. to double
+  %call = tail call double @sin(double %conv) #1
+  %conv1 = fptrunc double %call to float
+  ret float %conv1
+
+; CHECK-LABEL:      foosf10
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare double @sin(double) #0
+
+define float @foosf11() #0 {
+entry:
+  %b = alloca float, align 4
+  %b.0.b.0. = load volatile float, float* %b, align 4
+  %call = tail call float @ceilf(float %b.0.b.0.) #2
+  ret float %call
+
+; CHECK-LABEL:      foosf11
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare float @ceilf(float) #1
+
+define float @foosf12() #0 {
+entry:
+  %b = alloca float, align 4
+  %a = alloca float, align 4
+  %b.0.b.0. = load volatile float, float* %b, align 4
+  %a.0.a.0. = load volatile float, float* %a, align 4
+  %call = tail call float @fmaxf(float %b.0.b.0., float %a.0.a.0.) #2
+  ret float %call
+
+; CHECK-LABEL:      foosf12
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare float @fmaxf(float, float) #1
+
+define float @foosf13() #0 {
+entry:
+  %b = alloca float, align 4
+  %a = alloca float, align 4
+  %b.0.b.0. = load volatile float, float* %b, align 4
+  %a.0.a.0. = load volatile float, float* %a, align 4
+  %call = tail call float @fminf(float %b.0.b.0., float %a.0.a.0.) #2
+  ret float %call
+
+; CHECK-LABEL:      foosf13
+; CHECK-NOT:        dsll
+; CHECK-NOT:        dsrl
+; CHECK-NOT:        lwu
+}
+
+declare float @fminf(float, float) #1
+
+
+attributes #0 = { nounwind "use-soft-float"="true" }
+attributes #1 = { nounwind readnone "use-soft-float"="true" }
\ No newline at end of file