forked from OSchip/llvm-project
Fix PR4152: asm constraint validation happens before dag combine, so we
need to work a bit to combine things like (x+c1+c2) into x+c3. llvm-svn: 71232
This commit is contained in:
parent
0267955467
commit
f1d9b91434
|
@ -8519,40 +8519,39 @@ void X86TargetLowering::LowerAsmOperandForConstraint(SDValue Op,
|
|||
|
||||
// If we are in non-pic codegen mode, we allow the address of a global (with
|
||||
// an optional displacement) to be used with 'i'.
|
||||
GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
|
||||
GlobalAddressSDNode *GA = 0;
|
||||
int64_t Offset = 0;
|
||||
|
||||
// Match either (GA) or (GA+C)
|
||||
if (GA) {
|
||||
Offset = GA->getOffset();
|
||||
} else if (Op.getOpcode() == ISD::ADD) {
|
||||
ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
|
||||
GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0));
|
||||
if (C && GA) {
|
||||
Offset = GA->getOffset()+C->getZExtValue();
|
||||
} else {
|
||||
C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
|
||||
GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0));
|
||||
if (C && GA)
|
||||
Offset = GA->getOffset()+C->getZExtValue();
|
||||
else
|
||||
C = 0, GA = 0;
|
||||
// Match either (GA), (GA+C), (GA+C1+C2), etc.
|
||||
while (1) {
|
||||
if ((GA = dyn_cast<GlobalAddressSDNode>(Op))) {
|
||||
Offset += GA->getOffset();
|
||||
break;
|
||||
} else if (Op.getOpcode() == ISD::ADD) {
|
||||
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
||||
Offset += C->getZExtValue();
|
||||
Op = Op.getOperand(0);
|
||||
continue;
|
||||
}
|
||||
} else if (Op.getOpcode() == ISD::SUB) {
|
||||
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
|
||||
Offset += -C->getZExtValue();
|
||||
Op = Op.getOperand(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, this isn't something we can handle, reject it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (GA) {
|
||||
if (hasMemory)
|
||||
Op = LowerGlobalAddress(GA->getGlobal(), Op.getDebugLoc(),
|
||||
Offset, DAG);
|
||||
else
|
||||
Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0),
|
||||
Offset);
|
||||
Result = Op;
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, not valid for this mode.
|
||||
return;
|
||||
if (hasMemory)
|
||||
Op = LowerGlobalAddress(GA->getGlobal(), Op.getDebugLoc(), Offset, DAG);
|
||||
else
|
||||
Op = DAG.getTargetGlobalAddress(GA->getGlobal(), GA->getValueType(0),
|
||||
Offset);
|
||||
Result = Op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
; RUN: llvm-as < %s | llc -relocation-model=static > %t
|
||||
; RUN: grep "1: ._pv_cpu_ops+8" %t
|
||||
; RUN: grep "2: ._G" %t
|
||||
; PR4152
|
||||
|
||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||
target triple = "i386-apple-darwin9.6"
|
||||
%struct.pv_cpu_ops = type { i32, [2 x i32] }
|
||||
@pv_cpu_ops = external global %struct.pv_cpu_ops ; <%struct.pv_cpu_ops*> [#uses=1]
|
||||
@G = external global i32 ; <i32*> [#uses=1]
|
||||
|
||||
define void @x() nounwind {
|
||||
entry:
|
||||
tail call void asm sideeffect "1: $0", "i,~{dirflag},~{fpsr},~{flags}"(i32* getelementptr (%struct.pv_cpu_ops* @pv_cpu_ops, i32 0, i32 1, i32 1)) nounwind
|
||||
tail call void asm sideeffect "2: $0", "i,~{dirflag},~{fpsr},~{flags}"(i32* @G) nounwind
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue