aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp11
-rw-r--r--test/NaCl/X86/nacl64-addrmodes.ll55
2 files changed, 62 insertions, 4 deletions
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index f4a9ca38d2..6bef55c2b0 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -608,11 +608,14 @@ bool X86DAGToDAGISel::FoldOffsetIntoAddress(uint64_t Offset,
!isDispSafeForFrameIndex(Val))
return true;
// LOCALMOD-BEGIN
- // Do not allow negative displacements to be folded into memory operations.
- // This results in trying to dereference a negative offset from RZP
+ // Do not fold large offsets into displacements.
+ // Various constant folding and address-mode selections can result in
+ // 32-bit operations (e.g. from GEP) getting folded into the displacement
+ // and often results in a negative value in the index register
+ // (see also LegalizeAddressModeForNaCl)
else if (Subtarget->isTargetNaCl64() &&
- AM.BaseType == X86ISelAddressMode::RegBase && Val < 0 &&
- selectingMemOp)
+ AM.BaseType == X86ISelAddressMode::RegBase &&
+ (Val > 65535 || Val < -65536) && selectingMemOp)
return true;
// LOCALMOD-END
}
diff --git a/test/NaCl/X86/nacl64-addrmodes.ll b/test/NaCl/X86/nacl64-addrmodes.ll
index 772424b154..c4dc359bdb 100644
--- a/test/NaCl/X86/nacl64-addrmodes.ll
+++ b/test/NaCl/X86/nacl64-addrmodes.ll
@@ -12,3 +12,58 @@ define i16 @negativedisp(i32 %b) {
%c = load i16* %arrayidx, align 2
ret i16 %c
}
+
+@main.m2 = internal constant [1 x [1 x i32]] [[1 x i32] [i32 -60417067]], align 4
+define i1 @largeconst() nounwind {
+; CHECK: largeconst
+entry:
+ %retval = alloca i32, align 4
+ %i = alloca i32, align 4
+ %j = alloca i32, align 4
+ %madat = alloca i32*, align 4
+ store i32 0, i32* %retval
+ store i32 -270770481, i32* %i, align 4
+ store i32 -1912319477, i32* %j, align 4
+ %0 = load i32* %j, align 4
+ %mul = mul nsw i32 %0, 233468377
+ %add = add nsw i32 %mul, 689019309
+ %1 = load i32* %i, align 4
+ %mul1 = mul nsw i32 %1, 947877507
+ %add2 = add nsw i32 %mul1, 1574375955
+ %arrayidx = getelementptr inbounds [1 x i32]* getelementptr inbounds ([1 x [1 x i32]]* @main.m2, i32 0, i32 0), i32 %add2
+ %2 = bitcast [1 x i32]* %arrayidx to i32*
+ %arrayidx3 = getelementptr inbounds i32* %2, i32 %add
+ store i32* %arrayidx3, i32** %madat, align 4
+; Ensure the large constant doesn't get folded into the load
+; CHECK: nacl:(%r15
+ %3 = load i32** %madat, align 4
+ %4 = load i32* %3, align 4
+ %conv = zext i32 %4 to i64
+ %5 = load i32* %j, align 4
+ %mul4 = mul nsw i32 %5, 233468377
+ %add5 = add nsw i32 %mul4, 689019309
+ %6 = load i32* %i, align 4
+ %mul6 = mul nsw i32 %6, 947877507
+ %add7 = add nsw i32 %mul6, 1574375955
+ %arrayidx8 = getelementptr inbounds [1 x i32]* getelementptr inbounds ([1 x [1 x i32]]* @main.m2, i32 0, i32 0), i32 %add7
+ %7 = bitcast [1 x i32]* %arrayidx8 to i32*
+ %arrayidx9 = getelementptr inbounds i32* %7, i32 %add5
+; Ensure the large constant doesn't get folded into the load
+; CHECK: nacl:(%r15
+ %8 = load i32* %arrayidx9, align 4
+ %conv10 = zext i32 %8 to i64
+ %mul11 = mul nsw i64 3795428823, %conv10
+ %9 = load i32* %j, align 4
+ %mul12 = mul nsw i32 %9, 233468377
+ %add13 = add nsw i32 %mul12, 689019309
+ %conv14 = sext i32 %add13 to i64
+ %rem = srem i64 %conv14, 4294967295
+ %xor = xor i64 2597389499, %rem
+ %mul15 = mul nsw i64 %xor, 3795428823
+ %sub = sub nsw i64 %mul11, %mul15
+ %add16 = add nsw i64 %sub, 3829710203
+ %mul17 = mul nsw i64 %add16, 2824337475
+ %add18 = add nsw i64 %mul17, 2376483023
+ %cmp = icmp eq i64 %conv, %add18
+ ret i1 %cmp
+}