[PATCH] Workaround MSVC 32-bit miscompile of getCondCodeAction
Matt Arsenault
Matthew.Arsenault at amd.com
Fri Aug 30 16:49:39 PDT 2013
Use 32-bit types for the array instead of 64. This should
generally be better anyway.
In optimized + assert builds, I saw a failure when a
cond code / type combination that is never set was loading
a non-zero value and hitting the != Promote assert.
It turns out when loading the 64-bit value to do the shift,
the assembly loads the 2 32-bit halves from non-consecutive
addresses. The address the second half of the loaded uint64_t
doesn't include the offset of the array in the struct. Instead of being
offset + 4, it's just + 4.
I'm not entirely sure why this wasn't observed before.
setCondCodeAction isn't heavily used by the in-tree targets,
and not with the higher valued vector SimpleValueTypes. Only
PPC is using one of the > 32 valued types, and that is probably
never used by anyone on a 32-bit MSVC compiled host.
I ran into this when upgrading LLVM versions, so I guess the
value loaded from the nonsense address happened to work out
before.
No test since I'm not really sure if / how it can be reproduced with the
current in tree targets, and it's not supposed to change anything.
Here is the assembly for getCondCodeAction (asserts in the function removed)
plus my debugging notes if somebody wants to check if I'm crazy.
//LegalizeAction
//getCondCodeAction(ISD::CondCode CC, EVT VT) const {
push esi
mov esi,ecx ; Save this
mov ecx,dword ptr [esp+0Ch] ; Load VT.SimpleTy
push edi ; Do the assert that this is a simplety
cmp ecx,0FFh
jle llvm::TargetLowering::getCondCodeAction+2Bh (0ED715Bh)
push 295h
push offset string L"c:\\Users\\marsenau"...
push offset string L"isSimple() &&"...
call _wassert (1544800h)
mov ecx,dword ptr [esp+1Ch]
add esp,0Ch
mov eax,dword ptr [esp+0Ch] ; Load CC, Assert passed jumps here
mov edx,ecx ; Copy SimpleTy
shr edx,5 ; SimpleTy >> 5
and ecx,1Fh ; SimpleTy & 31
lea edx,[edx+eax*2] ; 2 * CC + (SimpleTy >> 5)
add ecx,ecx ; 2 * (SimpleTy & 31)
mov eax,dword ptr [esi+edx*8+3230h] ; load [this + edx * 8 + offsetof CondCodeActions] (0 as expected)
mov edx,dword ptr [esi+edx*8+4] ; load [this + edx * 8 + Not the offset of CondCodeActions] (nonsense value)
; Should add offset + 4, but instead just adds 4
call _aullshr (15467F0h) ; Calling shift with non-consecutive loaded 32-bit parts of 64-bit load
and eax,3
pop esi
ret 0Ch
/*
* unsigned long long
* __aullshr(unsigned long long Value, unsigned char Shift);
*
* Parameters:
* EDX:EAX - unsigned long long value to be shifted right
* CL - number of bits to shift by
* Registers:
* Destroys CL
* Returns:
* EDX:EAX - shifted value
*/
http://llvm-reviews.chandlerc.com/D1568
Files:
include/llvm/Target/TargetLowering.h
Index: include/llvm/Target/TargetLowering.h
===================================================================
--- include/llvm/Target/TargetLowering.h
+++ include/llvm/Target/TargetLowering.h
@@ -520,13 +520,12 @@
LegalizeAction
getCondCodeAction(ISD::CondCode CC, MVT VT) const {
assert((unsigned)CC < array_lengthof(CondCodeActions) &&
- (unsigned)VT.SimpleTy < sizeof(CondCodeActions[0])*4 &&
+ ((unsigned)VT.SimpleTy >> 4) < array_lengthof(CondCodeActions[0]) &&
"Table isn't big enough!");
- /// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 64bit
- /// value and the upper 27 bits index into the second dimension of the
- /// array to select what 64bit value to use.
- LegalizeAction Action = (LegalizeAction)
- ((CondCodeActions[CC][VT.SimpleTy >> 5] >> (2*(VT.SimpleTy & 0x1F))) & 3);
+ // See setCondCodeAction for how this is encoded.
+ uint32_t Shift = 2 * (VT.SimpleTy & 0xF);
+ uint32_t Value = CondCodeActions[CC][VT.SimpleTy >> 4];
+ LegalizeAction Action = (LegalizeAction) ((Value >> Shift) & 0x3);
assert(Action != Promote && "Can't promote condition code!");
return Action;
}
@@ -1016,13 +1015,12 @@
assert(VT < MVT::LAST_VALUETYPE &&
(unsigned)CC < array_lengthof(CondCodeActions) &&
"Table isn't big enough!");
- /// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 64bit
- /// value and the upper 27 bits index into the second dimension of the
- /// array to select what 64bit value to use.
- CondCodeActions[(unsigned)CC][VT.SimpleTy >> 5]
- &= ~(uint64_t(3UL) << (VT.SimpleTy & 0x1F)*2);
- CondCodeActions[(unsigned)CC][VT.SimpleTy >> 5]
- |= (uint64_t)Action << (VT.SimpleTy & 0x1F)*2;
+ /// The lower 5 bits of the SimpleTy index into Nth 2bit set from the 32-bit
+ /// value and the upper 27 bits index into the second dimension of the array
+ /// to select what 32-bit value to use.
+ uint32_t Shift = 2 * (VT.SimpleTy & 0xF);
+ CondCodeActions[CC][VT.SimpleTy >> 4] &= ~((uint32_t)0x3 << Shift);
+ CondCodeActions[CC][VT.SimpleTy >> 4] |= (uint32_t)Action << Shift;
}
/// If Opc/OrigVT is specified as being promoted, the promotion code defaults
@@ -1417,8 +1415,8 @@
///
/// Because each CC action takes up 2 bits, we need to have the array size be
/// large enough to fit all of the value types. This can be done by dividing
- /// the MVT::LAST_VALUETYPE by 32 and adding one.
- uint64_t CondCodeActions[ISD::SETCC_INVALID][(MVT::LAST_VALUETYPE / 32) + 1];
+ /// the MVT::LAST_VALUETYPE by 16 and adding one.
+ uint32_t CondCodeActions[ISD::SETCC_INVALID][(MVT::LAST_VALUETYPE / 16) + 1];
ValueTypeActionImpl ValueTypeActions;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1568.1.patch
Type: text/x-patch
Size: 2783 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130830/2c6a226e/attachment.bin>
More information about the llvm-commits
mailing list