}
-static bool generateSignBits(Value *V) {
+static bool GenerateSignBits(Value *V) {
+ if (auto *Arg = dyn_cast<Argument>(V))
+ return Arg->hasSExtAttr();
+
if (!isa<Instruction>(V))
return false;
unsigned Opc = cast<Instruction>(V)->getOpcode();
return Opc == Instruction::AShr || Opc == Instruction::SDiv ||
- Opc == Instruction::SRem;
+ Opc == Instruction::SRem || Opc == Instruction::SExt ||
+ Opc == Instruction::SIToFP;
}
static bool EqualTypeSize(Value *V) {
if (!isa<Instruction>(V))
return true;
- if (generateSignBits(V))
+ if (GenerateSignBits(V))
return false;
return !isa<OverflowingBinaryOperator>(V);
return EqualTypeSize(I->getOperand(0));
}
+ if (GenerateSignBits(V)) {
+ LLVM_DEBUG(dbgs() << "ARM CGP: No, instruction can generate sign bits.\n");
+ return false;
+ }
+
// Memory instructions
if (isa<StoreInst>(V) || isa<GetElementPtrInst>(V))
return true;
isa<LoadInst>(V))
return isSupportedType(V);
- if (isa<SExtInst>(V))
- return false;
-
if (auto *Cast = dyn_cast<CastInst>(V))
return isSupportedType(Cast) || isSupportedType(Cast->getOperand(0));
if (!isSupportedType(V))
return false;
- if (generateSignBits(V)) {
- LLVM_DEBUG(dbgs() << "ARM CGP: No, instruction can generate sign bits.\n");
- return false;
- }
return true;
}
; RUN: llc -mtriple=thumbv8.main -mcpu=cortex-m33 %s -arm-disable-cgp=false -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NODSP
; RUN: llc -mtriple=thumbv7-linux-android %s -arm-disable-cgp=false -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NODSP
-; RUN: llc -mtriple=thumbv7em %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DSP
+; RUN: llc -mtriple=thumbv7em -mcpu=cortex-m7 %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DSP
; RUN: llc -mtriple=thumbv8 %s -arm-disable-cgp=false -arm-enable-scalar-dsp=true -arm-enable-scalar-dsp-imms=true -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-DSP-IMM
; Transform will fail because the trunc is not a sink.
%cond = phi i32 [ %phitmp, %cond.false ], [ 0, %entry ]
ret i32 %cond
}
+
+; CHECK-LABEL: test_i8_sitofp
+; CHECK: uxtb [[UXT:r[0-9]+]], r1
+; CHECK: sxtb [[SXT:r[0-9]+]], r1
+; CHECK: vmov [[VMOV:s[0-9]+]], [[SXT]]
+; CHECK: vcvt.f32.s32 [[CVT:s[0-9]+]], [[VMOV]]
+define float @test_i8_sitofp(i8* %ptr, i8 %arg) {
+entry:
+ %0 = load i8, i8* %ptr, align 1
+ %cmp = icmp eq i8 %0, %arg
+ br i1 %cmp, label %exit, label %if.end
+
+if.end:
+ %conv = sitofp i8 %arg to float
+ %div = fdiv float %conv, 2.000000e+01
+ br label %exit
+
+exit:
+ %res = phi float [ 0.0, %entry ], [ %div, %if.end ]
+ ret float %res
+}
+
+; CHECK-LABEL: test_i16_sitofp
+; CHECK: uxth [[UXT:r[0-9]+]], r1
+; CHECK: sxth [[SXT:r[0-9]+]], r1
+; CHECK: vmov [[VMOV:s[0-9]+]], [[SXT]]
+; CHECK: vcvt.f32.s32 [[CVT:s[0-9]+]], [[VMOV]]
+define float @test_i16_sitofp(i16* %ptr, i16 %arg) {
+entry:
+ %0 = load i16, i16* %ptr, align 1
+ %cmp = icmp eq i16 %0, %arg
+ br i1 %cmp, label %exit, label %if.end
+
+if.end:
+ %conv = sitofp i16 %arg to float
+ %div = fdiv float %conv, 2.000000e+01
+ br label %exit
+
+exit:
+ %res = phi float [ 0.0, %entry ], [ %div, %if.end ]
+ ret float %res
+}
ret i16 %conv
}
+; CHECK-LABEL: test_signext_b
+; CHECK: ldrb [[LDR:r[0-9]+]], [r0]
+; CHECK: sxtb [[SXT:r[0-9]+]], [[LDR]]
+; CHECK: cm{{.*}} [[SXT]]
+define i32 @test_signext_b(i8* %ptr, i8 signext %arg) {
+entry:
+ %0 = load i8, i8* %ptr, align 1
+ %1 = add nuw nsw i8 %0, %arg
+ %cmp = icmp ult i8 %1, 128
+ %res = select i1 %cmp, i32 42, i32 20894
+ ret i32 %res
+}
+
+; CHECK-LABEL: test_signext_h
+; CHECK: ldrh [[LDR:r[0-9]+]], [r0]
+; CHECK: sxth [[SXT:r[0-9]+]], [[LDR]]
+; CHECK: cm{{.*}} [[SXT]]
+define i32 @test_signext_h(i16* %ptr, i16 signext %arg) {
+entry:
+ %0 = load i16, i16* %ptr, align 1
+ %1 = add nuw nsw i16 %0, %arg
+ %cmp = icmp ult i16 %1, 32768
+ %res = select i1 %cmp, i32 42, i32 20894
+ ret i32 %res
+}